/* Generated from "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod" by precompile.pike running Pike v8.0 release 1017
 *
 * Do NOT edit this file.
 */

#undef PRECOMPILE_API_VERSION
#define PRECOMPILE_API_VERSION 6

#undef PRECOMPILE_SUB_PIKEVARS
#define PRECOMPILE_SUB_PIKEVARS 1

#undef PRECOMPILE_DYNAMIC_TYPES
#define PRECOMPILE_DYNAMIC_TYPES 1



#undef cmod___CMOD__
#define cmod___CMOD__ 1
#line 1 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#line 1 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#line 1 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#line 3003 "/Users/hww3/devel/pike/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike"







#line 3010 "/Users/hww3/devel/pike/lib/modules/Tools.pmod/Standalone.pmod/precompile.pike"
#line 1 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#line 1 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
/* -*- c -*-
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
*/

/* JSON tools.
 *
 * Ref: RFC 4627
 *
 * Decoder comes from Public.Parser.JSON2 by Arne Gödeke.
 * Encoder created May 2010 by Martin Stjernholm.
 */

#include "array.h"
#include "cyclic.h"
#include "global.h"
#include "interpret.h"
#include "mapping.h"
#include "module.h"
#include "pike_error.h"
#include "pike_float.h"
#include "pike_types.h"
#include "stralloc.h"
#include "svalue.h"
#include "module_support.h"

#define DEFAULT_CMOD_STORAGE static



#ifndef PIKE_UNUSED_ATTRIBUTE
#define PIKE_UNUSED_ATTRIBUTE
#endif
#define CMOD_MAP_PROGRAM_IDS_DEFINED 1
static int ___cmod_map_program_ids(int id) PIKE_UNUSED_ATTRIBUTE;
#ifndef TYPEOF
/* Compat with older Pikes. */
#define TYPEOF(SVAL)	((SVAL).type)
#define SUBTYPEOF(SVAL)	((SVAL).subtype)
#define SET_SVAL_TYPE(SVAL, TYPE)	(TYPEOF(SVAL) = TYPE)
#define SET_SVAL_SUBTYPE(SVAL, TYPE)	(SUBTYPEOF(SVAL) = TYPE)
#define SET_SVAL(SVAL, TYPE, SUBTYPE, FIELD, EXPR) do {	\
    /* Set the type afterwards to avoid a clobbered	\
     * svalue in case EXPR throws. */			\
    (SVAL).u.FIELD = (EXPR);				\
    SET_SVAL_TYPE((SVAL), (TYPE));			\
    SET_SVAL_SUBTYPE((SVAL), (SUBTYPE));		\
  } while(0)
#endif /* !TYPEOF */
#ifndef PIKE_UNUSED
/* Compat with Pike 7.8 and earlier. */
/* NB: Not strictly correct; PIKE_UNUSED was added the
 *     day after set_program_id_to_id(), but good enough.
 */
#ifndef UNUSED
#define UNUSED(X)	X
#endif
#ifndef set_program_id_to_id
/* NB: Recent Pike 7.8 has a #define that conflicts with
 *     the following declaration.
 */
static void set_program_id_to_id(void*UNUSED(id)){}
#endif
#else /* */
PMOD_EXPORT void set_program_id_to_id( int (*to)(int) );
#endif /* !PIKE_UNUSED */


#ifndef DEFAULT_CMOD_STORAGE
#define CMOD_COND_USED
#define DEFAULT_CMOD_STORAGE static
#endif
#ifndef CMOD_COND_USED
# define f_JSON_encode_fun_num_used 1
#else
#undef f_JSON_encode_fun_num_used
#endif
#ifndef CMOD_COND_USED
# define f_JSON_escape_string_fun_num_used 1
#else
#undef f_JSON_escape_string_fun_num_used
#endif
#ifndef CMOD_COND_USED
# define f_JSON_validate_fun_num_used 1
#else
#undef f_JSON_validate_fun_num_used
#endif
#ifndef CMOD_COND_USED
# define f_JSON_decode_fun_num_used 1
#else
#undef f_JSON_decode_fun_num_used
#endif
#ifndef CMOD_COND_USED
# define f_JSON_validate_utf8_fun_num_used 1
#else
#undef f_JSON_validate_utf8_fun_num_used
#endif
#ifndef CMOD_COND_USED
# define f_JSON_decode_utf8_fun_num_used 1
#else
#undef f_JSON_decode_utf8_fun_num_used
#endif
/*! @module Standards */

