示例#1
0
文件: json.c 项目: hilesaz/drivle
struct json_val *json_parse_value(struct read_state *state)
{
    struct json_val *value;
    char ch;
    
    if (read_state_left(state) < 1) {
        json_error_print(state, "Unexpected end of file parsing generic value\n");
        return 0;
    }
    ch = *state->read;
    
    switch (ch) {
        case 't':
            value = json_parse_true(state);
            break;
        case 'f':
            value = json_parse_false(state);
            break;
        case 'n':
            value = json_parse_null(state);
            break;
        case '\"':
            value = json_parse_string(state);
            break;
        case '{':
            value = json_parse_object(state);
            break;
        case '[':
            value = json_parse_array(state);
            break;
        default:
            value = json_parse_number(state);
    }
    return value;
}
示例#2
0
文件: json.c 项目: pombredanne/spiz
int
json_generic_from_json(void *object, const ssr_t *buffer,
		       const json_t *table, size_t table_items)
{
    const char *s = buffer->data;
    size_t      n = buffer->size;

    while (n) {
	switch (*s) {
	case ' ':
	    break;
	case '\n':
	    break;
	case '\r':
	    break;
	case '{':
	    return (json_parse_object(&s, &n, "ROOT", 0,
				      object, table, table_items));
	    break;
	default:
	    WARN("Uknown character(%c)(%hhu) while searching "
		 "for start of JSON input\n",
		 isprint(*s)?*s:' ', *s);
	    return (-1);
	    break;

	}
	s++; n--;
    }
    return (-1);
}
示例#3
0
文件: wbt_json.c 项目: fcten/BitMQ
int json_parser( json_task_t *task ) {
    char ch;

    task->err_msg = "OK";
    task->count = 0;
    task->status = STS_START;
    task->root = NULL;
    
    if( task->str == NULL || task->len <= 0 ) {
        task->err_msg = "the input string is not specified";
        return -1;
    }
    
    while( task->count < task->len ) {
        ch = *(task->str + task->count);
        task->count ++;
        
        if( ch == ' ' || ch == '\n' || ch == '\t' ) {
            continue;
        }

        switch( task->status ) {
            case STS_START:
                if( ch == '{' ) {
                    if( json_parse_object( task, task->root ) != 0 ) {
                        return -1;
                    }
                    task->status = STS_END;
                } else if( ch == '[' ) {
                    if( json_parse_array( task, task->root ) != 0 ) {
                        return -1;
                    }
                    task->status = STS_END;
                } else {
                    task->err_msg = "expect '{' or '['";
                    return -1;
                }
                break;
            case STS_END:
                if( task->count >= task->len ) {
                    return 0;
                } else {
                    task->err_msg = "expect EOF";
                    return -1;
                }
                break;
            default:
                task->err_msg = "unknown status";
                return -1;
        }
    }
    
    if( task->status == STS_END ) {
        return 0;
    } else {
        return -1;
    }
}
示例#4
0
/******************************************************************************
 *                                                                            *
 * Function: json_parse_value                                                 *
 *                                                                            *
 * Purpose: Parses JSON object value                                          *
 *                                                                            *
 * 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                                                       *
 *                                                                            *
 ******************************************************************************/
