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.7/json_render.c

// vim:syntax=c
#include "pike_types.h"                                                                                                                        
#include "stralloc.h"                                                                                                                          
#include "mapping.h"                                                                                                                           
#include "object.h"                                                                                                                            
#include "builtin_functions.h"                                                                                                                 
#include "version.h"

#define FLAG_UTF8	1
#define FLAG_HUMAN	2
#define FLAG_BEAUTY	3

void low_append_substr(struct string_builder *s, struct pike_string *str, int a, int b) {
    if (b >= str->len && a <= b && a >= 0) {
	Pike_error("Index out of bounds.\n");
    }

    if (a == b) {
	string_builder_putchar(s, index_shared_string(str, a));
	return;
    }

#if VERSION_MAJOR >= 7 && VERSION_MINOR >= 7
    switch (str->size_shift) {
    case 0:
	string_builder_binary_strcat0(s, (p_wchar0*)str->str + a, b - a + 1);
    case 1:
	string_builder_binary_strcat1(s, (p_wchar1*)str->str + a, b - a + 1);
    case 2:
	string_builder_binary_strcat2(s, (p_wchar2*)str->str + a, b - a + 1);
    default:
	free_string_builder(s);
	Pike_error("Illegal shift size in low_append_string().\n");
    }
#else
    string_builder_append(s, MKPCHARP_OFF(str->str, str->size_shift, a), b - a + 1);
#endif
}
#define APPEND	if (mark != i) low_append_substr(s, str, mark, i);

void low_escape_string_append(struct string_builder *s, struct pike_string *str, int flags) {
    int i, mark;

    mark = 0;
    for (i = 0; i < str->len; i++) {
	unsigned INT32 c = index_shared_string(str, i);

	switch (c) {
	case '"': APPEND; string_builder_strcat(s, "\\\""); mark = i+1; break;
	case '\\': APPEND; string_builder_strcat(s, "\\\\"); mark = i+1; break;
	case  '/': APPEND; string_builder_strcat(s, "\\/"); mark = i+1; break;
	case '\b': APPEND; string_builder_strcat(s, "\\b"); mark = i+1; break;
	case '\f': APPEND; string_builder_strcat(s, "\\f"); mark = i+1; break;
	case '\n': APPEND; string_builder_strcat(s, "\\n"); mark = i+1; break;
	case '\r': APPEND; string_builder_strcat(s, "\\r"); mark = i+1; break;
	case '\t': APPEND; string_builder_strcat(s, "\\t"); mark = i+1; break;
	}
    }

    if (mark != str->len) low_append_substr(s, str, mark, str->len - 1);

}

#define APPENDN(n, c)	do { int _c; for (_c = 0; _c < n; _c++) string_builder_strcat(s, c); } while(0);

int json_low_render(struct string_builder *s, struct svalue *v, int flags, int level) {
    if (level < 0) {
	level = -level;
    } else if (flags & FLAG_HUMAN) APPENDN(level, "  ");

    switch (v->type) {
    case T_ARRAY: {
	struct array *a = v->u.array;
	INT32 i;
	string_builder_putchar(s, '[');
	if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');

	for (i = 0; i < a->size; i++) {
	    json_low_render(s, a->item + i, flags, level+1);
	    if (i != a->size-1) {
		string_builder_putchar(s, ',');
	    }
	    if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');
	}
	
	if (flags & FLAG_HUMAN) APPENDN(level, "  ");
	string_builder_putchar(s, ']');
	break;
    }
    case T_MAPPING: {
	struct mapping *m = v->u.mapping;
	int first = 1;
	struct keypair *k;
	INT32 e;

	string_builder_putchar(s, '{');
	if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');

	NEW_MAPPING_LOOP(m->data) {
	    
	    if (first) {
		first = 0;
	    } else { 
		string_builder_putchar(s, ',');
		if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');
	    }

	    if (k->ind.type != T_STRING) {
		Pike_error("JSON objects must have string keys.\n");
	    }

	    json_low_render(s, &k->ind, flags, level+1); // we cheat here
	    
	    if (flags & FLAG_HUMAN) string_builder_putchar(s, ' ');
	    string_builder_putchar(s, ':');
	    if (flags & FLAG_HUMAN) string_builder_putchar(s, ' ');

	    json_low_render(s, &k->val, flags, -level-1);
	}
	if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');

	if (flags & FLAG_HUMAN) APPENDN(level, "  ");
	string_builder_putchar(s, '}');
	break;
    }
    case T_OBJECT: {
	ref_push_object(v->u.object);
	o_cast(string_type_string, PIKE_T_STRING);
	if (Pike_sp[-1].type != T_STRING) {
	    pop_stack();
	    Pike_error("Could not cast object to string.\n");
	}

	v = Pike_sp-1;
	string_builder_shared_strcat(s, v->u.string);
	pop_stack();
	break;
    }
    case T_STRING:
	string_builder_putchar(s, '"');
	if (flags & FLAG_UTF8) {
#if PIKE_MAJOR_VERSION < 7 || PIKE_MINOR_VERSION < 7
	    // we have to check for non-unicode chars
	    // for pike versions older than 7.7
	    CHECK_UNICODE(v->u.string);
#endif
	    push_svalue(v);
	    f_string_to_utf8(1);

	    v = Pike_sp-1;
	    low_escape_string_append(s, v->u.string, flags);
	    pop_stack();
	} else {
	    CHECK_UNICODE(v->u.string);
	    low_escape_string_append(s, v->u.string, flags);
	}
	string_builder_putchar(s, '"');
	break;
    case T_INT: {
#if PIKE_MAJOR_VERSION >= 7 && PIKE_MINOR_VERSION >= 7
	string_builder_sprintf(s, "%d", v->u.integer);
#else
	struct pike_string *str; 
	push_constant_text("%d");
	push_svalue(v);
	f_sprintf(2);
	if (Pike_sp[-1].type != T_STRING) {
	    Pike_error("sprintf did not return a string.\n");
	}
	str = Pike_sp[-1].u.string;
	string_builder_shared_strcat(s, str);
	pop_stack();
#endif
	break;
    }
    case T_FLOAT: {
#if PIKE_MAJOR_VERSION >= 7 && PIKE_MINOR_VERSION >= 7
	string_builder_sprintf(s, "%f", v->u.float_number);
#else
	struct pike_string *str; 
	push_constant_text("%f");
	push_svalue(v);
	f_sprintf(2);
	if (Pike_sp[-1].type != T_STRING) {
	    Pike_error("sprintf did not return a string.\n");
	}
	str = Pike_sp[-1].u.string;
	string_builder_shared_strcat(s, str);
	pop_stack();
#endif
	break;
    }
    case T_MULTISET:
	Pike_error("Cannot render a multiset.\n");
    case T_FUNCTION:
	Pike_error("Cannot render a function.\n");
    default:
	Pike_error("Cannot render this.\n");
    }

    if (!level && flags & FLAG_HUMAN) string_builder_putchar(s, '\n');
    return 1;
}


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