summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--json-glib/json-parser.c49
-rw-r--r--json-glib/json-parser.h8
-rw-r--r--json-glib/tests/parser-test.c18
3 files changed, 56 insertions, 19 deletions
diff --git a/json-glib/json-parser.c b/json-glib/json-parser.c
index 4e22572..8df897e 100644
--- a/json-glib/json-parser.c
+++ b/json-glib/json-parser.c
@@ -1,8 +1,9 @@
/* json-parser.c - JSON streams parser
*
* This file is part of JSON-GLib
- * Copyright (C) 2007 OpenedHand Ltd.
- * Copyright (C) 2009 Intel Corp.
+ *
+ * Copyright © 2007, 2008, 2009 OpenedHand Ltd
+ * Copyright © 2009, 2010 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -48,8 +49,7 @@ json_parser_error_quark (void)
return g_quark_from_static_string ("json-parser-error");
}
-#define JSON_PARSER_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_PARSER, JsonParserPrivate))
+#define JSON_PARSER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), JSON_TYPE_PARSER, JsonParserPrivate))
struct _JsonParserPrivate
{
@@ -58,6 +58,7 @@ struct _JsonParserPrivate
JsonScanner *scanner;
+ JsonParserError error_code;
GError *last_error;
gchar *variable_name;
@@ -325,6 +326,9 @@ json_parser_init (JsonParser *parser)
priv->root = NULL;
priv->current_node = NULL;
+ priv->error_code = JSON_PARSER_ERROR_PARSE;
+ priv->last_error = NULL;
+
priv->has_assignment = FALSE;
priv->variable_name = NULL;
@@ -338,7 +342,8 @@ json_parse_value (JsonParser *parser,
guint token,
JsonNode **node)
{
- JsonNode *current_node = parser->priv->current_node;
+ JsonParserPrivate *priv = parser->priv;
+ JsonNode *current_node = priv->current_node;
gboolean is_negative = FALSE;
if (token == '-')
@@ -385,11 +390,14 @@ json_parse_value (JsonParser *parser,
case JSON_TOKEN_TRUE:
case JSON_TOKEN_FALSE:
*node = json_node_new (JSON_NODE_VALUE);
+ JSON_NOTE (PARSER, "node: '%s'",
+ JSON_TOKEN_TRUE ? "<true>" : "<false>");
json_node_set_boolean (*node, token == JSON_TOKEN_TRUE ? TRUE : FALSE);
break;
case JSON_TOKEN_NULL:
*node = json_node_new (JSON_NODE_NULL);
+ JSON_NOTE (PARSER, "node: <null>");
break;
default:
@@ -404,7 +412,10 @@ json_parse_value (JsonParser *parser,
else if (cur_type == JSON_NODE_OBJECT)
return G_TOKEN_RIGHT_CURLY;
else
- return G_TOKEN_SYMBOL;
+ {
+ priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+ return G_TOKEN_SYMBOL;
+ }
}
}
@@ -475,7 +486,11 @@ json_parse_array (JsonParser *parser,
token = json_scanner_get_next_token (scanner);
if (token == G_TOKEN_RIGHT_BRACE)
- return G_TOKEN_SYMBOL;
+ {
+ json_array_unref (array);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+ return G_TOKEN_SYMBOL;
+ }
continue;
}
@@ -523,7 +538,11 @@ json_parse_array (JsonParser *parser,
token = json_scanner_get_next_token (scanner);
if (token == G_TOKEN_RIGHT_BRACE)
- return G_TOKEN_SYMBOL;
+ {
+ json_array_unref (array);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
+ return G_TOKEN_SYMBOL;
+ }
continue;
}
@@ -557,12 +576,14 @@ json_parse_array (JsonParser *parser,
if (token == G_TOKEN_RIGHT_BRACE)
{
json_array_unref (array);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
return G_TOKEN_SYMBOL;
}
}
else if (token != G_TOKEN_RIGHT_BRACE)
{
json_array_unref (array);
+ priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
return G_TOKEN_RIGHT_BRACE;
}
}
@@ -671,6 +692,7 @@ json_parse_object (JsonParser *parser,
if (token == G_TOKEN_RIGHT_CURLY)
{
json_object_unref (object);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
return G_TOKEN_STRING;
}
@@ -723,6 +745,7 @@ json_parse_object (JsonParser *parser,
if (token == G_TOKEN_RIGHT_CURLY)
{
json_object_unref (object);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
return G_TOKEN_STRING;
}
@@ -760,6 +783,7 @@ json_parse_object (JsonParser *parser,
{
g_free (name);
json_object_unref (object);
+ priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;
return G_TOKEN_STRING;
}
}
@@ -767,6 +791,7 @@ json_parse_object (JsonParser *parser,
{
g_free (name);
json_object_unref (object);
+ priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;
return G_TOKEN_RIGHT_CURLY;
}
@@ -814,7 +839,10 @@ json_parse_statement (JsonParser *parser,
/* ... swallow the variable name... */
next_token = json_scanner_get_next_token (scanner);
if (next_token != G_TOKEN_IDENTIFIER)
- return G_TOKEN_IDENTIFIER;
+ {
+ priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
+ return G_TOKEN_IDENTIFIER;
+ }
name = g_strdup (scanner->value.v_identifier);
@@ -852,6 +880,7 @@ json_parse_statement (JsonParser *parser,
default:
json_scanner_get_next_token (scanner);
+ priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
return G_TOKEN_SYMBOL;
}
}
@@ -869,7 +898,7 @@ json_scanner_msg_handler (JsonScanner *scanner,
GError *error = NULL;
g_set_error (&error, JSON_PARSER_ERROR,
- JSON_PARSER_ERROR_PARSE,
+ priv->error_code,
"%s:%d: Parse error: %s",
priv->is_filename ? priv->filename : "<none>",
scanner->line,
diff --git a/json-glib/json-parser.h b/json-glib/json-parser.h
index 7589464..11bfb89 100644
--- a/json-glib/json-parser.h
+++ b/json-glib/json-parser.h
@@ -49,12 +49,20 @@ typedef struct _JsonParserClass JsonParserClass;
/**
* JsonParserError:
* @JSON_PARSER_ERROR_PARSE: parse error
+ * @JSON_PARSER_ERROR_TRAILING_COMMA: unexpected trailing comma
+ * @JSON_PARSER_ERROR_MISSING_COMMA: expected comma
+ * @JSON_PARSER_ERROR_INVALID_BAREWORD: invalid bareword
* @JSON_PARSER_ERROR_UNKNOWN: unknown error
*
* Error enumeration for #JsonParser
+ *
+ * This enumeration can be extended at later date
*/
typedef enum {
JSON_PARSER_ERROR_PARSE,
+ JSON_PARSER_ERROR_TRAILING_COMMA,
+ JSON_PARSER_ERROR_MISSING_COMMA,
+ JSON_PARSER_ERROR_INVALID_BAREWORD,
JSON_PARSER_ERROR_UNKNOWN
} JsonParserError;
diff --git a/json-glib/tests/parser-test.c b/json-glib/tests/parser-test.c
index 8f461ef..8fb11b1 100644
--- a/json-glib/tests/parser-test.c
+++ b/json-glib/tests/parser-test.c
@@ -131,14 +131,15 @@ static const struct
static const struct
{
const gchar *str;
+ JsonParserError code;
} test_invalid[] = {
- { "test" },
- { "[ foo, ]" },
- { "[ true, ]" },
- { "{ \"foo\" : true \"bar\" : false }" },
- { "[ true, [ false, ] ]" },
- { "{ \"foo\" : { \"bar\" : false, } }" },
- { "[ { }, { }, { }, ]" }
+ { "test", JSON_PARSER_ERROR_INVALID_BAREWORD },
+ { "[ foo, ]", JSON_PARSER_ERROR_INVALID_BAREWORD },
+ { "[ true, ]", JSON_PARSER_ERROR_TRAILING_COMMA },
+ { "{ \"foo\" : true \"bar\" : false }", JSON_PARSER_ERROR_MISSING_COMMA },
+ { "[ true, [ false, ] ]", JSON_PARSER_ERROR_TRAILING_COMMA },
+ { "{ \"foo\" : { \"bar\" : false, } }", JSON_PARSER_ERROR_TRAILING_COMMA },
+ { "[ { }, { }, { }, ]", JSON_PARSER_ERROR_TRAILING_COMMA }
};
static guint n_test_base_values = G_N_ELEMENTS (test_base_values);
@@ -671,8 +672,7 @@ test_invalid_json (void)
&error);
g_assert (!res);
- g_assert (error != NULL);
- g_assert (error->domain == JSON_PARSER_ERROR);
+ g_assert_error (error, JSON_PARSER_ERROR, test_invalid[i].code);
if (g_test_verbose ())
g_print ("Error: %s\n", error->message);