int	json_parse_value(const char *start, char **error)
{
	const char	*ptr = start;
	int		len;

	SKIP_WHITESPACE(ptr);

	switch (*ptr)
	{
		case '\0':
			return json_error("unexpected end of object value", NULL, error);
		case '"':
			if (0 == (len = json_parse_string(ptr, error)))
				return 0;
			break;
		case '{':
			if (0 == (len = json_parse_object(ptr, error)))
				return 0;
			break;
		case '[':
			if (0 == (len = json_parse_array(ptr, error)))
				return 0;
			break;
		case 't':
			if (0 == (len = json_parse_literal(ptr, "true", error)))
				return 0;
			break;
		case 'f':
			if (0 == (len = json_parse_literal(ptr, "false", error)))
				return 0;
			break;
		case 'n':
			if (0 == (len = json_parse_literal(ptr, "null", error)))
				return 0;
			break;
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '-':
			if (0 == (len = json_parse_number(ptr, error)))
				return 0;
			break;
		default:
			return json_error("invalid JSON object value starting character", ptr, error);
	}

	return ptr - start + len;
}
示例#5
0
文件: json.c 项目: wschnrid/yaz
static struct json_node *json_parse_value(json_parser_t p)
{
    int c = look_ch(p);
    if (c == '\"')
        return json_parse_string(p);
    else if (strchr("0123456789-", c))
        return json_parse_number(p);
    else if (c == '{')
        return json_parse_object(p);
    else if (c == '[')
        return json_parse_array(p);
    else if (c == '%')
    {
        struct json_subst_info *sb;
        int idx = 0;
        p->cp++;
        c = *p->cp;
        while (c >= '0' && c <= '9')
        {
            idx = idx*10 + (c - '0');
            p->cp++;
            c = *p->cp;
        }
        for (sb = p->subst; sb; sb = sb->next)
            if (sb->idx == idx)
                return sb->node;
    }
    else if (c == 0)
    {
        return 0;
    }
    else
    {
        char tok[8];
        int i = 0;
        while (c >= 'a' && c <= 'z' && i < 7)
        {
            tok[i++] = c;
            p->cp++;
            c = *p->cp;
        }
        tok[i] = 0;
        if (!strcmp(tok, "true"))
            return json_new_node(p, json_node_true);
        else if (!strcmp(tok, "false"))
            return json_new_node(p, json_node_false);
        else if (!strcmp(tok, "null"))
            return json_new_node(p, json_node_null);
    }
    p->err_msg = "bad token";
    return 0;
}
示例#6
0
/******************************************************************************
 *                                                                            *
 * Function: zbx_json_validate                                                *
 *                                                                            *
 * Purpose: Validates JSON object                                             *
 *                                                                            *
 * Parameters: start - [IN]  the string to validate                           *
 *             error - [OUT] the parse error message. If the error value is   *
 *                           set it must be freed by caller after it has      *
 *                           been used (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                                                       *
 *                                                                            *
 ******************************************************************************/
