Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Public.Parser.JSON2
Viewing contents of Public_Parser_JSON2-0.10/json.cmod

#line 1 "src/json.rl"
// vim:syntax=ragel

#include 
#include "global.h"
#include "interpret.h"
#include "stralloc.h"
#include "mapping.h"
#include "svalue.h"
#include "operators.h"
#include "object.h"
#include "array.h"
#include "builtin_functions.h"
#include "module.h"
#include "gc.h"
#include "config.h"

#include "json.h"

#include "json_utf8.c"

static p_wchar2 *_parse_JSON(p_wchar2 *p, p_wchar2 *pe, struct parser_state *state); 

#include "json_string.c"
#include "json_number.c"
#include "json_array.c"
#include "json_mapping.c"
#include "json_render.c"

#line 62 "src/json.rl"


static p_wchar2 *_parse_JSON(p_wchar2 *p, p_wchar2 *pe, struct parser_state *state) {
    p_wchar2 *i = p;
    int cs;
    int c = 0;
    
#line 39 "work/json.cmod"
static const int JSON_start = 1;
static const int JSON_first_final = 12;
static const int JSON_error = 0;

static const int JSON_en_main = 1;

#line 69 "src/json.rl"

    
#line 49 "work/json.cmod"
	{
	cs = JSON_start;
	}
#line 71 "src/json.rl"
    
#line 55 "work/json.cmod"
	{
	if ( p == pe )
		goto _out;
	switch ( cs )
	{
st1:
	if ( ++p == pe )
		goto _out1;
case 1:
	switch( (*p) ) {
		case 13: goto st1;
		case 32: goto st1;
		case 34: goto tr2;
		case 43: goto tr3;
		case 91: goto tr4;
		case 102: goto st2;
		case 110: goto st6;
		case 116: goto st9;
		case 123: goto tr8;
	}
	if ( (*p) < 45 ) {
		if ( 9 <= (*p) && (*p) <= 10 )
			goto st1;
	} else if ( (*p) > 46 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr3;
	} else
		goto tr3;
	goto st0;
st0:
	goto _out0;
tr2:
#line 43 "src/json.rl"
	{ PARSE(string, p); {p = (( i))-1;} }
	goto st12;
tr3:
#line 44 "src/json.rl"
	{ PARSE(number, p); {p = (( i))-1;} }
	goto st12;
tr4:
#line 46 "src/json.rl"
	{ PARSE(array, p); {p = (( i))-1;} }
	goto st12;
tr8:
#line 45 "src/json.rl"
	{ PARSE(mapping, p); {p = (( i))-1;} }
	goto st12;
tr12:
#line 50 "src/json.rl"
	{ PUSH_SPECIAL("false"); }
	goto st12;
tr15:
#line 51 "src/json.rl"
	{ PUSH_SPECIAL("null"); }
	goto st12;
tr18:
#line 49 "src/json.rl"
	{ PUSH_SPECIAL("true"); }
	goto st12;
st12:
	if ( ++p == pe )
		goto _out12;
case 12:
#line 61 "src/json.rl"
	{ if (state->level != 0) goto _out12; }
#line 121 "work/json.cmod"
	switch( (*p) ) {
		case 13: goto st12;
		case 32: goto st12;
	}
	if ( 9 <= (*p) && (*p) <= 10 )
		goto st12;
	goto st0;
st2:
	if ( ++p == pe )
		goto _out2;
case 2:
	if ( (*p) == 97 )
		goto st3;
	goto st0;
st3:
	if ( ++p == pe )
		goto _out3;
case 3:
	if ( (*p) == 108 )
		goto st4;
	goto st0;
st4:
	if ( ++p == pe )
		goto _out4;
case 4:
	if ( (*p) == 115 )
		goto st5;
	goto st0;
st5:
	if ( ++p == pe )
		goto _out5;
case 5:
	if ( (*p) == 101 )
		goto tr12;
	goto st0;
st6:
	if ( ++p == pe )
		goto _out6;
case 6:
	if ( (*p) == 117 )
		goto st7;
	goto st0;
st7:
	if ( ++p == pe )
		goto _out7;
case 7:
	if ( (*p) == 108 )
		goto st8;
	goto st0;
st8:
	if ( ++p == pe )
		goto _out8;
case 8:
	if ( (*p) == 108 )
		goto tr15;
	goto st0;
st9:
	if ( ++p == pe )
		goto _out9;
case 9:
	if ( (*p) == 114 )
		goto st10;
	goto st0;
st10:
	if ( ++p == pe )
		goto _out10;
case 10:
	if ( (*p) == 117 )
		goto st11;
	goto st0;
st11:
	if ( ++p == pe )
		goto _out11;
case 11:
	if ( (*p) == 101 )
		goto tr18;
	goto st0;
	}
	_out1: cs = 1; goto _out; 
	_out0: cs = 0; goto _out; 
	_out12: cs = 12; goto _out; 
	_out2: cs = 2; goto _out; 
	_out3: cs = 3; goto _out; 
	_out4: cs = 4; goto _out; 
	_out5: cs = 5; goto _out; 
	_out6: cs = 6; goto _out; 
	_out7: cs = 7; goto _out; 
	_out8: cs = 8; goto _out; 
	_out9: cs = 9; goto _out; 
	_out10: cs = 10; goto _out; 
	_out11: cs = 11; goto _out; 

	_out: {}
	}
#line 72 "src/json.rl"

    if (cs >= JSON_first_final) {
		return p;
    }

    if (!state->validate && c > 0) pop_n_elems(c);

    push_int((INT_TYPE)p);
    return NULL;
}

