Example #1
0
File: json.c Project: wschnrid/yaz
static struct json_node *json_parse_elements(json_parser_t p)
{
    struct json_node *n1 = json_parse_value(p);
    struct json_node *m0, *m1;
    if (!n1)
        return 0;
    m0 = m1 = json_new_node(p, json_node_list);
    m1->u.link[0] = n1;
    while (look_ch(p) == ',')
    {
        struct json_node *n2, *m2;
        move_ch(p);
        n2 = json_parse_value(p);
        if (!n2)
        {
            json_remove_node(m0);
            return 0;
        }
        m2 = json_new_node(p, json_node_list);
        m2->u.link[0] = n2;

        m1->u.link[1] = m2;
        m1 = m2;
    }
    return m0;
}
Example #2
0
static int json_parse_object_tail(struct json_parser* parser)
{
    for (;;)
    {
        skip_white_space(parser);
    
        switch (peek(parser))
        {
            // Finished when we reach the final closing brace
            case '}':
                skip(parser);
                return JSON_PARSE_SUCCESS;
                
            case '"':
                
                // Key
                skip(parser);
                json_parse_string_tail(parser);
                
                // Sep
                skip_white_space(parser);
                skip_char(parser, ':');
                
                // Value
                json_parse_value(parser);
                
                
                // Comma?
                break;
                
            default:
                return JSON_PARSE_FAIL;
        }
    }    
}
Example #3
0
/******************************************************************************
 *                                                                            *
 * Function: json_parse_array                                                 *
 *                                                                            *
 * Purpose: Parses JSON array value                                           *
 *                                                                            *
 * Parameters: start - [IN] the JSON data without leading whitespace          *
 *             error - [OUT] the parsing error message (can be NULL)          *
 *                                                                            *
 * Return value: The number of characters parsed. On error 0 is returned and  *
 *               error parameter (if not NULL) contains allocated error       *
 *               message.                                                     *
 *                                                                            *
 * Author: Andris Zeila                                                       *
 *                                                                            *
 ******************************************************************************/
static int	json_parse_array(const char *start, char **error)
{
	const char	*ptr = start;
	int		len;

	ptr++;
	SKIP_WHITESPACE(ptr);

	if (']' != *ptr)
	{
		while (1)
		{
			/* json_parse_value strips leading whitespace, so we don't have to do it here */
			if (0 == (len = json_parse_value(ptr, error)))
				return 0;

			ptr += len;
			SKIP_WHITESPACE(ptr);

			if (',' != *ptr)
				break;

			ptr++;
		}

		/* no closing ], failing */
		if (']' != *ptr)
			return json_error("invalid array format, expected closing character ']'", ptr, error);
	}

	return ptr - start + 1;
}
Example #4
0
static JSON *json_parse_array(struct lexer *lx) {
	
	JSON *v = malloc(sizeof *v);
	v->type = j_array;
	v->value = NULL;
	v->next = NULL;
	
	JSON *tail = NULL;
	
	if(!lx_expect(lx, '[')) {
		json_error("line %d: %s", lx_lineno(lx), lx_text(lx));
		return NULL;
	}
	if(lx_sym(lx) != ']') {
		do {		
			JSON *value = json_parse_value(lx);
			if(!value) 
				return NULL;
			if(v->value) {
				assert(tail);
				tail->next = value;			
			} else {
				v->value = value;
			}	
			tail = value;
			
		} while(lx_accept(lx, ','));
	}
	if(!lx_expect(lx, ']')) {
		json_error("line %d: %s", lx_lineno(lx), lx_text(lx));
		return NULL;
	}
	
	return v;
}
Example #5
0
File: json.c Project: wschnrid/yaz
struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
{
    int c;
    struct json_node *n;
    p->buf = json_str;
    p->cp = p->buf;
    p->err_msg = 0;
    p->parse_level = 0;
    p->max_level = 1000;

    n = json_parse_value(p);
    if (!n)
        return 0;
    if (p->err_msg)
    {
        json_remove_node(n);
        return 0;
    }
    c = look_ch(p);
    if (c != 0)
    {
        p->err_msg = "extra characters";
        json_remove_node(n);
        return 0;
    }
    return n;
}
Example #6
0
/******************************************************************************
 *                                                                            *
 * Function: json_parse_object                                                *
 *                                                                            *
 * Purpose: Parses JSON object                                                *
 *                                                                            *
 * Parameters: start - [IN] the JSON data                                     *
 *             error - [OUT] the parsing error message (can be NULL)          *
 *                                                                            *
 * Return value: The number of characters parsed. On error 0 is returned and  *
 *               error parameter (if not NULL) contains allocated error       *
 *               message.                                                     *
 *                                                                            *
 * Author: Andris Zeila                                                       *
 *                                                                            *
 ******************************************************************************/
