Exemplo n.º 1
0
/**
 * json_node_seal:
 * @node: a #JsonNode
 *
 * Seals the #JsonNode, making it immutable to further changes. In order to be
 * sealed, the @node must have a type and value set. The value will be
 * recursively sealed — if the node holds an object, that #JsonObject will be
 * sealed, etc.
 *
 * If the @node is already immutable, this is a no-op.
 *
 * Since: 1.2
 */
void
json_node_seal (JsonNode *node)
{
  g_return_if_fail (JSON_NODE_IS_VALID (node));

  if (node->immutable)
    return;

  switch (node->type)
    {
    case JSON_NODE_OBJECT:
      g_return_if_fail (node->data.object != NULL);
      json_object_seal (node->data.object);
      break;
    case JSON_NODE_ARRAY:
      g_return_if_fail (node->data.array != NULL);
      json_array_seal (node->data.array);
      break;
    case JSON_NODE_NULL:
      break;
    case JSON_NODE_VALUE:
      g_return_if_fail (node->data.value != NULL);
      json_value_seal (node->data.value);
      break;
    default:
      g_assert_not_reached ();
    }

  node->immutable = TRUE;
}
Exemplo n.º 2
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_unref (priv->current_node);
          priv->current_node = old_current;

          return token;
        }

      next_token = json_scanner_peek_next_token (scanner);

      /* look for missing commas */
      if (next_token != G_TOKEN_COMMA && next_token != G_TOKEN_RIGHT_BRACE)
        {
          priv->error_code = JSON_PARSER_ERROR_MISSING_COMMA;

          json_array_unref (array);
          json_node_free (priv->current_node);
          json_node_free (element);
          priv->current_node = old_current;

          return G_TOKEN_COMMA;
        }

      /* look for trailing commas */
      if (next_token == G_TOKEN_COMMA)
        {
          token = json_scanner_get_next_token (scanner);
          next_token = json_scanner_peek_next_token (scanner);

          if (next_token == G_TOKEN_RIGHT_BRACE)
            {
              priv->error_code = JSON_PARSER_ERROR_TRAILING_COMMA;

              json_array_unref (array);
              json_node_unref (priv->current_node);
              json_node_unref (element);
              priv->current_node = old_current;

              return G_TOKEN_RIGHT_BRACE;
            }
        }

      JSON_NOTE (PARSER, "Array element %d completed", idx);
      json_node_set_parent (element, priv->current_node);
      if (priv->is_immutable)
        json_node_seal (element);
      json_array_add_element (array, element);

      g_signal_emit (parser, parser_signals[ARRAY_ELEMENT], 0,
                     array,
                     idx);

      idx += 1;
      token = next_token;
    }

array_done:
  json_scanner_get_next_token (scanner);

  if (priv->is_immutable)
    json_array_seal (array);

  json_node_take_array (priv->current_node, array);
  if (priv->is_immutable)
    json_node_seal (priv->current_node);
  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;
}