int	zbx_json_validate(const char *start, char **error)
{
	int	len;

	if (0 == (len = json_parse_object(start, error)))
		return 0;

	start += len;
	SKIP_WHITESPACE(start);

	if ('\0' != *start)
		return json_error("invalid character following JSON object", start, error);

	return len;
}
示例#7
0
文件: test.c 项目: gansidui/minijson
void test(const char *text, const char *key) {
	char *value = 0, temp[100] = {0};
	int value_len = 0;
	json_type_t type = 0;

	json_parse_object(text, key, &value, &value_len, &type);

	if (type != json_type_error) {
		memcpy(temp, value, value_len);
		if (type == json_type_string) {
			printf("key[%s]  value[%s]  type[%d]\n", key, temp, type);
		}
		else if (type == json_type_number) {
			printf("key[%s]  value[%d]  type[%d]\n", key, atoi(temp), type);
		}
	}
	else {
		printf("key[%s]  ep[%s]  type[%d]\n", key, json_get_ep(), type);
	}
}
示例#8
0
文件: json.c 项目: wernsey/rengine
static JSON *json_parse_value(struct lexer *lx) {
	if(lx_sym(lx) == '{')
		return json_parse_object(lx);	
	else if(lx_sym(lx) == '[')
		return json_parse_array(lx);
	else {
		JSON *v = malloc(sizeof *v);
		v->type = j_null;
		v->value = NULL;
		v->next = NULL;
		if(lx_sym(lx) == LX_NUMBER || lx_sym(lx) == '-') {
			v->type = j_number;
			if(lx_sym(lx) == '-') {
				lx_getsym(lx);
				char *val = malloc(strlen(lx_text(lx)) + 2);
				sprintf(val, "-%s", lx_text(lx));
				v->value = val;
			} else
				v->value = strdup(lx_text(lx));
		} else if(lx_sym(lx) == LX_STRING) {
			v->type = j_string;
			v->value = strdup(lx_text(lx));
		} else if(lx_sym(lx) == J_TRUE) {
			v->type = j_true;
		} else if(lx_sym(lx) == J_FALSE) {
			v->type = j_false;
		}else if(lx_sym(lx) == J_NULL) {
			v->type = j_null;
		} else {
			if(isprint(lx_sym(lx))) {
				json_error("line %d: Unexpected operator: %c", lx_lineno(lx), lx_sym(lx));
			} else {
				json_error("line %d: Unexpected symbol type %d", lx_lineno(lx), lx_sym(lx));
			}
			return NULL;
		}
		lx_getsym(lx);	
		
		return v;
	}
}
示例#9
0
文件: wbt_json.c 项目: fcten/BitMQ
int json_parse_value( json_task_t *task, json_object_t *parent ) {
    char ch;
    while(( ch = *(task->str + task->count) )) {
        task->count ++;

        if( ch == '"' ) {
            parent->value_type = JSON_STRING;
            return json_parse_string( task );
        } else if( ch == '-' || ( ch >= '0' && ch <= '9' ) ) {
            task->count --;
            parent->value_type = JSON_LONGLONG;
            return json_parse_number( task, parent );
        } else if( ch == '{' ) {
            parent->value_type = JSON_OBJECT;
            return json_parse_object( task, parent );
        } else if( ch == '[' ) {
            parent->value_type = JSON_ARRAY;
            return json_parse_array( task, parent );
        } else if( ch == 't' ) {
            parent->value_type = JSON_TRUE;
            return json_parse_true( task );
        } else if( ch == 'f' ) {
            parent->value_type = JSON_FALSE;
            return json_parse_false( task );
        } else if( ch == 'n' ) {
            parent->value_type = JSON_NULL;
            return json_parse_null( task );
        } else {
            task->err_msg = "illegal value";
            return -1;
        }
    }

    task->err_msg = "unexpect EOF";
    return -1;
}
示例#10
0
文件: json.c 项目: Ludophonic/json.h
static void json_parse_value(struct json_parse_state_s *state,
                            int is_global_object, struct json_value_s *value) {
  if (is_global_object) {
    value->type = json_type_object;
    value->payload = state->dom;
    state->dom += sizeof(struct json_object_s);
    json_parse_object(state, /* is_global_object = */ 1, value->payload);
  } else {
    (void)json_skip_all_skippables(state);

    switch (state->src[state->offset]) {
    case '"':
      value->type = json_type_string;
      value->payload = state->dom;
      state->dom += sizeof(struct json_string_s);
      json_parse_string(state, value->payload);
      break;
    case '{':
      value->type = json_type_object;
      value->payload = state->dom;
      state->dom += sizeof(struct json_object_s);
      json_parse_object(state, /* is_global_object = */ 0,
                               value->payload);
      break;
    case '[':
      value->type = json_type_array;
      value->payload = state->dom;
      state->dom += sizeof(struct json_array_s);
      json_parse_array(state, value->payload);
      break;
    case '+':
    case '-':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    case '.':
      value->type = json_type_number;
      value->payload = state->dom;
      state->dom += sizeof(struct json_number_s);
      json_parse_number(state, value->payload);
      break;
    default:
      if ((state->offset + 4) <= state->size &&
          't' == state->src[state->offset + 0] &&
          'r' == state->src[state->offset + 1] &&
          'u' == state->src[state->offset + 2] &&
          'e' == state->src[state->offset + 3]) {
        value->type = json_type_true;
        value->payload = 0;
        state->offset += 4;
      } else if ((state->offset + 5) <= state->size &&
                 'f' == state->src[state->offset + 0] &&
                 'a' == state->src[state->offset + 1] &&
                 'l' == state->src[state->offset + 2] &&
                 's' == state->src[state->offset + 3] &&
                 'e' == state->src[state->offset + 4]) {
        value->type = json_type_false;
        value->payload = 0;
        state->offset += 5;
      } else if ((state->offset + 4) <= state->size &&
                 'n' == state->src[state->offset + 0] &&
                 'u' == state->src[state->offset + 1] &&
                 'l' == state->src[state->offset + 2] &&
                 'l' == state->src[state->offset + 3]) {
        value->type = json_type_null;
        value->payload = 0;
        state->offset += 4;
      }
      break;
    }
  }
}
示例#11
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;
    }
}
示例#12
0
static int
json_parse(const unsigned char **ucp, const unsigned char *ue,
    size_t *st, size_t lvl)
{
	const unsigned char *uc;
	int rv = 0;
	int t;

	uc = json_skip_space(*ucp, ue);
	if (uc == ue)
		goto out;

	// Avoid recursion
	if (lvl > 20)
		return 0;
#if JSON_COUNT
	/* bail quickly if not counting */
	if (lvl > 1 && (st[JSON_OBJECT] || st[JSON_ARRAY]))
		return 1;
#endif

	DPRINTF("Parse general: ", uc, *ucp);
	switch (*uc++) {
	case '"':
		rv = json_parse_string(&uc, ue);
		t = JSON_STRING;
		break;
	case '[':
		rv = json_parse_array(&uc, ue, st, lvl + 1);
		t = JSON_ARRAY;
		break;
	case '{': /* '}' */
		rv = json_parse_object(&uc, ue, st, lvl + 1);
		t = JSON_OBJECT;
		break;
	case 't':
		rv = json_parse_const(&uc, ue, "true", sizeof("true"));
		t = JSON_CONSTANT;
		break;
	case 'f':
		rv = json_parse_const(&uc, ue, "false", sizeof("false"));
		t = JSON_CONSTANT;
		break;
	case 'n':
		rv = json_parse_const(&uc, ue, "null", sizeof("null"));
		t = JSON_CONSTANT;
		break;
	default:
		--uc;
		rv = json_parse_number(&uc, ue);
		t = JSON_NUMBER;
		break;
	}
	if (rv)
		st[t]++;
	uc = json_skip_space(uc, ue);
out:
	*ucp = uc;
	DPRINTF("End general: ", uc, *ucp);
	if (lvl == 0)
		return rv && (st[JSON_ARRAY] || st[JSON_OBJECT]);
	return rv;
}
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;
    }
}
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_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;
}
示例#16
0
文件: json.c 项目: wernsey/rengine
JSON *json_parse(const char *text) {
	struct lexer * lx = lx_create(text, "{}[]-:,", json_keywds);
	JSON *v = json_parse_object(lx);
	lx_free(lx);
	return v;
}
示例#17
0
文件: json.c 项目: brenns10/nosj
/**
   @brief Parse an array.
   @param text The text we're parsing.
   @param arr The token buffer.
   @param maxtoken The length of the token buffer.
   @param p The parser state.
   @returns Parser state after parsing the array.
 */
