
Contents of /Public_Parser_JSON-0.2/JSON.cmod:
/* Pike "binding" for json-c (http://oss.metaparadigm.com/json-c/)
*
* - Johan Bjorklund <johbjo09@kth.se>
*/
/* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "global.h"
#include "svalue.h"
#include "interpret.h"
#include "program.h"
#include "array.h"
#include "mapping.h"
#include "builtin_functions.h"
#include <string.h>
#include <json/json.h>
#include "module.h"
struct json_object *encode_object(struct object *o);
struct json_object *encode_array(struct array *a);
struct json_object *encode_mapping(struct mapping *a);
struct json_object *encode_svalue(struct svalue *val) {
struct json_object *ret = NULL;
switch(val->type) {
case PIKE_T_STRING:
ret = json_object_new_string_len( (char*) STR0(val->u.string),
((struct pike_string *) val->u.string)->len * (((struct pike_string *) val->u.string)->size_shift+1) );
break;
case PIKE_T_INT:
ret = json_object_new_int(val->u.integer);
break;
case PIKE_T_ARRAY:
ret = encode_array(val->u.array);
break;
case PIKE_T_MAPPING:
ret = encode_mapping(val->u.mapping);
break;
case PIKE_T_FLOAT:
ret = json_object_new_double(val->u.float_number);
break;
case PIKE_T_OBJECT:
ret = encode_object(val->u.object);
}
return ret;
}
struct json_object *encode_array(struct array *a) {
int i;
struct json_object *ret = NULL;
struct json_object *new = NULL;
for(i=0; i < a->size; i++) {
if((new = encode_svalue(&ITEM(a)[i])) != NULL) {
if(!ret)
ret = json_object_new_array();
json_object_array_add(ret, new);
}
}
return ret;
}
char *itoa(int i) {
int s=0;
int a = i;
while((a=(a/10)) > 0) s++;
char *str = malloc(s+1);
sprintf(str, "%d\0", i);
return str;
}
struct json_object *encode_mapping(struct mapping *m) {
struct json_object *ret = NULL;
struct json_object *new;
INT32 e;
struct keypair *k;
char *ind;
char freeind = 0;
NEW_MAPPING_LOOP(m->data) {
switch(k->ind.type) {
case PIKE_T_STRING:
ind = (char*) STR0(k->ind.u.string);
freeind = 0;
break;
case PIKE_T_INT:
ind = itoa(k->ind.u.integer);
freeind = 1;
break;
default:
ind = NULL;
}
if(ind != NULL) {
if((new = encode_svalue(&k->val)) != NULL) {
if(ret == NULL)
ret = json_object_new_object();
json_object_object_add(ret, ind, new);
}
if(freeind)
free(ind);
}
}
return ret;
}
struct json_object *encode_object(struct object *o) {
struct json_object *ret = NULL;
struct json_object *new;
struct svalue *val;
struct array *indices = object_indices(o);
int i;
for(i=0; i<indices->size; i++) {
struct svalue index = *(ITEM(indices) + i);
object_index_no_free2(val, o, &index);
if((new = encode_svalue(val)) != NULL) {
if(!ret)
ret = json_object_new_object();
json_object_object_add(ret, (char*) STR0(index.u.string), new);
}
}
return ret;
}
void is_ok (struct json_object *o) {
if (is_error(o)) {
switch (- (enum json_tokener_error) o) {
case json_tokener_error_parse_array: Pike_error("Tokener error: parse array\n");
case json_tokener_error_parse_boolean: Pike_error("Tokener error: parse boolean\n");
case json_tokener_error_parse_comment: Pike_error("Tokener error: parse comment\n");
case json_tokener_error_parse_eof: Pike_error("Tokener error: parse eof\n");
case json_tokener_error_parse_null: Pike_error("Tokener error: parse null\n");
case json_tokener_error_parse_number: Pike_error("Tokener error: parse number\n");
case json_tokener_error_parse_string: Pike_error("Tokener error: parse string\n");
case json_tokener_error_parse_unexpected: Pike_error("Tokener error: parse unexpected\n");
}
Pike_error("Tokener error\n");
}
}
void decode_obj(struct json_object *o);
void decode_array(struct json_object *o);
void decode_val(struct json_object *o) {
if (!o) {
push_undefined();
return;
}
switch(json_object_get_type(o)) {
case json_type_boolean:
case json_type_int:
push_int(json_object_get_int(o));
break;
case json_type_double:
push_float(json_object_get_double(o));
break;
case json_type_string:
push_text(json_object_get_string(o));
break;
case json_type_array:
decode_array(o);
break;
case json_type_object:
decode_obj(o);
break;
case json_type_null:
default:
push_undefined();
}
}
void decode_array(struct json_object *o) {
struct json_object *obj;
int n, l = json_object_array_length(o);
for (n=0; n < l; n++) {
obj = json_object_array_get_idx(o, n);
decode_val(obj);
}
f_aggregate(n);
}
void decode_obj(struct json_object *o) {
int n=0;
json_object_object_foreach(o, key, val) {
if (!key) continue;
push_text(key);
decode_val(val);
n+=2;
}
f_aggregate_mapping(n);
}
void free_obj(struct json_object *o) {
int n, l;
switch (json_object_get_type(o)) {
case json_type_object: {
json_object_object_foreach(o, key, val)
free_obj(val);
json_object_put(o);
}
break;
case json_type_array: {
l = json_object_array_length(o);
for (n=0; n < l; n++)
free_obj(json_object_array_get_idx(o, n));
json_object_put(o);
}
break;
default:
json_object_put(o);
}
}
/*! @module Public
*/
/*! @module Parser
*/
/*! @module JSON
*/
/*! @decl mapping decode(string s)
*!
*! Parses a JSON-formatted string and returns the corresponding mapping.
*/
PIKEFUN mapping decode(string stream)
{
struct json_object *o;
pop_stack();
if(stream->size_shift == 0) {
o = json_tokener_parse((char*)STR0(stream));
is_ok(o);
decode_obj(o);
json_object_put(o);
} else {
Pike_error("Size shift = 1, don't know what to do.");
}
}
/*! @decl string encode(object|mapping o)
*!
*! Converts an object or mapping to a JSON-formatted string.
*/
PIKEFUN string encode(object|mapping o);
{
struct pike_string *ret = NULL;
struct json_object *jso = NULL;
if(o) {
switch(o->type) {
case PIKE_T_OBJECT: {
struct object *obj = o->u.object;
if (obj)
jso = encode_object(obj);
}
case PIKE_T_MAPPING: {
struct mapping *m = o->u.mapping;
if (m)
jso = encode_mapping(m);
}
}
}
if (jso) {
ret = make_shared_string(json_object_to_json_string(jso));
free_obj(jso);
} else {
ret = make_shared_binary_string("", 0);
}
RETURN ret;
}
/*! @endmodule
*/
/*! @endmodule
*/
/*! @endmodule
*/
EXTRA {
add_string_constant("__author", "Johan Björklund <johbjo09@kth.se>", 0);
add_string_constant("__version", "0.2", 0);
}