Blame json_tokener.c

Packit Service def718
/*
Packit Service def718
 * $Id: json_tokener.c,v 1.20 2006/07/25 03:24:50 mclark Exp $
Packit Service def718
 *
Packit Service def718
 * Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
Packit Service def718
 * Michael Clark <michael@metaparadigm.com>
Packit Service def718
 *
Packit Service def718
 * This library is free software; you can redistribute it and/or modify
Packit Service def718
 * it under the terms of the MIT license. See COPYING for details.
Packit Service def718
 *
Packit Service def718
 *
Packit Service def718
 * Copyright (c) 2008-2009 Yahoo! Inc.  All rights reserved.
Packit Service def718
 * The copyrights to the contents of this file are licensed under the MIT License
Packit Service def718
 * (http://www.opensource.org/licenses/mit-license.php)
Packit Service def718
 */
Packit Service def718
Packit Service def718
#include "config.h"
Packit Service def718
Packit Service def718
#include <math.h>
Packit Service def718
#include "math_compat.h"
Packit Service def718
#include <stdio.h>
Packit Service def718
#include <stdlib.h>
Packit Service def718
#include <stddef.h>
Packit Service def718
#include <ctype.h>
Packit Service def718
#include <string.h>
Packit Service def718
#include <limits.h>
Packit Service def718
Packit Service def718
#include "debug.h"
Packit Service def718
#include "printbuf.h"
Packit Service def718
#include "arraylist.h"
Packit Service def718
#include "json_inttypes.h"
Packit Service def718
#include "json_object.h"
Packit Service def718
#include "json_object_private.h"
Packit Service def718
#include "json_tokener.h"
Packit Service def718
#include "json_util.h"
Packit Service def718
#include "strdup_compat.h"
Packit Service def718
Packit Service def718
#ifdef HAVE_LOCALE_H
Packit Service def718
#include <locale.h>
Packit Service def718
#endif /* HAVE_LOCALE_H */
Packit Service def718
#ifdef HAVE_XLOCALE_H
Packit Service def718
#include <xlocale.h>
Packit Service def718
#endif
Packit Service def718
Packit Service def718
#define jt_hexdigit(x) (((x) <= '9') ? (x) - '0' : ((x) & 7) + 9)
Packit Service def718
Packit Service def718
#if !HAVE_STRNCASECMP && defined(_MSC_VER)
Packit Service def718
  /* MSC has the version as _strnicmp */