static struct json_parser json_parse_array(wchar_t *text, struct json_token *arr,
                                           size_t maxtoken, struct json_parser p)
{
  size_t array_tokenidx = p.tokenidx, prev_tokenidx, curr_tokenidx, length=0;
  struct json_token tok = {
    .type = JSON_ARRAY,
    .start = p.textidx,
    .length = 0,
    .end = 0,
    .child = 0,
    .next = 0,
  };
  json_settoken(arr, tok, p, maxtoken);

  // current char is [, so we need to go past it.
  p.textidx++;
  p.tokenidx++;

  // Skip through whitespace.
  p = json_skip_whitespace(text, p);
  while (text[p.textidx] != L']') {

    if (text[p.textidx] == L'\0') {
      p.error = JSONERR_PREMATURE_EOF;
      return p;
    }
    // Parse a value.
    prev_tokenidx = curr_tokenidx;
    curr_tokenidx = p.tokenidx;
    p = json_parse_rec(text, arr, maxtoken, p);
    if (p.error != JSONERR_NO_ERROR) {
      return p;
    }

    // Now set some bookkeeping of previous values.
    if (tok.child == 0) {
      // If this is the first element of the list, set the list's child to point
      // to it.
      tok.child = curr_tokenidx;
      json_setchild(arr, array_tokenidx, curr_tokenidx, maxtoken);
    } else {
      // Otherwise set the previous element's next pointer to point to it.
      json_setnext(arr, prev_tokenidx, curr_tokenidx, maxtoken);
    }

    length++;

    // Skip whitespace.
    p = json_skip_whitespace(text, p);
    if (text[p.textidx] == L',') {
      p.textidx++;
      p = json_skip_whitespace(text, p);
    } else if (text[p.textidx] != L']') {
      // If there was no comma, this better be the end of the object.
      p.error = JSONERR_EXPECTED_TOKEN;
      p.errorarg = L',';
      return p;
    }
  }

  // Set the end of the array token to point to the closing bracket, then move
  // it up.
  json_setend(arr, array_tokenidx, p.textidx, maxtoken);
  json_setlength(arr, array_tokenidx, length, maxtoken);
  p.textidx++;
  return p;
}

