static guint json_parse_object (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonObject *object; JsonNode *old_current; guint token; old_current = priv->current_node; priv->current_node = json_node_init_object (json_node_alloc (), NULL); object = json_object_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_CURLY); g_signal_emit (parser, parser_signals[OBJECT_START], 0); while (token != G_TOKEN_RIGHT_CURLY) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *member = NULL; gchar *name; /* we need to abort here because empty objects do not * have member names */ if (next_token == G_TOKEN_RIGHT_CURLY) break; /* parse the member's name */ if (next_token != G_TOKEN_STRING) { JSON_NOTE (PARSER, "Missing object member name"); priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD; json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_STRING; } /* member name */ token = json_scanner_get_next_token (scanner); name = g_strdup (scanner->value.v_string); if (name == NULL || *name == '\0') { JSON_NOTE (PARSER, "Empty object member name"); priv->error_code = JSON_PARSER_ERROR_EMPTY_MEMBER_NAME; json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_STRING; } JSON_NOTE (PARSER, "Object member '%s'", name); /* a colon separates names from values */ next_token = json_scanner_peek_next_token (scanner); if (next_token != ':') { JSON_NOTE (PARSER, "Missing object member name separator"); priv->error_code = JSON_PARSER_ERROR_MISSING_COLON; g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return ':'; } /* we swallow the ':' */ token = json_scanner_get_next_token (scanner); g_assert (token == ':'); next_token = json_scanner_peek_next_token (scanner); /* parse the member's value */ switch (next_token) { case G_TOKEN_LEFT_BRACE: JSON_NOTE (PARSER, "Nested array at member %s", name); token = json_parse_array (parser, scanner, &member); break; case G_TOKEN_LEFT_CURLY: JSON_NOTE (PARSER, "Nested object at member %s", name); token = json_parse_object (parser, scanner, &member); break; default: /* once a member name is defined we need a value */ token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &member); break; } if (token != G_TOKEN_NONE || member == NULL) { /* the json_parse_* functions will have set the error code */ g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_CURLY) { priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA; json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } else if (next_token == G_TOKEN_STRING) { priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA; json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_COMMA; } JSON_NOTE (PARSER, "Object member '%s' completed", name); json_node_set_parent (member, priv->current_node); json_object_set_member (object, name, member); g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, object, name); g_free (name); token = next_token; } json_scanner_get_next_token (scanner); json_node_take_object (priv->current_node, object); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[OBJECT_END], 0, object); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }
static guint json_parse_object (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonObject *object; JsonNode *old_current; guint token; old_current = priv->current_node; priv->current_node = json_node_new (JSON_NODE_OBJECT); object = json_object_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_CURLY); g_signal_emit (parser, parser_signals[OBJECT_START], 0); while (token != G_TOKEN_RIGHT_CURLY) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *member = NULL; gchar *name; /* we need to abort here because empty objects do not * have member names */ if (next_token == G_TOKEN_RIGHT_CURLY) break; /* parse the member's name */ if (next_token != G_TOKEN_STRING) { json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_STRING; } /* member name */ token = json_scanner_get_next_token (scanner); name = g_strdup (scanner->value.v_string); /* a colon separates names from values */ next_token = json_scanner_peek_next_token (scanner); if (next_token != ':') { g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return ':'; } /* we swallow the ':' */ token = json_scanner_get_next_token (scanner); g_assert (token == ':'); next_token = json_scanner_peek_next_token (scanner); /* parse the member's value */ switch (next_token) { case G_TOKEN_LEFT_BRACE: token = json_parse_array (parser, scanner, &member); break; case G_TOKEN_LEFT_CURLY: token = json_parse_object (parser, scanner, &member); break; case G_TOKEN_INT: case G_TOKEN_FLOAT: case G_TOKEN_STRING: case '-': case JSON_TOKEN_TRUE: case JSON_TOKEN_FALSE: case JSON_TOKEN_NULL: token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &member); break; default: /* once a member name is defined we need a value */ token = G_TOKEN_SYMBOL; break; } if (token != G_TOKEN_NONE || member == NULL) { /* the json_parse_* functions will have set the error code */ g_free (name); json_object_unref (object); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_CURLY) { json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } else if (next_token == G_TOKEN_STRING) { json_object_unref (object); json_node_free (member); json_node_free (priv->current_node); priv->current_node = old_current; return G_TOKEN_COMMA; } json_node_set_parent (member, priv->current_node); json_object_set_member (object, name, member); g_signal_emit (parser, parser_signals[OBJECT_MEMBER], 0, object, name); g_free (name); token = next_token; } json_scanner_get_next_token (scanner); json_node_take_object (priv->current_node, object); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[OBJECT_END], 0, object); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }
static guint json_parse_array (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonNode *old_current; JsonArray *array; guint token; gint idx; old_current = priv->current_node; priv->current_node = json_node_init_array (json_node_alloc (), NULL); array = json_array_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_BRACE); g_signal_emit (parser, parser_signals[ARRAY_START], 0); idx = 0; while (token != G_TOKEN_RIGHT_BRACE) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *element = NULL; /* parse the element */ switch (next_token) { case G_TOKEN_LEFT_BRACE: JSON_NOTE (PARSER, "Nested array at index %d", idx); token = json_parse_array (parser, scanner, &element); break; case G_TOKEN_LEFT_CURLY: JSON_NOTE (PARSER, "Nested object at index %d", idx); token = json_parse_object (parser, scanner, &element); break; case G_TOKEN_RIGHT_BRACE: goto array_done; default: token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &element); break; } if (token != G_TOKEN_NONE || element == NULL) { /* the json_parse_* functions will have set the error code */ json_array_unref (array); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_BRACE) { priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA; json_array_unref (array); json_node_free (priv->current_node); json_node_free (element); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } JSON_NOTE (PARSER, "Array element %d completed", idx + 1); json_node_set_parent (element, priv->current_node); json_array_add_element (array, element); g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0, array, idx); token = next_token; } array_done: json_scanner_get_next_token (scanner); json_node_take_array (priv->current_node, array); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[ARRAY_END], 0, array); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }
static guint json_parse_array (JsonParser *parser, JsonScanner *scanner, JsonNode **node) { JsonParserPrivate *priv = parser->priv; JsonNode *old_current; JsonArray *array; guint token; gint idx; old_current = priv->current_node; priv->current_node = json_node_new (JSON_NODE_ARRAY); array = json_array_new (); token = json_scanner_get_next_token (scanner); g_assert (token == G_TOKEN_LEFT_BRACE); g_signal_emit (parser, parser_signals[ARRAY_START], 0); idx = 0; while (token != G_TOKEN_RIGHT_BRACE) { guint next_token = json_scanner_peek_next_token (scanner); JsonNode *element = NULL; /* parse the element */ switch (next_token) { case G_TOKEN_LEFT_BRACE: token = json_parse_array (parser, scanner, &element); break; case G_TOKEN_LEFT_CURLY: token = json_parse_object (parser, scanner, &element); break; case G_TOKEN_INT: case G_TOKEN_FLOAT: case G_TOKEN_STRING: case '-': case JSON_TOKEN_TRUE: case JSON_TOKEN_FALSE: case JSON_TOKEN_NULL: token = json_scanner_get_next_token (scanner); token = json_parse_value (parser, scanner, token, &element); break; case G_TOKEN_RIGHT_BRACE: goto array_done; default: if (next_token != G_TOKEN_RIGHT_BRACE) token = G_TOKEN_RIGHT_BRACE; break; } if (token != G_TOKEN_NONE || element == NULL) { /* the json_parse_* functions will have set the error code */ json_array_unref (array); json_node_free (priv->current_node); priv->current_node = old_current; return token; } next_token = json_scanner_peek_next_token (scanner); if (next_token == G_TOKEN_COMMA) { token = json_scanner_get_next_token (scanner); next_token = json_scanner_peek_next_token (scanner); /* look for trailing commas */ if (next_token == G_TOKEN_RIGHT_BRACE) { json_array_unref (array); json_node_free (priv->current_node); json_node_free (element); priv->current_node = old_current; return G_TOKEN_RIGHT_BRACE; } } json_node_set_parent (element, priv->current_node); json_array_add_element (array, element); g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0, array, idx); token = next_token; } array_done: json_scanner_get_next_token (scanner); json_node_take_array (priv->current_node, array); json_node_set_parent (priv->current_node, old_current); g_signal_emit (parser, parser_signals[ARRAY_END], 0, array); if (node != NULL && *node == NULL) *node = priv->current_node; priv->current_node = old_current; return G_TOKEN_NONE; }