summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2012-12-04 19:38:58 -0500
committerOndrej Kos <okos@redhat.com>2012-12-06 14:23:26 +0100
commit854d077f8a7ded3f5c25f58fa4bfc46aa55095db (patch)
treef6946568ffca0856343cf17bdbf603cff7738cb6
parent85831de020e701104d0bcfbb274e5978faf31723 (diff)
downloadding-libs-854d077f8a7ded3f5c25f58fa4bfc46aa55095db.tar.gz
ding-libs-854d077f8a7ded3f5c25f58fa4bfc46aa55095db.tar.xz
ding-libs-854d077f8a7ded3f5c25f58fa4bfc46aa55095db.zip
Improve parser
1. Move the last comment into the config object Last comment in the file was previously treated as a special value in the last section in the configuration object. That created difficulties while merging. Storing an orphan comment as part of the config object is a better approach 2. Since the structure of the config object changed the internal header and serialization required update. 3. Parser code was updated to: - deal with the last comment on the top level - make sure the right error codes are returned in different modes - pass right information through the layers which caused some refactoring of the internal calls - prevent using an already used configuration object as an input to parser.
-rw-r--r--ini/ini_config_priv.h3
-rw-r--r--ini/ini_defines.h3
-rw-r--r--ini/ini_parse.c108
-rw-r--r--ini/ini_serialize.c12
-rw-r--r--ini/ini_valueobj.c6
5 files changed, 98 insertions, 34 deletions
diff --git a/ini/ini_config_priv.h b/ini/ini_config_priv.h
index 5d994f9..8b19d73 100644
--- a/ini/ini_config_priv.h
+++ b/ini/ini_config_priv.h
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include "collection.h"
+#include "ini_comment.h"
/* Configuration object */
struct ini_cfgobj {
@@ -33,6 +34,8 @@ struct ini_cfgobj {
struct collection_item *cfg;
/* Boundary */
uint32_t boundary;
+ /* Last comment */
+ struct ini_comment *last_comment;
/* Last search state */
char *section;
char *name;
diff --git a/ini/ini_defines.h b/ini/ini_defines.h
index b861f0e..db898c3 100644
--- a/ini/ini_defines.h
+++ b/ini/ini_defines.h
@@ -63,7 +63,6 @@
#define INI_ERROR_NAME "errname"
#define INI_CONFIG_NAME "INI"
-#define INI_SPECIAL_KEY "="
#define INI_SECTION_KEY "["
/* Internal sizes. MAX_KEY is defined in config.h */
@@ -81,6 +80,8 @@
/* This constant belongs here. */
#define COL_CLASS_INI_BASE 20000
+#define COL_CLASS_INI_CONFIG COL_CLASS_INI_BASE + 0
+
/**
* @brief A one level collection of parse errors.
*
diff --git a/ini/ini_parse.c b/ini/ini_parse.c
index c61536d..5d39375 100644
--- a/ini/ini_parse.c
+++ b/ini/ini_parse.c
@@ -55,6 +55,7 @@ struct parser_obj {
struct collection_item *top;
struct collection_item *el;
const char *filename;
+ struct ini_cfgobj *co;
/* Level of error reporting */
int error_level;
/* Collistion flags */
@@ -135,6 +136,7 @@ static void parser_destroy(struct parser_obj *po)
po->raw_lengths);
if (po->last_read) free(po->last_read);
if (po->key) free(po->key);
+ col_destroy_collection_with_cb(po->top, ini_cleanup_cb, NULL);
free(po);
}
@@ -146,25 +148,26 @@ static void parser_destroy(struct parser_obj *po)
* It assumes that the ini collection
* has been precreated.
*/
-static int parser_create(FILE *file,
+static int parser_create(struct ini_cfgobj *co,
+ FILE *file,
const char *config_filename,
- struct collection_item *ini_config,
int error_level,
uint32_t collision_flags,
struct collection_item *error_list,
- uint32_t boundary,
struct parser_obj **po)
{
int error = EOK;
struct parser_obj *new_po = NULL;
+ unsigned count = 0;
TRACE_FLOW_ENTRY();
/* Make sure that all the parts are initialized */
if ((!po) ||
+ (!co) ||
+ (!(co->cfg)) ||
(!file) ||
(!config_filename) ||
- (!ini_config) ||
(!error_list)) {
TRACE_ERROR_NUMBER("Invalid argument", EINVAL);
return EINVAL;
@@ -177,6 +180,17 @@ static int parser_create(FILE *file,
return EINVAL;
}
+ error = col_get_collection_count(co->cfg, &count);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to check object size", error);
+ return error;
+ }
+
+ if (count != 1) {
+ TRACE_ERROR_NUMBER("Configuration is not empty", EINVAL);
+ return EINVAL;
+ }
+
new_po = malloc(sizeof(struct parser_obj));
if (!new_po) {
TRACE_ERROR_NUMBER("No memory", ENOMEM);
@@ -185,12 +199,12 @@ static int parser_create(FILE *file,
/* Save external data */
new_po->file = file;
- new_po->top = ini_config;
new_po->el = error_list;
new_po->filename = config_filename;
new_po->error_level = error_level;
new_po->collision_flags = collision_flags;
- new_po->boundary = boundary;
+ new_po->boundary = co->boundary;
+ new_po->co = co;
/* Initialize internal varibles */
new_po->sec = NULL;
@@ -210,9 +224,20 @@ static int parser_create(FILE *file,
new_po->merge_key = NULL;
new_po->merge_vo = NULL;
new_po->merge_error = 0;
+ new_po->top = NULL;
+ new_po->queue = NULL;
+
+ /* Create top collection */
+ error = col_create_collection(&(new_po->top),
+ INI_CONFIG_NAME,
+ COL_CLASS_INI_CONFIG);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to create top collection", error);
+ parser_destroy(new_po);
+ return error;
+ }
/* Create a queue */
- new_po->queue = NULL;
error = col_create_queue(&(new_po->queue));
if (error) {
TRACE_ERROR_NUMBER("Failed to create queue", error);
@@ -1260,18 +1285,27 @@ static int parser_post(struct parser_obj *po)
TRACE_FLOW_ENTRY();
- /* If there was just a comment at the bottom add special key */
+ /* If there was just a comment at the bottom
+ * put it directly into the config object
+ */
if((po->ic) && (!(po->key))) {
- po->key_len = sizeof(INI_SPECIAL_KEY) - 1;
- po->key = strndup(INI_SPECIAL_KEY, sizeof(INI_SPECIAL_KEY));
- /* Create new arrays */
- error = value_create_arrays(&(po->raw_lines),
- &(po->raw_lengths));
- if (error) {
- TRACE_ERROR_NUMBER("Failed to create arrays", error);
- return error;
+ if (po->co->last_comment) {
+ error = ini_comment_add(po->ic, po->co->last_comment);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to merge comment", error);
+ return error;
+ }
+ }
+ else {
+ error = ini_comment_copy(po->ic, &(po->co->last_comment));
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to copy comment", error);
+ return error;
+ }
}
+ ini_comment_destroy(po->ic);
+ po->ic = NULL;
}
/* If there is a key being processed add it */
@@ -1482,6 +1516,7 @@ int ini_config_parse(struct ini_cfgfile *file_ctx,
{
int error = EOK;
struct parser_obj *po;
+ uint32_t fl1, fl2, fl3;
TRACE_FLOW_ENTRY();
@@ -1490,13 +1525,12 @@ int ini_config_parse(struct ini_cfgfile *file_ctx,
return EINVAL;
}
- error = parser_create(file_ctx->file,
+ error = parser_create(ini_config,
+ file_ctx->file,
file_ctx->filename,
- ini_config->cfg,
file_ctx->error_level,
file_ctx->collision_flags,
file_ctx->error_list,
- ini_config->boundary,
&po);
if (error) {
TRACE_ERROR_NUMBER("Failed to perform an action", error);
@@ -1505,17 +1539,39 @@ int ini_config_parse(struct ini_cfgfile *file_ctx,
error = parser_run(po);
if (error) {
- TRACE_ERROR_NUMBER("Failed to parse file", error);
- col_get_collection_count(file_ctx->error_list, &(file_ctx->count));
- if(file_ctx->count) (file_ctx->count)--;
- parser_destroy(po);
- return error;
+ fl1 = file_ctx->collision_flags & INI_MS_MASK;
+ fl2 = file_ctx->collision_flags & INI_MV1S_MASK;
+ fl3 = file_ctx->collision_flags & INI_MV2S_MASK;
+ if ((error == EEXIST) &&
+ (((fl1 == INI_MS_DETECT) &&
+ (fl2 != INI_MV1S_ERROR) &&
+ (fl3 != INI_MV2S_ERROR)) ||
+ ((fl2 == INI_MV1S_DETECT) &&
+ (fl1 != INI_MS_ERROR) &&
+ (fl3 != INI_MV2S_ERROR)) ||
+ ((fl3 == INI_MV2S_DETECT) &&
+ (fl1 != INI_MS_ERROR) &&
+ (fl2 != INI_MV1S_ERROR)))) {
+ TRACE_ERROR_NUMBER("No error in detect mode", error);
+ /* Fall through */
+ }
+ else {
+ TRACE_ERROR_NUMBER("Failed to parse file", error);
+ TRACE_ERROR_NUMBER("Mode", file_ctx->collision_flags);
+ col_get_collection_count(file_ctx->error_list, &(file_ctx->count));
+ if(file_ctx->count) (file_ctx->count)--;
+ parser_destroy(po);
+ return error;
+ }
}
- parser_destroy(po);
+ /* If should be empty anyways */
+ col_destroy_collection_with_cb(ini_config->cfg, ini_cleanup_cb, NULL);
+ ini_config->cfg = po->top;
+ po->top = NULL;
+ parser_destroy(po);
- TRACE_INFO_NUMBER("Count returned:", error);
TRACE_FLOW_EXIT();
return error;
}
diff --git a/ini/ini_serialize.c b/ini/ini_serialize.c
index 177979a..7a53f29 100644
--- a/ini/ini_serialize.c
+++ b/ini/ini_serialize.c
@@ -79,9 +79,19 @@ int ini_config_serialize(struct ini_cfgobj *ini_config,
COL_TRAVERSE_DEFAULT,
ini_serialize_cb,
(void *)sbobj);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to serialize collection", error);
+ return error;
+ }
}
- TRACE_INFO_NUMBER("Serialization returned:", error);
+ if (ini_config->last_comment) {
+ error = ini_comment_serialize(ini_config->last_comment, sbobj);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed serialize comment", error);
+ return error;
+ }
+ }
TRACE_FLOW_EXIT();
return error;
diff --git a/ini/ini_valueobj.c b/ini/ini_valueobj.c
index e0c8d98..6d4dc1f 100644
--- a/ini/ini_valueobj.c
+++ b/ini/ini_valueobj.c
@@ -967,12 +967,6 @@ int value_serialize(struct value_obj *vo,
}
}
- if (strncmp(key, INI_SPECIAL_KEY, sizeof(INI_SPECIAL_KEY)) == 0) {
- /* Special key carries only a comment */
- TRACE_FLOW_EXIT();
- return EOK;
- }
-
/* Handle the case it is a section key */
if (strncmp(key,
INI_SECTION_KEY,