static int	json_parse_object(const char *start, char **error)
{
	const char	*ptr = start;
	int		len;

	/* parse object name */
	SKIP_WHITESPACE(ptr);

	/* not an object, failing */
	if ('{' != *ptr)
		return json_error("invalid object format, expected opening character '{'", ptr, error);

	ptr++;
	SKIP_WHITESPACE(ptr);

	if ('}' != *ptr)
	{
		while (1)
		{
			if ('"' != *ptr)
				return json_error("invalid object name", ptr, error);

			/* cannot parse object name, failing */
			if (0 == (len = json_parse_string(ptr, error)))
				return 0;

			ptr += len;

			/* parse name:value separator */
			SKIP_WHITESPACE(ptr);

			if (':' != *ptr)
				return json_error("invalid object name/value separator", ptr, error);
			ptr++;

			if (0 == (len = json_parse_value(ptr, error)))
				return 0;

			ptr += len;

			SKIP_WHITESPACE(ptr);

			if (',' != *ptr)
				break;

			ptr++;
			SKIP_WHITESPACE(ptr);
		}

		/* object is not properly closed, failing */
		if ('}' != *ptr)
			return json_error("invalid object format, expected closing character '}'", ptr, error);
	}

	return ptr - start + 1;
}
Example #7
0
struct json_val *json_parse_base(struct read_state *state)
{
    if (read_state_left(state) >= 2) {
        if (*state->read == 0xfe) 
            state->read += 2;//Eat any BOMs
    }
    if (!eat_whitespace(state))
        return 0;
    return json_parse_value(state);
}
Example #8
0
static void *
json_parse_list(const char *s, const char **endp, const json_deserializer_t *jd,
		void *opaque, const char **failp, const char **failmsg)
{
  const char *s2;
  void *r;

  while(*s > 0 && *s < 33)
    s++;

  if(*s != '[')
    return NOT_THIS_TYPE;

  s++;

  r = jd->jd_create_list(opaque);
  
  while(*s > 0 && *s < 33)
    s++;

  if(*s != ']') {

    while(1) {

      s2 = json_parse_value(s, r, NULL, jd, opaque, failp, failmsg);

      if(s2 == NULL) {
	jd->jd_destroy_obj(opaque, r);
	return NULL;
      }

      s = s2;

      while(*s > 0 && *s < 33)
	s++;

      if(*s == ']')
	break;

      if(*s != ',') {
	jd->jd_destroy_obj(opaque, r);
	*failmsg = "Expected ','";
	*failp = s;
	return NULL;
      }
      s++;
    }
  }
  s++;
  *endp = s;
  return r;
}
Example #9
0
struct json_val *json_parse_array(struct read_state *state)
{
    struct json_val *value;
    char ch;
    int i;
    value = malloc(sizeof(*value));
    value->type = JSON_ARRAY;
    value->length = 0;
    value->array = 0;

    if (*state->read++ != '[') {
        json_error_print(state, "Internal error parsing array\n");
        goto fail;
    }

    if(!eat_whitespace(state)) {
        json_error_print(state, "Unexpected end of file parsing array\n");
        goto fail;
    }
    ch = *state->read++;
    if (ch == ']') {
        //pass
    } else {
            read_state_put_back(state);
        do {
            value->length++;
            value->array = realloc(value->object, value->length * sizeof(*value->object));
            value->array[value->length-1] = json_parse_value(state);
            if (value->array[value->length-1] == 0)
                goto fail;

            if (!eat_whitespace(state)) {
                json_error_print(state, "Unexpected end of file parsing array\n");
                goto fail;
            }
            ch = *state->read++;
            if (ch != ']' && ch != ',') {
                json_error_print(state, "Unexpected character found parsing array\n");
                goto fail;
            }
            if (!eat_whitespace(state) && ch != ']') {
                json_error_print(state, "Unexpected end of file parsing array\n");
                goto fail;
            }
        } while (ch == ',');
    }
    return value;

fail:
    json_free_value(value);
    return 0;
}
Example #10
0
static struct json_field json_parse_object_field(struct read_state *state)
{
    struct json_field ret = {0,0};
    