/**
   @brief Parse an object.
   @param text The text we're parsing.
   @param arr The token buffer.
   @param maxtoken The length of the token buffer.
   @param p The parser state.
   @returns Parser state after parsing the object.
 */
static struct json_parser json_parse_object(wchar_t *text, struct json_token *arr,
                                            size_t maxtoken, struct json_parser p)
{
  size_t object_tokenidx = p.tokenidx, prev_keyidx, curr_keyidx, length=0;
  struct json_token tok = {
    .type  = JSON_OBJECT,
    .start = p.textidx,
    .length = 0,
    .end   = 0,
    .child = 0,
    .next  = 0,
  };
  json_settoken(arr, tok, p, maxtoken);

  // current char is {, so we need to go past it.
  p.textidx++;
  p.tokenidx++;

  // Skip through whitespace.
  p = json_skip_whitespace(text, p);
  while (text[p.textidx] != L'}') {
    // Make sure the string didn't end.
    if (text[p.textidx] == L'\0') {
      p.error = JSONERR_PREMATURE_EOF;
      return p;
    }

    // Parse a string (key) and value.
    prev_keyidx = curr_keyidx;
    curr_keyidx = p.tokenidx;
    p = json_parse_string(text, arr, maxtoken, p);
    if (p.error != JSONERR_NO_ERROR) {
      return p;
    }
    p = json_skip_whitespace(text, p);
    if (text[p.textidx] != L':') {
      p.error = JSONERR_EXPECTED_TOKEN;
      p.errorarg = L':';
      return p;
    }
    p.textidx++;
    p = json_parse_rec(text, arr, maxtoken, p);
    if (p.error != JSONERR_NO_ERROR) {
      return p;
    }

    // Now set some bookkeeping of previous values.
    if (tok.child == 0) {
      // If this is the first element of the list, set the list's child to point
      // to it.
      tok.child = curr_keyidx;
      json_setchild(arr, object_tokenidx, curr_keyidx, maxtoken);
    } else {
      // Otherwise set the previous element's next pointer to point to it.
      json_setnext(arr, prev_keyidx, curr_keyidx, maxtoken);
    }
    // Set the key's child pointer to point at its value.  Just cause we can.
    json_setchild(arr, curr_keyidx, curr_keyidx + 1, maxtoken);

    length++;

    // Skip whitespace.
    p = json_skip_whitespace(text, p);
    if (text[p.textidx] == L',') {
      p.textidx++;
      p = json_skip_whitespace(text, p);
    } else if (text[p.textidx] != L'}') {
      // If there was no comma, this better be the end of the object.
      p.error = JSONERR_EXPECTED_TOKEN;
      p.errorarg = L',';
      return p;
    }
  }

  // Set the end of the array token to point to the closing bracket, then move
  // it up.
  json_setend(arr, object_tokenidx, p.textidx, maxtoken);
  json_setlength(arr, object_tokenidx, length, maxtoken);
  p.textidx++;
  return p;
}

char *parse_number_state[] = {
  "START", "MINUS", "ZERO", "DIGIT", "DECIMAL", "DECIMAL_ACCEPT", "EXPONENT",
  "EXPONENT_DIGIT", "EXPONENT_DIGIT_ACCEPT", "END"
};