/*! @module JSON */

#line 36 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#define ASCII_ONLY 1
#define HUMAN_READABLE 2
#define PIKE_CANONICAL 4

#define JSON_UTF8	1
#define JSON_ERROR	2
#define JSON_VALIDATE	4
#define JSON_FIRST_VALUE 8

static char *err_msg;

#define PUSH_SPECIAL(X) do {if (!(state->flags&JSON_VALIDATE)) {	\
    push_object (get_val_##X());					\
} c++; if (state->level > 0) return p+1; } while(0)

#define PARSE(X, FPC) do {						\
    state->level++;							\
    i = _parse_JSON_##X(str, FPC, pe, state);				\
    state->level--;							\
    if (state->flags&JSON_ERROR) {					\
	    return i;							\
    } else if (state->level > 0) return i;				\
    c++;								\
} while(0)

#define PARSE_STRING(FPC) do {						\
    state->level++;							\
    if (state->flags&JSON_UTF8) 					\
	i = _parse_JSON_string_utf8(str, FPC, pe, state);		\
    else								\
	i = _parse_JSON_string(str, FPC, pe, state);			\
    state->level--;							\
    if (state->flags&JSON_ERROR) {					\
	    return i;							\
    } else if (state->level > 0) return i;				\
    c++;								\
} while(0)

#define IS_SURROGATE(x) ((x) >= 0xd800 && (x) < 0xe000)
#define IS_HIGH_SURROGATE(x) ((x) >= 0xd800 && (x) < 0xdc00)
#define IS_LOW_SURROGATE(x) ((x) >= 0xdc00 && (x) < 0xe000)
#define IS_NUNICODE(x)	((x) < 0 || IS_SURROGATE (x) || (x) > 0x10ffff)
#define IS_NUNICODE1(x)	((x) < 0 || IS_SURROGATE (x))

static void json_escape_string (struct string_builder *buf, int flags,
struct pike_string *val)
{
PCHARP str = MKPCHARP_STR (val);
ptrdiff_t l = val->len, i, s;
for (s = 0, i = 0; i < l; i++) {
p_wchar2 c = INDEX_PCHARP (str, i);
if (c < 0 || c > 0x10ffff)
Pike_error ("Cannot json encode non-unicode char "
"0x%"PRINTPIKEINT"x.\n", (INT_TYPE) c);
if (c == '"' || c == '\\' || c <= 0x1f ||
(c >= 0x7f && flags & ASCII_ONLY) ||
/* Let's escape U+2028 and U+2029 as well for compat with
	 * parsers built in javascript - see
	 * http://timelessrepo.com/json-isnt-a-javascript-subset. */
c == 0x2028 || c == 0x2029) {
if (s < i) {
PCHARP piece = ADD_PCHARP (str, s);
string_builder_append (buf, piece, i - s);
}
string_builder_putchar (buf, '\\');
switch (c) {
case '"': string_builder_putchar (buf, '"'); break;
case '\\': string_builder_putchar (buf, '\\'); break;
case '\b': string_builder_putchar (buf, 'b'); break;
case '\f': string_builder_putchar (buf, 'f'); break;
case '\n': string_builder_putchar (buf, 'n'); break;
case '\r': string_builder_putchar (buf, 'r'); break;
case '\t': string_builder_putchar (buf, 't'); break;
default:
if (c <= 0xffff) {
string_builder_putchar (buf, 'u');
string_builder_append_integer (buf, c, 16, APPEND_ZERO_PAD, 4, 4);
}
else {
string_builder_putchar (buf, 'u');
c -= 0x10000;
string_builder_append_integer (buf, (c >> 10) + 0xd800, 16,
APPEND_ZERO_PAD, 4, 4);
string_builder_strcat (buf, "\\u");
string_builder_append_integer (buf, (c & 0x3ff) + 0xdc00, 16,
APPEND_ZERO_PAD, 4, 4);
}
break;
}
s = i + 1;
}
}
if (s < i) {
PCHARP piece = ADD_PCHARP (str, s);
string_builder_append (buf, piece, i - s);
}
}