    if (!eat_whitespace(state)) {
        json_error_print(state, "Unexpected end of file parsing object field key\n");
        goto fail;
    }
    ret.key = json_parse_value(state);
    if (ret.key == 0)
        goto fail;
    if (ret.key->type != JSON_STRING) {
        json_error_print(state, "Objected field key must be of type string\n");
        goto fail;
    }
    ;
    if (!eat_whitespace(state)) {
        json_error_print(state, "Unexpected end of file parsing object field\n");
        goto fail;
    }
    if (*state->read++ != ':') {
        json_error_print(state, "Didn't find expected ':' reading object\n");
        goto fail;
    }
    if (!eat_whitespace(state)) {
        json_error_print(state, "Unexpected end of file parsing object field value\n");
        goto fail;
    }
    ret.value = json_parse_value(state);
    if (ret.value == 0)
        goto fail;
    return ret;
        
fail:
    free(ret.key);
    ret.key == 0;
    return ret;
}
Example #11
0
int json_parse(const json_char* source, struct json_callbacks* callbacks)
{
    struct json_parser parser;
    parser.line = 0;
    parser.col  = 0;
    parser.callbacks = callbacks;
    parser.source = strdup(source);
    parser.position = parser.source;
    
    jmp_buf buffer; parser.buffer = &buffer;
    if (setjmp(buffer))
    {
        callbacks->on_error(parser.line, parser.col, parser.source);
        return JSON_PARSE_FAIL;
    }
    return json_parse_value(&parser);
}
Example #12
0
struct json_value_s* json_parse(const void* src, size_t src_size) {
  struct json_parse_state_s state;
  void* allocation;

  if (0 == src || 2 > src_size) {
    // absolute minimum valid json is either "{}" or "[]"
    return 0;
  }

  state.src = src;
  state.size = src_size;
  state.offset = 0;
  state.dom_size = 0;
  state.data_size = 0;

  if (json_get_value_size(&state)) {
    // parsing value's size failed (most likely an invalid JSON DOM!)
    return 0;
  }

  // our total allocation is the combination of the dom and data sizes (we
  // first encode the structure of the JSON, and then the data referenced by
  // the JSON values)
  allocation = malloc(state.dom_size + state.data_size);

  if (0 == allocation) {
    // malloc failed!
    return 0;
  }

  // reset offset so we can reuse it
  state.offset = 0;

  state.dom = allocation;
  state.data = state.dom + state.dom_size;

  state.dom += sizeof(struct json_value_s);

  if (json_parse_value(&state, (struct json_value_s* )allocation)) {
    // really bad chi here
    free(allocation);
    return 0;
  }

