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.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;
}
|
|
|