From 604eed33089fdef36bd2f63a73ed638d642b6856 Mon Sep 17 00:00:00 2001 From: Dmitri Pal Date: Thu, 25 Nov 2010 23:38:47 -0500 Subject: Enhancements to value object * Added capability to copy value. * Added function to set alternative wrapping boundary of the value. * Created a unit test for both new functions. --- ini/ini_valueobj.c | 122 ++++++++++++++++++++++++++++++++++++++++++ ini/ini_valueobj.h | 7 +++ ini/ini_valueobj_ut.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 272 insertions(+), 1 deletion(-) (limited to 'ini') diff --git a/ini/ini_valueobj.c b/ini/ini_valueobj.c index 02b9732..5ad8e97 100644 --- a/ini/ini_valueobj.c +++ b/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,92 @@ 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, + (const char *)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->keylen; + 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; + } + + /* Copy commetn */ + error = ini_comment_copy(vo->ic, &new_vo->ic); + if (error) { + TRACE_ERROR_NUMBER("Failed to copy comment", error); + value_destroy(new_vo); + return error; + } + + *copy_vo = new_vo; + + TRACE_FLOW_EXIT(); + + return error; +} + /* Get concatenated value */ int value_get_concatenated(struct value_obj *vo, const char **fullstr) @@ -643,6 +736,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/ini/ini_valueobj.h b/ini/ini_valueobj.h index 2e13c0d..3267bcc 100644 --- a/ini/ini_valueobj.h +++ b/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/ini/ini_valueobj_ut.c b/ini/ini_valueobj_ut.c index 3def3f7..e307ba2 100644 --- a/ini/ini_valueobj_ut.c +++ b/ini/ini_valueobj_ut.c @@ -214,7 +214,7 @@ int other_create_test(FILE *ff, struct value_obj **vo) /* Now do assertions and modifications to the object */ - /* NOTE: Below this line do need to free arrays or comment + /* NOTE: Below this line do not need to free arrays or comment * they became internal parts of the value object * and will be freed as a part of it. */ @@ -420,6 +420,7 @@ int vo_basic_test(void) if (error) { printf("Failed to save value to file %d.\n", error); value_destroy(vo); + fclose(ff); return error; } @@ -464,12 +465,153 @@ int vo_basic_test(void) return EOK; } +int vo_copy_test(void) +{ + int error = EOK; + const char *strvalue = "Test multi word value that " + "will be split between several lines"; + + struct value_obj *vo = NULL; + struct value_obj *vo_copy = NULL; + uint32_t wrap = 0; + struct ini_comment *ic = NULL; + FILE *ff = NULL; + char comment[100]; + + TRACE_FLOW_ENTRY(); + + VOOUT(printf("Copy test\n")); + + errno = 0; + ff = fopen("test.ini","a"); + if (ff == NULL) { + error = errno; + printf("Failed to open file. Error %d.\n", error); + return error; + } + + error = ini_comment_create(&ic); + if (error) { + printf("Failed to create comment object\n"); + fclose(ff); + return -1; + } + + error = ini_comment_append(ic, "#This is a copy test!"); + if (error) { + printf("Failed to add a line to the comment %d.\n", error); + ini_comment_destroy(ic); + fclose(ff); + return error; + } + + error = ini_comment_append(ic, "#Replacable comment line"); + if (error) { + printf("Failed to add a line to the comment %d.\n", error); + ini_comment_destroy(ic); + fclose(ff); + return error; + } + + error = value_create_new(strvalue, + strlen(strvalue), + INI_VALUE_CREATED, + 3, + 20, + ic, + &vo); + if (error) { + printf("Failed to create a new value object %d.\n", error); + ini_comment_destroy(ic); + fclose(ff); + return error; + } + + error = save_value(ff, "key", vo); + if (error) { + printf("Failed to save value to file %d.\n", error); + value_destroy(vo); + return error; + } + + for (wrap = 0; wrap < 80; wrap++) { + + TRACE_INFO_NUMBER("Iteration:", wrap); + + error = value_copy(vo, &vo_copy); + if (error) { + printf("Failed to create a new value object %d.\n", error); + value_destroy(vo); + fclose(ff); + return error; + } + + error = value_set_boundary(vo_copy, wrap); + if (error) { + printf("Failed to set boundary %d.\n", error); + value_destroy(vo); + value_destroy(vo_copy); + fclose(ff); + return error; + } + + /* Get comment from the value */ + error = value_extract_comment(vo_copy, &ic); + if (error) { + printf("Failed to extract comment %d.\n", error); + value_destroy(vo); + value_destroy(vo_copy); + fclose(ff); + return error; + } + + /* Replace comment in the value */ + sprintf(comment, ";This is value with boundary %d", wrap); + VOOUT(printf("Comment: %s\n", comment)); + error = ini_comment_replace(ic, 1, comment); + if (error) { + printf("Failed to replace comment %d.\n", error); + value_destroy(vo); + value_destroy(vo_copy); + fclose(ff); + return error; + } + + /* Set comment into the value */ + error = value_put_comment(vo_copy, ic); + if (error) { + printf("Failed to set comment %d.\n", error); + value_destroy(vo); + value_destroy(vo_copy); + fclose(ff); + return error; + } + + error = save_value(ff, "key", vo_copy); + if (error) { + printf("Failed to save value to file %d.\n", error); + value_destroy(vo); + value_destroy(vo_copy); + fclose(ff); + return error; + } + + value_destroy(vo_copy); + } + + value_destroy(vo); + TRACE_FLOW_EXIT(); + return EOK; +} + + /* Main function of the unit test */ int main(int argc, char *argv[]) { int error = 0; test_fn tests[] = { vo_basic_test, + vo_copy_test, NULL }; test_fn t; int i = 0; -- cgit