Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sys/configuration: add delta encoding/decoding
Browse files Browse the repository at this point in the history
fabian18 committed Jan 8, 2025
1 parent f6e06e6 commit d255c36
Showing 5 changed files with 83 additions and 10 deletions.
17 changes: 17 additions & 0 deletions sys/configuration/Makefile.dep
Original file line number Diff line number Diff line change
@@ -22,3 +22,20 @@ ifneq (,$(filter configuration_backend_flashdb%,$(USEMODULE)))
USEMODULE += flashdb_mtd
endif
endif

ifneq (,$(filter configuration_strings,$(USEMODULE)))
USEMODULE += configuration_handler_parent
endif

ifneq (,$(filter configuration_delta_encoding,$(USEMODULE)))
USEMODULE += configuration_handler_parent
endif

ifneq (,$(filter configuration_delta_decoding,$(USEMODULE)))
USEMODULE += configuration_handler_parent
endif

ifneq (,$(filter configuration_delta_encoding_decoding,$(USEMODULE)))
USEMODULE += configuration_delta_encoding
USEMODULE += configuration_delta_decoding
endif
12 changes: 12 additions & 0 deletions sys/configuration/Makefile.include
Original file line number Diff line number Diff line change
@@ -4,6 +4,9 @@ USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_configuration)
# any backend pseudo module
PSEUDOMODULES += configuration_backend_%

# Store a parent reference in the configuration handler
PSEUDOMODULES += configuration_handler_parent

# use if you want to use custom handlers for import, export, delete, encode, decode
PSEUDOMODULES += configuration_custom_operations

@@ -12,3 +15,12 @@ PSEUDOMODULES += configuration_destination_backend

# use if you want to construct a string path for a configuration item
PSEUDOMODULES += configuration_strings

# encode SIDs relative to their parent SID (delta encoding)
PSEUDOMODULES += configuration_delta_encoding

# decode SIDs relative to their parent SID (delta decoding)
PSEUDOMODULES += configuration_delta_decoding

# alias for configuration_delta_encoding and configuration_delta_decoding
PSEUDOMODULES += configuration_delta_encoding_decoding
22 changes: 20 additions & 2 deletions sys/configuration/configuration.c
Original file line number Diff line number Diff line change
@@ -164,6 +164,19 @@ static bool _sid_in_array_bounds(const conf_array_handler_t *array, conf_sid_t s
return _sid_array_index(array, sid) < array->array_size;
}

#if IS_USED(MODULE_CONFIGURATION_STRINGS)
static int _handler_level(const conf_handler_t *handler)
{
assert(handler);
int level = 0;
while (handler->parent) {
level++;
handler = handler->parent;
}
return level;
}
#endif

