summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2012-12-24 13:33:44 -0500
committerOndrej Kos <okos@redhat.com>2013-01-24 08:34:48 +0100
commitfa00e2e16e5c1d3ac56f1bbd3a84875642d0bb39 (patch)
treef97d1297511421e2b2b30c5a53f1f62a1e0f1311
parent3b9baa61367f2b651c8068efc99ce017331622e0 (diff)
downloadding-libs-fa00e2e16e5c1d3ac56f1bbd3a84875642d0bb39.tar.gz
ding-libs-fa00e2e16e5c1d3ac56f1bbd3a84875642d0bb39.tar.xz
ding-libs-fa00e2e16e5c1d3ac56f1bbd3a84875642d0bb39.zip
Introducing parsing flags
1. Added definition of the parsing flags to the header. 2. Added new argument to the parser. 3. Added function to check the correctness of the line. 4. Added new constants and strings for errors. 5. Refactored function that handles spaces. 6. Moved handle_space since it now calls handle_kvp. 7. Updated handle_kvp to trim spaces at the beginning. 8. Adjusted line inspection to handle any space character. 9. Adjusted exising unit tests. Added parameter to the call. 10. Found couple places where there was a space at the end of the line and cleaned them. The additional unit tests will be added in the follow up patch.
-rw-r--r--ini/ini_configobj.h25
-rw-r--r--ini/ini_parse.c215
-rw-r--r--ini/ini_parse_ut.c6
-rw-r--r--ini/ini_print.c6
4 files changed, 187 insertions, 65 deletions
diff --git a/ini/ini_configobj.h b/ini/ini_configobj.h
index 824df17..5e8d95b 100644
--- a/ini/ini_configobj.h
+++ b/ini/ini_configobj.h
@@ -172,7 +172,10 @@ enum ERR_PARSE {
ERR_DUPKEYSEC, /**< Duplicate key is detected while merging
sections (Error). */
ERR_DUPSECTION, /**< Duplicate section is not allowed (Error). */
- ERR_MAXPARSE = ERR_DUPSECTION /**< Special value. Size of the error array. */
+ ERR_SPECIAL, /**< Line contains invalid characters (Error). */
+ ERR_TAB, /**< Line starts with tab when it
+ should not (Error). */
+ ERR_MAXPARSE = ERR_TAB /**< Special value. Size of the error array. */
};
/**
@@ -321,6 +324,25 @@ enum ERR_PARSE {
*/
/**
+ * @defgroup parseflags Flags that define parsing rules
+ *
+ * Flags that define how the file should be parsed.
+ *
+ * @{
+ */
+
+/** @brief Do not wrap */
+#define INI_PARSE_NOWRAP 0x0001
+/** @brief No spaces are allowed to the left of the key */
+#define INI_PARSE_NOSPACE 0x0002
+/** @brief No tabs are allowed to the left of the key */
+#define INI_PARSE_NOTAB 0x0004
+
+/**
+ * @}
+ */
+
+/**
* @defgroup searchmode Constants that define how to look for a value
*
* Configuration file can allow several keys with the same name
@@ -664,6 +686,7 @@ int ini_config_changed(struct ini_cfgfile *file_ctx1,
int ini_config_parse(struct ini_cfgfile *file_ctx,
int error_level,
uint32_t collision_flags,
+ uint32_t parse_flags,
struct ini_cfgobj *ini_config);
/**
diff --git a/ini/ini_parse.c b/ini/ini_parse.c
index 2f65dfa..d009914 100644
--- a/ini/ini_parse.c
+++ b/ini/ini_parse.c
@@ -59,6 +59,8 @@ struct parser_obj {
int error_level;
/* Collistion flags */
uint32_t collision_flags;
+ /* Parseing flags */
+ uint32_t parse_flags;
/* Wrapping boundary */
uint32_t boundary;
/* Action queue */
@@ -121,6 +123,53 @@ int is_just_spaces(const char *str, uint32_t len)
return 1;
}
+/* Functions checks whether the line
+ * starts with the sequence of allowed blank characters.
+ * If spaces are allowed - function will say that line
+ * is OK. If tabls are allowed the function also would
+ * say that line is OK. If the mixture of both is allowed
+ * the line is OK too.
+ * Any other character will cause an error.
+ */
+int is_allowed_spaces(const char *str,
+ uint32_t len,
+ uint32_t parse_flags,
+ int *error)
+{
+ uint32_t i;
+ int line_ok = 1;
+
+ TRACE_FLOW_ENTRY();
+
+ for (i = 0; i < len; i++) {
+ if ((str[i] == ' ') &&
+ (parse_flags & INI_PARSE_NOSPACE)) {
+ /* Leading spaces are not allowed */
+ *error = ERR_SPACE;
+ line_ok = 0;
+ break;
+ }
+ else if ((str[i] == '\t') &&
+ (parse_flags & INI_PARSE_NOTAB)) {
+ /* Leading tabs are not allowed */
+ *error = ERR_TAB;
+ line_ok = 0;
+ break;
+ }
+ else if ((str[i] == '\f') ||
+ (str[i] == '\n') ||
+ (str[i] == '\r') ||
+ (str[i] == '\v')) {
+ *error = ERR_SPECIAL;
+ line_ok = 0;
+ break;
+ }
+ if (!isblank(str[i])) break;
+ }
+
+ TRACE_FLOW_EXIT();
+ return line_ok;
+}
/* Destroy parser object */
static void parser_destroy(struct parser_obj *po)
@@ -152,6 +201,7 @@ static int parser_create(struct ini_cfgobj *co,
const char *config_filename,
int error_level,
uint32_t collision_flags,
+ uint32_t parse_flags,
struct collection_item *error_list,
struct parser_obj **po)
{
@@ -202,6 +252,7 @@ static int parser_create(struct ini_cfgobj *co,
new_po->filename = config_filename;
new_po->error_level = error_level;
new_po->collision_flags = collision_flags;
+ new_po->parse_flags = parse_flags;
new_po->boundary = co->boundary;
new_po->co = co;
@@ -903,55 +954,6 @@ static int handle_comment(struct parser_obj *po, uint32_t *action)
return EOK;
}
-
-/* Process line starts with space */
-static int handle_space(struct parser_obj *po, uint32_t *action)
-{
- int error = EOK;
-
- TRACE_FLOW_ENTRY();
-
- /* Do we have current value object? */
- if (po->key) {
- /* This is a new line in a folded value */
- error = value_add_to_arrays(po->last_read,
- po->last_read_len,
- po->raw_lines,
- po->raw_lengths);
- if (error) {
- TRACE_ERROR_NUMBER("Failed to add line to value", error);
- return error;
- }
- /* Do not free the line, it is now an element of the array */
- po->last_read = NULL;
- po->last_read_len = 0;
- *action = PARSE_READ;
- }
- else {
- /* 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();
- return EOK;
-}
-
/* Handle key-value pair */
static int handle_kvp(struct parser_obj *po, uint32_t *action)
{
@@ -959,35 +961,46 @@ static int handle_kvp(struct parser_obj *po, uint32_t *action)
char *eq = NULL;
uint32_t len = 0;
char *dupval = NULL;
+ char *str;
+ uint32_t full_len;
TRACE_FLOW_ENTRY();
- TRACE_INFO_STRING("Last read:", po->last_read);
+ str = po->last_read;
+ full_len = po->last_read_len;
+
+ TRACE_INFO_STRING("Last read:", str);
+
+ /* Trim spaces at the beginning */
+ while ((full_len > 0) && (isspace(*(str)))) {
+ str++;
+ full_len--;
+ }
- /* We got a line with KVP */
- if (*(po->last_read) == '=') {
+ /* Check if we have the key */
+ if (*(str) == '=') {
po->last_error = ERR_NOKEY;
*action = PARSE_ERROR;
return EOK;
}
/* Find "=" */
- eq = strchr(po->last_read, '=');
+ eq = strchr(str, '=');
if (eq == NULL) {
- TRACE_ERROR_STRING("No equal sign", po->last_read);
+ TRACE_ERROR_STRING("No equal sign", str);
po->last_error = ERR_NOEQUAL;
*action = PARSE_ERROR;
return EOK;
}
/* Strip spaces around "=" */
- /* Since eq > po->last_read we can substract 1 */
- len = eq - po->last_read - 1;
- while ((len > 0) && (isspace(*(po->last_read + len)))) len--;
+ /* Since eq > str we can substract 1 */
+ len = eq - str - 1;
+ while ((len > 0) && (isspace(*(str + len)))) len--;
/* Adjust length properly */
len++;
if (!len) {
- TRACE_ERROR_STRING("No key", po->last_read);
+ TRACE_ERROR_STRING("No key", str);
po->last_error = ERR_NOKEY;
*action = PARSE_ERROR;
return EOK;
@@ -995,7 +1008,7 @@ static int handle_kvp(struct parser_obj *po, uint32_t *action)
/* Check the key length */
if(len >= MAX_KEY) {
- TRACE_ERROR_STRING("Key name is too long", po->last_read);
+ TRACE_ERROR_STRING("Key name is too long", str);
po->last_error = ERR_LONGKEY;
*action = PARSE_ERROR;
return EOK;
@@ -1017,14 +1030,14 @@ static int handle_kvp(struct parser_obj *po, uint32_t *action)
return ENOMEM;
}
- memcpy(po->key, po->last_read, len);
+ memcpy(po->key, str, len);
*(po->key + len) = '\0';
po->key_len = len;
TRACE_INFO_STRING("Key:", po->key);
TRACE_INFO_NUMBER("Keylen:", po->key_len);
- len = po->last_read_len - (eq - po->last_read) - 1;
+ len = full_len - (eq - str) - 1;
/* Trim spaces after equal sign */
eq++;
@@ -1081,6 +1094,81 @@ static int handle_kvp(struct parser_obj *po, uint32_t *action)
return EOK;
}
+/* Process line starts with space */
+static int handle_space(struct parser_obj *po, uint32_t *action)
+{
+ int error = EOK;
+ int space_err = 0;
+
+ TRACE_FLOW_ENTRY();
+
+ if (po->parse_flags & INI_PARSE_NOWRAP) {
+ /* In this case an empty line is a comment. */
+ if (is_just_spaces(po->last_read, po->last_read_len)) {
+ error = handle_comment(po, action);
+ TRACE_FLOW_EXIT();
+ return error;
+ }
+
+ /* Wrapping is not allowed */
+ if (!is_allowed_spaces(po->last_read,
+ po->last_read_len,
+ po->parse_flags,
+ &space_err)) {
+ *action = PARSE_ERROR;
+ po->last_error = space_err;
+ error = EOK;
+ }
+ else {
+ /* Allowed spaces will be trimmed
+ * inside KVP processing.
+ */
+ error = handle_kvp(po, action);
+ }
+ TRACE_FLOW_EXIT();
+ return error;
+ }
+
+ /* Do we have current value object? */
+ if (po->key) {
+ /* This is a new line in a folded value */
+ error = value_add_to_arrays(po->last_read,
+ po->last_read_len,
+ po->raw_lines,
+ po->raw_lengths);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to add line to value", error);
+ return error;
+ }
+ /* Do not free the line, it is now an element of the array */
+ po->last_read = NULL;
+ po->last_read_len = 0;
+ *action = PARSE_READ;
+ }
+ else {
+ /* 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();
+ return EOK;
+}
/* Parse and process section */
static int handle_section(struct parser_obj *po, uint32_t *action)
@@ -1231,8 +1319,7 @@ static int parser_inspect(struct parser_obj *po)
return error;
}
}
- else if ((*(po->last_read) == ' ') ||
- (*(po->last_read) == '\t')) {
+ else if (isspace(*(po->last_read))) {
error = handle_space(po, &action);
if (error) {
@@ -1507,6 +1594,7 @@ int parser_run(struct parser_obj *po)
int ini_config_parse(struct ini_cfgfile *file_ctx,
int error_level,
uint32_t collision_flags,
+ uint32_t parse_flags,
struct ini_cfgobj *ini_config)
{
int error = EOK;
@@ -1541,6 +1629,7 @@ int ini_config_parse(struct ini_cfgfile *file_ctx,
file_ctx->filename,
error_level,
collision_flags,
+ parse_flags,
file_ctx->error_list,
&po);
if (error) {
diff --git a/ini/ini_parse_ut.c b/ini/ini_parse_ut.c
index 2c77947..3526d48 100644
--- a/ini/ini_parse_ut.c
+++ b/ini/ini_parse_ut.c
@@ -81,6 +81,7 @@ int test_one_file(const char *in_filename,
error = ini_config_parse(file_ctx,
INI_STOP_ON_NONE,
0, /* TBD */
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
@@ -382,6 +383,7 @@ int merge_values_test(void)
error = ini_config_parse(file_ctx,
INI_STOP_ON_ANY,
mflags[i],
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n",
@@ -577,6 +579,7 @@ int merge_section_test(void)
error = ini_config_parse(file_ctx,
INI_STOP_ON_ANY,
msecflags[i] | mflags[j],
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. "
@@ -698,6 +701,7 @@ int read_one_file(char *name,
error = ini_config_parse(file_ctx,
INI_STOP_ON_ANY,
collision_flags,
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. "
@@ -1137,6 +1141,7 @@ int startup_test(void)
error = ini_config_parse(file_ctx,
INI_STOP_ON_NONE,
0,
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
@@ -1420,6 +1425,7 @@ int get_test(void)
INI_MS_MERGE |
INI_MV1S_ALLOW |
INI_MV2S_ALLOW,
+ 0,
ini_config);
if (error) {
INIOUT(printf("Failed to parse configuration. Error %d.\n", error));
diff --git a/ini/ini_print.c b/ini/ini_print.c
index d2d01c1..1812cd6 100644
--- a/ini/ini_print.c
+++ b/ini/ini_print.c
@@ -122,7 +122,11 @@ static const char *parsing_error_str(int parsing_error)
_("Duplicate key is not allowed."),
_("Duplicate key is detected while "
"merging sections."),
- _("Duplicate section is not allowed.")
+ _("Duplicate section is not allowed."),
+ _("Invalid character at the "
+ "beginning of the line."),
+ _("Invalid tab character at the "
+ "beginning of the line.")
};
/* Check the range */