/**
   @brief Parse a string number.
   @param text The text we're parsing.
   @param arr The token buffer.
   @param maxtoken The length of the token buffer.
   @param p The parser state.
   @returns Parser state after parsing the number.
 */
static struct json_parser json_parse_number(wchar_t *text, struct json_token *arr,
                                            size_t maxtoken, struct json_parser p)
{
  struct json_token tok = {
    .type  = JSON_NUMBER,
    .start = p.textidx,
    .length = 0, // not used
    .end   = 0,
    .child = 0,
    .next  = 0
  };
  enum state {
    START, MINUS, ZERO, DIGIT, DECIMAL, DECIMAL_ACCEPT, EXPONENT,
    EXPONENT_DIGIT, EXPONENT_DIGIT_ACCEPT, END
  } state = START;

  /*
    This function is completely described by this FSM.  States marked by
    asterisk are accepting.  Unexpected input at accepting states ends the
    number, and unexpected input at rejecting states causes an error.  This
    state machine is designed to accept any input given by the diagram in the
    ECMA JSON spec.

                         -----START-----
                        /       | (-)   \
                       /        v        \
                   (0) | +----MINUS----+ | (1-9)
                       v v (0)   (1-9) v v
                    *ZERO*            *DIGIT*--------
                     |  \ (.)       (.) / |-\ (0-9)  \
                     |   --->DECIMAL<---              \
                     |          |                      \
                     |          v (0-9)  /----\ (0-9)  |
                     |   *DECIMAL_ACCEPT* ----/        |
                     |          |                     /
                     |(e,E)     v (e,E)   (e,E)      /
                     +-----> EXPONENT <-------------
                           /        \
                      (+,-)v        v (0-9)
              EXPONENT_DIGIT        *EXPONENT_DIGIT_ACCEPT*
                          \-----------/         \    /(0-9)
                                 (0-9)           \--/
   */

  //printf("input: %s\n", text + p.textidx);
  while (state != END) {
    wchar_t c = text[p.textidx];
    //printf("state: %s\n", parse_number_state[state]);
    switch (state) {
    case START:
      if (c == L'0') {
        state = ZERO;
      } else if (c == L'-') {
        state = MINUS;
      } else if (L'1' <= c && c <= L'9') {
        state = DIGIT;
      } else {
        p.error = JSONERR_INVALID_NUMBER;
        state = END; // ERROR
      }
      break;
    case MINUS:
      if (c == L'0') {
        state = ZERO;
      } else if (L'1' <= c && c <= L'9') {
        state = DIGIT;
      } else {
        p.error = JSONERR_INVALID_NUMBER;
        state = END; // ERROR
      }
      break;
    case ZERO:
      if (c == L'.') {
        state = DECIMAL;
      } else if (c == L'e' || c == L'E') {
        state = EXPONENT;
      } else {
        state = END;
      }
      break;
    case DIGIT:
      if (c == L'.') {
        state = DECIMAL;
      } else if (c == L'e' || c == L'E') {
        state = EXPONENT;
      } else if (L'0' <= c && c <= L'9') {
        state = DIGIT;
      } else {
        state = END;
      }
      break;
    case DECIMAL:
      if (L'0' <= c && c <= L'9') {
        state = DECIMAL_ACCEPT;
      } else {
        p.error = JSONERR_INVALID_NUMBER;
        state = END; // ERROR
      }
      break;
    case DECIMAL_ACCEPT:
      if (L'0' <= c && c <= L'9') {
        state = DECIMAL_ACCEPT;
      } else if (c == L'e' || c == L'E') {
        state = EXPONENT;
      } else {
        state = END;
      }
      break;
    case EXPONENT:
      if (c == L'+' || c == L'-') {
        state = EXPONENT_DIGIT;
      } else if (L'0' <= c && c <= L'9') {
        state = EXPONENT_DIGIT_ACCEPT;
      } else {
        p.error = JSONERR_INVALID_NUMBER;
        state = END; // ERROR
      }
      break;
    case EXPONENT_DIGIT:
      if (L'0' <= c && c <= L'9') {
        state = EXPONENT_DIGIT_ACCEPT;
      } else {
        p.error = JSONERR_INVALID_NUMBER;
        state = END; // ERROR
      }
      break;
    case EXPONENT_DIGIT_ACCEPT:
      if (L'0' <= c && c <= L'9') {
        state = EXPONENT_DIGIT_ACCEPT;
      } else {
        state = END;
      }
      break;
    case END:
      // never happens
      assert(false);
    }
    p.textidx++;
  }

  p.textidx--; // the character we failed on
  tok.end = p.textidx - 1; // the previous character
  json_settoken(arr, tok, p, maxtoken);
  p.tokenidx++;
  return p;
}

