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

File Contents

Contents of /Public_Parser_JSON2-0.8/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	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) {
    int i, mark;

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

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

    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 - 2011 | Pike is a trademark of Department of Computer and Information Science, Linköping University