From 8ed793f9cdf2b7ccc90b3d2d6319a58f7843991a Mon Sep 17 00:00:00 2001 From: Dmitri Pal Date: Mon, 30 Aug 2010 10:10:02 -0400 Subject: WP --- common/ini/ini_comment.c | 256 ++++++++++++++++++++++------------------- common/ini/ini_config.h | 8 -- common/ini/ini_config_priv.h | 3 + common/ini/ini_configobj.c | 130 +++++++++++++++++++++ common/ini/ini_configobj.h | 8 -- common/ini/ini_defines.h | 6 + common/ini/ini_fileobj.c | 3 +- common/ini/ini_parse_ut.c | 9 +- common/ini/ini_print.c | 29 ++++- common/ini/ini_valueobj.c | 114 ++++++++++++++++++ common/ini/ini_valueobj.h | 7 ++ common/refarray/ref_array.c | 122 ++++++++++++++++---- common/refarray/ref_array.h | 44 +++++++ common/refarray/ref_array_ut.c | 117 +++++++++++++++++++ 14 files changed, 691 insertions(+), 165 deletions(-) diff --git a/common/ini/ini_comment.c b/common/ini/ini_comment.c index e700e98..19ee80e 100644 --- a/common/ini/ini_comment.c +++ b/common/ini/ini_comment.c @@ -26,10 +26,14 @@ #include "config.h" #include "trace.h" #include "ref_array.h" +#include "simplebuffer.h" #include "ini_comment.h" /* The lines will increment in this number */ #define INI_COMMENT_BLOCK 10 +/* Default comment length */ +#define INI_COMMENT_LEN 100 + /***************************/ /* Internal comment states */ @@ -57,7 +61,6 @@ /****************************************/ struct ini_comment { struct ref_array *ra; - struct ref_array *ra_len; uint32_t state; }; @@ -68,14 +71,13 @@ struct ini_comment { void ini_comment_destroy(struct ini_comment *ic) { - TRACE_FLOW_STRING("ini_comment_destroy", "Entry"); + TRACE_FLOW_ENTRY(); if (ic) { /* Function will check for NULL */ ref_array_destroy(ic->ra); - ref_array_destroy(ic->ra_len); free(ic); } - TRACE_FLOW_STRING("ini_comment_destroy", "Exit"); + TRACE_FLOW_EXIT(); } @@ -85,9 +87,9 @@ void ini_comment_cb(void *elem, void *data) { - TRACE_FLOW_STRING("ini_comment_cb", "Entry"); - free(*((char **)elem)); - TRACE_FLOW_STRING("ini_comment_cb", "Exit"); + TRACE_FLOW_ENTRY(); + simplebuffer_free(*((struct simplebuffer **)elem)); + TRACE_FLOW_EXIT(); } @@ -96,13 +98,12 @@ int ini_comment_create(struct ini_comment **ic) { int error = EOK; struct ref_array *ra = NULL; - struct ref_array *ra_len = NULL; struct ini_comment *ic_new = NULL; - TRACE_FLOW_STRING("ini_comment_create", "Entry"); + TRACE_FLOW_ENTRY(); error = ref_array_create(&ra, - sizeof(char *), + sizeof(struct simplebuffer *), INI_COMMENT_BLOCK, ini_comment_cb, NULL); @@ -111,14 +112,74 @@ int ini_comment_create(struct ini_comment **ic) return error; } - error = ref_array_create(&ra_len, - sizeof(uint32_t), - INI_COMMENT_BLOCK, - NULL, - NULL); - if (error) { - TRACE_ERROR_NUMBER("Error creating ref array", error); + ic_new = malloc(sizeof(struct ini_comment)); + if (!ic_new) { + TRACE_ERROR_NUMBER("Memory allocation error", ENOMEM); ref_array_destroy(ra); + return ENOMEM; + } + + /* Initialize members here */ + ic_new->ra = ra; + ic_new->state = INI_COMMENT_EMPTY; + + *ic = ic_new; + + TRACE_FLOW_EXIT(); + return error; +} + +/* Callback to copy comment */ +static int ini_comment_copy_cb(void *elem, + void *new_elem) +{ + int error = EOK; + struct simplebuffer *sb = NULL; + struct simplebuffer *sb_new = NULL; + struct simplebuffer **sb_acpt = NULL; + + TRACE_FLOW_ENTRY(); + + error = simplebuffer_alloc(&sb_new); + if (error) { + TRACE_ERROR_NUMBER("Failed to allocate buffer", error); + return error; + } + + sb = (struct simplebuffer *)elem; + error = simplebuffer_add_str(sb_new, + simplebuffer_get_buf(sb), + simplebuffer_get_len(sb), + INI_COMMENT_LEN); + if (error) { + TRACE_ERROR_NUMBER("Failed to allocate buffer", error); + simplebuffer_free(sb_new); + return error; + } + + sb_acpt = (struct simplebuffer **)new_elem; + *sb_acpt = sb_new; + + TRACE_FLOW_EXIT(); + return error; +} + + +/* Create a comment object */ +int ini_comment_copy(struct ini_comment *ic, + struct ini_comment **copy_ic) +{ + int error = EOK; + struct ref_array *ra = NULL; + struct ini_comment *ic_new = NULL; + + TRACE_FLOW_ENTRY(); + + error = ref_array_copy(ic->ra, + ini_comment_copy_cb, + &ra); + if (error) { + TRACE_ERROR_NUMBER("Error creating a copy of ref array", error); return error; } @@ -126,28 +187,25 @@ int ini_comment_create(struct ini_comment **ic) if (!ic_new) { TRACE_ERROR_NUMBER("Memory allocation error", ENOMEM); ref_array_destroy(ra); - ref_array_destroy(ra_len); return ENOMEM; } /* Initialize members here */ ic_new->ra = ra; - ic_new->ra_len = ra_len; - ic_new->state = INI_COMMENT_EMPTY; + ic_new->state = ic->state; - *ic = ic_new; + *ic_copy = ic_new; - TRACE_FLOW_STRING("ini_comment_create", "Exit"); + TRACE_FLOW_EXIT(); return error; } - /* Is the comment valid? */ static int ini_comment_is_valid(const char *line) { int i; - TRACE_FLOW_STRING("ini_comment_is_valid", "Entry"); + TRACE_FLOW_ENTRY(); /* Null is ok */ if (!line) { @@ -191,13 +249,13 @@ static int ini_comment_modify(struct ini_comment *ic, uint32_t length) { int error = EOK; - char *elem = NULL; + struct simplebuffer *elem = NULL; + struct simplebuffer *empty = NULL; char *input = NULL; - char *empty = NULL; uint32_t i, len = 0; uint32_t input_len = 0; - TRACE_FLOW_STRING("ini_comment_modify", "Entry"); + TRACE_FLOW_ENTRY(); if (!ic) { TRACE_ERROR_NUMBER("Invalid comment object", EINVAL); @@ -231,21 +289,28 @@ static int ini_comment_modify(struct ini_comment *ic, return EINVAL; } + error = simplebuffer_alloc(&elem); + if (error) { + TRACE_ERROR_NUMBER("Allocate buffer for the comment", error); + return error; + } + /* Dup it */ if (input) { + if (length == 0) input_len = strlen(input); else input_len = length; - elem = strndup(input, (size_t)(input_len + 1)); - } - else { - input_len = 0; - elem = strdup(""); + error = simplebuffer_add_str(elem, + input, + input_len, + INI_COMMENT_LEN); + if (error) { + TRACE_ERROR_NUMBER("Allocate buffer for the comment", error); + simplebuffer_free(elem); + return error; + } } - if (!elem) { - TRACE_ERROR_NUMBER("Memory allocation error", ENOMEM); - return ENOMEM; - } } /* Do action depending on mode */ @@ -256,15 +321,10 @@ static int ini_comment_modify(struct ini_comment *ic, error = ref_array_append(ic->ra, (void *)&elem); if (error) { TRACE_ERROR_NUMBER("Failed to append line to an array", error); - free(elem); + simplebuffer_free(elem); return error; } - error = ref_array_append(ic->ra_len, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to append length", error); - return error; - } break; case INI_COMMENT_MODE_APPEND: @@ -277,11 +337,6 @@ static int ini_comment_modify(struct ini_comment *ic, return error; } - error = ref_array_append(ic->ra_len, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to append length", error); - return error; - } break; case INI_COMMENT_MODE_INSERT: @@ -291,21 +346,17 @@ static int ini_comment_modify(struct ini_comment *ic, if (idx > len) { /* Fill in empty lines */ for (i = 0; i < (idx-len); i++) { - empty = strdup(""); - if (empty) { - TRACE_ERROR_NUMBER("Memory problem", ENOMEM); - return ENOMEM; - } - error = ref_array_append(ic->ra, (void *)&empty); + error = simplebuffer_alloc(&empty); if (error) { - TRACE_ERROR_NUMBER("Append problem", error); - free(empty); + TRACE_ERROR_NUMBER("Allocate buffer for the comment", error); + simplebuffer_free(elem); return error; } - error = ref_array_append(ic->ra_len, (void *)&input_len); + error = ref_array_append(ic->ra, (void *)&empty); if (error) { - TRACE_ERROR_NUMBER("Error adding lenghts", error); - free(empty); + TRACE_ERROR_NUMBER("Append problem", error); + simplebuffer_free(empty); + simplebuffer_free(elem); return error; } } @@ -313,27 +364,16 @@ static int ini_comment_modify(struct ini_comment *ic, error = ref_array_append(ic->ra, (void *)&elem); if (error) { TRACE_ERROR_NUMBER("Failed to append last line", error); + simplebuffer_free(elem); return error; } - - error = ref_array_append(ic->ra_len, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to append length", error); - return error; - } - } else { /* Insert inside the array */ error = ref_array_insert(ic->ra, idx, (void *)&elem); if (error) { TRACE_ERROR_NUMBER("Failed to append last line", error); - return error; - } - - error = ref_array_insert(ic->ra_len, idx, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to insert length", error); + simplebuffer_free(elem); return error; } @@ -347,13 +387,7 @@ static int ini_comment_modify(struct ini_comment *ic, error = ref_array_replace(ic->ra, idx, (void *)&elem); if (error) { TRACE_ERROR_NUMBER("Failed to replace", error); - free(elem); - return error; - } - - error = ref_array_replace(ic->ra_len, idx, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to remove length", error); + simplebuffer_free(elem); return error; } break; @@ -367,11 +401,6 @@ static int ini_comment_modify(struct ini_comment *ic, return error; } - error = ref_array_remove(ic->ra_len, idx); - if (error) { - TRACE_ERROR_NUMBER("Failed to remove length", error); - return error; - } break; case INI_COMMENT_MODE_CLEAR: @@ -380,13 +409,7 @@ static int ini_comment_modify(struct ini_comment *ic, error = ref_array_replace(ic->ra, idx, (void *)&elem); if (error) { TRACE_ERROR_NUMBER("Failed to replace", error); - free(elem); - return error; - } - - error = ref_array_replace(ic->ra_len, idx, (void *)&input_len); - if (error) { - TRACE_ERROR_NUMBER("Failed to replace length", error); + simplebuffer_free(elem); return error; } break; @@ -404,7 +427,7 @@ static int ini_comment_modify(struct ini_comment *ic, else ic->state = INI_COMMENT_CHANGED; - TRACE_FLOW_STRING("ini_comment_modify", "Exit"); + TRACE_FLOW_EXIT(); return error; } @@ -416,7 +439,7 @@ int ini_comment_build(struct ini_comment *ic, const char *line) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_build", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_BUILD, 0, line, 0); @@ -434,7 +457,7 @@ int ini_comment_build_wl(struct ini_comment *ic, { int error = EOK; - TRACE_FLOW_STRING("ini_comment_build", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_BUILD, 0, line, length); @@ -451,7 +474,7 @@ int ini_comment_insert(struct ini_comment *ic, { int error = EOK; - TRACE_FLOW_STRING("ini_comment_insert", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_INSERT, idx, line, 0); @@ -464,7 +487,7 @@ int ini_comment_append(struct ini_comment *ic, const char *line) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_append", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_APPEND, 0, line, 0); @@ -477,7 +500,7 @@ int ini_comment_remove(struct ini_comment *ic, uint32_t idx) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_remove", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_REMOVE, idx, NULL, 0); @@ -490,7 +513,7 @@ int ini_comment_clear(struct ini_comment *ic, uint32_t idx) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_clear", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_CLEAR, idx, NULL, 0); @@ -506,7 +529,7 @@ int ini_comment_replace(struct ini_comment *ic, { int error = EOK; - TRACE_FLOW_STRING("ini_comment_replace", "Entry"); + TRACE_FLOW_ENTRY(); error = ini_comment_modify(ic, INI_COMMENT_MODE_REPLACE, idx, line, 0); @@ -520,7 +543,7 @@ int ini_comment_reset(struct ini_comment *ic) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_reset", "Entry"); + TRACE_FLOW_ENTRY(); if (!ic) { TRACE_ERROR_NUMBER("Invalid comment object", EINVAL); @@ -533,7 +556,7 @@ int ini_comment_reset(struct ini_comment *ic) ic->state = INI_COMMENT_CHANGED; } - TRACE_FLOW_STRING("ini_comment_reset", "Exit"); + TRACE_FLOW_EXIT(); return error; } @@ -542,7 +565,7 @@ int ini_comment_get_numlines(struct ini_comment *ic, uint32_t *num) { int error = EOK; - TRACE_FLOW_STRING("ini_comment_get_numlines", "Entry"); + TRACE_FLOW_ENTRY(); if ((!ic) || (!num)) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); @@ -562,28 +585,24 @@ int ini_comment_get_line(struct ini_comment *ic, uint32_t idx, { int error = EOK; void *res = NULL; + struct simplebuffer *sb = NULL; - TRACE_FLOW_STRING("ini_comment_get_line", "Entry"); + TRACE_FLOW_ENTRY(); if ((!ic) || (!line)) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); return EINVAL; } - res = ref_array_get(ic->ra, idx, (void *)line); + res = ref_array_get(ic->ra, idx, (void *)&sb); if (!res) { error = EINVAL; *line = NULL; if (line_len) line_len = 0; } - - if (line_len) { - res = ref_array_get(ic->ra_len, idx, (void *)line_len); - if (!res) { - error = EINVAL; - *line = NULL; - *line_len = 0; - } + else { + *line = simplebuffer_get_buf(sb); + if (line_len) *line_len = simplebuffer_get_len(sb); } TRACE_FLOW_NUMBER("ini_comment_get_line - Returning", error); @@ -597,7 +616,7 @@ int ini_comment_swap(struct ini_comment *ic, { int error = EOK; - TRACE_FLOW_STRING("ini_comment_swap", "Entry"); + TRACE_FLOW_ENTRY(); if (!ic) { TRACE_ERROR_NUMBER("Invalid argument", EINVAL); @@ -613,7 +632,7 @@ int ini_comment_swap(struct ini_comment *ic, ic->state = INI_COMMENT_CHANGED; } - TRACE_FLOW_NUMBER("ini_comment_swap - Returning", error); + TRACE_FLOW_EXIT(); return error; } @@ -623,9 +642,9 @@ void ini_comment_print(struct ini_comment *ic, FILE *file) { int len; int i; - char *ret = NULL; + struct simplebuffer *sb = NULL; - TRACE_FLOW_STRING("ini_comment_print", "Entry"); + TRACE_FLOW_ENTRY(); if (!file) { TRACE_ERROR_NUMBER("Invalid file argument", EINVAL); @@ -635,11 +654,10 @@ void ini_comment_print(struct ini_comment *ic, FILE *file) if (ic) { len = ref_array_len(ic->ra); for (i = 0; i < len; i++) { - ref_array_get(ic->ra, i, &ret); - fprintf(file, "%s\n", ret); + ref_array_get(ic->ra, i, (void *)(&sb)); + fprintf(file, "%s\n", simplebuffer_get_buf(sb)); } } - TRACE_FLOW_STRING("ini_comment_print", "Exit"); - + TRACE_FLOW_EXIT(); } diff --git a/common/ini/ini_config.h b/common/ini/ini_config.h index c69e235..3b75012 100644 --- a/common/ini/ini_config.h +++ b/common/ini/ini_config.h @@ -498,14 +498,6 @@ struct parse_error { * @{ */ -/** @brief Function to return a parsing error as a string. - * - * @param[in] parsing_error Error code for the parsing error. - * - * @return Error string. - */ -const char *parsing_error_str(int parsing_error); - /** * @brief Read configuration information from a file. diff --git a/common/ini/ini_config_priv.h b/common/ini/ini_config_priv.h index 9185e14..1880c3f 100644 --- a/common/ini/ini_config_priv.h +++ b/common/ini/ini_config_priv.h @@ -78,4 +78,7 @@ void ini_cleanup_cb(const char *property, int length, void *custom_data); +/* Get parsing error */ +const char *ini_get_error_str(int parsing_error, int family); + #endif diff --git a/common/ini/ini_configobj.c b/common/ini/ini_configobj.c index 4da9a7c..44b8d32 100644 --- a/common/ini/ini_configobj.c +++ b/common/ini/ini_configobj.c @@ -113,3 +113,133 @@ int ini_config_create(struct ini_cfgobj **ini_config) TRACE_FLOW_EXIT(); return error; } + +/* Callback to set the boundary */ +int ini_boundary_cb(const char *property, + int property_len, + int type, + void *data, + int length, + void *custom_data, + int *dummy) +{ + int error = EOK; + struct value_obj *vo = NULL; + uint32_t boundary; + + TRACE_FLOW_ENTRY(); + + boundary = *((uint32_t *)(custom_data)); + /* Banary items are the values */ + if(type == COL_TYPE_BINARY) { + vo = *((struct value_obj **)(data)); + error = value_set_boundary(vo, boundary); + } + + TRACE_FLOW_EXIT(); + return error; +} + +/* Set the folding boundary for multiline values. + * Use before serializing and saving to a file if the + * default boundary of 80 characters does not work for you. + */ +int ini_config_set_wrap(struct ini_cfgobj *ini_config, + uint32_t boundary) +{ + int error = EOK; + + TRACE_FLOW_ENTRY(); + + if (!ini_config) { + TRACE_ERROR_NUMBER("Invalid argument", EINVAL); + return EINVAL; + } + + ini_config->boundary = boundary; + error = col_traverse_collection(ini_config->cfg, + COL_TRAVERSE_DEFAULT, + ini_boundary_cb, + (void *)(&(ini_config->boundary))); + if (error) { + TRACE_ERROR_NUMBER("Failed to set wrapping boundary", error); + return error; + } + + + TRACE_FLOW_EXIT(); + return error; +} + +/* Configuration copy callback */ +static int ini_copy_cb(struct collection_item *item, + void *ext_data, + int *skip) +{ + int error = EOK; + struct value_obj *vo = NULL; + struct value_obj *new_vo = NULL; + + TRACE_FLOW_ENTRY(); + + ext_data = NULL; + *skip = 0; + + /* Banary items are the values */ + if(type == COL_TYPE_BINARY) { + vo = *((struct value_obj **)(col_get_item_data(item))); + error = value_copy(vo, &new_vo); + if (error) { + TRACE_ERROR_NUMBER("Failed to copy value", error); + return error; + } + } + + TRACE_FLOW_EXIT(); + return error; +} + +/* Copy configuration */ +int ini_config_copy(struct ini_cfgobj *ini_config, + struct ini_cfgobj **ini_new) +{ + int error = EOK; + struct ini_cfgobj *new_co; + + TRACE_FLOW_ENTRY(); + + if ((!ini_config) || + (!ini_new)) { + TRACE_ERROR_NUMBER("Invalid argument", EINVAL); + return EINVAL; + } + + /* Create a new configuration object */ + errno = 0; + new_co = malloc(sizeof(struct ini_cfgobj)); + if (!new_co) { + error = errno; + TRACE_ERROR_NUMBER("Failed to allocate memory", ENOMEM); + return ENOMEM; + } + + new_co->cfg = NULL; + new_co->boundary = ini_config->boundary; + + error = col_copy_collection_with_cb(&(new_cfg->cfg), + ini_config->cfg, + INI_CONFIG_NAME, + COL_COPY_NORMAL, + ini_copy_cb, + NULL); + if (error) { + TRACE_ERROR_NUMBER("Failed to copy collection", error); + ini_config_destroy(new_co); + return error; + } + + *ini_new = new_co; + + TRACE_FLOW_EXIT(); + return error; +} diff --git a/common/ini/ini_configobj.h b/common/ini/ini_configobj.h index 8ecb148..81578c0 100644 --- a/common/ini/ini_configobj.h +++ b/common/ini/ini_configobj.h @@ -142,14 +142,6 @@ int ini_config_parse(struct ini_cfgfile *file_ctx, void ini_print_errors(FILE *file, char **error_list); -/* TBD rename the function */ -/** @brief Function to return a parsing error as a string. - * - * @param[in] parsing_error Error code for the parsing error. - * - * @return Error string. - */ -const char *parsing_error_str(int parsing_error); /* Merge two configurations together creating a new one */ diff --git a/common/ini/ini_defines.h b/common/ini/ini_defines.h index bead998..1d03835 100644 --- a/common/ini/ini_defines.h +++ b/common/ini/ini_defines.h @@ -95,6 +95,12 @@ */ #define COL_CLASS_INI_META COL_CLASS_INI_BASE + 4 +/* Family of errors */ +#define INI_FAMILY_PARSING 0 +#define INI_FAMILY_VALIDATION 1 +#define INI_FAMILY_GRAMMAR 2 + + /* Different error string functions can be passed as callbacks */ typedef const char * (*error_fn)(int error); diff --git a/common/ini/ini_fileobj.c b/common/ini/ini_fileobj.c index 117608c..29d5f90 100644 --- a/common/ini/ini_fileobj.c +++ b/common/ini/ini_fileobj.c @@ -241,7 +241,8 @@ int ini_config_get_errors(struct ini_cfgfile *file_ctx, col_get_item_property(item, NULL), pe->error, pe->line, - parsing_error_str(pe->error)); + ini_get_error_str(pe->error, + INI_FAMILY_PARSING)); errlist[count] = line; count++; diff --git a/common/ini/ini_parse_ut.c b/common/ini/ini_parse_ut.c index 36b7a33..7a10c25 100644 --- a/common/ini/ini_parse_ut.c +++ b/common/ini/ini_parse_ut.c @@ -49,7 +49,6 @@ int test_one_file(const char *filename) char **error_list = NULL; struct simplebuffer *sbobj = NULL; uint32_t left = 0; - unsigned count = 0; INIOUT(printf("<==== Testing file %s ====>\n", filename)); @@ -81,12 +80,20 @@ int test_one_file(const char *filename) ini_config_get_filename(file_ctx))); ini_config_get_errors(file_ctx, &error_list); INIOUT(ini_print_errors(stdout, error_list)); + ini_config_free_errors(error_list); } /* We do not return here intentionally */ } ini_config_file_close(file_ctx); + error = ini_config_set_wrap(ini_config, 5); + if (error) { + printf("Failed to set custom wrapper. Error %d.\n", error); + ini_config_destroy(ini_config); + return error; + } + error = simplebuffer_alloc(&sbobj); if (error) { TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error); diff --git a/common/ini/ini_print.c b/common/ini/ini_print.c index f12b27e..36ab5c3 100644 --- a/common/ini/ini_print.c +++ b/common/ini/ini_print.c @@ -66,7 +66,7 @@ /* Function to return parsing error */ -const char *parsing_error_str(int parsing_error) +static const char *parsing_error_str(int parsing_error) { const char *placeholder= _("Unknown pasing error."); const char *str_error[] = { _("Data is too long."), @@ -109,7 +109,7 @@ const char *parsing_error_str(int parsing_error) * @return Error string. */ -const char *grammar_error_str(int grammar_error) +static const char *grammar_error_str(int grammar_error) { const char *placeholder= _("Unknown grammar error."); /* THIS IS A TEMPORARY PLACEHOLDER !!!! */ @@ -150,7 +150,7 @@ const char *grammar_error_str(int grammar_error) * * @return Error string. */ -const char *validation_error_str(int validation_error) +static const char *validation_error_str(int validation_error) { const char *placeholder= _("Unknown validation error."); /* THIS IS A TEMPORARY PLACEHOLDER !!!! */ @@ -170,7 +170,30 @@ const char *validation_error_str(int validation_error) return str_error[validation_error-1]; } +/* Wrapper to print errors */ +const char *ini_get_error_str(int error, int family) +{ + const char *val; + TRACE_FLOW_ENTRY(); + + switch(family) { + case INI_FAMILY_PARSING: + val = parsing_error_str(error); + break; + case INI_FAMILY_VALIDATION: + val = validation_error_str(error); + break; + case INI_FAMILY_GRAMMAR: + val = grammar_error_str(error); + break; + default: + val = _("Unknown error category."); + break; + } + TRACE_FLOW_EXIT(); + return val; +} /* Internal function that prints errors */ static void print_error_list(FILE *file, diff --git a/common/ini/ini_valueobj.c b/common/ini/ini_valueobj.c index 02b9732..4659faa 100644 --- a/common/ini/ini_valueobj.c +++ b/common/ini/ini_valueobj.c @@ -195,8 +195,15 @@ static int value_fold(struct simplebuffer *unfolded, /* Get the buffer info */ len = simplebuffer_get_len(unfolded); + if (!len) { + /* Nothing to fold */ + TRACE_FLOW_EXIT(); + return EOK; + } + buf = (const char *)simplebuffer_get_buf(unfolded); + /* Make sure that we have at least one character to fold */ if (fold_bound == 0) fold_bound++; @@ -564,6 +571,84 @@ int value_create_new(const char *strvalue, return error; } +/* Create a copy of the value */ +int value_copy(struct value_obj *vo + struct value_obj **copy_vo) +{ + + int error = EOK; + struct value_obj *new_vo = NULL; + struct simplebuffer *oneline = NULL; + + TRACE_FLOW_ENTRY(); + + if ((!copy_vo) || (!vo)) { + TRACE_ERROR_NUMBER("Invalid argument", EINVAL); + return EINVAL; + } + + /* Create buffer to hold the value */ + error = simplebuffer_alloc(&oneline); + if (error) { + TRACE_ERROR_NUMBER("Failed to allocate dynamic string.", error); + return error; + } + + /* Put value into the buffer */ + error = simplebuffer_add_str(oneline, + simplebuffer_get_buf(vo->unfolded), + simplebuffer_get_len(vo->unfolded), + INI_VALUE_BLOCK); + if (error) { + TRACE_ERROR_NUMBER("Failed to add string", error); + simplebuffer_free(oneline); + return error; + } + + /* Acllocate new INI value structure */ + new_vo = malloc(sizeof(struct value_obj)); + if (!new_vo) { + TRACE_ERROR_NUMBER("No memory", ENOMEM); + simplebuffer_free(oneline); + return ENOMEM; + } + + new_vo->origin = vo->origin; + new_vo->line = vo->line; + new_vo->unfolded = oneline; + new_vo->keylen = vo->key_len; + new_vo->boundary = vo->boundary; + new_vo->raw_lines = NULL; + new_vo->raw_lengths = NULL; + + error = value_create_arrays(&(new_vo->raw_lines), + &(new_vo->raw_lengths)); + + if (error) { + TRACE_ERROR_NUMBER("Failed to fold", error); + value_destroy(new_vo); + return error; + } + + /* Create arrays by folding the value */ + error = value_fold(new_vo->unfolded, + new_vo->keylen, + new_vo->boundary, + new_vo->raw_lines, + new_vo->raw_lengths); + if (error) { + TRACE_ERROR_NUMBER("Failed to fold", error); + value_destroy(new_vo); + return error; + } + + *vo = new_vo; + + TRACE_FLOW_EXIT(); + + return error; +} + /* Get concatenated value */ int value_get_concatenated(struct value_obj *vo, const char **fullstr) @@ -643,6 +728,35 @@ int value_set_keylen(struct value_obj *vo, uint32_t key_len) return EOK; } +/* Change boundary */ +int value_set_boundary(struct value_obj *vo, uint32_t boundary) +{ + int error = EOK; + TRACE_FLOW_ENTRY(); + + if (!vo) { + TRACE_ERROR_NUMBER("Invalid object", EINVAL); + return EINVAL; + } + + vo->boundary = boundary; + + /* Fold in new value */ + error = value_fold(vo->unfolded, + vo->keylen, + vo->boundary, + vo->raw_lines, + vo->raw_lengths); + if (error) { + TRACE_ERROR_NUMBER("Failed to fold", error); + /* In this case nothing to free here but + * the object might be unusable */ + return error; + } + + TRACE_FLOW_EXIT(); + return EOK; +} /* Update value */ int value_update(struct value_obj *vo, diff --git a/common/ini/ini_valueobj.h b/common/ini/ini_valueobj.h index 2e13c0d..25c158c 100644 --- a/common/ini/ini_valueobj.h +++ b/common/ini/ini_valueobj.h @@ -87,6 +87,10 @@ int value_create_new(const char *strvalue, struct ini_comment *ic, struct value_obj **vo); +/* Create a copy of the value */ +int value_copy(struct value_obj *vo + struct value_obj **copy_vo); + /* Destroy a value object */ void value_destroy(struct value_obj *vo); @@ -105,6 +109,9 @@ int value_get_line(struct value_obj *vo, /* Update key length */ int value_set_keylen(struct value_obj *vo, uint32_t key_len); +/* Change boundary */ +int value_set_boundary(struct value_obj *vo, + uint32_t boundary); /* Update value */ int value_update(struct value_obj *vo, diff --git a/common/refarray/ref_array.c b/common/refarray/ref_array.c index a571804..464ac30 100644 --- a/common/refarray/ref_array.c +++ b/common/refarray/ref_array.c @@ -48,7 +48,7 @@ static int ref_array_grow(struct ref_array *ra) int error = EOK; void *newbuf = NULL; - TRACE_FLOW_STRING("ref_array_grow", "Entry"); + TRACE_FLOW_ENTRY(); TRACE_INFO_NUMBER("Current length: ", ra->len); TRACE_INFO_NUMBER("Current size: ", ra->size); @@ -83,7 +83,7 @@ int ref_array_create(struct ref_array **ra, { struct ref_array *new_ra = NULL; - TRACE_FLOW_STRING("ref_array_create", "Entry"); + TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); @@ -113,14 +113,14 @@ int ref_array_create(struct ref_array **ra, *ra = new_ra; - TRACE_FLOW_STRING("ref_array_create", "Exit"); + TRACE_FLOW_EXIT(); return EOK; } /* Get new reference to an array */ struct ref_array *ref_array_getref(struct ref_array *ra) { - TRACE_FLOW_STRING("ref_array_getref", "Entry"); + TRACE_FLOW_ENTRY(); /* Check if array is not NULL */ if (ra) { @@ -134,7 +134,7 @@ struct ref_array *ref_array_getref(struct ref_array *ra) TRACE_ERROR_STRING("Uninitialized array.", "Returning NULL"); } - TRACE_FLOW_STRING("ref_array_getref", "Exit"); + TRACE_FLOW_EXIT(); return ra; } @@ -143,7 +143,7 @@ void ref_array_destroy(struct ref_array *ra) { int idx; - TRACE_FLOW_STRING("ref_array_destroy", "Entry"); + TRACE_FLOW_ENTRY(); /* Check if array is not NULL */ if (!ra) { @@ -175,7 +175,7 @@ void ref_array_destroy(struct ref_array *ra) TRACE_ERROR_STRING("Reference count is 0.", "Coding error???"); } - TRACE_FLOW_STRING("ref_array_destroy", "Exit"); + TRACE_FLOW_EXIT(); } /* Add new element to the array */ @@ -183,7 +183,8 @@ int ref_array_append(struct ref_array *ra, void *element) { int error = EOK; - TRACE_FLOW_STRING("ref_array_append", "Entry"); + TRACE_FLOW_ENTRY(); + if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); return EINVAL; @@ -205,14 +206,14 @@ int ref_array_append(struct ref_array *ra, void *element) ra->len++; - TRACE_FLOW_STRING("ref_array_append", "Exit"); + TRACE_FLOW_EXIT(); return error; } /* Get element */ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr) { - TRACE_FLOW_STRING("ref_array_get", "Entry"); + TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_STRING("Uninitialized argument.", ""); @@ -235,7 +236,7 @@ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr) } - TRACE_FLOW_STRING("ref_array_get returning internal storage", "Exit"); + TRACE_FLOW_EXIT(); return (unsigned char *)(ra->storage) + idx * ra->elsize; } @@ -243,7 +244,7 @@ void *ref_array_get(struct ref_array *ra, uint32_t idx, void *acptr) /* Get length */ int ref_array_getlen(struct ref_array *ra, uint32_t *len) { - TRACE_FLOW_STRING("ref_array_getlen", "Entry"); + TRACE_FLOW_ENTRY(); if ((!ra) || (!len)) { TRACE_ERROR_STRING("Uninitialized argument.", ""); @@ -252,14 +253,14 @@ int ref_array_getlen(struct ref_array *ra, uint32_t *len) *len = ra->len; - TRACE_FLOW_STRING("ref_array_getlen", "Exit"); + TRACE_FLOW_EXIT(); return EOK; } /* Alternative function to get length */ uint32_t ref_array_len(struct ref_array *ra) { - TRACE_FLOW_STRING("ref_array_len", "Entry"); + TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_STRING("Uninitialized argument.", ""); @@ -267,7 +268,7 @@ uint32_t ref_array_len(struct ref_array *ra) return 0; } - TRACE_FLOW_STRING("ref_array_len", "Exit"); + TRACE_FLOW_EXIT(); return ra->len; } @@ -280,7 +281,7 @@ int ref_array_insert(struct ref_array *ra, int error = EOK; uint32_t i; - TRACE_FLOW_STRING("ref_array_insert", "Entry"); + TRACE_FLOW_ENTRY(); if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); @@ -315,7 +316,7 @@ int ref_array_insert(struct ref_array *ra, ra->len++; - TRACE_FLOW_STRING("ref_array_insert", "Exit"); + TRACE_FLOW_EXIT(); return error; } @@ -328,7 +329,7 @@ int ref_array_replace(struct ref_array *ra, { int error = EOK; - TRACE_FLOW_STRING("ref_array_replace", "Entry"); + TRACE_FLOW_ENTRY(); if ((!ra) || (!element)) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); @@ -351,7 +352,7 @@ int ref_array_replace(struct ref_array *ra, ra->elsize); - TRACE_FLOW_STRING("ref_array_replace", "Exit"); + TRACE_FLOW_EXIT(); return error; } @@ -363,7 +364,7 @@ int ref_array_remove(struct ref_array *ra, int error = EOK; uint32_t i; - TRACE_FLOW_STRING("ref_array_remove", "Entry"); + TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); @@ -389,7 +390,7 @@ int ref_array_remove(struct ref_array *ra, ra->len--; - TRACE_FLOW_STRING("ref_array_remove", "Exit"); + TRACE_FLOW_EXIT(); return error; } @@ -398,7 +399,7 @@ void ref_array_reset(struct ref_array *ra) { int idx; - TRACE_FLOW_STRING("ref_array_reset", "Entry"); + TRACE_FLOW_ENTRY(); /* Check if array is not NULL */ if (!ra) { @@ -418,7 +419,7 @@ void ref_array_reset(struct ref_array *ra) ra->size = 0; ra->len = 0; - TRACE_FLOW_STRING("ref_array_reset", "Exit"); + TRACE_FLOW_EXIT(); } /* Swap two elements in the array */ @@ -429,7 +430,7 @@ int ref_array_swap(struct ref_array *ra, int error = EOK; void *temp = NULL; - TRACE_FLOW_STRING("ref_array_swap", "Entry"); + TRACE_FLOW_ENTRY(); if (!ra) { TRACE_ERROR_NUMBER("Uninitialized argument.", EINVAL); @@ -465,10 +466,81 @@ int ref_array_swap(struct ref_array *ra, free(temp); - TRACE_FLOW_STRING("ref_array_swap", "Exit"); + TRACE_FLOW_EXIT(); + return error; +} + +/* Copy array */ +int ref_array_copy(struct ref_array *ra, + ref_array_copy_cb copy_cb, + struct ref_array **copy_ra) +{ + int error = EOK; + int idx; + struct ref_array *new_ra = NULL; + void *src; + void *dst; + + TRACE_FLOW_ENTRY(); + + /* Check if array is not NULL */ + if ((!ra) || (!copy_ra)) { + TRACE_ERROR_NUMBER("Invalid argument.", EINVAL); + return EINVAL; + } + + new_ra = (struct ref_array *)malloc(sizeof(struct ref_array)); + if (!new_ra) { + TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); + return ENOMEM; + } + + new_ra->storage = calloc(ra->size, ra->elsize); + if (!(new_ra->storage)) { + TRACE_ERROR_NUMBER("Failed to allocate memory.", ENOMEM); + free(new_ra); + return ENOMEM; + } + + new_ra->elsize = ra->elsize; + new_ra->size = ra->size; + new_ra->grow_by = ra->grow_by; + new_ra->len = 0; + new_ra->refcount = 1; + new_ra->cb = ra->cb; + new_ra->cb_data = ra->cb_data; + + for (idx = 0; idx < ra->len; idx++) { + if (copy_cb) { + THIS IS BROKEN!!! + src = (void *)((unsigned char *)(ra->storage) + idx * ra->elsize); + dst = (void *)((unsigned char *)(new_ra->storage) + + idx * new_ra->elsize); + + error = copy_cb(src, (void *)(dst)); + if (error) { + TRACE_ERROR_NUMBER("Failed to copy data.", error); + ref_array_destroy(new_ra); + return error; + } + } + else { + memcpy((unsigned char *)(new_ra->storage) + idx * new_ra->elsize, + (unsigned char *)(ra->storage) + idx * ra->elsize, + new_ra->elsize); + } + (new_ra->len)++; + } + + + *copy_ra = new_ra; + + TRACE_FLOW_EXIT(); return error; } + + /* Debug function */ void ref_array_debug(struct ref_array *ra) { diff --git a/common/refarray/ref_array.h b/common/refarray/ref_array.h index 4b4b2de..4012116 100644 --- a/common/refarray/ref_array.h +++ b/common/refarray/ref_array.h @@ -83,11 +83,34 @@ typedef enum * * Callback that can be provided by a caller * to free data when the storage is actually destroyed. + * + * @param[in] elem Pointer to the array element. + * @param[in] type Type of the operation performed. + * @param[in] data Application data that can be used + * inside the callback. + * No return value. */ typedef void (*ref_array_fn)(void *elem, ref_array_del_enum type, void *data); +/** + * @brief Copy callback + * + * Callback that can be provided by a caller + * to copy elements of the array. + * + * @param[in] elem Pointer to the array element. + * @param[out] new_elem Pointer to pointer to the new element. + * + * @return 0 - Success. + * @return ENOMEM - No memory. + * @return EINVAL - Invalid argument. + * + * Callback can return other errors and the implementor's discretion. + */ +typedef int (*ref_array_copy_cb)(void *elem, + void *new_elem); /** * @brief Create referenced array @@ -313,6 +336,27 @@ int ref_array_swap(struct ref_array *ra, */ void ref_array_reset(struct ref_array *ra); + +/** + * @brief Copy array + * + * Function copies all contents calling a provided + * callback for every entry of the array. + * + * + * @param[in] ra Existing array object to copy. + * @param[in] copy_cb Copy callback. + * @param[out] copy_ra Newly allocated copy. + * + * @return 0 - Success. + * @return ENOMEM - No memory. + * @return EINVAL - Invalid argument. + */ +int ref_array_copy(struct ref_array *ra, + ref_array_copy_cb copy_cb, + struct ref_array **copy_ra); + + /** * @} */ diff --git a/common/refarray/ref_array_ut.c b/common/refarray/ref_array_ut.c index 6e6009a..2b6f27c 100644 --- a/common/refarray/ref_array_ut.c +++ b/common/refarray/ref_array_ut.c @@ -560,7 +560,123 @@ int ref_array_adv_test(void) return EOK; } +int copy_cb(void *elem, + void *new_elem) +{ + char *ne = NULL; + + ne = strdup(*((char **)elem)); + *(char ***)new_elem = ≠ + + return EOK; +} + +int ref_array_copy_test(void) +{ + const char *line1 = "line1"; + const char *line2 = "line2"; + const char *line3 = "line3"; + const char *line4 = "line4"; + const char *line5 = "line5"; + const char *line6 = "line6"; + uint32_t i; + struct ref_array *ra; + struct ref_array *ra2; + int error = EOK; + uint32_t len = 0; + + error = ref_array_create(&ra, sizeof(char *), 1, NULL, NULL); + if (error) { + printf("Failed to create array %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line1); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 1 %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line2); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 2 %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line3); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 3 %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line4); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 4 %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line5); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 5 %d\n", error); + return error; + } + + RAOUT(ref_array_debug(ra)); + + error = ref_array_append(ra, &line6); + if (error) { + ref_array_destroy(ra); + printf("Failed to append to array line 6 %d\n", error); + return error; + } + RAOUT(ref_array_debug(ra)); + + RAOUT(printf("\n\nTest 1 - Printing lines.\n\n")); + + error = ref_array_copy(ra, copy_cb, &ra2); + if (error) { + ref_array_destroy(ra); + printf("Failed to get length %d\n", error); + return error; + } + + for (i = 0; i < len; i++) { + if (strcmp(ref_array_get(ra, i, NULL), + ref_array_get(ra2, i, NULL)) != 0) { + printf("\nRetrieved strings were expected to be same,\n"); + printf("but they are not:\n"); + printf("First:[%s]\nSecond:[%s]\n", + (char *)ref_array_get(ra, i, NULL), + (char *)ref_array_get(ra2, i, NULL)); + ref_array_destroy(ra); + ref_array_destroy(ra2); + return EFAULT; + } + } + + ref_array_destroy(ra); + ref_array_destroy(ra2); + + RAOUT(printf("\n\nDone!!!\n\n")); + return EOK; + +} /* Main function of the unit test */ int main(int argc, char *argv[]) @@ -569,6 +685,7 @@ int main(int argc, char *argv[]) test_fn tests[] = { ref_array_basic_test, ref_array_free_test, ref_array_adv_test, + ref_array_copy_test, NULL }; test_fn t; int i = 0; -- cgit