/**
   @brief Parse any JSON value.
   @param text The text we're parsing.
   @param arr The token buffer.
   @param maxtoken The length of the token buffer.
   @param p The parser state.
   @returns Parser state after parsing the value.
 */
static struct json_parser json_parse_rec(wchar_t *text, struct json_token *arr,
                                         size_t maxtoken, struct json_parser p)
{
  p = json_skip_whitespace(text, p);

  if (text[p.textidx] == '\0') {
    p.error = JSONERR_PREMATURE_EOF;
    return p;
  }

  switch (text[p.textidx]) {
  case L'{':
    return json_parse_object(text, arr, maxtoken, p);
  case L'[':
    return json_parse_array(text, arr, maxtoken, p);
  case L'"':
    return json_parse_string(text, arr, maxtoken, p);
  case L't':
    return json_parse_true(text, arr, maxtoken, p);
  case L'f':
    return json_parse_false(text, arr, maxtoken, p);
  case L'n':
    return json_parse_null(text, arr, maxtoken, p);
  default:
    if (json_isnumber(text[p.textidx])) {
      return json_parse_number(text, arr, maxtoken, p);
    } else {
      p.error = JSONERR_UNEXPECTED_TOKEN;
      return p;
    }
  }
}

char *json_type_str[] = {
  "object",
  "array",
  "number",
  "string",
  "true",
  "false",
  "null"
};

char *json_error_str[] = {
  "no error",
  "encountered an invalid numeric literal",
  "string ended prematurely",
  "unexpected token",
  "invalid surrogate pair",
  "expected token '%c'",
};

struct json_parser json_parse(wchar_t *text, struct json_token *arr, size_t maxtoken)
{
  struct json_parser parser = {
    .textidx = 0,
    .tokenidx = 0,
    .error = JSONERR_NO_ERROR,
    .errorarg = 0
  };
  return json_parse_rec(text, arr, maxtoken, parser);
}

void json_print(struct json_token *arr, size_t n)
{
  size_t i;
  for (i = 0; i < n; i++) {
    printf("%03lu: %6s\t%04lu-%04lu,\tlength=%lu,\tchild=%lu,\tnext=%lu\n", i,
           json_type_str[arr[i].type], arr[i].start, arr[i].end, arr[i].length,
           arr[i].child, arr[i].next);
  }
}