struct parser_state {
unsigned int level;
int flags;
};

struct encode_context {
struct string_builder buf;
int flags;
int indent;
struct svalue *callback;
};

static void json_encode_recur (struct encode_context *ctx, struct svalue *val);

static void encode_mapcont (struct encode_context *ctx, struct mapping *m)
/* Assumes there's at least one element. */
{
struct string_builder *buf = &ctx->buf;
int e, notfirst = 0;
struct keypair *k;
struct mapping_data *md = m->data;

NEW_MAPPING_LOOP (md) {
if (notfirst) {
string_builder_putchar (buf, ',');
if (ctx->indent >= 0) {
int indent = ctx->indent;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
}
else {
if (ctx->indent >= 0) {
int indent = ctx->indent = ctx->indent + 2;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
notfirst = 1;
}

if (TYPEOF(k->ind) != T_STRING)
Pike_error ("Cannot json encode mapping with non-string index %O.\n",
&k->ind);
json_encode_recur (ctx, &k->ind);

string_builder_putchar (buf, ':');
if (ctx->indent >= 0) string_builder_putchar (buf, ' ');
json_encode_recur (ctx, &k->val);
}
}

static void encode_mapcont_canon (struct encode_context *ctx, struct mapping *m)
/* Assumes there's at least one element. */
{
struct string_builder *buf = &ctx->buf;
int i, notfirst = 0;
struct array *inds = mapping_indices (m);
int size = inds->size;
ONERROR uwp;
SET_ONERROR (uwp, do_free_array, inds);

/* encode_value_canonic uses get_switch_order, but this sort is good
   * enough considering we only have to deal (correctly) with strings. */
sort_array_destructively (inds);

for (i = 0; i < size; i++) {
struct svalue *ind = ITEM (inds) + i;

{
/* Push the value on the stack so we know it's still there when
       * we get to formatting it. Probably not really necessary, but
       * better safe than sorry. */
struct svalue *val = low_mapping_lookup (m, ind);
if (val)
push_svalue (val);
else
/* The entry has disappeared since the array was created.
	 * Ignore it and continue is the right thing to do. */
continue;
}

if (notfirst) {
int indent = ctx->indent;
fast_check_threads_etc(8);
string_builder_putchar (buf, ',');
if (indent >= 0) {
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
}
else {
int indent = ctx->indent;
if (indent >= 0) {
ctx->indent = indent = indent + 2;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
notfirst = 1;
}

if (TYPEOF(*ind) != T_STRING)
Pike_error ("Cannot json encode mapping with non-string index %O.\n",
ind);
json_encode_recur (ctx, ind);

string_builder_putchar (buf, ':');
if (ctx->indent >= 0) string_builder_putchar (buf, ' ');

json_encode_recur (ctx, Pike_sp - 1);
pop_stack();
}

UNSET_ONERROR (uwp);
free_array (inds);
}

static void json_encode_recur (struct encode_context *ctx, struct svalue *val)
{
DECLARE_CYCLIC();

check_c_stack (1024);

if (TYPEOF(*val) <= MAX_COMPLEX && BEGIN_CYCLIC (val->u.ptr, 0))
Pike_error ("Cyclic data structure - already visited %O.\n", val);

switch (TYPEOF(*val)) {
case PIKE_T_STRING: {
struct string_builder *buf = &ctx->buf;
string_builder_putchar (buf, '"');
json_escape_string (buf, ctx->flags, val->u.string);
string_builder_putchar (buf, '"');
break;
}

case PIKE_T_INT:
if(SUBTYPEOF(*val))
string_builder_strcat(&ctx->buf,"null");
else
string_builder_append_integer (&ctx->buf, val->u.integer,
10, APPEND_SIGNED, 0, 0);
break;

case PIKE_T_FLOAT: {
FLOAT_TYPE f = val->u.float_number;
char b[MAX_FLOAT_SPRINTF_LEN];
if (PIKE_ISNAN (f) || PIKE_ISINF (f))
{
string_builder_strcat(&ctx->buf, "null");
break;
}
format_pike_float (b, f);
string_builder_strcat (&ctx->buf, b);
break;
}

case PIKE_T_ARRAY: {
struct string_builder *buf = &ctx->buf;
string_builder_putchar (buf, '[');
{
struct array *a = val->u.array;
int size = a->size;
if (size) {
int i;
if (ctx->indent >= 0 && size > 1) {
int indent = ctx->indent = ctx->indent + 2;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
json_encode_recur (ctx, ITEM (a));
for (i = 1; i < size; i++) {
fast_check_threads_etc(8);
string_builder_putchar (buf, ',');
if (ctx->indent >= 0) {
int indent = ctx->indent;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
json_encode_recur (ctx, ITEM (a) + i);
}
if (ctx->indent >= 0 && size > 1) {
int indent = ctx->indent = ctx->indent - 2;
string_builder_putchar (buf, '\n');
string_builder_putchars (buf, ' ', indent);
}
}
}
string_builder_putchar (buf, ']');
break;
}

case PIKE_T_MAPPING: {
string_builder_putchar (&ctx->buf, '{');
check_mapping_for_destruct (val->u.mapping);
if (m_sizeof (val->u.mapping)) {
if (ctx->flags & PIKE_CANONICAL)
encode_mapcont_canon (ctx, val->u.mapping);
else
encode_mapcont (ctx, val->u.mapping);
if (ctx->indent >= 0) {
int indent = ctx->indent = ctx->indent - 2;
string_builder_putchar (&ctx->buf, '\n');
string_builder_putchars (&ctx->buf, ' ', indent);
}
}
string_builder_putchar (&ctx->buf, '}');
break;
}

case PIKE_T_OBJECT: {
struct object *o = val->u.object;
if (o->prog) {
int fun = find_identifier ("encode_json", o->prog);
if (fun < 0) {
int args = 2;
if (!ctx->callback)
Pike_error ("Cannot json encode object %O "
"without encode_json function.\n", val);
if (TYPEOF(*ctx->callback) == PIKE_T_STRING) {
string_builder_shared_strcat (&ctx->buf, ctx->callback->u.string);
break;
}
push_svalue(val);
push_int(ctx->flags);
if (ctx->indent >= 0) {
args++;
push_int(ctx->indent);
}
apply_svalue(ctx->callback, args);
} else {
int args = 1;
push_int (ctx->flags);
if (ctx->indent >= 0) {
push_int (ctx->indent);
args++;
}
apply_low (o, fun, args);
}
if (TYPEOF(Pike_sp[-1]) != PIKE_T_STRING)
Pike_error ("Expected string from %O->encode_json(), got %s.\n",
val, get_name_of_type (TYPEOF(Pike_sp[-1])));
string_builder_shared_strcat (&ctx->buf, Pike_sp[-1].u.string);
free_string ((--Pike_sp)->u.string);
break;
}
}

default:
Pike_error ("Cannot json encode %s.\n", get_name_of_type (TYPEOF(*val)));
}

if (TYPEOF(*val) <= MAX_COMPLEX)
END_CYCLIC();
}

/*! @decl constant ASCII_ONLY
 *! @decl constant HUMAN_READABLE
 *! @decl constant PIKE_CANONICAL
 *!
 *! Bit field flags for use with @[encode]:
 *!
 *! @dl
 *! @item Standards.JSON.ASCII_ONLY
 *!   Use @expr{\uxxxx@} escapes for all non-ascii characters and DEL
 *!   (U+007f). The default is to escape only the characters that must
 *!   be escaped. The flag value is 1.
 *!
 *!   Characters above U+FFFF are encoded using escaped surrogate
 *!   pairs, as per RFC 4627.
 *!
 *! @item Standards.JSON.HUMAN_READABLE
 *!   Pretty print with indentation to make the result easier on human
 *!   eyes. The default is to use no extra whitespace at all. The flag
 *!   value is 2.
 *!
 *! @item Standards.JSON.PIKE_CANONICAL
 *!   Make the output canonical, so that the same value always
 *!   generates the same char-by-char equal string. In practice this
 *!   means that mapping elements are sorted on their indices. Note
 *!   that the other flags take precedence, so e.g. the canonical form
 *!   with @[HUMAN_READABLE] is not the same as the canonical form
 *!   without it. The flag value is 4.
 *!
 *!   This canonical form is stable for the @[encode] function,
 *!   providing floats aren't used (their formatting is currently
 *!   affected by float size and libc formatting code). In the future
 *!   there may be a standardized canonical form which quite likely
 *!   will be different from this one. In that case a separate flag
 *!   has to be added so this one doesn't change - hence the name
 *!   @[PIKE_CANONICAL].
 *! @enddl
 */

/*! @decl string encode (int|float|string|array|mapping|object val, @
 *!                      void|int flags, void|function|object|program|string callback)
 *!
 *! Encodes a value to a JSON string.
 *!
 *! @param val
 *!   The value to encode. It can contain integers, floats (except the
 *!   special numbers NaN and infinity), strings, arrays, mappings
 *!   with string indices, and the special object values @[null],
 *!   @[true] and @[false] defined in this module (or really any
 *!   object that implements an @expr{encode_json@} callback or
 *!   is handled by the supplied callback argument).
 *!
 *! @param flags
 *!   Flag bit field to control formatting. See @[ASCII_ONLY],
 *!   @[HUMAN_READABLE] and @[PIKE_CANONICAL] for further details.
 *!
 *! @param callback
 *!   A function that will be called for types that can not be encoded
 *!   otherwise.  It will be called with the value to be encoded as the first
 *!   argument, and optionally with flags and indent arguments. If a string is
 *!   supplied, it will be used to replace the value verbatim.
 *!   The callback must return a string or throw an error.
 *!
 *! @note
 *! 8-bit and wider characters in input strings are neither escaped
 *! nor utf-8 encoded by default. @[string_to_utf8] can be used safely
 *! on the returned string to get a valid transport encoded JSON
 *! string. See @[escape_string] for further details on string
 *! escaping.
 *!
 *! @seealso
 *! @[escape_string]
 */
#define f_JSON_encode_defined

#ifdef f_JSON_encode_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_encode_fun_num = 0;

#endif /* f_JSON_encode_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_encode(INT32 args) {
#line 460 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct svalue * val;
struct svalue * flags;
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct svalue * callback;
struct svalue * base_indent;
#line 460 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args < 1) wrong_number_of_args_error("encode",args,1);
#line 460 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args > 4) wrong_number_of_args_error("encode",args,4);
#line 460 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
val=Pike_sp+0-args; dmalloc_touch_svalue(Pike_sp+0-args);
if ((args > 1) &&
    ((TYPEOF(Pike_sp[1-args]) != PIKE_T_INT) ||
     (SUBTYPEOF(Pike_sp[1-args]) != NUMBER_UNDEFINED))) {
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[1-args]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("encode",2,"void|int");
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
flags=Pike_sp+1-args; dmalloc_touch_svalue(Pike_sp+1-args);
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
} else flags = NULL;
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if ((args > 2) &&
    ((TYPEOF(Pike_sp[2-args]) != PIKE_T_INT) ||
     (SUBTYPEOF(Pike_sp[2-args]) != NUMBER_UNDEFINED))) {
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
callback=Pike_sp+2-args; dmalloc_touch_svalue(Pike_sp+2-args);
#line 461 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
} else callback = NULL;
if ((args > 3) &&
    ((TYPEOF(Pike_sp[3-args]) != PIKE_T_INT) ||
     (SUBTYPEOF(Pike_sp[3-args]) != NUMBER_UNDEFINED))) {
#line 462 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[3-args]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("encode",4,"void|int");
#line 462 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
base_indent=Pike_sp+3-args; dmalloc_touch_svalue(Pike_sp+3-args);
#line 462 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
} else base_indent = NULL;
#line 464 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
{
struct encode_context ctx;
ONERROR uwp;
ctx.flags = (flags ? flags->u.integer : 0);
ctx.indent = (ctx.flags & HUMAN_READABLE ? base_indent ? base_indent->u.integer : 0 : -1);
ctx.callback = callback;
init_string_builder (&ctx.buf, 0);
SET_ONERROR (uwp, free_string_builder, &ctx.buf);
json_encode_recur (&ctx, val);
UNSET_ONERROR (uwp);
do { struct pike_string * ret_=(finish_string_builder (&ctx.buf)); pop_n_elems(args); push_string(ret_); return; }while(0);
#line 475 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
}

}
/*! @decl string escape_string (string str, void|int flags)
 *!
 *! Escapes string data for use in a JSON string.
 *!
 *! 8-bit and wider characters in input strings are neither escaped
 *! nor utf-8 encoded by default. @[string_to_utf8] can be used safely
 *! on the returned string to get a valid transport encoded JSON
 *! string.
 *!
 *! The characters U+2028 (LINE SEPARATOR) and U+2029 (PARAGRAPH
 *! SEPARATOR) are exceptions - they are encoded with \u escapes for
 *! compatibility. The reason is that those characters are not allowed
 *! in Javascript strings, so JSON parsers built in Javascript may
 *! have trouble with them otherwise.
 *!
 *! @param val
 *!   The string to escape.
 *!
 *! @param flags
 *!   Flag bit field to control formatting. @[ASCII_ONLY] is the only
 *!   flag that has any effect for this function.
 *!
 *! @note
 *! The difference between using this function and @[encode] on a
 *! string is that @[encode] returns quotations marks around the
 *! result.
 *!
 *! @seealso
 *! @[encode]
 */
#define f_JSON_escape_string_defined

#ifdef f_JSON_escape_string_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_escape_string_fun_num = 0;

#endif /* f_JSON_escape_string_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_escape_string(INT32 args) {
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct pike_string * str;
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct svalue * flags;
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args < 1) wrong_number_of_args_error("escape_string",args,1);
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args > 2) wrong_number_of_args_error("escape_string",args,2);
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[0-args]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("escape_string",1,"string");
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
debug_malloc_pass(str=Pike_sp[0-args].u.string);
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if ((args > 1) &&
    ((TYPEOF(Pike_sp[1-args]) != PIKE_T_INT) ||
     (SUBTYPEOF(Pike_sp[1-args]) != NUMBER_UNDEFINED))) {
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[1-args]) != PIKE_T_INT) SIMPLE_ARG_TYPE_ERROR("escape_string",2,"void|int");
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
flags=Pike_sp+1-args; dmalloc_touch_svalue(Pike_sp+1-args);
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
} else flags = NULL;
{
struct string_builder buf;
ONERROR uwp;
init_string_builder (&buf, 0);
SET_ONERROR (uwp, free_string_builder, &buf);
json_escape_string (&buf, flags ? flags->u.integer : 0, str);
UNSET_ONERROR (uwp);
do { struct pike_string * ret_=(finish_string_builder (&buf)); pop_n_elems(args); push_string(ret_); return; }while(0);
#line 516 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
}

}
#line 518 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
#include "json_parser.c"