DECLARATIONS

/*! @module Public
 */

/*! @module Parser
 */

/*! @module JSON2
 *! This module contains a parser to parse JSON into native pike types. The parser has been written
 *! in c using ragel (@[http://www.cs.queensu.ca/~thurston/ragel/]).
 *! The parser is supposed to handle Unicode strings (internally 8, 16 and 32 bit wide strings that is).
 *! There are special functions for handling utf8 encoded Unicode strings.
 *! 
 *! Have a look at @[http://www.json.org] or @[http://www.ietf.org/rfc/rfc4627.txt?number=4627] for
 *! information about what JSON is.
 */

/*! @decl int validate(string s)
 *!
 *! Takes a string and checks if it is valid JSON.
 *! 
 *! @returns
 *! 	In case the string contains valid JSON @expr{-1@} is returned. It is then guarenteed to be parsed
 *! 	without errors by @[parse()].
 *! 	In case the string is not valid JSON, the integer position inside the string
 *! 	where the error occures is returned.
 */
PIKEFUN int validate(string data) {
    p_wchar2 *start;
    struct parser_state state;
    p_wchar2 *p;

    state.validate = 1;
    JSON_CONVERT(data, start);

    state.level = 0;
#ifdef JSON_CUSTOM_TYPES
    state.custom_chars = NULL;
#endif
    state.data = data;

    pop_stack();

    p = _parse_JSON(start, start + data->len, &state);

    if (data->size_shift < 2)
		free(start);

	if (p != NULL) {
		if (p == start + data->len) {
			push_int(-1);
			return;
		}

		push_int((INT_TYPE)(p - start) / 4);
		return;
    }

    push_int((INT_TYPE)start);
    f_minus(2);
    push_int(4);
    o_divide();

    return;
}

/*! @decl array|mapping|string|float|int parse(string s)
 *!
 *! Parses a JSON-formatted string and returns the corresponding pike data type.
 *! 
 *! @throws
 *! 	Throws an exception in case the data contained in @expr{s@} is not valid
 *! 	JSON.
 */
PIKEFUN mixed parse(string data) {
    p_wchar2 *start, *stop;
    struct parser_state state;
    int error_offset;

    state.validate = 0;
    JSON_CONVERT(data, start);

    state.level = 0;
#ifdef JSON_CUSTOM_TYPES
    state.custom_chars = NULL;
#endif
    state.data = data;

    stop = _parse_JSON(start, start + data->len, &state);

    if (data->size_shift < 2)
		free(start);

    if (stop != NULL) {
			
		if (stop == start + data->len) {
			stack_pop_keep_top(); // pop string data
			return;
		}

		pop_stack(); // pop unlegitimate result
		push_int((INT_TYPE)stop);
    }

    error_offset = (((struct svalue*)(Pike_sp - 1))->u.integer - (INT_TYPE)start) / 4;
    pop_stack();
    push_int(error_offset);
    push_int(error_offset+10);
    f_index(3);

    if (((struct svalue*)(Pike_sp - 1))->type != PIKE_T_STRING) {
		Pike_error("Parsing JSON failed and I dont know where.\n");
    } else {
		push_text("Parsing JSON failed in position %d (%O).\n");
		stack_swap();
		push_int(error_offset);
		stack_swap();
		f_sprintf(3);
		f_aggregate(1);
		f_throw(1);
    }

    return;
}

/*! @decl int validate_utf8(string s)
 *!
 *! Takes a utf8 encoded string and checks if it is valid JSON.
 *! 
 *! @returns
 *! 	In case the string contains valid JSON @expr{-1@} is returned. It is then guarenteed to be parsed
 *! 	without errors by @[parse()].
 *! 	In case the string is not valid JSON, the integer position inside the string
 *! 	where the error occures is returned.
 */
PIKEFUN int validate_utf8(string data) {
    char *start, *stop;
    struct parser_state state;

    switch (data->size_shift) {
    case 0:
        break;
    case 1:
    case 2:
		Pike_error("Strings wider than 1 byte are NOT valid UTF-8.\n");
        break;
    }

    start = (char *)STR0(data);

    state.validate = 1;
    state.level = 0;
#ifdef JSON_CUSTOM_TYPES
    state.custom_chars = NULL;
#endif
    state.data = data;

    pop_stack();
    if ((stop = _parse_JSON_utf8(start, (start + data->len), &state)) == NULL) {

		push_int((INT_TYPE)start);
		f_minus(2);

	} else {
		if (stop == start + data->len) {
			push_int(-1);
		} else {
			push_int((INT_TYPE)(stop - start));
		}
    }

    return;
}