Packit Service def718
# define strncasecmp _strnicmp
Packit Service def718
#elif !HAVE_STRNCASECMP
Packit Service def718
# error You do not have strncasecmp on your system.
Packit Service def718
#endif /* HAVE_STRNCASECMP */
Packit Service def718
Packit Service def718
/* Use C99 NAN by default; if not available, nan("") should work too. */
Packit Service def718
#ifndef NAN
Packit Service def718
#define NAN nan("")
Packit Service def718
#endif /* !NAN */
Packit Service def718
Packit Service def718
static const char json_null_str[] = "null";
Packit Service def718
static const int json_null_str_len = sizeof(json_null_str) - 1;
Packit Service def718
static const char json_inf_str[] = "Infinity";
Packit Service def718
static const char json_inf_str_lower[] = "infinity";
Packit Service def718
static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1;
Packit Service def718
static const char json_nan_str[] = "NaN";
Packit Service def718
static const int json_nan_str_len = sizeof(json_nan_str) - 1;
Packit Service def718
static const char json_true_str[] = "true";
Packit Service def718
static const int json_true_str_len = sizeof(json_true_str) - 1;
Packit Service def718
static const char json_false_str[] = "false";
Packit Service def718
static const int json_false_str_len = sizeof(json_false_str) - 1;
Packit Service def718
Packit Service def718
static const char* json_tokener_errors[] = {
Packit Service def718
  "success",
Packit Service def718
  "continue",
Packit Service def718
  "nesting too deep",
Packit Service def718
  "unexpected end of data",
Packit Service def718
  "unexpected character",
Packit Service def718
  "null expected",
Packit Service def718
  "boolean expected",
Packit Service def718
  "number expected",
Packit Service def718
  "array value separator ',' expected",
Packit Service def718
  "quoted object property name expected",
Packit Service def718
  "object property name separator ':' expected",
Packit Service def718
  "object value separator ',' expected",
Packit Service def718
  "invalid string sequence",
Packit Service def718
  "expected comment",
Packit Service def718
  "buffer size overflow"
Packit Service def718
};
Packit Service def718
Packit Service def718
const char *json_tokener_error_desc(enum json_tokener_error jerr)
Packit Service def718
{
Packit Service def718
	int jerr_int = (int) jerr;
Packit Service def718
	if (jerr_int < 0 ||
Packit Service def718
	    jerr_int >= (int)(sizeof(json_tokener_errors) / sizeof(json_tokener_errors[0])))
Packit Service def718
		return "Unknown error, "
Packit Service def718
		       "invalid json_tokener_error value passed to json_tokener_error_desc()";
Packit Service def718
	return json_tokener_errors[jerr];
Packit Service def718
}
Packit Service def718
Packit Service def718
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok)
Packit Service def718
{
Packit Service def718
	return tok->err;
Packit Service def718
}
Packit Service def718
Packit Service def718
/* Stuff for decoding unicode sequences */
Packit Service def718
#define IS_HIGH_SURROGATE(uc) (((uc) & 0xFC00) == 0xD800)
Packit Service def718
#define IS_LOW_SURROGATE(uc)  (((uc) & 0xFC00) == 0xDC00)
Packit Service def718
#define DECODE_SURROGATE_PAIR(hi,lo) ((((hi) & 0x3FF) << 10) + ((lo) & 0x3FF) + 0x10000)
Packit Service def718
static unsigned char utf8_replacement_char[3] = { 0xEF, 0xBF, 0xBD };
Packit Service def718
Packit Service def718
struct json_tokener* json_tokener_new_ex(int depth)
Packit Service def718
{
Packit Service def718
  struct json_tokener *tok;
Packit Service def718
Packit Service def718
  tok = (struct json_tokener*)calloc(1, sizeof(struct json_tokener));
Packit Service def718
  if (!tok) return NULL;
Packit Service def718
  tok->stack = (struct json_tokener_srec *) calloc(depth,
Packit Service def718
						   sizeof(struct json_tokener_srec));
Packit Service def718
  if (!tok->stack) {
Packit Service def718
    free(tok);
Packit Service def718
    return NULL;
Packit Service def718
  }
Packit Service def718
  tok->pb = printbuf_new();
Packit Service def718
  tok->max_depth = depth;
Packit Service def718
  json_tokener_reset(tok);
Packit Service def718
  return tok;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_tokener* json_tokener_new(void)
Packit Service def718
{
Packit Service def718
  return json_tokener_new_ex(JSON_TOKENER_DEFAULT_DEPTH);
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_tokener_free(struct json_tokener *tok)
Packit Service def718
{
Packit Service def718
  json_tokener_reset(tok);
Packit Service def718
  if (tok->pb) printbuf_free(tok->pb);
Packit Service def718
  free(tok->stack);
Packit Service def718
  free(tok);
Packit Service def718
}
Packit Service def718
Packit Service def718
static void json_tokener_reset_level(struct json_tokener *tok, int depth)
Packit Service def718
{
Packit Service def718
  tok->stack[depth].state = json_tokener_state_eatws;
Packit Service def718
  tok->stack[depth].saved_state = json_tokener_state_start;
Packit Service def718
  json_object_put(tok->stack[depth].current);
Packit Service def718
  tok->stack[depth].current = NULL;
Packit Service def718
  free(tok->stack[depth].obj_field_name);
Packit Service def718
  tok->stack[depth].obj_field_name = NULL;
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_tokener_reset(struct json_tokener *tok)
Packit Service def718
{
Packit Service def718
  int i;
Packit Service def718
  if (!tok)
Packit Service def718
    return;
Packit Service def718
Packit Service def718
  for(i = tok->depth; i >= 0; i--)
Packit Service def718
    json_tokener_reset_level(tok, i);
Packit Service def718
  tok->depth = 0;
Packit Service def718
  tok->err = json_tokener_success;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_tokener_parse(const char *str)
Packit Service def718
{
Packit Service def718
    enum json_tokener_error jerr_ignored;
Packit Service def718
    struct json_object* obj;
Packit Service def718
    obj = json_tokener_parse_verbose(str, &jerr_ignored);
Packit Service def718
    return obj;
Packit Service def718
}
Packit Service def718
Packit Service def718
struct json_object* json_tokener_parse_verbose(const char *str,
Packit Service def718
					       enum json_tokener_error *error)
Packit Service def718
{
Packit Service def718
    struct json_tokener* tok;
Packit Service def718
    struct json_object* obj;
Packit Service def718
Packit Service def718
    tok = json_tokener_new();
Packit Service def718
    if (!tok)
Packit Service def718
      return NULL;
Packit Service def718
    obj = json_tokener_parse_ex(tok, str, -1);
Packit Service def718
    *error = tok->err;
Packit Service def718
    if(tok->err != json_tokener_success) {
Packit Service def718
		if (obj != NULL)
Packit Service def718
			json_object_put(obj);
Packit Service def718
        obj = NULL;
Packit Service def718
    }
Packit Service def718
Packit Service def718
    json_tokener_free(tok);
Packit Service def718
    return obj;
Packit Service def718
}
Packit Service def718
Packit Service def718
#define state  tok->stack[tok->depth].state
Packit Service def718
#define saved_state  tok->stack[tok->depth].saved_state
Packit Service def718
#define current tok->stack[tok->depth].current
Packit Service def718
#define obj_field_name tok->stack[tok->depth].obj_field_name
Packit Service def718
Packit Service def718
/* Optimization:
Packit Service def718
 * json_tokener_parse_ex() consumed a lot of CPU in its main loop,
Packit Service def718
 * iterating character-by character.  A large performance boost is
Packit Service def718
 * achieved by using tighter loops to locally handle units such as
Packit Service def718
 * comments and strings.  Loops that handle an entire token within
Packit Service def718
 * their scope also gather entire strings and pass them to
Packit Service def718
 * printbuf_memappend() in a single call, rather than calling
Packit Service def718
 * printbuf_memappend() one char at a time.
Packit Service def718
 *
Packit Service def718
 * PEEK_CHAR() and ADVANCE_CHAR() macros are used for code that is
Packit Service def718
 * common to both the main loop and the tighter loops.
Packit Service def718
 */
Packit Service def718
Packit Service def718
/* PEEK_CHAR(dest, tok) macro:
Packit Service def718
 *   Peeks at the current char and stores it in dest.
Packit Service def718
 *   Returns 1 on success, sets tok->err and returns 0 if no more chars.
Packit Service def718
 *   Implicit inputs:  str, len vars
Packit Service def718
 */
Packit Service def718
#define PEEK_CHAR(dest, tok)			\
Packit Service def718
  (((tok)->char_offset == len) ?		\
Packit Service def718
   (((tok)->depth == 0 &&			\
Packit Service def718
     state == json_tokener_state_eatws &&	\
Packit Service def718
     saved_state == json_tokener_state_finish	\
Packit Service def718
     ) ?					\
Packit Service def718
    (((tok)->err = json_tokener_success), 0)	\
Packit Service def718
    :						\
Packit Service def718
    (((tok)->err = json_tokener_continue), 0)	\
Packit Service def718
    ) :						\
Packit Service def718
   (((dest) = *str), 1)				\
Packit Service def718
   )
Packit Service def718
Packit Service def718
/* ADVANCE_CHAR() macro:
Packit Service def718
 *   Incrementes str & tok->char_offset.
Packit Service def718
 *   For convenience of existing conditionals, returns the old value of c (0 on eof)
Packit Service def718
 *   Implicit inputs:  c var
Packit Service def718
 */
Packit Service def718
#define ADVANCE_CHAR(str, tok) \
Packit Service def718
  ( ++(str), ((tok)->char_offset)++, c)
Packit Service def718
Packit Service def718
Packit Service def718
/* End optimization macro defs */
Packit Service def718
Packit Service def718
Packit Service def718
struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
Packit Service def718
					  const char *str, int len)
Packit Service def718
{
Packit Service def718
  struct json_object *obj = NULL;
Packit Service def718
  char c = '\1';
Packit Service def718
#ifdef HAVE_USELOCALE
Packit Service def718
  locale_t oldlocale = uselocale(NULL);
Packit Service def718
  locale_t newloc;
Packit Service def718
#elif defined(HAVE_SETLOCALE)
Packit Service def718
  char *oldlocale = NULL;
Packit Service def718
#endif
Packit Service def718
Packit Service def718
  tok->char_offset = 0;
Packit Service def718
  tok->err = json_tokener_success;
Packit Service def718
Packit Service def718
  /* this interface is presently not 64-bit clean due to the int len argument
Packit Service def718
     and the internal printbuf interface that takes 32-bit int len arguments
Packit Service def718
     so the function limits the maximum string size to INT32_MAX (2GB).
Packit Service def718
     If the function is called with len == -1 then strlen is called to check
Packit Service def718
     the string length is less than INT32_MAX (2GB) */
Packit Service def718
  if ((len < -1) || (len == -1 && strlen(str) > INT32_MAX)) {
Packit Service def718
    tok->err = json_tokener_error_size;
Packit Service def718
    return NULL;
Packit Service def718
  }
Packit Service def718
Packit Service def718
#ifdef HAVE_USELOCALE
Packit Service def718
  {
Packit Service def718
    locale_t duploc = duplocale(oldlocale);
Packit Service def718
    newloc = newlocale(LC_NUMERIC, "C", duploc);
Packit Service def718
    // XXX at least Debian 8.4 has a bug in newlocale where it doesn't
Packit Service def718
    //  change the decimal separator unless you set LC_TIME!
Packit Service def718
    if (newloc)
Packit Service def718
    {
Packit Service def718
      duploc = newloc; // original duploc has been freed by newlocale()
Packit Service def718
      newloc = newlocale(LC_TIME, "C", duploc);
Packit Service def718
    }
Packit Service def718
    if (newloc == NULL)
Packit Service def718
    {
Packit Service def718
      freelocale(duploc);
Packit Service def718
      return NULL;
Packit Service def718
    }
Packit Service def718
    uselocale(newloc);
Packit Service def718
  }
Packit Service def718
#elif defined(HAVE_SETLOCALE)
Packit Service def718
  {
Packit Service def718
    char *tmplocale;
Packit Service def718
    tmplocale = setlocale(LC_NUMERIC, NULL);
Packit Service def718
    if (tmplocale) oldlocale = strdup(tmplocale);
Packit Service def718
    setlocale(LC_NUMERIC, "C");
Packit Service def718
  }
Packit Service def718
#endif
Packit Service def718
Packit Service def718
  while (PEEK_CHAR(c, tok)) {
Packit Service def718
Packit Service def718
  redo_char:
Packit Service def718
    switch(state) {
Packit Service def718
Packit Service def718
    case json_tokener_state_eatws:
Packit Service def718
      /* Advance until we change state */
Packit Service def718
      while (isspace((int)c)) {
Packit Service def718
	if ((!ADVANCE_CHAR(str, tok)) || (!PEEK_CHAR(c, tok)))
Packit Service def718
	  goto out;
Packit Service def718
      }
Packit Service def718
      if(c == '/' && !(tok->flags & JSON_TOKENER_STRICT)) {
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
	state = json_tokener_state_comment_start;
Packit Service def718
      } else {
Packit Service def718
	state = saved_state;
Packit Service def718
	goto redo_char;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_start:
Packit Service def718
      switch(c) {
Packit Service def718
      case '{':
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
	saved_state = json_tokener_state_object_field_start;
Packit Service def718
	current = json_object_new_object();
Packit Service def718
	if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	break;
Packit Service def718
      case '[':
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
	saved_state = json_tokener_state_array;
Packit Service def718
	current = json_object_new_array();
Packit Service def718
	if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	break;
Packit Service def718
      case 'I':
Packit Service def718
      case 'i':
Packit Service def718
	state = json_tokener_state_inf;
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	tok->st_pos = 0;
Packit Service def718
	goto redo_char;
Packit Service def718
      case 'N':
Packit Service def718
      case 'n':
Packit Service def718
	state = json_tokener_state_null; // or NaN
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	tok->st_pos = 0;
Packit Service def718
	goto redo_char;
Packit Service def718
      case '\'':
Packit Service def718
        if (tok->flags & JSON_TOKENER_STRICT) {
Packit Service def718
            /* in STRICT mode only double-quote are allowed */
Packit Service def718
            tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
            goto out;
Packit Service def718
        }
Packit Service def718
	/* FALLTHRU */
Packit Service def718
      case '"':
Packit Service def718
	state = json_tokener_state_string;
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	tok->quote_char = c;
Packit Service def718
	break;
Packit Service def718
      case 'T':
Packit Service def718
      case 't':
Packit Service def718
      case 'F':
Packit Service def718
      case 'f':
Packit Service def718
	state = json_tokener_state_boolean;
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	tok->st_pos = 0;
Packit Service def718
	goto redo_char;
Packit Service def718
      case '0':
Packit Service def718
      case '1':
Packit Service def718
      case '2':
Packit Service def718
      case '3':
Packit Service def718
      case '4':
Packit Service def718
      case '5':
Packit Service def718
      case '6':
Packit Service def718
      case '7':
Packit Service def718
      case '8':
Packit Service def718
      case '9':
Packit Service def718
      case '-':
Packit Service def718
	state = json_tokener_state_number;
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	tok->is_double = 0;
Packit Service def718
	goto redo_char;
Packit Service def718
      default:
Packit Service def718
	tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_finish:
Packit Service def718
      if(tok->depth == 0) goto out;
Packit Service def718
      obj = json_object_get(current);
Packit Service def718
      json_tokener_reset_level(tok, tok->depth);
Packit Service def718
      tok->depth--;
Packit Service def718
      goto redo_char;
Packit Service def718
Packit Service def718
    case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */
Packit Service def718
      {
Packit Service def718
	/* If we were guaranteed to have len set, then we could (usually) handle
Packit Service def718
	 * the entire "Infinity" check in a single strncmp (strncasecmp), but
Packit Service def718
	 * since len might be -1 (i.e. "read until \0"), we need to check it
Packit Service def718
	 * a character at a time.
Packit Service def718
	 * Trying to handle it both ways would make this code considerably more
Packit Service def718
	 * complicated with likely little performance benefit.
Packit Service def718
	 */
Packit Service def718
	int is_negative = 0;
Packit Service def718
	const char *_json_inf_str = json_inf_str;
Packit Service def718
	if (!(tok->flags & JSON_TOKENER_STRICT))
Packit Service def718
		_json_inf_str = json_inf_str_lower;
Packit Service def718
Packit Service def718
	/* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */
Packit Service def718
	while (tok->st_pos < (int)json_inf_str_len)
Packit Service def718
	{
Packit Service def718
		char inf_char = *str;
Packit Service def718
		if (!(tok->flags & JSON_TOKENER_STRICT))
Packit Service def718
			inf_char = tolower((int)*str);
Packit Service def718
		if (inf_char != _json_inf_str[tok->st_pos])
Packit Service def718
		{
Packit Service def718
			tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
			goto out;
Packit Service def718
		}
Packit Service def718
		tok->st_pos++;
Packit Service def718
		(void)ADVANCE_CHAR(str, tok);
Packit Service def718
		if (!PEEK_CHAR(c, tok))
Packit Service def718
		{
Packit Service def718
			/* out of input chars, for now at least */
Packit Service def718
			goto out;
Packit Service def718
		}
Packit Service def718
	}
Packit Service def718
	/* We checked the full length of "Infinity", so create the object.
Packit Service def718
	 * When handling -Infinity, the number parsing code will have dropped
Packit Service def718
	 * the "-" into tok->pb for us, so check it now.
Packit Service def718
	 */
Packit Service def718
	if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-')
Packit Service def718
	{
Packit Service def718
		is_negative = 1;
Packit Service def718
	}
Packit Service def718
	current = json_object_new_double(is_negative
Packit Service def718
					 ? -INFINITY : INFINITY);
Packit Service def718
	if (current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	saved_state = json_tokener_state_finish;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
	goto redo_char;
Packit Service def718
	 
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
    case json_tokener_state_null: /* aka starts with 'n' */
Packit Service def718
      {
Packit Service def718
	int size;
Packit Service def718
	int size_nan;
Packit Service def718
	printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
	size = json_min(tok->st_pos+1, json_null_str_len);
Packit Service def718
	size_nan = json_min(tok->st_pos+1, json_nan_str_len);
Packit Service def718
	if((!(tok->flags & JSON_TOKENER_STRICT) &&
Packit Service def718
	  strncasecmp(json_null_str, tok->pb->buf, size) == 0)
Packit Service def718
	  || (strncmp(json_null_str, tok->pb->buf, size) == 0)
Packit Service def718
	  ) {
Packit Service def718
	  if (tok->st_pos == json_null_str_len) {
Packit Service def718
	    current = NULL;
Packit Service def718
	    saved_state = json_tokener_state_finish;
Packit Service def718
	    state = json_tokener_state_eatws;
Packit Service def718
	    goto redo_char;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
	else if ((!(tok->flags & JSON_TOKENER_STRICT) &&
Packit Service def718
	          strncasecmp(json_nan_str, tok->pb->buf, size_nan) == 0) ||
Packit Service def718
	         (strncmp(json_nan_str, tok->pb->buf, size_nan) == 0)
Packit Service def718
	        )
Packit Service def718
	{
Packit Service def718
		if (tok->st_pos == json_nan_str_len)
Packit Service def718
		{
Packit Service def718
			current = json_object_new_double(NAN);
Packit Service def718
			if (current == NULL)
Packit Service def718
			    goto out;
Packit Service def718
			saved_state = json_tokener_state_finish;
Packit Service def718
			state = json_tokener_state_eatws;
Packit Service def718
			goto redo_char;
Packit Service def718
		}
Packit Service def718
	} else {
Packit Service def718
	  tok->err = json_tokener_error_parse_null;
Packit Service def718
	  goto out;
Packit Service def718
	}
Packit Service def718
	tok->st_pos++;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_comment_start:
Packit Service def718
      if(c == '*') {
Packit Service def718
	state = json_tokener_state_comment;
Packit Service def718
      } else if(c == '/') {
Packit Service def718
	state = json_tokener_state_comment_eol;
Packit Service def718
      } else {
Packit Service def718
	tok->err = json_tokener_error_parse_comment;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_comment:
Packit Service def718
              {
Packit Service def718
          /* Advance until we change state */
Packit Service def718
          const char *case_start = str;
Packit Service def718
          while(c != '*') {
Packit Service def718
            if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
              printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
              goto out;
Packit Service def718
            }
Packit Service def718
          }
Packit Service def718
          printbuf_memappend_fast(tok->pb, case_start, 1+str-case_start);
Packit Service def718
          state = json_tokener_state_comment_end;
Packit Service def718
        }
Packit Service def718
            break;
Packit Service def718
Packit Service def718
    case json_tokener_state_comment_eol:
Packit Service def718
      {
Packit Service def718
	/* Advance until we change state */
Packit Service def718
	const char *case_start = str;
Packit Service def718
	while(c != '\n') {
Packit Service def718
	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
	printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_comment_end:
Packit Service def718
      printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
      if(c == '/') {
Packit Service def718
	MC_DEBUG("json_tokener_comment: %s\n", tok->pb->buf);
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else {
Packit Service def718
	state = json_tokener_state_comment;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_string:
Packit Service def718
      {
Packit Service def718
	/* Advance until we change state */
Packit Service def718
	const char *case_start = str;
Packit Service def718
	while(1) {
Packit Service def718
	  if(c == tok->quote_char) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    current = json_object_new_string_len(tok->pb->buf, tok->pb->bpos);
Packit Service def718
	    if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	    saved_state = json_tokener_state_finish;
Packit Service def718
	    state = json_tokener_state_eatws;
Packit Service def718
	    break;
Packit Service def718
	  } else if(c == '\\') {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    saved_state = json_tokener_state_string;
Packit Service def718
	    state = json_tokener_state_string_escape;
Packit Service def718
	    break;
Packit Service def718
	  }
Packit Service def718
	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_string_escape:
Packit Service def718
      switch(c) {
Packit Service def718
      case '"':
Packit Service def718
      case '\\':
Packit Service def718
      case '/':
Packit Service def718
	printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
	state = saved_state;
Packit Service def718
	break;
Packit Service def718
      case 'b':
Packit Service def718
      case 'n':
Packit Service def718
      case 'r':
Packit Service def718
      case 't':
Packit Service def718
      case 'f':
Packit Service def718
	if(c == 'b') printbuf_memappend_fast(tok->pb, "\b", 1);
Packit Service def718
	else if(c == 'n') printbuf_memappend_fast(tok->pb, "\n", 1);
Packit Service def718
	else if(c == 'r') printbuf_memappend_fast(tok->pb, "\r", 1);
Packit Service def718
	else if(c == 't') printbuf_memappend_fast(tok->pb, "\t", 1);
Packit Service def718
	else if(c == 'f') printbuf_memappend_fast(tok->pb, "\f", 1);
Packit Service def718
	state = saved_state;
Packit Service def718
	break;
Packit Service def718
      case 'u':
Packit Service def718
	tok->ucs_char = 0;
Packit Service def718
	tok->st_pos = 0;
Packit Service def718
	state = json_tokener_state_escape_unicode;
Packit Service def718
	break;
Packit Service def718
      default:
Packit Service def718
	tok->err = json_tokener_error_parse_string;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_escape_unicode:
Packit Service def718
	{
Packit Service def718
          unsigned int got_hi_surrogate = 0;
Packit Service def718
Packit Service def718
	  /* Handle a 4-byte sequence, or two sequences if a surrogate pair */
Packit Service def718
	  while(1) {
Packit Service def718
	    if (c && strchr(json_hex_chars, c)) {
Packit Service def718
	      tok->ucs_char += ((unsigned int)jt_hexdigit(c) << ((3-tok->st_pos++)*4));
Packit Service def718
	      if(tok->st_pos == 4) {
Packit Service def718
		unsigned char unescaped_utf[4];
Packit Service def718
Packit Service def718
                if (got_hi_surrogate) {
Packit Service def718
		  if (IS_LOW_SURROGATE(tok->ucs_char)) {
Packit Service def718
                    /* Recalculate the ucs_char, then fall thru to process normally */
Packit Service def718
                    tok->ucs_char = DECODE_SURROGATE_PAIR(got_hi_surrogate, tok->ucs_char);
Packit Service def718
                  } else {
Packit Service def718
                    /* Hi surrogate was not followed by a low surrogate */
Packit Service def718
                    /* Replace the hi and process the rest normally */
Packit Service def718
		    printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
Packit Service def718
                  }
Packit Service def718
                  got_hi_surrogate = 0;
Packit Service def718
                }
Packit Service def718
Packit Service def718
		if (tok->ucs_char < 0x80) {
Packit Service def718
		  unescaped_utf[0] = tok->ucs_char;
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 1);
Packit Service def718
		} else if (tok->ucs_char < 0x800) {
Packit Service def718
		  unescaped_utf[0] = 0xc0 | (tok->ucs_char >> 6);
Packit Service def718
		  unescaped_utf[1] = 0x80 | (tok->ucs_char & 0x3f);
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 2);
Packit Service def718
		} else if (IS_HIGH_SURROGATE(tok->ucs_char)) {
Packit Service def718
                  /* Got a high surrogate.  Remember it and look for the
Packit Service def718
                   * the beginning of another sequence, which should be the
Packit Service def718
                   * low surrogate.
Packit Service def718
                   */
Packit Service def718
                  got_hi_surrogate = tok->ucs_char;
Packit Service def718
                  /* Not at end, and the next two chars should be "\u" */
Packit Service def718
                  if ((len == -1 || len > (tok->char_offset + 2)) &&
Packit Service def718
                      // str[0] != '0' &&  // implied by json_hex_chars, above.
Packit Service def718
                      (str[1] == '\\') &&
Packit Service def718
                      (str[2] == 'u'))
Packit Service def718
                  {
Packit Service def718
                /* Advance through the 16 bit surrogate, and move on to the
Packit Service def718
                 * next sequence. The next step is to process the following
Packit Service def718
                 * characters.
Packit Service def718
                 */
Packit Service def718
	            if( !ADVANCE_CHAR(str, tok) || !ADVANCE_CHAR(str, tok) ) {
Packit Service def718
                    printbuf_memappend_fast(tok->pb,
Packit Service def718
					    (char*) utf8_replacement_char, 3);
Packit Service def718
		    }
Packit Service def718
                    /* Advance to the first char of the next sequence and
Packit Service def718
                     * continue processing with the next sequence.
Packit Service def718
                     */
Packit Service def718
	            if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
	              printbuf_memappend_fast(tok->pb,
Packit Service def718
					      (char*) utf8_replacement_char, 3);
Packit Service def718
	              goto out;
Packit Service def718
                    }
Packit Service def718
	            tok->ucs_char = 0;
Packit Service def718
                    tok->st_pos = 0;
Packit Service def718
                    continue; /* other json_tokener_state_escape_unicode */
Packit Service def718
                  } else {
Packit Service def718
                    /* Got a high surrogate without another sequence following
Packit Service def718
                     * it.  Put a replacement char in for the hi surrogate
Packit Service def718
                     * and pretend we finished.
Packit Service def718
                     */
Packit Service def718
		    printbuf_memappend_fast(tok->pb,
Packit Service def718
					    (char*) utf8_replacement_char, 3);
Packit Service def718
                  }
Packit Service def718
		} else if (IS_LOW_SURROGATE(tok->ucs_char)) {
Packit Service def718
                  /* Got a low surrogate not preceded by a high */
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
Packit Service def718
                } else if (tok->ucs_char < 0x10000) {
Packit Service def718
		  unescaped_utf[0] = 0xe0 | (tok->ucs_char >> 12);
Packit Service def718
		  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
Packit Service def718
		  unescaped_utf[2] = 0x80 | (tok->ucs_char & 0x3f);
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 3);
Packit Service def718
		} else if (tok->ucs_char < 0x110000) {
Packit Service def718
		  unescaped_utf[0] = 0xf0 | ((tok->ucs_char >> 18) & 0x07);
Packit Service def718
		  unescaped_utf[1] = 0x80 | ((tok->ucs_char >> 12) & 0x3f);
Packit Service def718
		  unescaped_utf[2] = 0x80 | ((tok->ucs_char >> 6) & 0x3f);
Packit Service def718
		  unescaped_utf[3] = 0x80 | (tok->ucs_char & 0x3f);
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)unescaped_utf, 4);
Packit Service def718
		} else {
Packit Service def718
                  /* Don't know what we got--insert the replacement char */
Packit Service def718
		  printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
Packit Service def718
                }
Packit Service def718
		state = saved_state;
Packit Service def718
		break;
Packit Service def718
	      }
Packit Service def718
	    } else {
Packit Service def718
	      tok->err = json_tokener_error_parse_string;
Packit Service def718
	      goto out;
Packit Service def718
	    }
Packit Service def718
	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
            if (got_hi_surrogate) /* Clean up any pending chars */
Packit Service def718
	      printbuf_memappend_fast(tok->pb, (char*)utf8_replacement_char, 3);
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_boolean:
Packit Service def718
      {
Packit Service def718
	int size1, size2;
Packit Service def718
	printbuf_memappend_fast(tok->pb, &c, 1);
Packit Service def718
	size1 = json_min(tok->st_pos+1, json_true_str_len);
Packit Service def718
	size2 = json_min(tok->st_pos+1, json_false_str_len);
Packit Service def718
	if((!(tok->flags & JSON_TOKENER_STRICT) &&
Packit Service def718
	  strncasecmp(json_true_str, tok->pb->buf, size1) == 0)
Packit Service def718
	  || (strncmp(json_true_str, tok->pb->buf, size1) == 0)
Packit Service def718
	  ) {
Packit Service def718
	  if(tok->st_pos == json_true_str_len) {
Packit Service def718
	    current = json_object_new_boolean(1);
Packit Service def718
	    if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	    saved_state = json_tokener_state_finish;
Packit Service def718
	    state = json_tokener_state_eatws;
Packit Service def718
	    goto redo_char;
Packit Service def718
	  }
Packit Service def718
	} else if((!(tok->flags & JSON_TOKENER_STRICT) &&
Packit Service def718
	  strncasecmp(json_false_str, tok->pb->buf, size2) == 0)
Packit Service def718
	  || (strncmp(json_false_str, tok->pb->buf, size2) == 0)) {
Packit Service def718
	  if(tok->st_pos == json_false_str_len) {
Packit Service def718
	    current = json_object_new_boolean(0);
Packit Service def718
	    if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
	    saved_state = json_tokener_state_finish;
Packit Service def718
	    state = json_tokener_state_eatws;
Packit Service def718
	    goto redo_char;
Packit Service def718
	  }
Packit Service def718
	} else {
Packit Service def718
	  tok->err = json_tokener_error_parse_boolean;
Packit Service def718
	  goto out;
Packit Service def718
	}
Packit Service def718
	tok->st_pos++;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_number:
Packit Service def718
      {
Packit Service def718
	/* Advance until we change state */
Packit Service def718
	const char *case_start = str;
Packit Service def718
	int case_len=0;
Packit Service def718
	int is_exponent=0;
Packit Service def718
	int negativesign_next_possible_location=1;
Packit Service def718
	while(c && strchr(json_number_chars, c)) {
Packit Service def718
	  ++case_len;
Packit Service def718
Packit Service def718
	  /* non-digit characters checks */
Packit Service def718
	  /* note: since the main loop condition to get here was
Packit Service def718
	           an input starting with 0-9 or '-', we are
Packit Service def718
	           protected from input starting with '.' or
Packit Service def718
	           e/E. */
Packit Service def718
	  if (c == '.') {
Packit Service def718
	    if (tok->is_double != 0) {
Packit Service def718
	      /* '.' can only be found once, and out of the exponent part.
Packit Service def718
	         Thus, if the input is already flagged as double, it
Packit Service def718
	         is invalid. */
Packit Service def718
	      tok->err = json_tokener_error_parse_number;
Packit Service def718
	      goto out;
Packit Service def718
	    }
Packit Service def718
	    tok->is_double = 1;
Packit Service def718
	  }
Packit Service def718
	  if (c == 'e' || c == 'E') {
Packit Service def718
	    if (is_exponent != 0) {
Packit Service def718
	      /* only one exponent possible */
Packit Service def718
	      tok->err = json_tokener_error_parse_number;
Packit Service def718
	      goto out;
Packit Service def718
	    }
Packit Service def718
	    is_exponent = 1;
Packit Service def718
	    tok->is_double = 1;
Packit Service def718
	    /* the exponent part can begin with a negative sign */
Packit Service def718
	    negativesign_next_possible_location = case_len + 1;
Packit Service def718
	  }
Packit Service def718
	  if (c == '-' && case_len != negativesign_next_possible_location) {
Packit Service def718
	    /* If the negative sign is not where expected (ie
Packit Service def718
	       start of input or start of exponent part), the
Packit Service def718
	       input is invalid. */
Packit Service def718
	    tok->err = json_tokener_error_parse_number;
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
Packit Service def718
	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, case_len);
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
        if (case_len>0)
Packit Service def718
          printbuf_memappend_fast(tok->pb, case_start, case_len);
Packit Service def718
Packit Service def718
	// Check for -Infinity
Packit Service def718
	if (tok->pb->buf[0] == '-' && case_len <= 1 &&
Packit Service def718
	    (c == 'i' || c == 'I'))
Packit Service def718
	{
Packit Service def718
		state = json_tokener_state_inf;
Packit Service def718
		tok->st_pos = 0;
Packit Service def718
		goto redo_char;
Packit Service def718
	}
Packit Service def718
      }
Packit Service def718
      {
Packit Service def718
	int64_t num64;
Packit Service def718
	double  numd;
Packit Service def718
	if (!tok->is_double && json_parse_int64(tok->pb->buf, &num64) == 0) {
Packit Service def718
		if (num64 && tok->pb->buf[0]=='0' &&
Packit Service def718
		    (tok->flags & JSON_TOKENER_STRICT)) {
Packit Service def718
			/* in strict mode, number must not start with 0 */
Packit Service def718
			tok->err = json_tokener_error_parse_number;
Packit Service def718
			goto out;
Packit Service def718
		}
Packit Service def718
		current = json_object_new_int64(num64);
Packit Service def718
		if(current == NULL)
Packit Service def718
		    goto out;
Packit Service def718
	}
Packit Service def718
	else if(tok->is_double && json_parse_double(tok->pb->buf, &numd) == 0)
Packit Service def718
	{
Packit Service def718
          current = json_object_new_double_s(numd, tok->pb->buf);
Packit Service def718
	  if(current == NULL)
Packit Service def718
		goto out;
Packit Service def718
        } else {
Packit Service def718
          tok->err = json_tokener_error_parse_number;
Packit Service def718
          goto out;
Packit Service def718
        }
Packit Service def718
        saved_state = json_tokener_state_finish;
Packit Service def718
        state = json_tokener_state_eatws;
Packit Service def718
        goto redo_char;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_array_after_sep:
Packit Service def718
    case json_tokener_state_array:
Packit Service def718
      if(c == ']') {
Packit Service def718
	if (state == json_tokener_state_array_after_sep &&
Packit Service def718
	    (tok->flags & JSON_TOKENER_STRICT))
Packit Service def718
	  {
Packit Service def718
	    tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	saved_state = json_tokener_state_finish;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else {
Packit Service def718
	if(tok->depth >= tok->max_depth-1) {
Packit Service def718
	  tok->err = json_tokener_error_depth;
Packit Service def718
	  goto out;
Packit Service def718
	}
Packit Service def718
	state = json_tokener_state_array_add;
Packit Service def718
	tok->depth++;
Packit Service def718
	json_tokener_reset_level(tok, tok->depth);
Packit Service def718
	goto redo_char;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_array_add:
Packit Service def718
      if( json_object_array_add(current, obj) != 0 )
Packit Service def718
        goto out;
Packit Service def718
      saved_state = json_tokener_state_array_sep;
Packit Service def718
      state = json_tokener_state_eatws;
Packit Service def718
      goto redo_char;
Packit Service def718
Packit Service def718
    case json_tokener_state_array_sep:
Packit Service def718
      if(c == ']') {
Packit Service def718
	saved_state = json_tokener_state_finish;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else if(c == ',') {
Packit Service def718
	saved_state = json_tokener_state_array_after_sep;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else {
Packit Service def718
	tok->err = json_tokener_error_parse_array;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_field_start:
Packit Service def718
    case json_tokener_state_object_field_start_after_sep:
Packit Service def718
      if(c == '}') {
Packit Service def718
		if (state == json_tokener_state_object_field_start_after_sep &&
Packit Service def718
		    (tok->flags & JSON_TOKENER_STRICT))
Packit Service def718
		{
Packit Service def718
			tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
			goto out;
Packit Service def718
		}
Packit Service def718
	saved_state = json_tokener_state_finish;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else if (c == '"' || c == '\'') {
Packit Service def718
	tok->quote_char = c;
Packit Service def718
	printbuf_reset(tok->pb);
Packit Service def718
	state = json_tokener_state_object_field;
Packit Service def718
      } else {
Packit Service def718
	tok->err = json_tokener_error_parse_object_key_name;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_field:
Packit Service def718
      {
Packit Service def718
	/* Advance until we change state */
Packit Service def718
	const char *case_start = str;
Packit Service def718
	while(1) {
Packit Service def718
	  if(c == tok->quote_char) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    obj_field_name = strdup(tok->pb->buf);
Packit Service def718
	    saved_state = json_tokener_state_object_field_end;
Packit Service def718
	    state = json_tokener_state_eatws;
Packit Service def718
	    break;
Packit Service def718
	  } else if(c == '\\') {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    saved_state = json_tokener_state_object_field;
Packit Service def718
	    state = json_tokener_state_string_escape;
Packit Service def718
	    break;
Packit Service def718
	  }
Packit Service def718
	  if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) {
Packit Service def718
	    printbuf_memappend_fast(tok->pb, case_start, str-case_start);
Packit Service def718
	    goto out;
Packit Service def718
	  }
Packit Service def718
	}
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_field_end:
Packit Service def718
      if(c == ':') {
Packit Service def718
	saved_state = json_tokener_state_object_value;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else {
Packit Service def718
	tok->err = json_tokener_error_parse_object_key_sep;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_value:
Packit Service def718
      if(tok->depth >= tok->max_depth-1) {
Packit Service def718
	tok->err = json_tokener_error_depth;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      state = json_tokener_state_object_value_add;
Packit Service def718
      tok->depth++;
Packit Service def718
      json_tokener_reset_level(tok, tok->depth);
Packit Service def718
      goto redo_char;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_value_add:
Packit Service def718
      json_object_object_add(current, obj_field_name, obj);
Packit Service def718
      free(obj_field_name);
Packit Service def718
      obj_field_name = NULL;
Packit Service def718
      saved_state = json_tokener_state_object_sep;
Packit Service def718
      state = json_tokener_state_eatws;
Packit Service def718
      goto redo_char;
Packit Service def718
Packit Service def718
    case json_tokener_state_object_sep:
Packit Service def718
      /* { */
Packit Service def718
      if(c == '}') {
Packit Service def718
	saved_state = json_tokener_state_finish;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else if(c == ',') {
Packit Service def718
	saved_state = json_tokener_state_object_field_start_after_sep;
Packit Service def718
	state = json_tokener_state_eatws;
Packit Service def718
      } else {
Packit Service def718
	tok->err = json_tokener_error_parse_object_value_sep;
Packit Service def718
	goto out;
Packit Service def718
      }
Packit Service def718
      break;
Packit Service def718
Packit Service def718
    }
Packit Service def718
    if (!ADVANCE_CHAR(str, tok))
Packit Service def718
      goto out;
Packit Service def718
  } /* while(PEEK_CHAR) */
Packit Service def718
Packit Service def718
 out:
Packit Service def718
  if (c &&
Packit Service def718
     (state == json_tokener_state_finish) &&
Packit Service def718
     (tok->depth == 0) &&
Packit Service def718
     (tok->flags & JSON_TOKENER_STRICT)) {
Packit Service def718
      /* unexpected char after JSON data */
Packit Service def718
      tok->err = json_tokener_error_parse_unexpected;
Packit Service def718
  }
Packit Service def718
  if (!c) { /* We hit an eof char (0) */
Packit Service def718
    if(state != json_tokener_state_finish &&
Packit Service def718
       saved_state != json_tokener_state_finish)
Packit Service def718
      tok->err = json_tokener_error_parse_eof;
Packit Service def718
  }
Packit Service def718
Packit Service def718
#ifdef HAVE_USELOCALE
Packit Service def718
  uselocale(oldlocale);
Packit Service def718
  freelocale(newloc); 
Packit Service def718
#elif defined(HAVE_SETLOCALE)
Packit Service def718
  setlocale(LC_NUMERIC, oldlocale);
Packit Service def718
  free(oldlocale);
Packit Service def718
#endif
Packit Service def718
Packit Service def718
  if (tok->err == json_tokener_success)
Packit Service def718
  {
Packit Service def718
    json_object *ret = json_object_get(current);
Packit Service def718
	int ii;
Packit Service def718
Packit Service def718
	/* Partially reset, so we parse additional objects on subsequent calls. */
Packit Service def718
    for(ii = tok->depth; ii >= 0; ii--)
Packit Service def718
      json_tokener_reset_level(tok, ii);
Packit Service def718
    return ret;
Packit Service def718
  }
Packit Service def718
Packit Service def718
  MC_DEBUG("json_tokener_parse_ex: error %s at offset %d\n",
Packit Service def718
	   json_tokener_errors[tok->err], tok->char_offset);
Packit Service def718
  return NULL;
Packit Service def718
}
Packit Service def718
Packit Service def718
void json_tokener_set_flags(struct json_tokener *tok, int flags)
Packit Service def718
{
Packit Service def718
	tok->flags = flags;
Packit Service def718
}