void low_validate(struct pike_string *data, int flags) {
ptrdiff_t stop;
struct parser_state state;

state.flags = flags|JSON_VALIDATE;
state.level = 0;

stop = _parse_JSON(MKPCHARP_STR(data), 0, data->len, &state);

if (state.flags & JSON_ERROR || stop != data->len) {
push_int((INT_TYPE)stop);
} else {
push_int(-1);
}

return;
}

ptrdiff_t parse_json_pcharp( PCHARP data, size_t len, int flags, char **err_out )
{
ptrdiff_t stop;
struct parser_state state;

err_msg = NULL;
state.flags = flags;
state.level = 0;
stop = _parse_JSON(data, 0, len, &state );
if (state.flags & JSON_ERROR )
{
if( err_out )
*err_out = err_msg;
return -stop;
}
return stop;
}

void low_decode(struct pike_string *data, int flags) {
ptrdiff_t stop;
struct parser_state state;

err_msg = NULL;

state.level = 0;
state.flags = flags;

stop = _parse_JSON(MKPCHARP_STR(data), 0, data->len, &state);

if (!(state.flags&JSON_ERROR)) {
if (stop == data->len) {
return;
}
}

ref_push_string(data);
push_int((INT_TYPE)stop);
if (err_msg) {
push_text (err_msg);
apply (Pike_fp->current_object, "decode_error", 3);
}
else
apply (Pike_fp->current_object, "decode_error", 2);

return;
}


