/* Generated by re2c 0.13.5 on Sat Apr 20 16:07:45 2013 */
#line 1 "sjson.c"
/**
 * sjson - fast string based JSON parser/generator library
 * Copyright (C) 2013  Ondřej Jirman <megous@megous.com>
 *
 * WWW: https://github.com/megous/sjson
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <string.h>
#include <stdio.h>
#include "sjson.h"

enum
{
  TOK_NONE = 0, // no more tokens
  TOK_OBJ_START,
  TOK_OBJ_END,
  TOK_ARRAY_START,
  TOK_ARRAY_END,
  TOK_COLON,
  TOK_COMMA,
  TOK_STRING,
  TOK_NOESC_STRING,
  TOK_NUMBER,
  TOK_FALSE,
  TOK_TRUE,
  TOK_NULL,
  TOK_INVALID
};

#line 66 "sjson.c"


static gint s_json_get_token(const gchar* json, const gchar** start, const gchar** end)
{
  g_return_val_if_fail(json != NULL, FALSE);

  const guchar* c = (const guchar*)json;
  const guchar* m = NULL;
  const guchar* s;
  gint token;

  while (TRUE)
  {
    s = c;


#line 63 "sjson.gen.c"
	{
		guchar yych;
		unsigned int yyaccept = 0;

		yych = (guchar)*c;
		if (yych <= '9') {
			if (yych <= ' ') {
				if (yych <= '\n') {
					if (yych <= 0x00) goto yy25;
					if (yych <= 0x08) goto yy27;
				} else {
					if (yych == '\r') goto yy2;
					if (yych <= 0x1F) goto yy27;
				}
			} else {
				if (yych <= ',') {
					if (yych == '"') goto yy12;
					if (yych <= '+') goto yy27;
					goto yy16;
				} else {
					if (yych <= '-') goto yy18;
					if (yych <= '/') goto yy27;
					if (yych <= '0') goto yy19;
					goto yy21;
				}
			}
		} else {
			if (yych <= 'm') {
				if (yych <= '\\') {
					if (yych <= ':') goto yy14;
					if (yych == '[') goto yy8;
					goto yy27;
				} else {
					if (yych <= ']') goto yy10;
					if (yych == 'f') goto yy23;
					goto yy27;
				}
			} else {
				if (yych <= 'z') {
					if (yych <= 'n') goto yy24;
					if (yych == 't') goto yy22;
					goto yy27;
				} else {
					if (yych <= '{') goto yy4;
					if (yych == '}') goto yy6;
					goto yy27;
				}
			}
		}
yy2:
		++c;
		yych = (guchar)*c;
		goto yy66;
yy3:
#line 82 "sjson.c"
		{ 
      continue; 
    }
#line 122 "sjson.gen.c"
yy4:
		++c;
#line 86 "sjson.c"
		{
      token = TOK_OBJ_START;
      goto done;
    }
#line 130 "sjson.gen.c"
yy6:
		++c;
#line 91 "sjson.c"
		{
      token = TOK_OBJ_END;
      goto done;
    }
#line 138 "sjson.gen.c"
yy8:
		++c;
#line 96 "sjson.c"
		{
      token = TOK_ARRAY_START;
      goto done;
    }
#line 146 "sjson.gen.c"
yy10:
		++c;
#line 101 "sjson.c"
		{
      token = TOK_ARRAY_END;
      goto done;
    }
#line 154 "sjson.gen.c"
yy12:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych >= 0x01) goto yy53;
yy13:
#line 150 "sjson.c"
		{
      return TOK_INVALID;
    }
#line 164 "sjson.gen.c"
yy14:
		++c;
#line 116 "sjson.c"
		{
      token = TOK_COLON;
      goto done;
    }
#line 172 "sjson.gen.c"
yy16:
		++c;
#line 121 "sjson.c"
		{
      token = TOK_COMMA;
      goto done;
    }
#line 180 "sjson.gen.c"
yy18:
		yych = (guchar)*++c;
		if (yych <= '/') goto yy13;
		if (yych <= '0') goto yy51;
		if (yych <= '9') goto yy42;
		goto yy13;
yy19:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych <= 'D') {
			if (yych == '.') goto yy44;
		} else {
			if (yych <= 'E') goto yy45;
			if (yych == 'e') goto yy45;
		}
yy20:
#line 126 "sjson.c"
		{
      token = TOK_NUMBER;
      goto done;
    }
#line 202 "sjson.gen.c"
yy21:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		goto yy43;
yy22:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych == 'r') goto yy38;
		goto yy13;
yy23:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych == 'a') goto yy33;
		goto yy13;
yy24:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych == 'u') goto yy28;
		goto yy13;
yy25:
		++c;
#line 146 "sjson.c"
		{ 
      return TOK_NONE;
    }
#line 228 "sjson.gen.c"
yy27:
		yych = (guchar)*++c;
		goto yy13;
yy28:
		yych = (guchar)*++c;
		if (yych == 'l') goto yy30;
yy29:
		c = m;
		if (yyaccept <= 0) {
			goto yy13;
		} else {
			goto yy20;
		}
yy30:
		yych = (guchar)*++c;
		if (yych != 'l') goto yy29;
		++c;
#line 141 "sjson.c"
		{
      token = TOK_NULL;
      goto done;
    }
#line 251 "sjson.gen.c"
yy33:
		yych = (guchar)*++c;
		if (yych != 'l') goto yy29;
		yych = (guchar)*++c;
		if (yych != 's') goto yy29;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy29;
		++c;
#line 136 "sjson.c"
		{
      token = TOK_FALSE;
      goto done;
    }
#line 265 "sjson.gen.c"
yy38:
		yych = (guchar)*++c;
		if (yych != 'u') goto yy29;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy29;
		++c;
#line 131 "sjson.c"
		{
      token = TOK_TRUE;
      goto done;
    }
#line 277 "sjson.gen.c"
yy42:
		yyaccept = 1;
		m = ++c;
		yych = (guchar)*c;
yy43:
		if (yych <= '9') {
			if (yych == '.') goto yy44;
			if (yych <= '/') goto yy20;
			goto yy42;
		} else {
			if (yych <= 'E') {
				if (yych <= 'D') goto yy20;
				goto yy45;
			} else {
				if (yych == 'e') goto yy45;
				goto yy20;
			}
		}
yy44:
		yych = (guchar)*++c;
		if (yych <= '/') goto yy29;
		if (yych <= '9') goto yy49;
		goto yy29;
yy45:
		yych = (guchar)*++c;
		if (yych <= ',') {
			if (yych != '+') goto yy29;
		} else {
			if (yych <= '-') goto yy46;
			if (yych <= '/') goto yy29;
			if (yych <= '9') goto yy47;
			goto yy29;
		}
yy46:
		yych = (guchar)*++c;
		if (yych <= '/') goto yy29;
		if (yych >= ':') goto yy29;
yy47:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy20;
		if (yych <= '9') goto yy47;
		goto yy20;
yy49:
		yyaccept = 1;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '/') goto yy20;
			if (yych <= '9') goto yy49;
			goto yy20;
		} else {
			if (yych <= 'E') goto yy45;
			if (yych == 'e') goto yy45;
			goto yy20;
		}
yy51:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych <= 'D') {
			if (yych == '.') goto yy44;
			goto yy20;
		} else {
			if (yych <= 'E') goto yy45;
			if (yych == 'e') goto yy45;
			goto yy20;
		}
yy52:
		++c;
		yych = (guchar)*c;
yy53:
		if (yych <= '"') {
			if (yych <= 0x00) goto yy29;
			if (yych <= '!') goto yy52;
			goto yy55;
		} else {
			if (yych != '\\') goto yy52;
		}
yy54:
		++c;
		yych = (guchar)*c;
		if (yych <= 'e') {
			if (yych <= '/') {
				if (yych == '"') goto yy58;
				if (yych <= '.') goto yy29;
				goto yy58;
			} else {
				if (yych <= '\\') {
					if (yych <= '[') goto yy29;
					goto yy58;
				} else {
					if (yych == 'b') goto yy58;
					goto yy29;
				}
			}
		} else {
			if (yych <= 'q') {
				if (yych <= 'f') goto yy58;
				if (yych == 'n') goto yy58;
				goto yy29;
			} else {
				if (yych <= 's') {
					if (yych <= 'r') goto yy58;
					goto yy29;
				} else {
					if (yych <= 't') goto yy58;
					if (yych <= 'u') goto yy57;
					goto yy29;
				}
			}
		}
yy55:
		++c;
#line 106 "sjson.c"
		{
      token = TOK_NOESC_STRING;
      goto done;
    }
#line 396 "sjson.gen.c"
yy57:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy29;
			if (yych <= '9') goto yy62;
			goto yy29;
		} else {
			if (yych <= 'F') goto yy62;
			if (yych <= '`') goto yy29;
			if (yych <= 'f') goto yy62;
			goto yy29;
		}
yy58:
		++c;
		yych = (guchar)*c;
		if (yych <= '"') {
			if (yych <= 0x00) goto yy29;
			if (yych <= '!') goto yy58;
		} else {
			if (yych == '\\') goto yy54;
			goto yy58;
		}
		++c;
#line 111 "sjson.c"
		{
      token = TOK_STRING;
      goto done;
    }
#line 426 "sjson.gen.c"
yy62:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy29;
			if (yych >= ':') goto yy29;
		} else {
			if (yych <= 'F') goto yy63;
			if (yych <= '`') goto yy29;
			if (yych >= 'g') goto yy29;
		}
yy63:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy29;
			if (yych >= ':') goto yy29;
		} else {
			if (yych <= 'F') goto yy64;
			if (yych <= '`') goto yy29;
			if (yych >= 'g') goto yy29;
		}
yy64:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy29;
			if (yych <= '9') goto yy58;
			goto yy29;
		} else {
			if (yych <= 'F') goto yy58;
			if (yych <= '`') goto yy29;
			if (yych <= 'f') goto yy58;
			goto yy29;
		}
yy65:
		++c;
		yych = (guchar)*c;
yy66:
		if (yych <= '\f') {
			if (yych <= 0x08) goto yy3;
			if (yych <= '\n') goto yy65;
			goto yy3;
		} else {
			if (yych <= '\r') goto yy65;
			if (yych == ' ') goto yy65;
			goto yy3;
		}
	}
#line 153 "sjson.c"

  }

done:
  if (start)
    *start = s;
  if (end)
    *end = c;
  return token;
}

static SJsonType token_to_type(gint token)
{
  switch (token)
  {
    case TOK_NONE        : return S_JSON_TYPE_NONE;
    case TOK_OBJ_START   : return S_JSON_TYPE_OBJECT;
    case TOK_ARRAY_START : return S_JSON_TYPE_ARRAY;
    case TOK_STRING      : return S_JSON_TYPE_STRING;
    case TOK_NOESC_STRING: return S_JSON_TYPE_STRING;
    case TOK_NUMBER      : return S_JSON_TYPE_NUMBER;
    case TOK_FALSE       : return S_JSON_TYPE_BOOL;
    case TOK_TRUE        : return S_JSON_TYPE_BOOL;
    case TOK_NULL        : return S_JSON_TYPE_NULL;
    default              : return S_JSON_TYPE_INVALID;
  }
}

// public api

static gboolean s_json_is_valid_inner(const gchar* json, const gchar** end)
{
  const gchar* next;
  gint token;

  g_return_val_if_fail(json != NULL, FALSE);
  
  token = s_json_get_token(json, NULL, &next);
  if (token == TOK_ARRAY_START)
  {
    const gchar* array_elem = next;
    const gchar* array_next = NULL;
    gboolean expect_comma = FALSE;

    while (TRUE)
    {
      // check end of array
      token = s_json_get_token(array_elem, NULL, &array_next);
      if (token == TOK_ARRAY_END)
      {
        if (end)
          *end = array_next;
        return TRUE;
      }

      if (expect_comma)
      {
        if (token == TOK_COMMA)
          array_elem = array_next; // skip comma
        else
          return FALSE;
      }

      // check element
      if (!s_json_is_valid_inner(array_elem, &array_elem))
        return FALSE;

      expect_comma = TRUE;
    }
  }
  else if (token == TOK_OBJ_START)
  {
    const gchar* obj_next = next;
    gboolean expect_comma = FALSE;

    while (TRUE)
    {
      // check end of object
      token = s_json_get_token(obj_next, NULL, &obj_next);
      if (token == TOK_OBJ_END)
      {
        if (end)
          *end = obj_next;

        return TRUE;
      }

      // eat comma
      if (expect_comma)
      {
        if (token != TOK_COMMA)
          return FALSE;

        token = s_json_get_token(obj_next, NULL, &obj_next);
      }

      // check member name and colon
      if (token != TOK_STRING && token != TOK_NOESC_STRING)
        return FALSE;

      token = s_json_get_token(obj_next, NULL, &obj_next);
      if (token != TOK_COLON)
        return FALSE;

      // check member value
      if (!s_json_is_valid_inner(obj_next, &obj_next))
        return FALSE;

      expect_comma = TRUE;
    }
  }
  else if (token == TOK_STRING || token == TOK_NOESC_STRING || token == TOK_NUMBER || token == TOK_FALSE || token == TOK_TRUE || token == TOK_NULL)
  {
    if (end)
      *end = next;
    return TRUE;
  }

  return FALSE;
}

gboolean s_json_is_valid(const gchar* json)
{
  const gchar* next;

  g_return_val_if_fail(json != NULL, FALSE);
  
  return s_json_is_valid_inner(json, &next) && s_json_get_token(next, NULL, NULL) == TOK_NONE;
}

gchar* s_json_get(const gchar* json)
{
  const gchar* next;
  const gchar* start = NULL;

  g_return_val_if_fail(json != NULL, NULL);
  
  if (s_json_is_valid_inner(json, &next))
  {
    s_json_get_token(json, &start, NULL); // must set start

    return g_strndup(start, next - start);
  }

  return NULL;
}

SJsonType s_json_get_type(const gchar* json)
{
  g_return_val_if_fail(json != NULL, S_JSON_TYPE_INVALID);

  return token_to_type(s_json_get_token(json, NULL, NULL));
}

const gchar* s_json_get_element_first(const gchar* json)
{
  const gchar* next_elem;
  gint token;

  g_return_val_if_fail(json != NULL, NULL);

  token = s_json_get_token(json, NULL, &next_elem);
  if (token != TOK_ARRAY_START)
    return NULL;

  if (s_json_get_token(next_elem, NULL, NULL) == TOK_ARRAY_END)
    return NULL;

  return next_elem;
}

const gchar* s_json_get_element_next(const gchar* iter)
{
  const gchar* next_elem;
  gint token;

  g_return_val_if_fail(iter != NULL, NULL);

  if (!s_json_is_valid_inner(iter, &next_elem))
    return NULL;

  token = s_json_get_token(next_elem, NULL, &next_elem);
  if (token != TOK_COMMA)
    return NULL;

  return next_elem;
}

const gchar* s_json_get_element(const gchar* json, guint index)
{
  guint current_index = 0;

  g_return_val_if_fail(json != NULL, NULL);

  S_JSON_FOREACH_ELEMENT(json, elem)

    if (current_index == index)
      return elem;

    current_index++;

  S_JSON_FOREACH_END()

  return NULL;
}

gchar** s_json_get_elements(const gchar* json)
{
  GPtrArray* arr;

  g_return_val_if_fail(json != NULL, NULL);

  arr = g_ptr_array_sized_new(64);

  S_JSON_FOREACH_ELEMENT(json, elem)
    g_ptr_array_add(arr, (gchar*)elem);
  S_JSON_FOREACH_END()

  g_ptr_array_add(arr, NULL);

  return (gchar**)g_ptr_array_free(arr, FALSE);
}

const gchar* s_json_get_member_first(const gchar* json, const gchar** value)
{
  const gchar* key;
  const gchar* colon;
  const gchar* val;
  gint token;

  g_return_val_if_fail(json != NULL, NULL);
  g_return_val_if_fail(value != NULL, NULL);

  if (s_json_get_token(json, NULL, &key) != TOK_OBJ_START)
    return NULL;

  token = s_json_get_token(key, NULL, &colon);
  if (token != TOK_STRING && token != TOK_NOESC_STRING)
    return NULL;

  if (s_json_get_token(colon, NULL, &val) != TOK_COLON)
    return NULL;

  *value = val;
  return key;
}

const gchar* s_json_get_member_next(const gchar** value)
{
  const gchar* comma;
  const gchar* key;
  const gchar* colon;
  const gchar* val;
  gint token;

  g_return_val_if_fail(value != NULL && *value != NULL, NULL);

  if (!s_json_is_valid_inner(*value, &comma))
    return NULL;

  if (s_json_get_token(comma, NULL, &key) != TOK_COMMA)
    return NULL;

  token = s_json_get_token(key, NULL, &colon);
  if (token != TOK_STRING && token != TOK_NOESC_STRING)
    return NULL;

  if (s_json_get_token(colon, NULL, &val) != TOK_COLON)
    return NULL;

  *value = val;
  return key;
}

const gchar* s_json_get_member(const gchar* json, const gchar* name)
{
  g_return_val_if_fail(json != NULL, NULL);
  g_return_val_if_fail(name != NULL, NULL);

  S_JSON_FOREACH_MEMBER(json, key, value)

    if (s_json_string_match(key, name))
      return value;

  S_JSON_FOREACH_END()

  return NULL;
}

gchar* s_json_get_string(const gchar* json)
{
  const gchar* start;
  const gchar* end;
  gint token;

  g_return_val_if_fail(json != NULL, NULL);

  token = s_json_get_token(json, &start, &end);
  if (token != TOK_STRING && token != TOK_NOESC_STRING)
    return NULL;

  if (token == TOK_NOESC_STRING)
    return g_strndup(start + 1, (end - start) - 2);

  GString* str = g_string_sized_new(end - start);
  const guchar* c = (const guchar*)start + 1;
  const guchar* m = NULL;
  const guchar* s;

  while (TRUE)
  {
    s = c;


#line 791 "sjson.gen.c"
	{
		guchar yych;
		yych = (guchar)*c;
		if (yych <= '"') {
			if (yych <= 0x00) goto yy75;
			if (yych >= '"') goto yy73;
		} else {
			if (yych == '\\') goto yy71;
		}
		++c;
		yych = (guchar)*c;
		goto yy86;
yy70:
#line 467 "sjson.c"
		{
      g_string_append_len(str, s, c - s);
      continue;
    }
#line 810 "sjson.gen.c"
yy71:
		yych = (guchar)*(m = ++c);
		if (yych <= 'e') {
			if (yych <= '/') {
				if (yych == '"') goto yy78;
				if (yych >= '/') goto yy78;
			} else {
				if (yych <= '\\') {
					if (yych >= '\\') goto yy78;
				} else {
					if (yych == 'b') goto yy78;
				}
			}
		} else {
			if (yych <= 'q') {
				if (yych <= 'f') goto yy78;
				if (yych == 'n') goto yy78;
			} else {
				if (yych <= 's') {
					if (yych <= 'r') goto yy78;
				} else {
					if (yych <= 't') goto yy78;
					if (yych <= 'u') goto yy76;
				}
			}
		}
yy72:
#line 502 "sjson.c"
		{ 
      g_assert_not_reached();
    }
#line 842 "sjson.gen.c"
yy73:
		++c;
#line 498 "sjson.c"
		{
      return g_string_free(str, FALSE);
    }
#line 849 "sjson.gen.c"
yy75:
		yych = (guchar)*++c;
		goto yy72;
yy76:
		yych = (guchar)*++c;
		if (yych <= '@') {
			if (yych <= '/') goto yy77;
			if (yych <= '9') goto yy80;
		} else {
			if (yych <= 'F') goto yy80;
			if (yych <= '`') goto yy77;
			if (yych <= 'f') goto yy80;
		}
yy77:
		c = m;
		goto yy72;
yy78:
		++c;
#line 472 "sjson.c"
		{
      gchar ch = (gchar)s[1];

      if (ch == 'b')
        g_string_append_c(str, '\b');
      else if (ch == 'n')
        g_string_append_c(str, '\n');
      else if (ch == 'r')
        g_string_append_c(str, '\r');
      else if (ch == 't')
        g_string_append_c(str, '\t');
      else if (ch == 'f')
        g_string_append_c(str, '\f');
      else
        g_string_append_c(str, ch);

      continue;
    }
#line 887 "sjson.gen.c"
yy80:
		yych = (guchar)*++c;
		if (yych <= '@') {
			if (yych <= '/') goto yy77;
			if (yych >= ':') goto yy77;
		} else {
			if (yych <= 'F') goto yy81;
			if (yych <= '`') goto yy77;
			if (yych >= 'g') goto yy77;
		}
yy81:
		yych = (guchar)*++c;
		if (yych <= '@') {
			if (yych <= '/') goto yy77;
			if (yych >= ':') goto yy77;
		} else {
			if (yych <= 'F') goto yy82;
			if (yych <= '`') goto yy77;
			if (yych >= 'g') goto yy77;
		}
yy82:
		yych = (guchar)*++c;
		if (yych <= '@') {
			if (yych <= '/') goto yy77;
			if (yych >= ':') goto yy77;
		} else {
			if (yych <= 'F') goto yy83;
			if (yych <= '`') goto yy77;
			if (yych >= 'g') goto yy77;
		}
yy83:
		++c;
#line 491 "sjson.c"
		{
      guint ch = 0;
      sscanf(s + 2, "%4x", &ch);
      g_string_append_unichar(str, ch);
      continue;
    }
#line 927 "sjson.gen.c"
yy85:
		++c;
		yych = (guchar)*c;
yy86:
		if (yych <= '"') {
			if (yych <= 0x00) goto yy70;
			if (yych <= '!') goto yy85;
			goto yy70;
		} else {
			if (yych == '\\') goto yy70;
			goto yy85;
		}
	}
#line 505 "sjson.c"

  }

  return NULL;
}

gint64 s_json_get_int(const gchar* json, gint64 fallback)
{
  const gchar* start;
  const gchar* end;

  g_return_val_if_fail(json != NULL, fallback);

  if (s_json_get_token(json, &start, &end) != TOK_NUMBER)
    return fallback;

  gchar* str = g_alloca(end - start + 1);
  memcpy(str, start, end - start);
  str[end - start] = 0;

  gint64 v = fallback;
  sscanf(str, "%" G_GINT64_FORMAT, &v);
  return v;
}

gdouble s_json_get_double(const gchar* json, gdouble fallback)
{
  const gchar* start;
  const gchar* end;

  g_return_val_if_fail(json != NULL, fallback);

  if (s_json_get_token(json, &start, &end) != TOK_NUMBER)
    return fallback;

  gchar* str = g_alloca(end - start + 1);
  memcpy(str, start, end - start);
  str[end - start] = 0;

  gdouble v = fallback;
  sscanf(str, "%lf", &v);
  return v;
}

gboolean s_json_get_bool(const gchar* json)
{
  g_return_val_if_fail(json != NULL, FALSE);

  gint token = s_json_get_token(json, NULL, NULL);
  if (token == TOK_TRUE)
    return TRUE;

  return FALSE;
}

gboolean s_json_is_null(const gchar* json)
{
  g_return_val_if_fail(json != NULL, FALSE);

  gint token = s_json_get_token(json, NULL, NULL);
  if (token == TOK_NULL)
    return TRUE;

  return FALSE;
}

gboolean s_json_string_match(const gchar* json_str, const gchar* c_str)
{
  const gchar *start, *end;
  gint token;

  g_return_val_if_fail(json_str != NULL, FALSE);
  g_return_val_if_fail(c_str != NULL, FALSE);

  token = s_json_get_token(json_str, &start, &end);
  if (token == TOK_NOESC_STRING)
  {
    // fast path
    gsize json_len = ((end - start) - 2);
    gint rs = strncmp(start + 1, c_str, json_len);

    return rs == 0 ? strlen(c_str) == json_len : FALSE;
  }
  else if (token == TOK_STRING)
  {
    // slow path
    gchar* str = s_json_get_string(json_str);
    gint rs = strcmp(str, c_str);
    g_free(str);

    return rs == 0;
  }
  else
  {
    return FALSE;
  }
}

// helpers

gchar* s_json_get_member_string(const gchar* json, const gchar* name)
{
  g_return_val_if_fail(json != NULL, NULL);
  g_return_val_if_fail(name != NULL, NULL);

  const gchar* member = s_json_get_member(json, name);
  if (member)
    return s_json_get_string(member);

  return NULL;
}

gint64 s_json_get_member_int(const gchar* json, const gchar* name, gint64 fallback)
{
  g_return_val_if_fail(json != NULL, fallback);
  g_return_val_if_fail(name != NULL, fallback);

  const gchar* member = s_json_get_member(json, name);
  if (member)
    return s_json_get_int(member, fallback);

  return fallback;
}

gdouble s_json_get_member_double(const gchar* json, const gchar* name, gdouble fallback)
{
  g_return_val_if_fail(json != NULL, fallback);
  g_return_val_if_fail(name != NULL, fallback);

  const gchar* member = s_json_get_member(json, name);
  if (member)
    return s_json_get_double(member, fallback);

  return fallback;
}

gboolean s_json_get_member_bool(const gchar* json, const gchar* name)
{
  g_return_val_if_fail(json != NULL, FALSE);
  g_return_val_if_fail(name != NULL, FALSE);

  const gchar* member = s_json_get_member(json, name);
  if (member)
    return s_json_get_bool(member);

  return FALSE;
}

gboolean s_json_member_is_null(const gchar* json, const gchar* name)
{
  g_return_val_if_fail(json != NULL, FALSE);
  g_return_val_if_fail(name != NULL, FALSE);

  const gchar* member = s_json_get_member(json, name);
  if (member)
    return s_json_is_null(member);

  return TRUE;
}

// generator api

struct _SJsonGen
{
  GString* str;
};

SJsonGen* s_json_gen_new(void)
{
  SJsonGen* gen = g_slice_new(SJsonGen);
  gen->str = g_string_sized_new(512);
  return gen;
}

static void strip_comma(SJsonGen* json)
{
  if (json->str->len > 0)
  {
    if (json->str->str[json->str->len - 1] == ',')
      g_string_truncate(json->str, json->str->len - 1);
  }
}

void s_json_gen_start_object(SJsonGen* json)
{
  g_return_if_fail(json != NULL);

  g_string_append_c(json->str, '{');
}

void s_json_gen_end_object(SJsonGen* json)
{
  g_return_if_fail(json != NULL);

  strip_comma(json);
  g_string_append(json->str, "},");
}


void s_json_gen_start_array(SJsonGen* json)
{
  g_return_if_fail(json != NULL);

  g_string_append_c(json->str, '[');
}

void s_json_gen_end_array(SJsonGen* json)
{
  g_return_if_fail(json != NULL);

  strip_comma(json);
  g_string_append(json->str, "],");
}


static void escape_string(GString* str, const gchar* v)
{
  g_return_if_fail(str != NULL);
  g_return_if_fail(v != NULL);

  const guchar* c = (const guchar*)v;
  const guchar* m = NULL;
  const guchar* s;

  g_string_append_c(str, '"');

  while (TRUE)
  {
    s = c;


#line 1173 "sjson.gen.c"
	{
		guchar yych;
		yych = (guchar)*c;
		if (yych <= '\v') {
			if (yych <= 0x08) {
				if (yych <= 0x00) goto yy103;
				if (yych <= 0x07) goto yy105;
				goto yy93;
			} else {
				if (yych <= '\t') goto yy95;
				if (yych >= '\v') goto yy105;
			}
		} else {
			if (yych <= '!') {
				if (yych <= '\f') goto yy97;
				if (yych <= '\r') goto yy91;
				goto yy105;
			} else {
				if (yych <= '"') goto yy99;
				if (yych == '\\') goto yy101;
				goto yy105;
			}
		}
		++c;
#line 736 "sjson.c"
		{ g_string_append(str, "\\n"); continue; }
#line 1200 "sjson.gen.c"
yy91:
		++c;
#line 737 "sjson.c"
		{ g_string_append(str, "\\r"); continue; }
#line 1205 "sjson.gen.c"
yy93:
		++c;
#line 738 "sjson.c"
		{ g_string_append(str, "\\b"); continue; }
#line 1210 "sjson.gen.c"
yy95:
		++c;
#line 739 "sjson.c"
		{ g_string_append(str, "\\t"); continue; }
#line 1215 "sjson.gen.c"
yy97:
		++c;
		if ((yych = (guchar)*c) <= '\r') {
			if (yych <= 0x07) {
				if (yych >= 0x01) goto yy105;
			} else {
				if (yych <= '\n') goto yy98;
				if (yych <= '\f') goto yy105;
			}
		} else {
			if (yych <= '"') {
				if (yych <= '!') goto yy105;
			} else {
				if (yych != '\\') goto yy105;
			}
		}
yy98:
#line 740 "sjson.c"
		{ g_string_append(str, "\\f"); continue; }
#line 1235 "sjson.gen.c"
yy99:
		++c;
#line 741 "sjson.c"
		{ g_string_append(str, "\\\""); continue; }
#line 1240 "sjson.gen.c"
yy101:
		++c;
#line 742 "sjson.c"
		{ g_string_append(str, "\\\\"); continue; }
#line 1245 "sjson.gen.c"
yy103:
		++c;
#line 744 "sjson.c"
		{ 
    break;
  }
#line 1252 "sjson.gen.c"
yy105:
		++c;
		yych = (guchar)*c;
		if (yych <= '\r') {
			if (yych <= 0x07) {
				if (yych >= 0x01) goto yy105;
			} else {
				if (yych <= '\n') goto yy107;
				if (yych <= '\f') goto yy105;
			}
		} else {
			if (yych <= '"') {
				if (yych <= '!') goto yy105;
			} else {
				if (yych != '\\') goto yy105;
			}
		}
yy107:
#line 748 "sjson.c"
		{
    g_string_append_len(str, (gchar*)s, c - s);
    continue;
  }
#line 1276 "sjson.gen.c"
	}
#line 752 "sjson.c"

  }

  g_string_append_c(str, '"');
}

void s_json_gen_build(SJsonGen* json, const gchar* fmt, ...)
{
  va_list args;
  gchar* v;

  g_return_if_fail(json != NULL);
  g_return_if_fail(fmt != NULL);

  va_start(args, fmt);
  v = s_json_buildv(fmt, args);
  va_end(args);

  s_json_gen_json(json, v);

  g_free(v);
}

void s_json_gen_json(SJsonGen* json, const gchar* v)
{
  g_return_if_fail(json != NULL);

  if (v)
  {
    g_string_append(json->str, v);
    g_string_append_c(json->str, ',');
  }
  else
    s_json_gen_null(json);
}

void s_json_gen_string(SJsonGen* json, const gchar* v)
{
  g_return_if_fail(json != NULL);

  if (v)
  {
    escape_string(json->str, v);
    g_string_append_c(json->str, ',');
  }
  else
    s_json_gen_null(json);
}

void s_json_gen_int(SJsonGen* json, gint64 v)
{
  g_return_if_fail(json != NULL);

  g_string_append_printf(json->str, "%" G_GINT64_FORMAT ",", v);
}

void s_json_gen_double(SJsonGen* json, gdouble v)
{
  g_return_if_fail(json != NULL);

  g_string_append_printf(json->str, "%lg,", v);
}

void s_json_gen_bool(SJsonGen* json, gboolean v)
{
  g_return_if_fail(json != NULL);

  g_string_append(json->str, v ? "true," : "false,");
}

void s_json_gen_null(SJsonGen* json)
{
  g_return_if_fail(json != NULL);

  g_string_append(json->str, "null,");
}


void s_json_gen_member_build(SJsonGen* json, const gchar* name, const gchar* fmt, ...)
{
  va_list args;
  gchar* v;

  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);
  g_return_if_fail(fmt != NULL);

  va_start(args, fmt);
  v = s_json_buildv(fmt, args);
  va_end(args);

  s_json_gen_member_json(json, name, v);

  g_free(v);
}

void s_json_gen_member_json(SJsonGen* json, const gchar* name, const gchar* v)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_json(json, v);
}

void s_json_gen_member_string(SJsonGen* json, const gchar* name, const gchar* v)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_string(json, v);
}

void s_json_gen_member_int(SJsonGen* json, const gchar* name, gint64 v)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_int(json, v);
}

void s_json_gen_member_double(SJsonGen* json, const gchar* name, gdouble v)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_double(json, v);
}

void s_json_gen_member_bool(SJsonGen* json, const gchar* name, gboolean v)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_bool(json, v);
}

void s_json_gen_member_null(SJsonGen* json, const gchar* name)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_null(json);
}

void s_json_gen_member_array(SJsonGen* json, const gchar* name)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_start_array(json);
}

void s_json_gen_member_object(SJsonGen* json, const gchar* name)
{
  g_return_if_fail(json != NULL);
  g_return_if_fail(name != NULL);

  s_json_gen_string(json, name);
  strip_comma(json);
  g_string_append_c(json->str, ':');
  s_json_gen_start_object(json);
}


gchar* s_json_gen_done(SJsonGen* json)
{
  g_return_val_if_fail(json != NULL, NULL);

  strip_comma(json);
  gchar* str = g_string_free(json->str, FALSE);
  g_slice_free(SJsonGen, json);

  if (s_json_is_valid(str))
    return str;

  g_free(str);
  return NULL;
}

// build

// formats:
// - % ? format
// format: sidbnjSJ

gchar* s_json_buildv(const gchar* format, va_list args)
{
  g_return_val_if_fail(format != NULL, NULL);

  GString* str = g_string_sized_new(strlen(format));
  const guchar* c = (const guchar*)format;
  const guchar* m = NULL;
  const guchar* s;

#define IS_NULLABLE (s[1] == '?')
#define FMT_FULL(arg_type, code_format, code_leave) \
  gboolean is_null = (IS_NULLABLE ? va_arg(args, gboolean) : FALSE); \
  gchar fmt = s[IS_NULLABLE ? 2 : 1]; \
  arg_type arg = va_arg(args, arg_type); \
  if (is_null) { \
    g_string_append(str, "null"); \
  } else { \
    code_format \
  } \
  code_leave \
  continue;

#define FMT(arg_type, code) FMT_FULL(arg_type, code, )

  while (TRUE)
  {
    s = c;


#line 1514 "sjson.gen.c"
	{
		guchar yych;
		unsigned int yyaccept = 0;
		yych = (guchar)*c;
		if (yych <= ':') {
			if (yych <= '"') {
				if (yych <= '\f') {
					if (yych <= 0x00) goto yy123;
					if (yych <= 0x08) goto yy125;
					if (yych >= '\v') goto yy125;
				} else {
					if (yych <= 0x1F) {
						if (yych >= 0x0E) goto yy125;
					} else {
						if (yych <= ' ') goto yy110;
						if (yych <= '!') goto yy125;
						goto yy112;
					}
				}
			} else {
				if (yych <= ',') {
					if (yych == '%') goto yy122;
					if (yych <= '+') goto yy125;
				} else {
					if (yych <= '/') {
						if (yych <= '-') goto yy114;
						goto yy125;
					} else {
						if (yych <= '0') goto yy116;
						if (yych <= '9') goto yy117;
					}
				}
			}
		} else {
			if (yych <= 'e') {
				if (yych <= '\\') {
					if (yych <= '@') goto yy125;
					if (yych <= 'Z') goto yy121;
					if (yych >= '\\') goto yy125;
				} else {
					if (yych <= '^') {
						if (yych >= '^') goto yy125;
					} else {
						if (yych == '`') goto yy125;
						goto yy121;
					}
				}
			} else {
				if (yych <= 't') {
					if (yych <= 'm') {
						if (yych <= 'f') goto yy119;
						goto yy121;
					} else {
						if (yych <= 'n') goto yy120;
						if (yych <= 's') goto yy121;
						goto yy118;
					}
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy121;
					} else {
						if (yych != '}') goto yy125;
					}
				}
			}
		}
yy110:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		goto yy144;
yy111:
#line 987 "sjson.c"
		{
      g_string_append_len(str, s, c - s);
      continue;
    }
#line 1591 "sjson.gen.c"
yy112:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych >= 0x01) goto yy146;
yy113:
#line 1034 "sjson.c"
		{
      goto err;
    }
#line 1601 "sjson.gen.c"
yy114:
		++c;
		if ((yych = (guchar)*c) <= '/') goto yy139;
		if (yych <= '0') goto yy148;
		if (yych <= '9') goto yy150;
		goto yy139;
yy115:
#line 992 "sjson.c"
		{
      g_string_append_c(str, '"');
      g_string_append_len(str, s, c - s);
      g_string_append_c(str, '"');
      continue;
    }
#line 1616 "sjson.gen.c"
yy116:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= 'D') {
			if (yych == '.') goto yy161;
			goto yy144;
		} else {
			if (yych <= 'E') goto yy163;
			if (yych == 'e') goto yy163;
			goto yy144;
		}
yy117:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= '0') {
			if (yych == '.') goto yy161;
			if (yych <= '/') goto yy144;
			goto yy181;
		} else {
			if (yych <= 'E') {
				if (yych <= 'D') goto yy144;
				goto yy163;
			} else {
				if (yych == 'e') goto yy163;
				goto yy144;
			}
		}
yy118:
		yych = (guchar)*++c;
		if (yych == 'r') goto yy158;
		goto yy139;
yy119:
		yych = (guchar)*++c;
		if (yych == 'a') goto yy155;
		goto yy139;
yy120:
		yych = (guchar)*++c;
		if (yych == 'u') goto yy140;
		goto yy139;
yy121:
		yych = (guchar)*++c;
		goto yy139;
yy122:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych <= 'b') {
			if (yych <= 'J') {
				if (yych == '?') goto yy126;
				if (yych <= 'I') goto yy113;
				goto yy134;
			} else {
				if (yych == 'S') goto yy136;
				if (yych <= 'a') goto yy113;
				goto yy128;
			}
		} else {
			if (yych <= 'i') {
				if (yych == 'd') goto yy130;
				if (yych <= 'h') goto yy113;
				goto yy132;
			} else {
				if (yych <= 'j') goto yy134;
				if (yych == 's') goto yy136;
				goto yy113;
			}
		}
yy123:
		++c;
#line 1030 "sjson.c"
		{ 
      break;   
    }
#line 1689 "sjson.gen.c"
yy125:
		yych = (guchar)*++c;
		goto yy113;
yy126:
		yych = (guchar)*++c;
		if (yych <= 'c') {
			if (yych <= 'R') {
				if (yych == 'J') goto yy134;
			} else {
				if (yych <= 'S') goto yy136;
				if (yych == 'b') goto yy128;
			}
		} else {
			if (yych <= 'i') {
				if (yych <= 'd') goto yy130;
				if (yych >= 'i') goto yy132;
			} else {
				if (yych <= 'j') goto yy134;
				if (yych == 's') goto yy136;
			}
		}
yy127:
		c = m;
		if (yyaccept <= 1) {
			if (yyaccept <= 0) {
				goto yy111;
			} else {
				goto yy113;
			}
		} else {
			goto yy115;
		}
yy128:
		++c;
#line 1026 "sjson.c"
		{
      FMT(gboolean, g_string_append(str, arg ? "true" : "false");)
    }
#line 1728 "sjson.gen.c"
yy130:
		++c;
#line 1022 "sjson.c"
		{
      FMT(gdouble, g_string_append_printf(str, "%lg" , arg);)
    }
#line 1735 "sjson.gen.c"
yy132:
		++c;
#line 1018 "sjson.c"
		{
      FMT(gint64, g_string_append_printf(str, "%" G_GINT64_FORMAT, arg);)
    }
#line 1742 "sjson.gen.c"
yy134:
		++c;
#line 1005 "sjson.c"
		{
      FMT_FULL(gchar*, 
        if (arg) {
          const gchar* end;
          if (s_json_is_valid_inner(arg, &end))
            g_string_append_len(str, arg, end - arg); 
          else
            g_string_append(str, "null");
        } else {
          g_string_append(str, "null");
        }, if (fmt == 'J') g_free(arg);)
    }
#line 1758 "sjson.gen.c"
yy136:
		++c;
#line 1001 "sjson.c"
		{
      FMT_FULL(gchar*, if (arg) escape_string(str, arg); else g_string_append(str, "null");, if (fmt == 'S') g_free(arg);)
    }
#line 1765 "sjson.gen.c"
yy138:
		++c;
		yych = (guchar)*c;
yy139:
		if (yych <= '@') {
			if (yych <= '-') {
				if (yych <= ',') goto yy115;
				goto yy138;
			} else {
				if (yych <= '/') goto yy115;
				if (yych <= '9') goto yy138;
				goto yy115;
			}
		} else {
			if (yych <= '_') {
				if (yych <= 'Z') goto yy138;
				if (yych <= '^') goto yy115;
				goto yy138;
			} else {
				if (yych <= '`') goto yy115;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy140:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'l') goto yy141;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy141:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'l') goto yy142;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy142:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '/') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy147;
					goto yy111;
				} else {
					if (yych <= '9') {
						if (yych <= '0') goto yy148;
						goto yy150;
					} else {
						if (yych <= ':') goto yy143;
						if (yych <= '@') goto yy111;
						goto yy138;
					}
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '^') {
					if (yych == '\\') goto yy111;
					if (yych >= '^') goto yy111;
				} else {
					if (yych == '`') goto yy111;
					if (yych <= 'e') goto yy138;
					goto yy153;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy154;
					if (yych <= 's') goto yy138;
					goto yy152;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
					} else {
						if (yych != '}') goto yy111;
					}
				}
			}
		}
yy143:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
yy144:
		if (yych <= ':') {
			if (yych <= '!') {
				if (yych <= '\f') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					goto yy111;
				} else {
					if (yych <= '\r') goto yy143;
					if (yych == ' ') goto yy143;
					goto yy111;
				}
			} else {
				if (yych <= '-') {
					if (yych <= '"') goto yy145;
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					goto yy164;
				} else {
					if (yych <= '/') goto yy111;
					if (yych <= '0') goto yy179;
					if (yych <= '9') goto yy181;
					goto yy143;
				}
			}
		} else {
			if (yych <= 'm') {
				if (yych <= '\\') {
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych == 'f') goto yy170;
					goto yy111;
				}
			} else {
				if (yych <= 'z') {
					if (yych <= 'n') goto yy171;
					if (yych == 't') goto yy169;
					goto yy111;
				} else {
					if (yych == '|') goto yy111;
					if (yych <= '}') goto yy143;
					goto yy111;
				}
			}
		}
yy145:
		++c;
		yych = (guchar)*c;
yy146:
		if (yych <= '"') {
			if (yych <= 0x00) goto yy127;
			if (yych <= '!') goto yy145;
			goto yy143;
		} else {
			if (yych == '\\') goto yy195;
			goto yy145;
		}
yy147:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '0') goto yy148;
				if (yych <= '9') goto yy150;
				goto yy115;
			}
		} else {
			if (yych <= '_') {
				if (yych <= 'Z') goto yy138;
				if (yych <= '^') goto yy115;
				goto yy138;
			} else {
				if (yych <= '`') goto yy115;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy148:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'E') {
			if (yych <= '+') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych <= ' ') {
						if (yych <= 0x1F) goto yy111;
						goto yy143;
					} else {
						if (yych == '"') goto yy145;
						goto yy111;
					}
				}
			} else {
				if (yych <= '0') {
					if (yych <= '-') {
						if (yych <= ',') goto yy143;
						goto yy147;
					} else {
						if (yych <= '.') goto yy161;
						if (yych <= '/') goto yy111;
						goto yy148;
					}
				} else {
					if (yych <= ':') {
						if (yych >= ':') goto yy143;
					} else {
						if (yych <= '@') goto yy111;
						if (yych <= 'D') goto yy138;
						goto yy160;
					}
				}
			}
		} else {
			if (yych <= 'e') {
				if (yych <= ']') {
					if (yych <= 'Z') goto yy138;
					if (yych == '\\') goto yy111;
					goto yy143;
				} else {
					if (yych <= '_') {
						if (yych <= '^') goto yy111;
						goto yy138;
					} else {
						if (yych <= '`') goto yy111;
						if (yych <= 'd') goto yy138;
						goto yy160;
					}
				}
			} else {
				if (yych <= 't') {
					if (yych <= 'm') {
						if (yych <= 'f') goto yy153;
						goto yy138;
					} else {
						if (yych <= 'n') goto yy154;
						if (yych <= 's') goto yy138;
						goto yy152;
					}
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy150:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'E') {
			if (yych <= '+') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych <= ' ') {
						if (yych <= 0x1F) goto yy111;
						goto yy143;
					} else {
						if (yych == '"') goto yy145;
						goto yy111;
					}
				}
			} else {
				if (yych <= '/') {
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy147;
					if (yych <= '.') goto yy161;
					goto yy111;
				} else {
					if (yych <= ':') {
						if (yych <= '9') goto yy150;
						goto yy143;
					} else {
						if (yych <= '@') goto yy111;
						if (yych <= 'D') goto yy138;
						goto yy160;
					}
				}
			}
		} else {
			if (yych <= 'e') {
				if (yych <= ']') {
					if (yych <= 'Z') goto yy138;
					if (yych == '\\') goto yy111;
					goto yy143;
				} else {
					if (yych <= '_') {
						if (yych <= '^') goto yy111;
						goto yy138;
					} else {
						if (yych <= '`') goto yy111;
						if (yych <= 'd') goto yy138;
						goto yy160;
					}
				}
			} else {
				if (yych <= 't') {
					if (yych <= 'm') {
						if (yych <= 'f') goto yy153;
						goto yy138;
					} else {
						if (yych <= 'n') goto yy154;
						if (yych <= 's') goto yy138;
					}
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy152:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'r') goto yy158;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy153:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych <= 'a') goto yy155;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy154:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'u') goto yy140;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy155:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'l') goto yy156;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy156:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 's') goto yy157;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy157:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'e') goto yy142;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy158:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'u') goto yy159;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy159:
		++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '/') {
				if (yych == '-') goto yy138;
				goto yy115;
			} else {
				if (yych <= '9') goto yy138;
				if (yych <= '@') goto yy115;
				goto yy138;
			}
		} else {
			if (yych <= '`') {
				if (yych == '_') goto yy138;
				goto yy115;
			} else {
				if (yych == 'e') goto yy142;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy160:
		yyaccept = 2;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '9') {
			if (yych <= ',') {
				if (yych == '+') goto yy183;
				goto yy115;
			} else {
				if (yych <= '-') goto yy189;
				if (yych <= '/') goto yy115;
				goto yy190;
			}
		} else {
			if (yych <= '^') {
				if (yych <= '@') goto yy115;
				if (yych <= 'Z') goto yy138;
				goto yy115;
			} else {
				if (yych == '`') goto yy115;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy161:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy127;
		if (yych >= ':') goto yy127;
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '/') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy111;
				} else {
					if (yych <= '0') goto yy165;
					if (yych <= '9') goto yy167;
					if (yych <= ':') goto yy143;
					goto yy111;
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych >= 'f') goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy163:
		++c;
		yych = (guchar)*c;
		if (yych <= ',') {
			if (yych == '+') goto yy183;
			goto yy127;
		} else {
			if (yych <= '-') goto yy183;
			if (yych <= '/') goto yy127;
			if (yych <= '9') goto yy184;
			goto yy127;
		}
yy164:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy127;
		if (yych <= '0') goto yy179;
		if (yych <= '9') goto yy181;
		goto yy127;
yy165:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '0') {
						if (yych <= '/') goto yy111;
						goto yy165;
					} else {
						if (yych <= '9') goto yy167;
						if (yych <= ':') goto yy143;
						goto yy111;
					}
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy167:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '/') goto yy111;
					if (yych <= '9') goto yy167;
					if (yych <= ':') goto yy143;
					goto yy111;
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy169:
		++c;
		yych = (guchar)*c;
		if (yych == 'r') goto yy177;
		goto yy127;
yy170:
		++c;
		yych = (guchar)*c;
		if (yych == 'a') goto yy174;
		goto yy127;
yy171:
		++c;
		yych = (guchar)*c;
		if (yych != 'u') goto yy127;
		++c;
		yych = (guchar)*c;
		if (yych != 'l') goto yy127;
		++c;
		yych = (guchar)*c;
		if (yych == 'l') goto yy143;
		goto yy127;
yy174:
		++c;
		yych = (guchar)*c;
		if (yych != 'l') goto yy127;
		++c;
		yych = (guchar)*c;
		if (yych != 's') goto yy127;
		++c;
		yych = (guchar)*c;
		if (yych == 'e') goto yy143;
		goto yy127;
yy177:
		++c;
		yych = (guchar)*c;
		if (yych != 'u') goto yy127;
		++c;
		yych = (guchar)*c;
		if (yych == 'e') goto yy143;
		goto yy127;
yy179:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '0') {
						if (yych <= '/') goto yy111;
						goto yy179;
					} else {
						if (yych <= '9') goto yy181;
						if (yych <= ':') goto yy143;
						goto yy111;
					}
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy181:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '/') goto yy111;
					if (yych <= '9') goto yy181;
					if (yych <= ':') goto yy143;
					goto yy111;
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy183:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy127;
		if (yych >= ':') goto yy127;
yy184:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= ':') {
			if (yych <= '!') {
				if (yych <= '\f') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					goto yy111;
				} else {
					if (yych <= '\r') goto yy143;
					if (yych == ' ') goto yy143;
					goto yy111;
				}
			} else {
				if (yych <= '-') {
					if (yych <= '"') goto yy145;
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					goto yy164;
				} else {
					if (yych <= '/') goto yy111;
					if (yych <= '0') goto yy185;
					if (yych <= '9') goto yy187;
					goto yy143;
				}
			}
		} else {
			if (yych <= 'm') {
				if (yych <= '\\') {
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych == 'f') goto yy170;
					goto yy111;
				}
			} else {
				if (yych <= 'z') {
					if (yych <= 'n') goto yy171;
					if (yych == 't') goto yy169;
					goto yy111;
				} else {
					if (yych == '|') goto yy111;
					if (yych <= '}') goto yy143;
					goto yy111;
				}
			}
		}
yy185:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '0') {
						if (yych <= '/') goto yy111;
						goto yy185;
					} else {
						if (yych <= '9') goto yy187;
						if (yych <= ':') goto yy143;
						goto yy111;
					}
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy187:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'D') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '.') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy164;
					goto yy161;
				} else {
					if (yych <= '/') goto yy111;
					if (yych <= '9') goto yy187;
					if (yych <= ':') goto yy143;
					goto yy111;
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '\\') {
					if (yych <= 'E') goto yy163;
					if (yych == '[') goto yy143;
					goto yy111;
				} else {
					if (yych <= ']') goto yy143;
					if (yych <= 'd') goto yy111;
					if (yych <= 'e') goto yy163;
					goto yy170;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy171;
					if (yych <= 's') goto yy111;
					goto yy169;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy111;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy189:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '-') {
				if (yych <= ',') goto yy115;
				goto yy138;
			} else {
				if (yych <= '/') goto yy115;
				if (yych >= ':') goto yy115;
			}
		} else {
			if (yych <= '_') {
				if (yych <= 'Z') goto yy138;
				if (yych <= '^') goto yy115;
				goto yy138;
			} else {
				if (yych <= '`') goto yy115;
				if (yych <= 'z') goto yy138;
				goto yy115;
			}
		}
yy190:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'Z') {
			if (yych <= '"') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych == ' ') goto yy143;
					if (yych <= '!') goto yy111;
					goto yy145;
				}
			} else {
				if (yych <= '/') {
					if (yych <= '+') goto yy111;
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy147;
					goto yy111;
				} else {
					if (yych <= '9') {
						if (yych >= '1') goto yy193;
					} else {
						if (yych <= ':') goto yy143;
						if (yych <= '@') goto yy111;
						goto yy138;
					}
				}
			}
		} else {
			if (yych <= 'f') {
				if (yych <= '^') {
					if (yych == '\\') goto yy111;
					if (yych <= ']') goto yy143;
					goto yy111;
				} else {
					if (yych == '`') goto yy111;
					if (yych <= 'e') goto yy138;
					goto yy153;
				}
			} else {
				if (yych <= 't') {
					if (yych == 'n') goto yy154;
					if (yych <= 's') goto yy138;
					goto yy152;
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy191:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'E') {
			if (yych <= '+') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych <= ' ') {
						if (yych <= 0x1F) goto yy111;
						goto yy143;
					} else {
						if (yych == '"') goto yy145;
						goto yy111;
					}
				}
			} else {
				if (yych <= '0') {
					if (yych <= '-') {
						if (yych <= ',') goto yy143;
						goto yy147;
					} else {
						if (yych <= '.') goto yy161;
						if (yych <= '/') goto yy111;
						goto yy191;
					}
				} else {
					if (yych <= ':') {
						if (yych >= ':') goto yy143;
					} else {
						if (yych <= '@') goto yy111;
						if (yych <= 'D') goto yy138;
						goto yy160;
					}
				}
			}
		} else {
			if (yych <= 'e') {
				if (yych <= ']') {
					if (yych <= 'Z') goto yy138;
					if (yych == '\\') goto yy111;
					goto yy143;
				} else {
					if (yych <= '_') {
						if (yych <= '^') goto yy111;
						goto yy138;
					} else {
						if (yych <= '`') goto yy111;
						if (yych <= 'd') goto yy138;
						goto yy160;
					}
				}
			} else {
				if (yych <= 't') {
					if (yych <= 'm') {
						if (yych <= 'f') goto yy153;
						goto yy138;
					} else {
						if (yych <= 'n') goto yy154;
						if (yych <= 's') goto yy138;
						goto yy152;
					}
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy193:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= 'E') {
			if (yych <= '+') {
				if (yych <= '\r') {
					if (yych <= 0x08) goto yy111;
					if (yych <= '\n') goto yy143;
					if (yych <= '\f') goto yy111;
					goto yy143;
				} else {
					if (yych <= ' ') {
						if (yych <= 0x1F) goto yy111;
						goto yy143;
					} else {
						if (yych == '"') goto yy145;
						goto yy111;
					}
				}
			} else {
				if (yych <= '/') {
					if (yych <= ',') goto yy143;
					if (yych <= '-') goto yy147;
					if (yych <= '.') goto yy161;
					goto yy111;
				} else {
					if (yych <= ':') {
						if (yych <= '9') goto yy193;
						goto yy143;
					} else {
						if (yych <= '@') goto yy111;
						if (yych <= 'D') goto yy138;
						goto yy160;
					}
				}
			}
		} else {
			if (yych <= 'e') {
				if (yych <= ']') {
					if (yych <= 'Z') goto yy138;
					if (yych == '\\') goto yy111;
					goto yy143;
				} else {
					if (yych <= '_') {
						if (yych <= '^') goto yy111;
						goto yy138;
					} else {
						if (yych <= '`') goto yy111;
						if (yych <= 'd') goto yy138;
						goto yy160;
					}
				}
			} else {
				if (yych <= 't') {
					if (yych <= 'm') {
						if (yych <= 'f') goto yy153;
						goto yy138;
					} else {
						if (yych <= 'n') goto yy154;
						if (yych <= 's') goto yy138;
						goto yy152;
					}
				} else {
					if (yych <= '{') {
						if (yych <= 'z') goto yy138;
						goto yy143;
					} else {
						if (yych == '}') goto yy143;
						goto yy111;
					}
				}
			}
		}
yy195:
		++c;
		yych = (guchar)*c;
		if (yych <= 'e') {
			if (yych <= '/') {
				if (yych == '"') goto yy197;
				if (yych <= '.') goto yy127;
				goto yy197;
			} else {
				if (yych <= '\\') {
					if (yych <= '[') goto yy127;
					goto yy197;
				} else {
					if (yych == 'b') goto yy197;
					goto yy127;
				}
			}
		} else {
			if (yych <= 'q') {
				if (yych <= 'f') goto yy197;
				if (yych == 'n') goto yy197;
				goto yy127;
			} else {
				if (yych <= 's') {
					if (yych <= 'r') goto yy197;
					goto yy127;
				} else {
					if (yych <= 't') goto yy197;
					if (yych >= 'v') goto yy127;
				}
			}
		}
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy127;
			if (yych <= '9') goto yy199;
			goto yy127;
		} else {
			if (yych <= 'F') goto yy199;
			if (yych <= '`') goto yy127;
			if (yych <= 'f') goto yy199;
			goto yy127;
		}
yy197:
		++c;
		yych = (guchar)*c;
		if (yych <= '"') {
			if (yych <= 0x00) goto yy127;
			if (yych <= '!') goto yy197;
			goto yy143;
		} else {
			if (yych == '\\') goto yy195;
			goto yy197;
		}
yy199:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy127;
			if (yych >= ':') goto yy127;
		} else {
			if (yych <= 'F') goto yy200;
			if (yych <= '`') goto yy127;
			if (yych >= 'g') goto yy127;
		}
yy200:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy127;
			if (yych >= ':') goto yy127;
		} else {
			if (yych <= 'F') goto yy201;
			if (yych <= '`') goto yy127;
			if (yych >= 'g') goto yy127;
		}
yy201:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy127;
			if (yych <= '9') goto yy197;
			goto yy127;
		} else {
			if (yych <= 'F') goto yy197;
			if (yych <= '`') goto yy127;
			if (yych <= 'f') goto yy197;
			goto yy127;
		}
	}
#line 1037 "sjson.c"

  }

  if (s_json_is_valid(str->str))
    return g_string_free(str, FALSE);

err:
  g_string_free(str, TRUE);
  return NULL;
}

gchar* s_json_build(const gchar* format, ...)
{
  va_list args;
  gchar* json;

  g_return_val_if_fail(format != NULL, NULL);

  va_start(args, format);
  json = s_json_buildv(format, args);
  va_end(args);

  return json;
}

gchar* s_json_pretty(const gchar* json)
{
  const gchar* start;
  const gchar* end;
  GString *str, *ind;
  gchar* json_valid;

  g_return_val_if_fail(json != NULL, NULL);

  // validate and isolate
  json_valid = s_json_get(json);
  if (!json_valid)
    return NULL;

  start = json_valid;

  str = g_string_sized_new(strlen(json) * 2);
  ind = g_string_sized_new(50);

#define PUSH_INDENT() g_string_append_c(ind, '\t')
#define POP_INDENT() g_string_truncate(ind, MAX(ind->len - 1, 0))
#define INDENT() g_string_append_len(str, ind->str, ind->len)

  gint prev_token = TOK_NONE;
  while (TRUE)
  {
    gint token = s_json_get_token(start, &start, &end);
    if (token == TOK_NONE)
      break;
    gint next_token = s_json_get_token(end, NULL, NULL);

    if ((token == TOK_OBJ_END && prev_token != TOK_OBJ_START) || (token == TOK_ARRAY_END && prev_token != TOK_ARRAY_START && prev_token != TOK_OBJ_END))
    {
      g_string_append_c(str, '\n');
      POP_INDENT();
      INDENT();
    }

    g_string_append_len(str, start, end - start);

    if ((token == TOK_OBJ_START && next_token != TOK_OBJ_END) || (token == TOK_ARRAY_START && next_token != TOK_OBJ_START && next_token != TOK_ARRAY_END))
    {
      g_string_append_c(str, '\n');
      PUSH_INDENT();
      INDENT();
    }
    else if (token == TOK_COMMA)
    {
      if ((prev_token == TOK_OBJ_END && next_token == TOK_OBJ_START) || (prev_token == TOK_ARRAY_END && next_token == TOK_ARRAY_START))
      {
        g_string_append_c(str, ' ');
      }
      else
      {
        g_string_append_c(str, '\n');
        INDENT();
      }
    }
    else if (token == TOK_COLON)
    {
      g_string_append_c(str, ' ');
    }

    prev_token = token;
    start = end;
  }

  g_string_free(ind, TRUE);
  g_free(json_valid);

  return g_string_free(str, FALSE);
}


const gchar* s_json_path(const gchar* json, const gchar* path)
{
  const guchar* c = (const guchar*)path;
  const guchar* m = NULL;
  const guchar* s;
  const gchar* cur_node = json;

  g_return_val_if_fail(json != NULL, NULL);
  g_return_val_if_fail(path != NULL, NULL);

#define CHECK_TYPE(type) \
  if (cur_node && s_json_get_type(cur_node) == type) \
    return cur_node; \
  if ((!cur_node || s_json_get_type(cur_node) == S_JSON_TYPE_NULL) && s[0] == '?') \
    return "null"; \
  return NULL;

  while (TRUE)
  {
    s = c;


#line 3298 "sjson.gen.c"
	{
		guchar yych;
		unsigned int yyaccept = 0;
		yych = (guchar)*c;
		if (yych <= '!') {
			if (yych <= '\f') {
				if (yych <= 0x00) goto yy212;
				if (yych <= 0x08) goto yy214;
				if (yych >= '\v') goto yy214;
			} else {
				if (yych <= '\r') goto yy204;
				if (yych <= 0x1F) goto yy214;
				if (yych >= '!') goto yy211;
			}
		} else {
			if (yych <= '.') {
				if (yych == '$') goto yy206;
				if (yych <= '-') goto yy214;
				goto yy208;
			} else {
				if (yych <= '?') {
					if (yych <= '>') goto yy214;
					goto yy211;
				} else {
					if (yych == '[') goto yy210;
					goto yy214;
				}
			}
		}
yy204:
		++c;
		yych = (guchar)*c;
		goto yy268;
yy205:
#line 1158 "sjson.c"
		{
      // skip whitespace
      continue;
    }
#line 3338 "sjson.gen.c"
yy206:
		++c;
#line 1163 "sjson.c"
		{
      // root
      cur_node = json;
      continue;
    }
#line 3347 "sjson.gen.c"
yy208:
		++c;
		if ((yych = (guchar)*c) <= 'Z') {
			if (yych == '-') goto yy264;
			if (yych >= 'A') goto yy264;
		} else {
			if (yych <= '_') {
				if (yych >= '_') goto yy264;
			} else {
				if (yych <= '`') goto yy209;
				if (yych <= 'z') goto yy264;
			}
		}
yy209:
#line 1236 "sjson.c"
		{
      return NULL;
    }
#line 3366 "sjson.gen.c"
yy210:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= '/') goto yy209;
		if (yych <= '0') goto yy259;
		if (yych <= '9') goto yy260;
		goto yy209;
yy211:
		yych = (guchar)*++c;
		switch (yych) {
		case 'a':	goto yy215;
		case 'b':	goto yy219;
		case 'i':	goto yy221;
		case 'n':	goto yy225;
		case 'o':	goto yy217;
		case 's':	goto yy223;
		default:	goto yy209;
		}
yy212:
		++c;
#line 1232 "sjson.c"
		{ 
      break;
    }
#line 3391 "sjson.gen.c"
yy214:
		yych = (guchar)*++c;
		goto yy209;
yy215:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych == 'r') goto yy255;
yy216:
#line 1228 "sjson.c"
		{
      CHECK_TYPE(S_JSON_TYPE_ARRAY)
    }
#line 3404 "sjson.gen.c"
yy217:
		yyaccept = 2;
		yych = (guchar)*(m = ++c);
		if (yych == 'b') goto yy250;
yy218:
#line 1224 "sjson.c"
		{
      CHECK_TYPE(S_JSON_TYPE_OBJECT)
    }
#line 3414 "sjson.gen.c"
yy219:
		yyaccept = 3;
		yych = (guchar)*(m = ++c);
		if (yych == 'o') goto yy244;
yy220:
#line 1220 "sjson.c"
		{
      CHECK_TYPE(S_JSON_TYPE_BOOL)
    }
#line 3424 "sjson.gen.c"
yy221:
		yyaccept = 4;
		yych = (guchar)*(m = ++c);
		if (yych == 'n') goto yy238;
yy222:
#line 1203 "sjson.c"
		{
      if (cur_node && s_json_get_type(cur_node) == S_JSON_TYPE_NUMBER)
      {
        const gchar *int_start, *int_end, *i;
        g_assert(s_json_get_token(cur_node, &int_start, &int_end) == TOK_NUMBER);
        for (i = int_start; i < int_end; i++)
          if (*i > '9' || *i < '0')
            return NULL;
        return cur_node;
      }

      if ((!cur_node || s_json_get_type(cur_node) == S_JSON_TYPE_NULL) && s[0] == '?')
        return "null";

      return NULL;
    }
#line 3447 "sjson.gen.c"
yy223:
		yyaccept = 5;
		yych = (guchar)*(m = ++c);
		if (yych == 't') goto yy233;
yy224:
#line 1199 "sjson.c"
		{
      CHECK_TYPE(S_JSON_TYPE_STRING)
    }
#line 3457 "sjson.gen.c"
yy225:
		yyaccept = 6;
		yych = (guchar)*(m = ++c);
		if (yych == 'u') goto yy227;
yy226:
#line 1195 "sjson.c"
		{
      CHECK_TYPE(S_JSON_TYPE_NUMBER)
    }
#line 3467 "sjson.gen.c"
yy227:
		yych = (guchar)*++c;
		if (yych == 'm') goto yy229;
yy228:
		c = m;
		if (yyaccept <= 3) {
			if (yyaccept <= 1) {
				if (yyaccept <= 0) {
					goto yy209;
				} else {
					goto yy216;
				}
			} else {
				if (yyaccept <= 2) {
					goto yy218;
				} else {
					goto yy220;
				}
			}
		} else {
			if (yyaccept <= 5) {
				if (yyaccept <= 4) {
					goto yy222;
				} else {
					goto yy224;
				}
			} else {
				goto yy226;
			}
		}
yy229:
		yych = (guchar)*++c;
		if (yych != 'b') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'r') goto yy228;
		yych = (guchar)*++c;
		goto yy226;
yy233:
		yych = (guchar)*++c;
		if (yych != 'r') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'i') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'n') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'g') goto yy228;
		yych = (guchar)*++c;
		goto yy224;
yy238:
		yych = (guchar)*++c;
		if (yych != 't') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'g') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'r') goto yy228;
		yych = (guchar)*++c;
		goto yy222;
yy244:
		yych = (guchar)*++c;
		if (yych != 'o') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'l') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'a') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'n') goto yy228;
		yych = (guchar)*++c;
		goto yy220;
yy250:
		yych = (guchar)*++c;
		if (yych != 'j') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'e') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'c') goto yy228;
		yych = (guchar)*++c;
		if (yych != 't') goto yy228;
		yych = (guchar)*++c;
		goto yy218;
yy255:
		yych = (guchar)*++c;
		if (yych != 'r') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'a') goto yy228;
		yych = (guchar)*++c;
		if (yych != 'y') goto yy228;
		yych = (guchar)*++c;
		goto yy216;
yy259:
		yych = (guchar)*++c;
		if (yych == ']') goto yy262;
		goto yy228;
yy260:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy228;
		if (yych <= '9') goto yy260;
		if (yych != ']') goto yy228;
yy262:
		++c;
#line 1182 "sjson.c"
		{
      if (!cur_node || s_json_get_type(cur_node) != S_JSON_TYPE_ARRAY)
        return NULL;

      guint index;
      sscanf(s + 1, "%u", &index);

      cur_node = s_json_get_element(cur_node, index);
      continue;
    }
#line 3587 "sjson.gen.c"
yy264:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '-') {
				if (yych >= '-') goto yy264;
			} else {
				if (yych <= '/') goto yy266;
				if (yych <= '9') goto yy264;
			}
		} else {
			if (yych <= '_') {
				if (yych <= 'Z') goto yy264;
				if (yych >= '_') goto yy264;
			} else {
				if (yych <= '`') goto yy266;
				if (yych <= 'z') goto yy264;
			}
		}
yy266:
#line 1169 "sjson.c"
		{
      if (!cur_node || s_json_get_type(cur_node) != S_JSON_TYPE_OBJECT)
        return NULL;

      // zero terminate member name on stack
      gchar* name = g_alloca((c - s));
      memcpy(name, s + 1, c - (s + 1));
      name[c - (s + 1)] = '\0';

      cur_node = s_json_get_member(cur_node, name);
      continue;
    }
#line 3621 "sjson.gen.c"
yy267:
		++c;
		yych = (guchar)*c;
yy268:
		if (yych <= '\f') {
			if (yych <= 0x08) goto yy205;
			if (yych <= '\n') goto yy267;
			goto yy205;
		} else {
			if (yych <= '\r') goto yy267;
			if (yych == ' ') goto yy267;
			goto yy205;
		}
	}
#line 1239 "sjson.c"

  }

  return cur_node;
}

gchar* s_json_compact(const gchar* json)
{
  g_return_val_if_fail(json != NULL, NULL);

  GString* str = g_string_sized_new(strlen(json));
  const guchar* c = (const guchar*)json;
  const guchar* m = NULL;
  const guchar* s;

  while (TRUE)
  {
    s = c;


#line 3657 "sjson.gen.c"
	{
		guchar yych;
		unsigned int yyaccept = 0;
		yych = (guchar)*c;
		if (yych <= '9') {
			if (yych <= ' ') {
				if (yych <= '\n') {
					if (yych <= 0x00) goto yy283;
					if (yych <= 0x08) goto yy285;
					goto yy281;
				} else {
					if (yych == '\r') goto yy281;
					if (yych <= 0x1F) goto yy285;
					goto yy281;
				}
			} else {
				if (yych <= ',') {
					if (yych == '"') goto yy273;
					if (yych <= '+') goto yy285;
				} else {
					if (yych <= '-') goto yy275;
					if (yych <= '/') goto yy285;
					if (yych <= '0') goto yy276;
					goto yy277;
				}
			}
		} else {
			if (yych <= 'm') {
				if (yych <= '\\') {
					if (yych <= ':') goto yy271;
					if (yych != '[') goto yy285;
				} else {
					if (yych <= ']') goto yy271;
					if (yych == 'f') goto yy279;
					goto yy285;
				}
			} else {
				if (yych <= 'z') {
					if (yych <= 'n') goto yy280;
					if (yych == 't') goto yy278;
					goto yy285;
				} else {
					if (yych == '|') goto yy285;
					if (yych >= '~') goto yy285;
				}
			}
		}
yy271:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= '\\') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy296;
					if (yych <= '9') goto yy298;
					goto yy291;
				} else {
					if (yych == '[') goto yy291;
				}
			}
		} else {
			if (yych <= 's') {
				if (yych <= 'f') {
					if (yych <= ']') goto yy291;
					if (yych >= 'f') goto yy301;
				} else {
					if (yych == 'n') goto yy302;
				}
			} else {
				if (yych <= '{') {
					if (yych <= 't') goto yy300;
					if (yych >= '{') goto yy291;
				} else {
					if (yych == '}') goto yy291;
				}
			}
		}
yy272:
#line 1259 "sjson.c"
		{
      g_string_append_len(str, s, c - s);
      continue;
    }
#line 3748 "sjson.gen.c"
yy273:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych >= 0x01) goto yy294;
yy274:
#line 1272 "sjson.c"
		{
      goto err;
    }
#line 3758 "sjson.gen.c"
yy275:
		yych = (guchar)*++c;
		if (yych <= '/') goto yy274;
		if (yych <= '9') goto yy297;
		goto yy274;
yy276:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= '[') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					if (yych <= '.') goto yy308;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy296;
					if (yych <= '9') goto yy298;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy277:
		yyaccept = 0;
		yych = (guchar)*(m = ++c);
		if (yych <= '[') {
			if (yych <= '.') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy308;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '/') goto yy272;
					if (yych <= '9') goto yy298;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy278:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych == 'r') goto yy306;
		goto yy274;
yy279:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych == 'a') goto yy303;
		goto yy274;
yy280:
		yyaccept = 1;
		yych = (guchar)*(m = ++c);
		if (yych == 'u') goto yy288;
		goto yy274;
yy281:
		++c;
		yych = (guchar)*c;
		goto yy287;
yy282:
#line 1264 "sjson.c"
		{
      continue;
    }
#line 3881 "sjson.gen.c"
yy283:
		++c;
#line 1268 "sjson.c"
		{ 
      break;   
    }
#line 3888 "sjson.gen.c"
yy285:
		yych = (guchar)*++c;
		goto yy274;
yy286:
		++c;
		yych = (guchar)*c;
yy287:
		if (yych <= '\f') {
			if (yych <= 0x08) goto yy282;
			if (yych <= '\n') goto yy286;
			goto yy282;
		} else {
			if (yych <= '\r') goto yy286;
			if (yych == ' ') goto yy286;
			goto yy282;
		}
yy288:
		++c;
		yych = (guchar)*c;
		if (yych == 'l') goto yy290;
yy289:
		c = m;
		if (yyaccept <= 0) {
			goto yy272;
		} else {
			goto yy274;
		}
yy290:
		++c;
		yych = (guchar)*c;
		if (yych != 'l') goto yy289;
yy291:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '\\') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych != '"') goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy296;
					if (yych <= '9') goto yy298;
					goto yy291;
				} else {
					if (yych == '[') goto yy291;
					goto yy272;
				}
			}
		} else {
			if (yych <= 's') {
				if (yych <= 'f') {
					if (yych <= ']') goto yy291;
					if (yych <= 'e') goto yy272;
					goto yy301;
				} else {
					if (yych == 'n') goto yy302;
					goto yy272;
				}
			} else {
				if (yych <= '{') {
					if (yych <= 't') goto yy300;
					if (yych <= 'z') goto yy272;
					goto yy291;
				} else {
					if (yych == '}') goto yy291;
					goto yy272;
				}
			}
		}
yy293:
		++c;
		yych = (guchar)*c;
yy294:
		if (yych <= '"') {
			if (yych <= 0x00) goto yy289;
			if (yych <= '!') goto yy293;
			goto yy291;
		} else {
			if (yych == '\\') goto yy321;
			goto yy293;
		}
yy295:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy289;
		if (yych <= '0') goto yy296;
		if (yych <= '9') goto yy298;
		goto yy289;
yy296:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
yy297:
		if (yych <= '[') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					if (yych <= '.') goto yy308;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy296;
					if (yych >= ':') goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy298:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '.') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy308;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '/') goto yy272;
					if (yych <= '9') goto yy298;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych != 't') goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy300:
		++c;
		yych = (guchar)*c;
		if (yych == 'r') goto yy306;
		goto yy289;
yy301:
		++c;
		yych = (guchar)*c;
		if (yych == 'a') goto yy303;
		goto yy289;
yy302:
		++c;
		yych = (guchar)*c;
		if (yych == 'u') goto yy288;
		goto yy289;
yy303:
		++c;
		yych = (guchar)*c;
		if (yych != 'l') goto yy289;
		++c;
		yych = (guchar)*c;
		if (yych != 's') goto yy289;
		++c;
		yych = (guchar)*c;
		if (yych == 'e') goto yy291;
		goto yy289;
yy306:
		++c;
		yych = (guchar)*c;
		if (yych != 'u') goto yy289;
		++c;
		yych = (guchar)*c;
		if (yych == 'e') goto yy291;
		goto yy289;
yy308:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy289;
		if (yych <= '9') goto yy316;
		goto yy289;
yy309:
		++c;
		yych = (guchar)*c;
		if (yych <= ',') {
			if (yych != '+') goto yy289;
		} else {
			if (yych <= '-') goto yy310;
			if (yych <= '/') goto yy289;
			if (yych <= '9') goto yy311;
			goto yy289;
		}
yy310:
		++c;
		yych = (guchar)*c;
		if (yych <= '/') goto yy289;
		if (yych >= ':') goto yy289;
yy311:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '\\') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy312;
					if (yych <= '9') goto yy314;
					goto yy291;
				} else {
					if (yych == '[') goto yy291;
					goto yy272;
				}
			}
		} else {
			if (yych <= 's') {
				if (yych <= 'f') {
					if (yych <= ']') goto yy291;
					if (yych <= 'e') goto yy272;
					goto yy301;
				} else {
					if (yych == 'n') goto yy302;
					goto yy272;
				}
			} else {
				if (yych <= '{') {
					if (yych <= 't') goto yy300;
					if (yych <= 'z') goto yy272;
					goto yy291;
				} else {
					if (yych == '}') goto yy291;
					goto yy272;
				}
			}
		}
yy312:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					if (yych <= '.') goto yy308;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy312;
					if (yych >= ':') goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy314:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '.') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy308;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '/') goto yy272;
					if (yych <= '9') goto yy314;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy316:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy317;
					if (yych <= '9') goto yy319;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy317:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '/') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					if (yych <= '.') goto yy308;
					goto yy272;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '0') goto yy317;
					if (yych >= ':') goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy319:
		yyaccept = 0;
		m = ++c;
		yych = (guchar)*c;
		if (yych <= '[') {
			if (yych <= '.') {
				if (yych <= '+') {
					if (yych == '"') goto yy293;
					goto yy272;
				} else {
					if (yych <= ',') goto yy291;
					if (yych <= '-') goto yy295;
					goto yy308;
				}
			} else {
				if (yych <= ':') {
					if (yych <= '/') goto yy272;
					if (yych <= '9') goto yy319;
					goto yy291;
				} else {
					if (yych == 'E') goto yy309;
					if (yych <= 'Z') goto yy272;
					goto yy291;
				}
			}
		} else {
			if (yych <= 'n') {
				if (yych <= 'd') {
					if (yych == ']') goto yy291;
					goto yy272;
				} else {
					if (yych <= 'e') goto yy309;
					if (yych <= 'f') goto yy301;
					if (yych <= 'm') goto yy272;
					goto yy302;
				}
			} else {
				if (yych <= 'z') {
					if (yych == 't') goto yy300;
					goto yy272;
				} else {
					if (yych == '|') goto yy272;
					if (yych <= '}') goto yy291;
					goto yy272;
				}
			}
		}
yy321:
		++c;
		yych = (guchar)*c;
		if (yych <= 'e') {
			if (yych <= '/') {
				if (yych == '"') goto yy323;
				if (yych <= '.') goto yy289;
				goto yy323;
			} else {
				if (yych <= '\\') {
					if (yych <= '[') goto yy289;
					goto yy323;
				} else {
					if (yych == 'b') goto yy323;
					goto yy289;
				}
			}
		} else {
			if (yych <= 'q') {
				if (yych <= 'f') goto yy323;
				if (yych == 'n') goto yy323;
				goto yy289;
			} else {
				if (yych <= 's') {
					if (yych <= 'r') goto yy323;
					goto yy289;
				} else {
					if (yych <= 't') goto yy323;
					if (yych >= 'v') goto yy289;
				}
			}
		}
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy289;
			if (yych <= '9') goto yy325;
			goto yy289;
		} else {
			if (yych <= 'F') goto yy325;
			if (yych <= '`') goto yy289;
			if (yych <= 'f') goto yy325;
			goto yy289;
		}
yy323:
		++c;
		yych = (guchar)*c;
		if (yych <= '"') {
			if (yych <= 0x00) goto yy289;
			if (yych <= '!') goto yy323;
			goto yy291;
		} else {
			if (yych == '\\') goto yy321;
			goto yy323;
		}
yy325:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy289;
			if (yych >= ':') goto yy289;
		} else {
			if (yych <= 'F') goto yy326;
			if (yych <= '`') goto yy289;
			if (yych >= 'g') goto yy289;
		}
yy326:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy289;
			if (yych >= ':') goto yy289;
		} else {
			if (yych <= 'F') goto yy327;
			if (yych <= '`') goto yy289;
			if (yych >= 'g') goto yy289;
		}
yy327:
		++c;
		yych = (guchar)*c;
		if (yych <= '@') {
			if (yych <= '/') goto yy289;
			if (yych <= '9') goto yy323;
			goto yy289;
		} else {
			if (yych <= 'F') goto yy323;
			if (yych <= '`') goto yy289;
			if (yych <= 'f') goto yy323;
			goto yy289;
		}
	}
#line 1275 "sjson.c"

  }

  return g_string_free(str, FALSE);

err:
  g_string_free(str, TRUE);
  return NULL;
}
