Esempio n. 1
0
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;
}
Esempio n. 3
0
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;
}