]> source.dussan.org Git - rspamd.git/commitdiff
Fix rcl test suite and parser.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 12 Aug 2013 15:07:29 +0000 (16:07 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 12 Aug 2013 15:07:29 +0000 (16:07 +0100)
src/rcl/rcl_parser.c
src/rcl/rcl_util.c
test/rspamd_rcl_test.c

index cf5ca76b928b68455dc48af19d045a3c57ba7a3b..16552d325068bb64f9ea68c691584f046635fce6 100644 (file)
@@ -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;
                                                }
index 3216a27d8674ccf7442e52e1c9699b5fc2baef20..1c9d6a652cbf269e3fed307d2a9e7fb997f56723 100644 (file)
@@ -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,22 +48,32 @@ 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)
 {
@@ -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);
+}
index 01b3ba8350f8c8f545ae99297224039f281320e3..695002de569b5e8fa7ba6993f73aa2848f64074d 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "../src/config.h"
 #include "../src/rcl/rcl.h"
+#include "../src/main.h"
 #include "tests.h"
 
 const gchar *rcl_test_valid[] = {
@@ -33,7 +34,7 @@ const gchar *rcl_test_valid[] = {
                "\"key1\": \"value;\""
                "}\n",
                /* Nginx like */
-               "section1 { param1 = value; param2 = value, param3 = [\"value1\", 100500]}\n"
+               "section1 { param1 = value; param2 = value, param3 = [\"value1\", value2, 100500]}\n"
                "section2 { param1 = {key = value}, param1 = [\"key\"]}",
                /* Numbers */
                "key = 1s\n"
@@ -57,6 +58,7 @@ rspamd_rcl_test_func (void)
        struct rspamd_cl_parser *parser;
        rspamd_cl_object_t *obj;
        const gchar **cur;
+       guchar *emitted;
        GError *err = NULL;
 
        cur = rcl_test_valid;
@@ -65,6 +67,13 @@ rspamd_rcl_test_func (void)
                g_assert (parser != NULL);
                rspamd_cl_parser_add_chunk (parser, *cur, strlen (*cur), &err);
                g_assert_no_error (err);
+               obj = rspamd_cl_parser_get_object (parser, &err);
+               g_assert_no_error (err);
+               emitted = rspamd_cl_object_emit (obj, RSPAMD_CL_EMIT_JSON);
+               g_assert (emitted != NULL);
+               msg_info ("got json output: %s", emitted);
+               g_free (emitted);
+               rspamd_cl_parser_free (parser);
                cur ++;
        }