/*! @decl int validate(string s)
 *!
 *! Checks if a string is valid JSON.
 *! 
 *! @returns
 *! 	In case the string contains valid JSON @expr{-1@} is returned. It is then guaranteed to be parsed
 *! 	without errors by @[decode()].
 *! 	In case the string is not valid JSON, the error position is returned.
 */
#define f_JSON_validate_defined

#ifdef f_JSON_validate_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_validate_fun_num = 0;

#endif /* f_JSON_validate_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_validate(INT32 args) {
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct pike_string * data;
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args != 1) wrong_number_of_args_error("validate",args,1);
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[0-1]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("validate",1,"string");
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
debug_malloc_pass(data=Pike_sp[0-1].u.string);
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
{
low_validate(data, 0);
}

}
/*! @decl array|mapping|string|float|int|object decode(string s)
 *!
 *! Decodes a JSON string.
 *! 
 *! @throws
 *! 	Throws an exception in case the data contained in @expr{s@} is not valid
 *! 	JSON.
 */
#define f_JSON_decode_defined

#ifdef f_JSON_decode_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_decode_fun_num = 0;

#endif /* f_JSON_decode_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_decode(INT32 args) {
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct pike_string * data;
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args != 1) wrong_number_of_args_error("decode",args,1);
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[0-1]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("decode",1,"string");
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
debug_malloc_pass(data=Pike_sp[0-1].u.string);
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
{
low_decode(data, 0);
}

}
/*! @decl int validate_utf8(string s)
 *!
 *! Checks if a string is valid utf8 encoded JSON.
 *! 
 *! @returns
 *! 	In case the string contains valid JSON @expr{-1@} is returned. It is then guaranteed to be parsed
 *! 	without errors by @[decode()].
 *! 	In case the string is not valid JSON, the integer position inside the string
 *! 	where the error occurs is returned.
 */
