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

File Contents

Contents of /Public_Parser_JSON2-0.9/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, size_t a, size_t b) {
    if (b >= (size_t)str->len || a > b) {
		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:
		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	do { if (mark < i) low_append_substr(s, str, mark, i-1); } while(0);

void low_escape_string_append(struct string_builder *s, struct pike_string *str, int flags) {
    size_t i, mark;
	// we assume here that str->len is always positive. 

    mark = 0;
    if (flags & FLAG_HUMAN) for (i = 0; i < (size_t)str->len; i++) {
		p_wchar2 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;
		}
    } else for (i = 0; i < (size_t)str->len; i++) {
		p_wchar2 c = index_shared_string(str, i);

		if (c == '"' || c == '\\') {
			APPEND;
			string_builder_putchar(s, '\\');
			string_builder_putchar(s, c);
			mark = i+1;
		}
    }

    if (mark < (size_t)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;
		size_t i;
		string_builder_putchar(s, '[');
		if (flags & FLAG_HUMAN) string_builder_putchar(s, '\n');

		for (i = 0; i < (size_t)a->size; i++) {
			json_low_render(s, a->item + i, flags, level+1);
			if (i+1 != (size_t)a->size) {
				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 - 2012 | Pike is a trademark of Department of Computer and Information Science, Linköping University