diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-08-12 16:07:29 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-08-12 16:07:29 +0100 |
commit | 9d3180655c79d9a557e57fab78de11ab13792ca3 (patch) | |
tree | 447f2484a75d182374721fd3302e090270604e2d /src/rcl | |
parent | 7c75e68788215e21bd88a6d581429df9bf8cfbaf (diff) | |
download | rspamd-9d3180655c79d9a557e57fab78de11ab13792ca3.tar.gz rspamd-9d3180655c79d9a557e57fab78de11ab13792ca3.zip |
Fix rcl test suite and parser.
Diffstat (limited to 'src/rcl')
-rw-r--r-- | src/rcl/rcl_parser.c | 28 | ||||
-rw-r--r-- | src/rcl/rcl_util.c | 54 |
2 files changed, 66 insertions, 16 deletions
diff --git a/src/rcl/rcl_parser.c b/src/rcl/rcl_parser.c index cf5ca76b9..16552d325 100644 --- a/src/rcl/rcl_parser.c +++ b/src/rcl/rcl_parser.c @@ -232,7 +232,7 @@ rspamd_cl_lex_is_atom_end (const guchar c) * @return TRUE if a number has been parsed */ static gboolean -rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser, +rspamd_cl_lex_number (struct rspamd_cl_parser *parser, struct rspamd_cl_chunk *chunk, rspamd_cl_object_t *obj, GError **err) { const guchar *p = chunk->pos, *c = chunk->pos; @@ -362,10 +362,10 @@ rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser, p ++; goto set_obj; } - else if (chunk->end - p > 3) { + else if (chunk->end - p >= 3) { if (g_ascii_tolower (p[0]) == 'm' && g_ascii_tolower (p[1]) == 'i' && - g_ascii_tolower (p[2]) == 'm') { + g_ascii_tolower (p[2]) == 'n') { /* Minutes */ if (!need_double) { need_double = TRUE; @@ -413,14 +413,15 @@ rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser, case 'W': case 'Y': case 'y': - if (p == chunk->end - 1 || rspamd_cl_lex_is_atom_end (*++p)) { + if (p == chunk->end - 1 || rspamd_cl_lex_is_atom_end (p[1])) { if (!need_double) { need_double = TRUE; dv = lv; } is_date = TRUE; - rspamd_cl_chunk_skipc (chunk, *p); dv *= rspamd_cl_lex_time_multiplier (*p); + rspamd_cl_chunk_skipc (chunk, *p); + p ++; goto set_obj; } break; @@ -668,12 +669,13 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, HASH_FIND_STR (container, nobj->key, tobj); if (tobj != NULL) { /* Just insert a new object as the next element */ - tobj->next = nobj; - } - else { - HASH_ADD_KEYPTR (hh, container, nobj->key, strlen (nobj->key), nobj); + LL_PREPEND (tobj, nobj); + HASH_DELETE (hh, container, tobj); } + HASH_ADD_KEYPTR (hh, container, nobj->key, strlen (nobj->key), nobj); + parser->stack->obj->value.ov = container; + parser->cur_obj = nobj; return TRUE; @@ -783,6 +785,8 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err) if (parser->stack->obj->type == RSPAMD_CL_ARRAY) { /* Object must be allocated */ obj = rspamd_cl_object_new (); + parser->cur_obj = obj; + LL_PREPEND (parser->stack->obj->value.ov, parser->cur_obj); } else { /* Object has been already allocated */ @@ -797,8 +801,8 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err) parser->state = RSPAMD_RCL_STATE_ERROR; return FALSE; } - obj->value.sv = g_malloc (chunk->pos - c); - rspamd_strlcpy (obj->value.sv, c + 1, chunk->pos - c); + obj->value.sv = g_malloc (chunk->pos - c - 1); + rspamd_strlcpy (obj->value.sv, c + 1, chunk->pos - c - 1); rspamd_cl_unescape_json_string (obj->value.sv); obj->type = RSPAMD_CL_STRING; parser->state = RSPAMD_RCL_STATE_AFTER_VALUE; @@ -845,7 +849,7 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err) } /* Parse atom */ if (g_ascii_isdigit (*p) || *p == '-') { - if (!rspamd_cl_lex_json_number (parser, chunk, obj, err)) { + if (!rspamd_cl_lex_number (parser, chunk, obj, err)) { if (parser->state == RSPAMD_RCL_STATE_ERROR) { return FALSE; } diff --git a/src/rcl/rcl_util.c b/src/rcl/rcl_util.c index 3216a27d8..1c9d6a652 100644 --- a/src/rcl/rcl_util.c +++ b/src/rcl/rcl_util.c @@ -31,8 +31,8 @@ */ -void -rspamd_cl_obj_free (rspamd_cl_object_t *obj) +static void +rspamd_cl_obj_free_internal (rspamd_cl_object_t *obj, gboolean allow_rec) { rspamd_cl_object_t *sub, *tmp; @@ -48,23 +48,33 @@ rspamd_cl_obj_free (rspamd_cl_object_t *obj) sub = obj->value.ov; while (sub != NULL) { tmp = sub->next; - rspamd_cl_obj_free (sub); + rspamd_cl_obj_free_internal (sub, FALSE); 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); + rspamd_cl_obj_free_internal (sub, TRUE); } } tmp = obj->next; g_slice_free1 (sizeof (rspamd_cl_object_t), obj); obj = tmp; + + if (!allow_rec) { + break; + } } } void +rspamd_cl_obj_free (rspamd_cl_object_t *obj) +{ + rspamd_cl_obj_free_internal (obj, TRUE); +} + +void rspamd_cl_unescape_json_string (gchar *str) { gchar *t = str, *h = str; @@ -112,6 +122,7 @@ rspamd_cl_unescape_json_string (gchar *str) uval += h[i] - 'A' + 10; } } + h += 3; /* Encode */ if(uval < 0x80) { t[0] = (char)uval; @@ -143,9 +154,44 @@ rspamd_cl_unescape_json_string (gchar *str) *t++ = '?'; break; } + h ++; } else { *t++ = *h++; } } } + +rspamd_cl_object_t* +rspamd_cl_parser_get_object (struct rspamd_cl_parser *parser, GError **err) +{ + if (parser->state != RSPAMD_RCL_STATE_INIT && parser->state != RSPAMD_RCL_STATE_ERROR) { + return parser->top_obj; + } + + return NULL; +} + +void +rspamd_cl_parser_free (struct rspamd_cl_parser *parser) +{ + struct rspamd_cl_stack *stack, *stmp; + struct rspamd_cl_macro *macro, *mtmp; + struct rspamd_cl_chunk *chunk, *ctmp; + + if (parser->top_obj != NULL) { + rspamd_cl_obj_free (parser->top_obj); + } + + LL_FOREACH_SAFE (parser->stack, stack, stmp) { + g_slice_free1 (sizeof (struct rspamd_cl_stack), stack); + } + HASH_ITER (hh, parser->macroes, macro, mtmp) { + g_slice_free1 (sizeof (struct rspamd_cl_macro), macro); + } + LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) { + g_slice_free1 (sizeof (struct rspamd_cl_chunk), chunk); + } + + g_slice_free1 (sizeof (struct rspamd_cl_parser), parser); +} |