summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2010-11-26 23:11:07 -0500
committerStephen Gallagher <sgallagh@redhat.com>2010-12-21 11:16:09 -0500
commit5dadfb4371b8ba694b8d9431cb6789bf6de485c4 (patch)
tree2b6843eb1b30a5aa4b23a77a74c7d0a797f9d464
parent500eaf3ef5d53a9961443d2f3ea0d7e8b01d4c1f (diff)
downloadding-libs-5dadfb4371b8ba694b8d9431cb6789bf6de485c4.tar.gz
ding-libs-5dadfb4371b8ba694b8d9431cb6789bf6de485c4.tar.xz
ding-libs-5dadfb4371b8ba694b8d9431cb6789bf6de485c4.zip
New copy and folding functionality
* Added method to copy configuration. * Added unit test for it. * Added method to reset boandary for the whole configuration. * Added unit test for it. * Unit test now can read a file save it read again and save. Both saves produce same files! * Reworked the way the parser was dealing with empty lines. It was sutting off the value in the middle if the folded line consisted of just spaces.
-rw-r--r--ini/ini_configobj.c141
-rw-r--r--ini/ini_configobj.h4
-rw-r--r--ini/ini_parse.c74
-rw-r--r--ini/ini_parse_ut.c129
4 files changed, 274 insertions, 74 deletions
diff --git a/ini/ini_configobj.c b/ini/ini_configobj.c
index 4da9a7c..3e5dec4 100644
--- a/ini/ini_configobj.c
+++ b/ini/ini_configobj.c
@@ -113,3 +113,144 @@ 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(col_get_item_type(item) == 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;
+ }
+
+ error = col_modify_binary_item(item,
+ NULL,
+ &new_vo,
+ sizeof(struct value_obj *));
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to copy value", error);
+ value_destroy(new_vo);
+ 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_co->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/ini/ini_configobj.h b/ini/ini_configobj.h
index 81578c0..21198db 100644
--- a/ini/ini_configobj.h
+++ b/ini/ini_configobj.h
@@ -138,6 +138,10 @@ void ini_config_free_errors(char **errors);
int ini_config_parse(struct ini_cfgfile *file_ctx,
struct ini_cfgobj *ini_config);
+/* Copy configuration */
+int ini_config_copy(struct ini_cfgobj *ini_config,
+ struct ini_cfgobj **ini_new);
+
/* Function to print errors from the list */
void ini_print_errors(FILE *file, char **error_list);
diff --git a/ini/ini_parse.c b/ini/ini_parse.c
index 253b78b..c92a163 100644
--- a/ini/ini_parse.c
+++ b/ini/ini_parse.c
@@ -79,6 +79,20 @@ typedef int (*action_fn)(struct parser_obj *);
#define PARSE_DONE 4 /* We are done */
+int is_just_spaces(const char *str, uint32_t len)
+{
+ uint32_t i;
+
+ TRACE_FLOW_ENTRY();
+
+ for (i = 0; i < len; i++) {
+ if (!isspace(str[i])) return 0;
+ }
+
+ TRACE_FLOW_EXIT();
+ return 1;
+}
+
/* Destroy parser object */
void parser_destroy(struct parser_obj *po)
@@ -401,14 +415,24 @@ static int handle_space(struct parser_obj *po, uint32_t *action)
*action = PARSE_READ;
}
else {
- /* We do not have an active value
- * but have a line is starting with a space.
- * For now it is error.
- * We can change it in future if
- * people find it being too restrictive
- */
- *action = PARSE_ERROR;
- po->last_error = ERR_SPACE;
+ /* Check if this is a completely empty line */
+ if (is_just_spaces(po->last_read, po->last_read_len)) {
+ error = handle_comment(po, action);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to process comment", error);
+ return error;
+ }
+ }
+ else {
+ /* We do not have an active value
+ * but have a line is starting with a space.
+ * For now it is error.
+ * We can change it in future if
+ * people find it being too restrictive
+ */
+ *action = PARSE_ERROR;
+ po->last_error = ERR_SPACE;
+ }
}
TRACE_FLOW_EXIT();
@@ -425,6 +449,8 @@ static int handle_kvp(struct parser_obj *po, uint32_t *action)
TRACE_FLOW_ENTRY();
+ TRACE_INFO_STRING("Last read:", po->last_read);
+
/* We got a line with KVP */
if (*(po->last_read) == '=') {
po->last_error = ERR_NOKEY;
@@ -681,20 +707,6 @@ static int handle_section(struct parser_obj *po, uint32_t *action)
}
-int is_just_spaces(const char *str, uint32_t len)
-{
- uint32_t i;
-
- TRACE_FLOW_ENTRY();
-
- for (i = 0; i < len; i++) {
- if (!isspace(str[i])) return 0;
- }
-
- TRACE_FLOW_EXIT();
- return 1;
-}
-
/* Inspect the line */
static int parser_inspect(struct parser_obj *po)
{
@@ -716,20 +728,10 @@ static int parser_inspect(struct parser_obj *po)
else if ((*(po->last_read) == ' ') ||
(*(po->last_read) == '\t')) {
- /* Check if this is a completely empty line */
- if (is_just_spaces(po->last_read, po->last_read_len)) {
- error = handle_comment(po, &action);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to process comment", error);
- return error;
- }
- }
- else {
- error = handle_space(po, &action);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to process line wrapping", error);
- return error;
- }
+ error = handle_space(po, &action);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to process line wrapping", error);
+ return error;
}
}
else if (*(po->last_read) == '[') {
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c
index 01b7077..cc37c21 100644
--- a/ini/ini_parse_ut.c
+++ b/ini/ini_parse_ut.c
@@ -23,13 +23,16 @@
#include <string.h>
#include <errno.h>
#include <stdlib.h>
+#include <limits.h>
#include "ini_defines.h"
#include "ini_configobj.h"
+#include "ini_config_priv.h"
#include "simplebuffer.h"
#include "path_utils.h"
#include "config.h"
#define TRACE_HOME
#include "trace.h"
+#include "collection_tools.h"
int verbose = 0;
char *confdir = NULL;
@@ -41,19 +44,19 @@ char *confdir = NULL;
typedef int (*test_fn)(void);
-int test_one_file(const char *filename)
+int test_one_file(const char *in_filename,
+ const char *out_filename)
{
int error = EOK;
struct ini_cfgfile *file_ctx = NULL;
FILE *ff = NULL;
- char new_file[100];
struct ini_cfgobj *ini_config = NULL;
+ struct ini_cfgobj *ini_copy = NULL;
char **error_list = NULL;
struct simplebuffer *sbobj = NULL;
uint32_t left = 0;
- char filename_base[96];
- INIOUT(printf("<==== Testing file %s ====>\n", filename));
+ INIOUT(printf("<==== Testing file %s ====>\n", in_filename));
/* Create config collection */
error = ini_config_create(&ini_config);
@@ -62,7 +65,7 @@ int test_one_file(const char *filename)
return error;
}
- error = ini_config_file_open(filename,
+ error = ini_config_file_open(in_filename,
INI_STOP_ON_NONE,
0, /* TBD */
0, /* TBD */
@@ -83,12 +86,35 @@ 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);
+ INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
+
+ /* Copy configuration */
+ error = ini_config_copy(ini_config, &ini_copy);
+ if (error) {
+ printf("Failed to copy configuration. Error %d.\n", error);
+ ini_config_destroy(ini_config);
+ return error;
+ }
+
+ ini_config_destroy(ini_config);
+ ini_config = ini_copy;
+
+ INIOUT(col_debug_collection(ini_config->cfg, COL_TRAVERSE_DEFAULT));
+
+ 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);
@@ -104,11 +130,8 @@ int test_one_file(const char *filename)
return error;
}
- error = get_basename(filename_base, 96, filename);
- sprintf(new_file, "%s.out", filename_base);
-
errno = 0;
- ff = fopen(new_file, "w");
+ ff = fopen(out_filename, "w");
if(!ff) {
error = errno;
printf("Failed to open file for writing. Error %d.\n", error);
@@ -143,41 +166,79 @@ int read_save_test(void)
{
int error = EOK;
int i = 0;
- int lasterr = EOK;
- char *files[5];
-
- files[0] = malloc(sizeof(char)*512);
- sprintf(files[0], "%s/ini.d/real.conf", confdir);
- files[1] = malloc(sizeof(char)*512);
- sprintf(files[1], "%s/ini.d/mysssd.conf", confdir);
- files[2] = malloc(sizeof(char)*512);
- sprintf(files[2], "%s/ini.d/ipa.conf", confdir);
- files[3] = malloc(sizeof(char)*512);
- sprintf(files[3], "%s/ini.d/test.conf", confdir);
- files[4] = NULL;
+ char infile[PATH_MAX];
+ char outfile[PATH_MAX];
+ char *srcdir;
+ const char *files[] = { "real",
+ "mysssd",
+ "ipa",
+ "test",
+ NULL };
+
+
+ srcdir = getenv("srcdir");
while(files[i]) {
- error = test_one_file(files[i]);
- INIOUT(printf("Test fo file: %s returned %d\n", files[i], error));
- if (error) lasterr = error;
+
+ sprintf(infile, "%s/ini/ini.d/%s.conf", (srcdir == NULL) ? "." : srcdir,
+ files[i]);
+ sprintf(outfile, "%s/%s.conf.out", (srcdir == NULL) ? "." : srcdir,
+ files[i]);
+ error = test_one_file(infile, outfile);
+ INIOUT(printf("Test for file: %s returned %d\n", files[i], error));
i++;
}
- free(files[3]);
- free(files[2]);
- free(files[1]);
- free(files[0]);
+ return EOK;
+}
+
+/* Run tests for multiple files */
+int read_again_test(void)
+{
+ int error = EOK;
+ int i = 0;
+ char infile[PATH_MAX];
+ char outfile[PATH_MAX];
+ char *srcdir;
+ char command[PATH_MAX * 3];
+ const char *files[] = { "real",
+ "mysssd",
+ "ipa",
+ "test",
+ NULL };
+
- return lasterr;
+ srcdir = getenv("srcdir");
+
+ while(files[i]) {
+
+ sprintf(infile, "%s/%s.conf.out", (srcdir == NULL) ? "." : srcdir,
+ files[i]);
+ sprintf(outfile, "%s/%s.conf.2.out", (srcdir == NULL) ? "." : srcdir,
+ files[i]);
+ error = test_one_file(infile, outfile);
+ INIOUT(printf("Test for file: %s returned %d\n", files[i], error));
+ if (error) break;
+ sprintf(command,"diff -q %s %s", infile, outfile);
+ error = system(command);
+ INIOUT(printf("Comparison of %s %s returned: %d\n",
+ infile, outfile, error));
+ if (error) break;
+
+ i++;
+ }
+
+ return error;
}
+
/* Main function of the unit test */
int main(int argc, char *argv[])
{
int error = 0;
test_fn tests[] = { read_save_test,
+ read_again_test,
NULL };
- char *srcdir;
test_fn t;
int i = 0;
char *var;
@@ -190,14 +251,6 @@ int main(int argc, char *argv[])
INIOUT(printf("Start\n"));
- srcdir = getenv("srcdir");
- if(!srcdir) {
- confdir = strdup("./ini");
- } else {
- confdir = malloc(strlen(srcdir)+5*sizeof(char));
- sprintf(confdir, "%s/ini", srcdir);
- }
-
while ((t = tests[i++])) {
error = t();
if (error) {