Skip to content

Commit

Permalink
lib: Code cleanup to json-parser - assume less that the root is an ob…
Browse files Browse the repository at this point in the history
…ject
  • Loading branch information
sirainen committed Feb 1, 2016
1 parent 1dc963a commit 736b180
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 16 deletions.
30 changes: 14 additions & 16 deletions src/lib/json-parser.c
Expand Up @@ -335,21 +335,16 @@ static int json_parse_denest(struct json_parser *parser)
json_parser_update_input_pos(parser);

nested_states = array_get(&parser->nesting, &count);
if (count == 0) {
i_assert(count > 0);
if (count == 1) {
/* closing root */
parser->state = JSON_STATE_DONE;
return 0;
}

/* closing a nested object */
if (count == 1) {
/* we're back to root */
parser->state = JSON_STATE_OBJECT_NEXT;
} else {
/* back to previous nested object */
parser->state = nested_states[count-2] == JSON_STATE_OBJECT_OPEN ?
JSON_STATE_OBJECT_NEXT : JSON_STATE_ARRAY_NEXT;
}
parser->state = nested_states[count-2] == JSON_STATE_OBJECT_OPEN ?
JSON_STATE_OBJECT_NEXT : JSON_STATE_ARRAY_NEXT;
array_delete(&parser->nesting, count-1, 1);

if (parser->nested_skip_count > 0) {
Expand Down Expand Up @@ -377,6 +372,14 @@ json_parse_close_array(struct json_parser *parser, enum json_type *type_r)
return 1;
}

static void json_parser_object_open(struct json_parser *parser)
{
parser->data++;
parser->state = JSON_STATE_OBJECT_OPEN;
array_append(&parser->nesting, &parser->state, 1);
json_parser_update_input_pos(parser);
}

static int
json_try_parse_next(struct json_parser *parser, enum json_type *type_r,
const char **value_r)
Expand All @@ -393,17 +396,12 @@ json_try_parse_next(struct json_parser *parser, enum json_type *type_r,
parser->error = "Object doesn't begin with '{'";
return -1;
}
parser->data++;
parser->state = JSON_STATE_OBJECT_OPEN;
json_parser_update_input_pos(parser);
json_parser_object_open(parser);
return 0;
case JSON_STATE_OBJECT_VALUE:
case JSON_STATE_ARRAY_VALUE:
if (*parser->data == '{') {
parser->data++;
parser->state = JSON_STATE_OBJECT_OPEN;
array_append(&parser->nesting, &parser->state, 1);
json_parser_update_input_pos(parser);
json_parser_object_open(parser);

if (parser->skipping) {
parser->nested_skip_count++;
Expand Down
41 changes: 41 additions & 0 deletions src/lib/test-json-parser.c
Expand Up @@ -163,6 +163,46 @@ static void test_json_parser_success(bool full_size)
test_end();
}

static int test_json_parse_input(const char *test_input)
{
struct json_parser *parser;
struct istream *input;
enum json_type type;
const char *value, *error;
int ret = 0;

input = test_istream_create_data(test_input, strlen(test_input));
parser = json_parser_init(input);
while (json_parse_next(parser, &type, &value) > 0)
ret++;
if (json_parser_deinit(&parser, &error) < 0)
ret = -1;
i_stream_unref(&input);
return ret;
}

static void test_json_parser_errors(void)
{
static const char *test_inputs[] = {
"{",
"{:}",
"{\"foo\":}",
"{\"foo\" []}",
"{\"foo\": [1}",
"{\"foo\": [1,]}",
"{\"foo\": [1,]}",
"{\"foo\": 1,}",
"{\"foo\": 1.}}",
"{\"foo\": 1},{}"
};
unsigned int i;

test_begin("json parser error handling");
for (i = 0; i < N_ELEMENTS(test_inputs); i++)
test_assert_idx(test_json_parse_input(test_inputs[i]) < 0, i);
test_end();
}

static void test_json_append_escaped(void)
{
string_t *str = t_str_new(32);
Expand All @@ -189,6 +229,7 @@ void test_json_parser(void)
{
test_json_parser_success(TRUE);
test_json_parser_success(FALSE);
test_json_parser_errors();
test_json_append_escaped();
test_json_append_escaped_data();
}

0 comments on commit 736b180

Please sign in to comment.