#define f_JSON_validate_utf8_defined

#ifdef f_JSON_validate_utf8_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_validate_utf8_fun_num = 0;

#endif /* f_JSON_validate_utf8_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_validate_utf8(INT32 args) {
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct pike_string * data;
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args != 1) wrong_number_of_args_error("validate_utf8",args,1);
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[0-1]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("validate_utf8",1,"string");
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
debug_malloc_pass(data=Pike_sp[0-1].u.string);
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
{
if (data->size_shift)
Pike_error("Strings wider than 1 byte are NOT valid UTF-8.\n");

low_validate(data, JSON_UTF8);
}

}
/*! @decl array|mapping|string|float|int|object decode_utf8(string s)
 *!
 *! Decodes an utf8 encoded JSON string.
 *! Should give the same result as @expr{Standards.JSON.decode(utf8_to_string(s))@}.
 *! 
 *! @throws
 *! 	Throws an exception in case the data contained in @expr{s@} is not valid
 *! 	JSON.
 */
#define f_JSON_decode_utf8_defined

#ifdef f_JSON_decode_utf8_fun_num_used
DEFAULT_CMOD_STORAGE ptrdiff_t f_JSON_decode_utf8_fun_num = 0;

#endif /* f_JSON_decode_utf8_fun_num_used */
DEFAULT_CMOD_STORAGE void f_JSON_decode_utf8(INT32 args) {
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
struct pike_string * data;
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(args != 1) wrong_number_of_args_error("decode_utf8",args,1);
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
if(TYPEOF(Pike_sp[0-1]) != PIKE_T_STRING) SIMPLE_ARG_TYPE_ERROR("decode_utf8",1,"string");
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
debug_malloc_pass(data=Pike_sp[0-1].u.string);
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
{
if (data->size_shift) {
ref_push_string(data);
push_int(0);
push_text("Strings wider than 1 byte are NOT valid UTF-8.");
apply (Pike_fp->current_object, "decode_error", 3);
}

low_decode(data, JSON_UTF8);
}

}
/*! @endmodule */

