summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/reference/json-glib-sections.txt1
-rw-r--r--json-glib/json-parser.c80
-rw-r--r--json-glib/json-parser.h5
-rw-r--r--tests/test-02.c5
4 files changed, 89 insertions, 2 deletions
diff --git a/doc/reference/json-glib-sections.txt b/doc/reference/json-glib-sections.txt
index 46d78ae..e781b45 100644
--- a/doc/reference/json-glib-sections.txt
+++ b/doc/reference/json-glib-sections.txt
@@ -99,6 +99,7 @@ json_parser_get_root
<SUBSECTION>
json_parser_get_current_line
json_parser_get_current_pos
+json_parser_has_assignment
<SUBSECTION Standard>
JSON_TYPE_PARSER
diff --git a/json-glib/json-parser.c b/json-glib/json-parser.c
index 4b89db1..5df7999 100644
--- a/json-glib/json-parser.c
+++ b/json-glib/json-parser.c
@@ -51,6 +51,9 @@ struct _JsonParserPrivate
GScanner *scanner;
GError *last_error;
+
+ guint has_assignment : 1;
+ gchar *variable_name;
};
static const GScannerConfig json_scanner_config =
@@ -95,7 +98,8 @@ static const GScannerConfig json_scanner_config =
static const gchar symbol_names[] =
"true\0"
"false\0"
- "null\0";
+ "null\0"
+ "var\0";
static const struct
{
@@ -104,7 +108,8 @@ static const struct
} symbols[] = {
{ 0, JSON_TOKEN_TRUE },
{ 5, JSON_TOKEN_FALSE },
- { 11, JSON_TOKEN_NULL }
+ { 11, JSON_TOKEN_NULL },
+ { 16, JSON_TOKEN_VAR }
};
static const guint n_symbols = G_N_ELEMENTS (symbols);
@@ -152,6 +157,8 @@ json_parser_dispose (GObject *gobject)
priv->last_error = NULL;
}
+ g_free (priv->variable_name);
+
G_OBJECT_CLASS (json_parser_parent_class)->dispose (gobject);
}
@@ -326,6 +333,9 @@ json_parser_init (JsonParser *parser)
priv->root = NULL;
priv->current_node = NULL;
+
+ priv->has_assignment = FALSE;
+ priv->variable_name = NULL;
}
static guint
@@ -735,6 +745,38 @@ json_parse_statement (JsonParser *parser,
priv->root = priv->current_node = json_node_new (JSON_NODE_ARRAY);
return json_parse_array (parser, scanner, FALSE);
+ /* some web APIs are not only passing the data structures: they are
+ * also passing an assigment, which makes parsing horribly complicated
+ * only because web developers are lazy, and writing "var foo = " is
+ * evidently too much to request from them.
+ */
+ case JSON_TOKEN_VAR:
+ {
+ guint next_token;
+ gchar *name;
+
+ /* swallow the 'var' token... */
+ token = g_scanner_get_next_token (scanner);
+
+ /* ... swallow the variable name... */
+ next_token = g_scanner_get_next_token (scanner);
+ if (next_token != G_TOKEN_IDENTIFIER)
+ return G_TOKEN_IDENTIFIER;
+
+ name = g_strdup (scanner->value.v_identifier);
+
+ /* ... and finally swallow the '=' */
+ next_token = g_scanner_get_next_token (scanner);
+ if (next_token != '=')
+ return '=';
+
+ priv->has_assignment = TRUE;
+ priv->variable_name = name;
+
+ return json_parse_statement (parser, scanner);
+ }
+ break;
+
case JSON_TOKEN_NULL:
priv->root = priv->current_node = json_node_new (JSON_NODE_NULL);
return G_TOKEN_NONE;
@@ -1074,3 +1116,37 @@ json_parser_get_current_pos (JsonParser *parser)
return 0;
}
+
+/**
+ * json_parser_has_assignment:
+ * @parser: a #JsonParser
+ * @variable_name: return location for the variable name, or %NULL
+ *
+ * A JSON data stream might sometimes contain an assignment, even though
+ * it would technically constitute a violation of the RFC. #JsonParser
+ * will ignore the left hand identifier and parse the right hand value
+ * of the assignment. It will record, though, the existence of the
+ * assignment in the data stream and the variable name used.
+ *
+ * Return value: %TRUE if there was an assignment, %FALSE otherwise. If
+ * @variable_name is not %NULL it will be set to the name of the variable
+ * used in the assignment. The string is owned by #JsonParser and should
+ * never be modified or freed.
+ *
+ * Since: 0.4
+ */
+gboolean
+json_parser_has_assignment (JsonParser *parser,
+ gchar **variable_name)
+{
+ JsonParserPrivate *priv;
+
+ g_return_val_if_fail (JSON_IS_PARSER (parser), FALSE);
+
+ priv = parser->priv;
+
+ if (priv->has_assignment && variable_name)
+ *variable_name = priv->variable_name;
+
+ return priv->has_assignment;
+}
diff --git a/json-glib/json-parser.h b/json-glib/json-parser.h
index 71a17cb..37324a9 100644
--- a/json-glib/json-parser.h
+++ b/json-glib/json-parser.h
@@ -53,9 +53,12 @@ typedef enum {
typedef enum {
JSON_TOKEN_INVALID = G_TOKEN_LAST,
+
JSON_TOKEN_TRUE,
JSON_TOKEN_FALSE,
JSON_TOKEN_NULL,
+ JSON_TOKEN_VAR,
+
JSON_TOKEN_LAST
} JsonTokenType;
@@ -141,6 +144,8 @@ JsonNode * json_parser_get_root (JsonParser *parser);
guint json_parser_get_current_line (JsonParser *parser);
guint json_parser_get_current_pos (JsonParser *parser);
+gboolean json_parser_has_assignment (JsonParser *parser,
+ gchar **variable_name);
G_END_DECLS
diff --git a/tests/test-02.c b/tests/test-02.c
index b307a7c..b5fb7a8 100644
--- a/tests/test-02.c
+++ b/tests/test-02.c
@@ -13,6 +13,7 @@ static const gchar *test_arrays[] = {
"[ [ false, true, 42 ], [ true, false, 3.14 ], \"test\" ]",
"[ true, { } ]",
"[ false, { \"test\" : 42 } ]",
+ "var test = [ false, false, true ]",
};
static guint n_test_arrays = G_N_ELEMENTS (test_arrays);
@@ -190,6 +191,7 @@ main (int argc, char *argv[])
GError *error = NULL;
JsonNode *node;
JsonArray *array;
+ gchar *var_name;
if (!json_parser_load_from_data (parser, test_arrays[i], -1, &error))
{
@@ -210,6 +212,9 @@ main (int argc, char *argv[])
g_assert (array != NULL);
g_print ("*** Test %d: '%s' ***\n", i, test_arrays[i]);
+ if (json_parser_has_assignment (parser, &var_name))
+ g_print ("*** Test %d: assigns '%s'\n", i, var_name);
+
print_array (1, array);
}