From ef10b8b188fc04082f7e42579a3fd11790b067e5 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 7 Aug 2013 17:19:54 +0100 Subject: [PATCH] Improve keys parsing. --- src/rcl/rcl.h | 6 +++ src/rcl/rcl_internal.h | 6 +++ src/rcl/rcl_parser.c | 105 +++++-------------------------------- src/rcl/rcl_util.c | 115 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 91 deletions(-) diff --git a/src/rcl/rcl.h b/src/rcl/rcl.h index 54c3c81e5..545dd19f9 100644 --- a/src/rcl/rcl.h +++ b/src/rcl/rcl.h @@ -281,6 +281,12 @@ rspamd_cl_object_t* rspamd_cl_parser_get_object (struct rspamd_cl_parser *parser */ void rspamd_cl_parser_free (struct rspamd_cl_parser *parser); +/** + * Free cl object + * @param obj cl object to free + */ +void rspamd_cl_obj_free (rspamd_cl_object_t *obj); + /** * Emit object to a string * @param obj object diff --git a/src/rcl/rcl_internal.h b/src/rcl/rcl_internal.h index 33256119d..e76c09fd8 100644 --- a/src/rcl/rcl_internal.h +++ b/src/rcl/rcl_internal.h @@ -84,4 +84,10 @@ struct rspamd_cl_parser { struct rspamd_cl_chunk *chunks; }; +/** + * Unescape json string inplace + * @param str + */ +void rspamd_cl_unescape_json_string (gchar *str); + #endif /* RCL_INTERNAL_H_ */ diff --git a/src/rcl/rcl_parser.c b/src/rcl/rcl_parser.c index f727991de..1c32bde59 100644 --- a/src/rcl/rcl_parser.c +++ b/src/rcl/rcl_parser.c @@ -235,96 +235,6 @@ rspamd_cl_lex_json_string (struct rspamd_cl_parser *parser, return FALSE; } -/** - * Unescape json string inplace - * @param str - */ -static void -rspamd_cl_unescape_json_string (gchar *str) -{ - gchar *t = str, *h = str; - gint i, uval; - - /* t is target (tortoise), h is source (hare) */ - - while (*h != '\0') { - if (*h == '\\') { - h ++; - switch (*h) { - case 'n': - *t++ = '\n'; - break; - case 'r': - *t++ = '\r'; - break; - case 'b': - *t++ = '\b'; - break; - case 't': - *t++ = '\t'; - break; - case 'f': - *t++ = '\f'; - break; - case '\\': - *t++ = '\\'; - break; - case '"': - *t++ = '"'; - break; - case 'u': - /* Unicode escape */ - uval = 0; - for (i = 0; i < 4; i++) { - uval <<= 4; - if (g_ascii_isdigit (h[i])) { - uval += h[i] - '0'; - } - else if (h[i] >= 'a' && h[i] <= 'f') { - uval += h[i] - 'a' + 10; - } - else if (h[i] >= 'A' && h[i] <= 'F') { - uval += h[i] - 'A' + 10; - } - } - /* Encode */ - if(uval < 0x80) { - t[0] = (char)uval; - t ++; - } - else if(uval < 0x800) { - t[0] = 0xC0 + ((uval & 0x7C0) >> 6); - t[1] = 0x80 + ((uval & 0x03F)); - t += 2; - } - else if(uval < 0x10000) { - t[0] = 0xE0 + ((uval & 0xF000) >> 12); - t[1] = 0x80 + ((uval & 0x0FC0) >> 6); - t[2] = 0x80 + ((uval & 0x003F)); - t += 3; - } - else if(uval <= 0x10FFFF) { - t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); - t[1] = 0x80 + ((uval & 0x03F000) >> 12); - t[2] = 0x80 + ((uval & 0x000FC0) >> 6); - t[3] = 0x80 + ((uval & 0x00003F)); - t += 4; - } - else { - *t++ = '?'; - } - break; - default: - *t++ = '?'; - break; - } - } - else { - *t++ = *h++; - } - } -} - /** * Parse a key in an object * @param parser @@ -338,7 +248,7 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, { const guchar *p, *c = NULL, *end; gboolean got_quote = FALSE, got_eq = FALSE, got_semicolon = FALSE; - rspamd_cl_object_t *nobj; + rspamd_cl_object_t *nobj, *tobj; p = chunk->pos; @@ -442,6 +352,12 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, return FALSE; } } + else if (*p == '/' || *p == '#') { + /* Check for comment */ + if (!rspamd_cl_skip_comments (parser, err)) { + return FALSE; + } + } else { /* Start value */ break; @@ -462,6 +378,13 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, rspamd_cl_unescape_json_string (nobj->key); } + HASH_FIND_STR (parser->cur_obj->value.ov, nobj->key, tobj); + if (tobj != NULL) { + /* We are going to replace old key with new one */ + HASH_DELETE (hh, parser->cur_obj->value.ov, tobj); + rspamd_cl_obj_free (tobj); + } + HASH_ADD_KEYPTR (hh, parser->cur_obj->value.ov, nobj->key, strlen (nobj->key), nobj); return TRUE; diff --git a/src/rcl/rcl_util.c b/src/rcl/rcl_util.c index 96fc8dda4..58a6e2cd2 100644 --- a/src/rcl/rcl_util.c +++ b/src/rcl/rcl_util.c @@ -29,3 +29,118 @@ * @file rcl_util.c * Utilities for rcl parsing */ + + +void +rspamd_cl_obj_free (rspamd_cl_object_t *obj) +{ + rspamd_cl_object_t *sub, *tmp; + + if (obj->key != NULL) { + g_free (obj->key); + } + + if (obj->type == RSPAMD_CL_STRING) { + g_free (obj->value.sv); + } + else if (obj->type == RSPAMD_CL_ARRAY) { + sub = obj->value.ov; + while (sub != NULL) { + tmp = sub->next; + rspamd_cl_obj_free (sub); + sub = tmp; + } + } + else if (obj->type == RSPAMD_CL_OBJECT) { + HASH_ITER (hh, obj->value.ov, sub, tmp) { + HASH_DELETE (hh, obj->value.ov, sub); + rspamd_cl_obj_free (sub); + } + } +} + +void +rspamd_cl_unescape_json_string (gchar *str) +{ + gchar *t = str, *h = str; + gint i, uval; + + /* t is target (tortoise), h is source (hare) */ + + while (*h != '\0') { + if (*h == '\\') { + h ++; + switch (*h) { + case 'n': + *t++ = '\n'; + break; + case 'r': + *t++ = '\r'; + break; + case 'b': + *t++ = '\b'; + break; + case 't': + *t++ = '\t'; + break; + case 'f': + *t++ = '\f'; + break; + case '\\': + *t++ = '\\'; + break; + case '"': + *t++ = '"'; + break; + case 'u': + /* Unicode escape */ + uval = 0; + for (i = 0; i < 4; i++) { + uval <<= 4; + if (g_ascii_isdigit (h[i])) { + uval += h[i] - '0'; + } + else if (h[i] >= 'a' && h[i] <= 'f') { + uval += h[i] - 'a' + 10; + } + else if (h[i] >= 'A' && h[i] <= 'F') { + uval += h[i] - 'A' + 10; + } + } + /* Encode */ + if(uval < 0x80) { + t[0] = (char)uval; + t ++; + } + else if(uval < 0x800) { + t[0] = 0xC0 + ((uval & 0x7C0) >> 6); + t[1] = 0x80 + ((uval & 0x03F)); + t += 2; + } + else if(uval < 0x10000) { + t[0] = 0xE0 + ((uval & 0xF000) >> 12); + t[1] = 0x80 + ((uval & 0x0FC0) >> 6); + t[2] = 0x80 + ((uval & 0x003F)); + t += 3; + } + else if(uval <= 0x10FFFF) { + t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); + t[1] = 0x80 + ((uval & 0x03F000) >> 12); + t[2] = 0x80 + ((uval & 0x000FC0) >> 6); + t[3] = 0x80 + ((uval & 0x00003F)); + t += 4; + } + else { + *t++ = '?'; + } + break; + default: + *t++ = '?'; + break; + } + } + else { + *t++ = *h++; + } + } +} -- 2.39.5