  return allocation;
}
Example #13
0
static JSON *json_parse_object(struct lexer *lx) {
	
	Hash_Tbl *h = ht_create (16);
	JSON *v = malloc(sizeof *v);
	v->type = j_object;
	v->value = h;
	v->next = NULL;
	
	if(!lx_expect(lx, '{')) {
		json_error("line %d: %s", lx_lineno(lx), lx_text(lx));
		free(v);
		return NULL;
	}
	if(lx_sym(lx) != '}') {
		do {
			char *key;
			JSON *value;
			lx_accept(lx, LX_STRING);
			key = strdup(lx_text(lx));
			lx_accept(lx, ':');		
			value = json_parse_value(lx);
			if(!value) {
				free(key);
				free(v);
				return NULL;
			}
			
			ht_put (h, key, value);
			
			free(key);	
			
		} while(lx_accept(lx, ','));
	}
	if(!lx_expect(lx, '}')) {
		json_error("line %d: %s", lx_lineno(lx), lx_text(lx));
		free(v);
		return NULL;
	}
		
	return v;
}
Example #14
0
static int json_parse_array_tail(struct json_parser* parser)
{
    for (;;)
    {
        if (peek(parser) == ']')
        {
            skip(parser);
            return JSON_PARSE_SUCCESS;
        }

        int more = 0;
        do
        {
            json_parse_value(parser);
            skip_white_space(parser);
            if (peek(parser) == ',')
            {
                skip(parser);
                more = 1;
            }
        } while (more);
    }
}
Example #15
0
File: json.c Project: wschnrid/yaz
static struct json_node *json_parse_pair(json_parser_t p)
{
    struct json_node *s = json_parse_string(p);
    struct json_node *v, *n;
    if (!s)
        return 0;
    if (look_ch(p) != ':')
    {
        p->err_msg = "missing :";
        json_remove_node(s);
        return 0;
    }
    move_ch(p);
    v = json_parse_value(p);
    if (!v)
    {
        json_remove_node(s);
        return 0;
    }
    n = json_new_node(p, json_node_pair);
    n->u.link[0] = s;
    n->u.link[1] = v;
    return n;
}
Example #16
0
static int json_parse_object(struct json_parse_state_s* state,
  struct json_object_s* object) {
  size_t elements = 0;
  struct json_object_element_s* previous = 0;

  if ('{' != state->src[state->offset]) {
    // expected object to begin with leading '{'
    return 1;
  }

  // skip leading '{'
  state->offset++;

  if (json_skip_whitespace(state)) {
    // consumed the whole buffer when we expected a value!
    return 1;
  }

  if ('}' != state->src[state->offset]) {
    // we have at least one element as we definitely don't have
    // an empty object {   }!
    elements++;
  }

  // reset elements
  elements = 0;

  while (state->offset < state->size) {
	struct json_object_element_s* element = 0;
	struct json_string_s* string = 0;
	struct json_value_s* value = 0;

    if (json_skip_whitespace(state)) {
      // reached end of buffer before object was complete!
      return 1;
    }

    if ('}' == state->src[state->offset]) {
      // skip trailing '}'
      state->offset++;

      // finished the object!
      break;
    }

    // if we parsed at least one element previously, grok for a comma
    if (0 < elements) {
      if (',' != state->src[state->offset]) {
        // expected a comma where there was none!
        return 1;
      }

      // skip comma
      state->offset++;

      if (json_skip_whitespace(state)) {
        // reached end of buffer before object was complete!
        return 1;
      }
    }

    element = (struct json_object_element_s* )state->dom;

    state->dom += sizeof(struct json_object_element_s);

    if (0 == previous) {
      // this is our first element, so record it in our object
      object->start = element;
    } else {
      previous->next = element;
    }

    previous = element;

    string = (struct json_string_s* )state->dom;

    state->dom += sizeof(struct json_string_s);

    element->name = string;

    if (json_parse_string(state, string)) {
      // string parsing failed!
      return 1;
    }

    if (json_skip_whitespace(state)) {
      // reached end of buffer before object was complete!
      return 1;
    }

    if (':' != state->src[state->offset]) {
      // colon seperating name/value pair was missing!
      return 1;
    }

    // skip colon
    state->offset++;

    if (json_skip_whitespace(state)) {
      // reached end of buffer before object was complete!
      return 1;
    }

    value = (struct json_value_s* )state->dom;

    state->dom += sizeof(struct json_value_s);

    element->value = value;

    if (json_parse_value(state, value)) {
      // value parsing failed!
      return 1;
    }

    // successfully parsed a name/value pair!
    elements++;
  }

  // if we had at least one element, end the linked list
  if (previous) {
    previous->next = 0;
  }

  if (0 == elements) {
    object->start = 0;
  }

  object->length = elements;

  return 0;
}
Example #17
0
int json_parse_array( json_task_t *task, json_object_t *parent ) {
    char ch;
    json_object_t node, * append = NULL;
    
    node.next = parent;
    node.key = NULL;
    node.key_len = 0;
    
    if( !task->callback ) {
        if( !task->root ) {
            append = task->root = json_create_array();
        } else {
            append = parent->value.p = json_create_array();
        }
    }
    
    task->status = STS_ARRAY_START;

    while(( ch = *(task->str + task->count) )) {
        task->count ++;
        
        if( ch == ' ' || ch == '\n' || ch == '\t' ) {
            continue;
        }
        
        switch( task->status ) {
            case STS_ARRAY_START:
                if( ch == ']' ) {
                    return 0;
                } else {
                    /* 这里需要将计数减一,因为 json_parse_value 需要根据这一个字符判断 value 类型 */
                    task->count --;

                    node.value.s = task->str + task->count;
                    if( json_parse_value( task, &node ) != 0 ) {
                        if( node.value_type == JSON_OBJECT ||
                            node.value_type == JSON_ARRAY ) {
                            json_delete_object(node.value.p);
                        }
                        return -1;
                    }
                    // WARNING: value_len 可能发生溢出
                    node.value_len = task->str + task->count - node.value.s;
                    
                    // 对 value 进行处理
                    switch(node.value_type) {
                        case JSON_STRING:
                            // 去除字符串两端的引号
                            node.value.s += 1;
                            node.value_len -= 2;
                            break;
                        case JSON_DOUBLE:
                            // TODO 在解析测试用例时,atof 与 atoll 使解析时间延长了几乎一半
                            // 移除对数值的默认解析可以显著提升性能
                            node.value.d = atof(node.value.s);
                            break;
                        case JSON_LONGLONG:
                            node.value.l = atoll(node.value.s);
                            break;
                        case JSON_ARRAY:
                        case JSON_OBJECT:
                            break;
                    }

                    // 需要放在 node.key_len ++ 之前以便正确输出数组下标
                    if( task->callback ) {
                        task->callback( task, &node );
                    }

                    if( !task->callback ) {
                        switch( node.value_type ) {
                            case JSON_ARRAY:
                            case JSON_OBJECT:
                            case JSON_STRING:
                                append = json_append(append, node.key, node.key_len,
                                        node.value_type, node.value.p, node.value_len);
                                break;
                            default:
                                append = json_append(append, node.key, node.key_len,
                                        node.value_type, &node.value, node.value_len);
                        }
                    }
                    
                    node.key_len ++;
                    task->status = STS_ARRAY_COMMA;
                }
                break;
            case STS_ARRAY_COMMA:
                if( ch == ',' ) {
                    task->status = STS_ARRAY_START;
                } else if( ch == ']' ) {
                    return 0;
                } else {
                    task->err_msg = "expect ',' or ']'";
                    return -1;
                }
                break;
            default:
                task->err_msg = "unknown status";
                return -1;
        }
    }

    task->err_msg = "unexpect EOF";
    return -1;
}
Example #18
0
int json_parse_object( json_task_t *task, json_object_t *parent ) {
    char ch;
    json_object_t node, * append = NULL;
    
    node.next = parent;
    node.key = NULL;
    node.key_len = 0;
    
    if( !task->callback ) {
        if( !task->root ) {
            append = task->root = json_create_object();
        } else {
            append = parent->value.p = json_create_object();
        }
    }
    
    task->status = STS_OBJECT_START;

    while(( ch = *(task->str + task->count) )) {
        task->count ++;
        
        if( ch == ' ' || ch == '\n' || ch == '\t' ) {
            continue;
        }
        
        switch( task->status ) {
            case STS_OBJECT_START:
                if( ch == '"' ) {
                    node.key = task->str + task->count;
                    if( json_parse_string( task ) != 0 ) {
                        return -1;
                    }
                    // WARNING: key_len 可能发生溢出
                    node.key_len = task->str + task->count - node.key - 1;
                    
                    task->status = STS_OBJECT_COLON;
                } else if( ch == '}' ) {
                    // 空对象 {},忽略
                    return 0;
                } else {
                    task->err_msg = "expect '\"' or '}'";
                    return -1;
                }
                break;
            case STS_OBJECT_COLON:
                if( ch == ':' ) {
                    task->status = STS_OBJECT_VALUE;
                } else {
                    task->err_msg = "expect ':'";
                    return -1;
                }
                break;
            case STS_OBJECT_VALUE:
                /* 这里需要将计数减一,因为 json_parse_value 需要根据这一个字符判断 value 类型 */
                task->count --;
                
                node.value.s = task->str + task->count;
                if( json_parse_value( task, &node ) != 0 ) {
                    if( node.value_type == JSON_OBJECT ||
                        node.value_type == JSON_ARRAY ) {
                        json_delete_object(node.value.p);
                    }
                    return -1;
                }
                // WARNING: value_len 可能发生溢出
                node.value_len = task->str + task->count - node.value.s;

                task->status = STS_OBJECT_COMMA;
                break;
            case STS_OBJECT_COMMA:
                if( ( ch == ',' || ch == '}' ) ) {
                    // 对 value 进行处理
                    switch(node.value_type) {
                        case JSON_STRING:
                            // 去除字符串两端的引号
                            node.value.s += 1;
                            node.value_len -= 2;
                            break;
                        case JSON_DOUBLE:
                            node.value.d = atof(node.value.s);
                            break;
                        case JSON_LONGLONG:
                            node.value.l = atoll(node.value.s);
                            break;
                        case JSON_ARRAY:
                        case JSON_OBJECT:
                            break;
                    }

                    if( task->callback ) {
                        task->callback( task, &node );
                    }
                    
                    if( !task->callback ) {
                        switch( node.value_type ) {
                            case JSON_ARRAY:
                            case JSON_OBJECT:
                            case JSON_STRING:
                                append = json_append(append, node.key, node.key_len,
                                        node.value_type, node.value.p, node.value_len);
                                break;
                            default:
                                append = json_append(append, node.key, node.key_len,
                                        node.value_type, &node.value, node.value_len);
                        }
                    }
                }
                
                if( ch == ',' ) {
                    task->status = STS_OBJECT_START;
                } else if( ch == '}' ) {
                    return 0;
                } else {
                    task->err_msg = "expect ',' or '}'";
                    return -1;
                }
                break;
            default:
                task->err_msg = "unknown status";
                return -1;
        }
    }
    
    task->err_msg = "unexpect EOF";
    return -1;
}
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;
}
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;
}
Example #21
0
static guint
json_parse_statement (JsonParser  *parser,
                      JsonScanner *scanner)
{
  JsonParserPrivate *priv = parser->priv;
  guint token;

  token = json_scanner_peek_next_token (scanner);
  switch (token)
    {
    case G_TOKEN_LEFT_CURLY:
      JSON_NOTE (PARSER, "Statement is object declaration");
      return json_parse_object (parser, scanner, &priv->root);

    case G_TOKEN_LEFT_BRACE:
      JSON_NOTE (PARSER, "Statement is array declaration");
      return json_parse_array (parser, scanner, &priv->root);

    /* 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;

        JSON_NOTE (PARSER, "Statement is an assignment");

        /* swallow the 'var' token... */
        token = json_scanner_get_next_token (scanner);

        /* ... swallow the variable name... */
        next_token = json_scanner_get_next_token (scanner);
        if (next_token != G_TOKEN_IDENTIFIER)
          {
            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
            return G_TOKEN_IDENTIFIER;
          }

        name = g_strdup (scanner->value.v_identifier);

        /* ... and finally swallow the '=' */
        next_token = json_scanner_get_next_token (scanner);
        if (next_token != '=')
          {
            priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
            g_free (name);
            return '=';
          }

        priv->has_assignment = TRUE;
        priv->variable_name = name;

        token = json_parse_statement (parser, scanner);

        /* remove the trailing semi-colon */
        next_token = json_scanner_peek_next_token (scanner);
        if (next_token == ';')
          {
            token = json_scanner_get_next_token (scanner);
            return G_TOKEN_NONE;
          }

        return token;
      }
      break;

    case JSON_TOKEN_NULL:
    case JSON_TOKEN_TRUE:
    case JSON_TOKEN_FALSE:
    case '-':
    case G_TOKEN_INT:
    case G_TOKEN_FLOAT:
    case G_TOKEN_STRING:
    case G_TOKEN_IDENTIFIER:
      JSON_NOTE (PARSER, "Statement is a value");
      token = json_scanner_get_next_token (scanner);
      return json_parse_value (parser, scanner, token, &priv->root);

    default:
      JSON_NOTE (PARSER, "Unknown statement");
      json_scanner_get_next_token (scanner);
      priv->error_code = JSON_PARSER_ERROR_INVALID_BAREWORD;
      return G_TOKEN_SYMBOL;
    }
}
static guint
json_parse_statement (JsonParser  *parser,
                      JsonScanner *scanner)
{
  JsonParserPrivate *priv = parser->priv;
  guint token;

  token = json_scanner_peek_next_token (scanner);
  switch (token)
    {
    case G_TOKEN_LEFT_CURLY:
      return json_parse_object (parser, scanner, &priv->root);

    case G_TOKEN_LEFT_BRACE:
      return json_parse_array (parser, scanner, &priv->root);

    /* 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 = json_scanner_get_next_token (scanner);

        /* ... swallow the variable name... */
        next_token = json_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 = json_scanner_get_next_token (scanner);
        if (next_token != '=')
          return '=';

        priv->has_assignment = TRUE;
        priv->variable_name = name;

        token = json_parse_statement (parser, scanner);

        /* remove the trailing semi-colon */
        next_token = json_scanner_peek_next_token (scanner);
        if (next_token == ';')
          {
            token = json_scanner_get_next_token (scanner);
            return G_TOKEN_NONE;
          }

        return token;
      }
      break;

    case JSON_TOKEN_NULL:
      priv->root = priv->current_node = json_node_new (JSON_NODE_NULL);
      json_scanner_get_next_token (scanner);
      return G_TOKEN_NONE;

    case JSON_TOKEN_TRUE:
    case JSON_TOKEN_FALSE:
      priv->root = priv->current_node = json_node_new (JSON_NODE_VALUE);
      json_node_set_boolean (priv->current_node,
                             token == JSON_TOKEN_TRUE ? TRUE : FALSE);
      json_scanner_get_next_token (scanner);
      return G_TOKEN_NONE;

    case '-':
      {
        guint next_token;
        
        token = json_scanner_get_next_token (scanner);
        next_token = json_scanner_peek_next_token (scanner);

        if (next_token == G_TOKEN_INT || next_token == G_TOKEN_FLOAT)
          {
            priv->root = priv->current_node = json_node_new (JSON_NODE_VALUE);
            
            token = json_scanner_get_next_token (scanner);
            switch (token)
              {
              case G_TOKEN_INT:
                json_node_set_int (priv->current_node,
                                   scanner->value.v_int64 * -1);
                break;
              case G_TOKEN_FLOAT:
                json_node_set_double (priv->current_node,
                                      scanner->value.v_float * -1.0);
                break;
              default:
                return G_TOKEN_INT;
              }

            json_scanner_get_next_token (scanner);
            return G_TOKEN_NONE;
          }
        else
          return G_TOKEN_INT;
      }
      break;

    case G_TOKEN_INT:
    case G_TOKEN_FLOAT:
    case G_TOKEN_STRING:
      token = json_scanner_get_next_token (scanner);
      return json_parse_value (parser, scanner, token, &priv->root);

    default:
      json_scanner_get_next_token (scanner);
      return G_TOKEN_SYMBOL;
    }
}
Example #23
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;
}
Example #24
0
static void json_parse_array(struct json_parse_state_s *state,
                            struct json_array_s *array) {
  size_t elements = 0;
  int allow_comma = 0;
  struct json_array_element_s *previous = 0;

  // skip leading '['
  state->offset++;

  (void)json_skip_all_skippables(state);

  // reset elements
  elements = 0;

  while (state->offset < state->size) {
    struct json_array_element_s *element = 0;
    struct json_value_s *value = 0;

    (void)json_skip_all_skippables(state);

    if (']' == state->src[state->offset]) {
      // skip trailing ']'
      state->offset++;

      // finished the array!
      break;
    }

    // if we parsed at least one element previously, grok for a comma
    if (allow_comma) {
      if (',' == state->src[state->offset]) {
        // skip comma
        state->offset++;
        allow_comma = 0;
        continue;
      }
    }

    element = (struct json_array_element_s *)state->dom;

    state->dom += sizeof(struct json_array_element_s);

    if (0 == previous) {
      // this is our first element, so record it in our array
      array->start = element;
    } else {
      previous->next = element;
    }

    previous = element;

    value = (struct json_value_s *)state->dom;

    state->dom += sizeof(struct json_value_s);

    element->value = value;

    json_parse_value(state, /* is_global_object = */ 0, value);

    // successfully parsed an array element!
    elements++;
    allow_comma = 1;
  }

  // end the linked list
  if (previous) {
    previous->next = 0;
  }

  if (0 == elements) {
    array->start = 0;
  }

  array->length = elements;
}
Example #25
0
static void json_parse_object(struct json_parse_state_s *state,
                             int is_global_object,
                             struct json_object_s *object) {
  size_t elements = 0;
  int allow_comma = 0;
  struct json_object_element_s *previous = 0;

  if (!is_global_object) {
    // skip leading '{'
    state->offset++;
  }

  (void)json_skip_all_skippables(state);

  // reset elements
  elements = 0;

  while (state->offset < state->size) {
    struct json_object_element_s *element = 0;
    struct json_string_s *string = 0;
    struct json_value_s *value = 0;

    if (!is_global_object) {
      (void)json_skip_all_skippables(state);

      if ('}' == state->src[state->offset]) {
        // skip trailing '}'
        state->offset++;

        // finished the object!
        break;
      }
    } else {
      if (json_skip_all_skippables(state)) {
        // global object ends when the file ends!
        break;
      }
    }

    // if we parsed at least one element previously, grok for a comma
    if (allow_comma) {
      if (',' == state->src[state->offset]) {
        // skip comma
        state->offset++;
        allow_comma = 0;
        continue;
      }
    }

    element = (struct json_object_element_s *)state->dom;

    state->dom += sizeof(struct json_object_element_s);

    if (0 == previous) {
      // this is our first element, so record it in our object
      object->start = element;
    } else {
      previous->next = element;
    }

    previous = element;

    string = (struct json_string_s *)state->dom;

    state->dom += sizeof(struct json_string_s);

    element->name = string;

    (void)json_parse_key(state, string);

    (void)json_skip_all_skippables(state);

    // skip colon or equals
    state->offset++;

    (void)json_skip_all_skippables(state);

    value = (struct json_value_s *)state->dom;

    state->dom += sizeof(struct json_value_s);

    element->value = value;

    json_parse_value(state, /* is_global_object = */ 0, value);

    // successfully parsed a name/value pair!
    elements++;
    allow_comma = 1;
  }

  // if we had at least one element, end the linked list
  if (previous) {
    previous->next = 0;
  }

  if (0 == elements) {
    object->start = 0;
  }

  object->length = elements;
}
Example #26
0
static int json_parse_array(struct json_parse_state_s* state,
  struct json_array_s* array) {
  size_t elements = 0;
  struct json_array_element_s* previous = 0;

  if ('[' != state->src[state->offset]) {
    // expected object to begin with leading '['
    return 1;
  }

  // skip leading '['
  state->offset++;

  if (json_skip_whitespace(state)) {
    // consumed the whole buffer when we expected a value!
    return 1;
  }

  // reset elements
  elements = 0;

  while (state->offset < state->size) {
	struct json_array_element_s* element = 0;
	struct json_value_s* value = 0;

    if (json_skip_whitespace(state)) {
      // reached end of buffer before array was complete!
      return 1;
    }

    if (']' == state->src[state->offset]) {
      // skip trailing ']'
      state->offset++;

      // finished the array!
      break;
    }

    // if we parsed at least one element previously, grok for a comma
    if (0 < elements) {
      if (',' != state->src[state->offset]) {
        // expected a comma where there was none!
        return 1;
      }

      // skip comma
      state->offset++;

      if (json_skip_whitespace(state)) {
        // reached end of buffer before array was complete!
        return 1;
      }
    }

    element = (struct json_array_element_s* )state->dom;

    state->dom += sizeof(struct json_array_element_s);

    if (0 == previous) {
      // this is our first element, so record it in our array
      array->start = element;
    } else {
      previous->next = element;
    }

    previous = element;

    value = (struct json_value_s* )state->dom;

    state->dom += sizeof(struct json_value_s);

    element->value = value;

    if (json_parse_value(state, value)) {
      // value parsing failed!
      return 1;
    }

    // successfully parsed an array element!
    elements++;
  }

  // end the linked list
  if (previous) {
    previous->next = 0;
  }

  if (0 == elements) {
    array->start = 0;
  }

  array->length = elements;

  return 0;
}
Example #27
0
static void *
json_parse_map(const char *s, const char **endp, const json_deserializer_t *jd,
	       void *opaque, const char **failp, const char **failmsg)