/*! @decl array|mapping|string|float|int parse_utf8(string s)
 *!
 *! Parses a utf8 encoded JSON-formatted string and returns the corresponding pike data type.
 *! Should give the same results as @expr{Public.Parser.JSON2.parse(utf8_to_string(s))@}.
 *! 
 *! @throws
 *! 	Throws an exception in case the data contained in @expr{s@} is not valid
 *! 	JSON.
 */
PIKEFUN mixed parse_utf8(string data) {
    char *start, *stop;
    struct parser_state state;
    INT_TYPE error_offset;

    switch (data->size_shift) {
    case 0:
        break;
    case 1:
    case 2:
	Pike_error("Strings wider than 1 byte are NOT valid UTF-8.\n");
        break;
    }

    start = (char *)STR0(data);

    state.validate = 0;
    state.level = 0;
#ifdef JSON_CUSTOM_TYPES
    state.custom_chars = NULL;
#endif
    state.data = data;

    stop = _parse_JSON_utf8(start, (start + data->len), &state);

    if (stop != NULL) {
		if (stop == start + data->len) {
			stack_pop_keep_top(); // pop string data
			return;
		}

		pop_stack(); // pop the unlegitimate result
		push_int((INT_TYPE)stop);
    }

    error_offset = (((struct svalue*)(Pike_sp - 1))->u.integer - (INT_TYPE)start);
    pop_stack();
    push_int(error_offset);
    push_int(error_offset+10);
    f_index(3);
    if (((struct svalue*)(Pike_sp - 1))->type != PIKE_T_STRING) {
		Pike_error("Parsing JSON failed and I dont know where.\n");
    } else {
		push_text("Parsing JSON failed in position %d (%O).\n");
		stack_swap();
		push_int(error_offset);
		stack_swap();
		f_sprintf(3);
		f_aggregate(1);
		f_throw(1);
    }

    return;
}

/*! @decl string render(mixed data, int|void flags)
 *! @decl String.Buffer render(mixed data, int flags, String.Buffer buf)
 *!
 *! Encodes a native pike data structure into a Unicode string.
 *! 
 *! @note
 *! 	Multisets and mappings with non-string keys are not supported
 *! 	by JSON.
 *! @throws
 *! 	Throws an exception in case the data contains multisets or a
 *! 	mapping with non-string keys.
 */ 
PIKEFUN string render(mixed value, int|void flags, object|void buf) {
    struct string_builder s;
    ONERROR handle;

    init_string_builder(&s, 0);
    SET_ONERROR (handle, free_string_builder, &s);

    if (flags) {
		json_low_render(&s, value, flags->u.integer & 14, 0);
    } else json_low_render(&s, value, 0, 0);

    if (buf) {
		struct svalue sv;

		pop_n_elems(args);
		push_constant_text("add");
#if PIKE_MAJOR_VERSION < 7 || PIKE_MINOR_VERSION < 7
		object_index_no_free(&sv, buf, Pike_sp-1);
#else
		object_index_no_free(&sv, buf, 0, Pike_sp-1);
#endif
		pop_stack();

		push_svalue(&sv);
		UNSET_ONERROR (handle);
		push_string(finish_string_builder(&s));
		f_call_function(2);
		pop_stack();
		push_object(buf);
    } 

    UNSET_ONERROR (handle);
    RETURN(finish_string_builder(&s));
}

/*! @decl string render_utf8(mixed data, int|void flags)
 *! @decl String.Buffer render_utf8(mixed data, int flags, String.Buffer buf)
 *!
 *! Encodes a native pike data structure into a UTF8 encoded Unicode string.
 *! 
 *! @note
 *! 	Multisets and mappings with non-string keys are not supported
 *! 	by JSON.
 *! @throws
 *! 	Throws an exception in case the data contains multisets or a
 *! 	mapping with non-string keys.
 */ 
PIKEFUN string render_utf8(mixed value, int|void flags, object|void buf) {
    struct string_builder s;
    ONERROR handle;

    init_string_builder(&s, 0);
    SET_ONERROR (handle, free_string_builder, &s);

    if (flags) {
		json_low_render(&s, value, FLAG_UTF8 | (flags->u.integer & 14), 0);
    } else json_low_render(&s, value, FLAG_UTF8, 0);


    if (buf) {
		struct svalue sv;

		pop_n_elems(args);
		push_constant_text("add");
#if PIKE_MAJOR_VERSION < 7 || PIKE_MINOR_VERSION < 7
		object_index_no_free(&sv, buf, Pike_sp-1);
#else
		object_index_no_free(&sv, buf, 0, Pike_sp-1);
#endif
		pop_stack();

		push_svalue(&sv);
		UNSET_ONERROR (handle);
		push_string(finish_string_builder(&s));
		f_call_function(2);
		pop_stack();
		push_object(buf);
    } 

    UNSET_ONERROR (handle);
    RETURN(finish_string_builder(&s));
}

/*! @endmodule
 */
/*! @endmodule
 */
/*! @endmodule
 */


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University