static int _configuration_append_segment(const conf_handler_t *next, conf_key_buf_t *key,
char *key_buf, size_t key_buf_len)
{
@@ -173,7 +186,7 @@ static int _configuration_append_segment(const conf_handler_t *next, conf_key_bu
char *buf = key_buf;
size_t size = key_buf_len;
if (*next->node_id->subtree) {
for (int l = 0; l < (int)next->level - 1; l++) {
for (int l = 0; l < _handler_level(next) - 1; l++) {
if (*buf++ != '/') {
return -EINVAL;
}
@@ -778,7 +791,9 @@ void configuration_register(conf_handler_t *parent, conf_handler_t *node)
while (*end) {
end = (conf_handler_t **)&(*end)->node.next;
}
node->level = parent->level + 1;
#if IS_USED(MODULE_CONFIGURATION_HANDLER_PARENT)
node->parent = parent;
#endif
*end = node;
}

@@ -915,6 +930,9 @@ int configuration_decode_internal(conf_path_iterator_t *iter, conf_iterator_rest
#endif
bool skip = false; /* skip structure is parsed SID is not known */
if (!ret) {
#if IS_USED(MODULE_CONFIGURATION_DELTA_DECODING)
key->sid += iter->stack[iter->sp - 1].node->node_id->sid_lower;
#endif
key->offset = 0;
key->sid_normal = key->sid;
/* for a new SID we must start from the root to get the full key->offset */
38 changes: 31 additions & 7 deletions sys/configuration/default_handlers.c
Original file line number Diff line number Diff line change
@@ -280,9 +280,13 @@ static int _encode_node_handler_cbor(const conf_handler_t *handler,
#if IS_USED(MODULE_NANOCBOR)
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (key->sid_normal== handler->node_id->sid_lower) {
if (key->sid_normal == handler->node_id->sid_lower) {
if (*sid_start != key->sid) {
if (nanocbor_fmt_uint(&enc, handler->node_id->sid_lower) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->node_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode node SID %"PRIu64" handler %p\n",
key->sid, (const void *)handler);
return -ENOBUFS;
@@ -363,7 +367,11 @@ static int _encode_array_handler_cbor(const conf_handler_t *handler,
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (key->sid_normal == arr_handler->handler.array_id->sid_lower) {
if (*sid_start != key->sid) {
if (nanocbor_fmt_uint(&enc, arr_handler->handler.array_id->sid_lower) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->array_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode array SID %"PRIu64" handler %p\n",
key->sid, (const void *)arr_handler);
return -ENOBUFS;
@@ -488,7 +496,11 @@ static int _encode_uint_cbor(const conf_handler_t *handler,
const void *data = ((const uint8_t *)handler->data) + key->offset;
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (nanocbor_fmt_uint(&enc, key->sid) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->node_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode SID %"PRIu64" for CBOR uint handler %p\n",
key->sid, (const void *)handler);
return -ENOBUFS;
@@ -579,7 +591,11 @@ static int _encode_int_cbor(const conf_handler_t *handler,
const void *data = ((const uint8_t *)handler->data) + key->offset;
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (nanocbor_fmt_uint(&enc, key->sid) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->node_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode SID %"PRIu64" for CBOR int handler %p\n",
key->sid, (const void *)handler);
return -ENOBUFS;
@@ -670,7 +686,11 @@ static int _encode_byte_string_cbor(const conf_handler_t *handler,
const uint8_t *data = ((const uint8_t *)handler->data) + key->offset;
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (nanocbor_fmt_uint(&enc, key->sid) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->node_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode SID %"PRIu64" for CBOR byte string handler %p\n",
key->sid, (const void *)handler);
return -ENOBUFS;
@@ -727,7 +747,11 @@ static int _encode_text_string_cbor(const conf_handler_t *handler,
const char *data = ((const char *)handler->data) + key->offset;
nanocbor_encoder_t enc;
nanocbor_encoder_init(&enc, *enc_data, *enc_size);
if (nanocbor_fmt_uint(&enc, key->sid) < 0) {
uint64_t sid = key->sid;
#if IS_USED(MODULE_CONFIGURATION_DELTA_ENCODING)
sid = key->sid - handler->parent->node_id->sid_lower;
#endif
if (nanocbor_fmt_uint(&enc, sid) < 0) {
DEBUG("configuration: failed to encode SID %"PRIu64" for CBOR test string handler %p\n",
key->sid, (const void *)handler);
return -ENOBUFS;
4 changes: 3 additions & 1 deletion sys/include/configuration.h
Original file line number Diff line number Diff line change
@@ -632,6 +632,9 @@ enum {
*/
typedef struct conf_handler {
list_node_t node; /**< Every node is in a list, managed by its parent */
#if IS_USED(MODULE_CONFIGURATION_HANDLER_PARENT)
struct conf_handler *parent; /**< Pointer to the parent node */
#endif
struct conf_handler *subnodes; /**< Every node has a list of subnodes */
union {
const conf_handler_array_id_t *array_id; /**< Pointer to handler array identification */
@@ -649,7 +652,6 @@ typedef struct conf_handler {
#endif
void *data; /**< Pointer to the configuration item data location (may be NULL) */
uint32_t size; /**< Configuration item size in bytes */
unsigned level; /**< Level in the configuration tree (root = 0) */
conf_handler_flags_t conf_flags; /**< Configuration of handler behavior */
mutex_t mutex; /**< Lock for unique access to the configuration item */
} conf_handler_t;

0 comments on commit d255c36

Please sign in to comment.