{
  char *name;
  const char *s2;
  void *r;

  while(*s > 0 && *s < 33)
    s++;

  if(*s != '{')
    return NOT_THIS_TYPE;

  s++;

  r = jd->jd_create_map(opaque);
  
  while(*s > 0 && *s < 33)
    s++;

  if(*s != '}') {

    while(1) {
      name = json_parse_string(s, &s2, failp, failmsg);
      if(name == NOT_THIS_TYPE) {
	*failmsg = "Expected string";
	*failp = s;
	return NULL;
      }

      if(name == NULL)
	return NULL;

      s = s2;
    
      while(*s > 0 && *s < 33)
	s++;

      if(*s != ':') {
	jd->jd_destroy_obj(opaque, r);
	free(name);
	*failmsg = "Expected ':'";
	*failp = s;
	return NULL;
      }
      s++;

      s2 = json_parse_value(s, r, name, jd, opaque, failp, failmsg);
      free(name);

      if(s2 == NULL) {
	jd->jd_destroy_obj(opaque, r);
	return NULL;
      }

      s = s2;

      while(*s > 0 && *s < 33)
	s++;

      if(*s == '}')
	break;

      if(*s != ',') {
	jd->jd_destroy_obj(opaque, r);
	*failmsg = "Expected ','";
	*failp = s;
	return NULL;
      }
      s++;
    }
  }

  s++;
  *endp = s;
  return r;
}
Example #28
0
struct json_value_s *json_parse_ex(const void *src, size_t src_size,
                                   size_t flags_bitset,
                                   struct json_parse_result_s *result) {
  struct json_parse_state_s state;
  void *allocation;

  if (result) {
    result->error = json_parse_error_none;
    result->error_offset = 0;
    result->error_line_no = 0;
    result->error_row_no = 0;
  }

  if (0 == src) {
    // invalid src pointer was null!
    return 0;
  } else if (!(json_parse_flags_allow_global_object & flags_bitset) && src_size < 2) {
    // absolute minimum valid json is either "{}" or "[]"
    return 0;
  }

  state.src = src;
  state.size = src_size;
  state.offset = 0;
  state.line_no = 1;
  state.line_offset = 0;
  state.error = json_parse_error_none;
  state.dom_size = 0;
  state.data_size = 0;
  state.flags_bitset = flags_bitset;

  if (json_get_value_size(
          &state, /* is_global_object = */ (
              json_parse_flags_allow_global_object & state.flags_bitset))) {
    // parsing value's size failed (most likely an invalid JSON DOM!)
    if (result) {
      result->error = state.error;
      result->error_offset = state.offset;
      result->error_line_no = state.line_no;
      result->error_row_no = state.offset - state.line_offset;
    }
    return 0;
  }

  // our total allocation is the combination of the dom and data sizes (we
  // first encode the structure of the JSON, and then the data referenced by
  // the JSON values)
  allocation = malloc(state.dom_size + state.data_size);

  if (0 == allocation) {
    // malloc failed!
    return 0;
  }

  // reset offset so we can reuse it
  state.offset = 0;

  state.dom = allocation;
  state.data = state.dom + state.dom_size;

  state.dom += sizeof(struct json_value_s);

  json_parse_value(
          &state, /* is_global_object = */ (
              json_parse_flags_allow_global_object & state.flags_bitset),
          (struct json_value_s *)allocation);

  return allocation;
}
Example #29
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;
}