/*! @endmodule */

#line 652 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
PIKE_MODULE_INIT
{
add_integer_constant ("ASCII_ONLY", ASCII_ONLY, 0);
add_integer_constant ("HUMAN_READABLE", HUMAN_READABLE, 0);
add_integer_constant ("PIKE_CANONICAL", PIKE_CANONICAL, 0);


#ifdef CMOD_MAP_PROGRAM_IDS_DEFINED
set_program_id_to_id( ___cmod_map_program_ids );

#endif /* CMOD_MAP_PROGRAM_IDS_DEFINED */

#ifdef f_JSON_encode_defined

#ifdef f_JSON_encode_fun_num_used
  f_JSON_encode_fun_num =
#endif /* f_JSON_encode_fun_num_used */
#line 460 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("encode", f_JSON_encode, tFunc(tOr6("\10\200\0\0\0\177\377\377\377",tFloat,tStr,tArray,tMapping,tObj) tOr(tVoid,"\10\200\0\0\0\177\377\377\377") tOr5(tVoid,tFuncV(tNone,tMix,tAny),tObj,tPrg(tObj),tStr) tOr(tVoid,"\10\200\0\0\0\177\377\377\377"),tStr), 0, OPT_TRY_OPTIMIZE);

#endif /* f_JSON_encode_defined */

#ifdef f_JSON_escape_string_defined

#ifdef f_JSON_escape_string_fun_num_used
  f_JSON_escape_string_fun_num =
#endif /* f_JSON_escape_string_fun_num_used */
#line 507 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("escape_string", f_JSON_escape_string, tFunc(tStr tOr(tVoid,"\10\200\0\0\0\177\377\377\377"),tStr), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_JSON_escape_string_defined */

#ifdef f_JSON_validate_defined

#ifdef f_JSON_validate_fun_num_used
  f_JSON_validate_fun_num =
#endif /* f_JSON_validate_fun_num_used */
#line 595 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("validate", f_JSON_validate, tFunc(tStr,"\10\200\0\0\0\177\377\377\377"), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_JSON_validate_defined */

#ifdef f_JSON_decode_defined

#ifdef f_JSON_decode_fun_num_used
  f_JSON_decode_fun_num =
#endif /* f_JSON_decode_fun_num_used */
#line 607 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("decode", f_JSON_decode, tFunc(tStr,tOr6(tArray,tMapping,tStr,tFloat,"\10\200\0\0\0\177\377\377\377",tObj)), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_JSON_decode_defined */

#ifdef f_JSON_validate_utf8_defined

#ifdef f_JSON_validate_utf8_fun_num_used
  f_JSON_validate_utf8_fun_num =
#endif /* f_JSON_validate_utf8_fun_num_used */
#line 621 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("validate_utf8", f_JSON_validate_utf8, tFunc(tStr,"\10\200\0\0\0\177\377\377\377"), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_JSON_validate_utf8_defined */

#ifdef f_JSON_decode_utf8_defined

#ifdef f_JSON_decode_utf8_fun_num_used
  f_JSON_decode_utf8_fun_num =
#endif /* f_JSON_decode_utf8_fun_num_used */
#line 637 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
    ADD_FUNCTION2("decode_utf8", f_JSON_decode_utf8, tFunc(tStr,tOr6(tArray,tMapping,tStr,tFloat,"\10\200\0\0\0\177\377\377\377",tObj)), 0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);

#endif /* f_JSON_decode_utf8_defined */

#ifdef CMOD_MAP_PROGRAM_IDS_DEFINED
set_program_id_to_id( 0 );
#endif /* CMOD_MAP_PROGRAM_IDS_DEFINED */
#line 658 "/Users/hww3/devel/pike/src/post_modules/JSON/json.cmod"
;

PIKE_MODULE_EXPORT(Standards.JSON, parse_json_pcharp );
}

PIKE_MODULE_EXIT
{
;
}


#ifdef CMOD_MAP_PROGRAM_IDS_DEFINED
static int ___cmod_map_program_ids(int id)
{
  int i = 0;
  if( (id&0x7f000000) != 0x7f000000 ) return id;
  id = id&0x00ffffff;
  return 0;
}
#endif /* CMOD_MAP_PROGRAM_IDS_DEFINED */