void json_print_error(FILE *f, struct json_parser p)
{
  fprintf(f, "at character %lu: ", p.textidx);
  fprintf(f, json_error_str[p.error], p.errorarg);
  fprintf(f, "\n");
}
示例#18
0
文件: json.c 项目: pombredanne/spiz
static int
json_parse_object (const char **s, size_t *n, const char *objname,
		   size_t objsize, void *obj, const json_t *table,
		   size_t table_items)
{
    ssr_t        value;
    int          rc;
    const json_t *element;
    uint64_t     int_value;

    element = NULL;
    if (**s != '{') {
	WARN("Expected '{' at start of object parsing\n"
	     "Current position: %.*s\n",
	     (int)*n, *s);
	return (-1);
    }

    element = NULL;
    value.size = 0;
    value.data = NULL;
    (*s)++; (*n)--;
    while (*n) {
	if (**s ==  '"') {
	    rc = json_parse_string(s, n, &value);
	    if (rc == -1) {
		WARN("Value name for object %s failed at: %.*s\n",
		     objname, (int)*n, *s);
	    }
	    if (element) {
		rc = json_set_value(obj, element, &value);
		if (rc == -1) {return (-1);}
		element = NULL;
	    } else {
		element = json_find_element(&value, table, table_items);
		if (!element) {
		    WARN("Could not find element '%.*s' in object '%s'\n",
			 (int)value.size, value.data, objname);
		    return (-1);
		}
	    }
	} else if (**s == '{') {
	    if (element && element->type == JSON_ELEMENT_STRUCT_POINTER) {
		rc = json_parse_object(s, n, element->name, element->size,
				       *(void**)ELEMENTAT(obj, element->offset),
				       element->json, element->json_size);
		if (rc == -1) {
		    return (-1);
		}
	    } else if (element &&
		       element->type == JSON_ELEMENT_STRUCT_EMBEDDED) {
		rc = json_parse_object(s, n, element->name, element->size,
				       (void*)ELEMENTAT(obj, element->offset),
				       element->json, element->json_size);
		if (rc == -1) {
		    return (-1);
		}
	    } else {
		WARN("Unexpected '{' at %.*s\n",
		     (int)*n, *s);
		return (-1);
	    }
	} else if (**s == '}') {
	    return (0);
	} else if (**s >= '0' && **s <= '9') {
	    if (!element) {
		WARN("Unexpected digit at %.*s",
		     (int)*n, *s);
		return (-1);
	    }
	    json_parse_uint64(s, n, &int_value);
	    rc = json_set_int_value(obj, element, int_value);
	    if (rc == -1) {return (-1);}
	    element = NULL;
	}
	(*s)++; (*n)--;
    }
    return (0);
}
示例#19
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;
}
示例#20
0
文件: json.c 项目: Grouflon/json.h
static int json_parse_value(struct json_parse_state_s* state,
  struct json_value_s* value) {
  if (json_skip_whitespace(state)) {
    // consumed the whole buffer when we expected a value!
    return 1;
  }

  switch (state->src[state->offset]) {
  case '"':
    value->type = json_type_string;
    value->payload = state->dom;
    state->dom += sizeof(struct json_string_s);
    return json_parse_string(state, value->payload);
  case '{':
    value->type = json_type_object;
    value->payload = state->dom;
    state->dom += sizeof(struct json_object_s);
    return json_parse_object(state, value->payload);
  case '[':
    value->type = json_type_array;
    value->payload = state->dom;
    state->dom += sizeof(struct json_array_s);
    return json_parse_array(state, value->payload);
  case '-':
  case '0':
  case '1':
  case '2':
  case '3':
  case '4':
  case '5':
  case '6':
  case '7':
  case '8':
  case '9':
    value->type = json_type_number;
    value->payload = state->dom;
    state->dom += sizeof(struct json_number_s);
    return json_parse_number(state, value->payload);
  default:
    if ((state->offset + 4) < state->size &&
      't' == state->src[state->offset + 0] &&
      'r' == state->src[state->offset + 1] &&
      'u' == state->src[state->offset + 2] &&
      'e' == state->src[state->offset + 3]) {
      value->type = json_type_true;
      value->payload = 0;
      state->offset += 4;
      return 0;
    } else if ((state->offset + 5) < state->size &&
      'f' == state->src[state->offset + 0] &&
      'a' == state->src[state->offset + 1] &&
      'l' == state->src[state->offset + 2] &&
      's' == state->src[state->offset + 3] &&
      'e' == state->src[state->offset + 4]) {
      value->type = json_type_false;
      value->payload = 0;
      state->offset += 5;
      return 0;
    } else if ((state->offset + 4) < state->size &&
      'n' == state->src[state->offset + 0] &&
      'u' == state->src[state->offset + 1] &&
      'l' == state->src[state->offset + 2] &&
      'l' == state->src[state->offset + 3]) {
      value->type = json_type_null;
      value->payload = 0;
      state->offset += 4;
      return 0;
    }

    // invalid value!
    return 1;
  }
}
示例#21
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;
}