2 Copyright (C) 2006 Georgia Public Library Service
3 Bill Erickson <billserickson@gmail.com>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
16 #include <opensrf/osrf_json.h>
17 #include <opensrf/osrf_json_utils.h>
19 jsonObject* jsonNewObject(const char* data) {
22 OSRF_MALLOC(o, sizeof(jsonObject));
26 o->type = JSON_STRING;
27 o->value.s = strdup(data);
33 jsonObject* jsonNewObjectFmt(const char* data, ...) {
36 OSRF_MALLOC(o, sizeof(jsonObject));
40 VA_LIST_TO_STRING(data);
41 o->type = JSON_STRING;
42 o->value.s = strdup(VA_BUF);
48 jsonObject* jsonNewNumberObject( double num ) {
49 jsonObject* o = jsonNewObject(NULL);
50 o->type = JSON_NUMBER;
55 jsonObject* jsonNewBoolObject(int val) {
56 jsonObject* o = jsonNewObject(NULL);
62 jsonObject* jsonNewObjectType(int type) {
63 jsonObject* o = jsonNewObject(NULL);
68 void jsonObjectFree( jsonObject* o ) {
70 if(!o || o->parent) return;
74 case JSON_HASH : osrfHashFree(o->value.h); break;
75 case JSON_ARRAY : osrfListFree(o->value.l); break;
76 case JSON_STRING : free(o->value.s); break;
81 static void _jsonFreeHashItem(char* key, void* item){
83 jsonObject* o = (jsonObject*) item;
84 o->parent = NULL; /* detach the item */
87 static void _jsonFreeListItem(void* item){
89 jsonObject* o = (jsonObject*) item;
90 o->parent = NULL; /* detach the item */
94 void jsonSetBool(jsonObject* bl, int val) {
96 JSON_INIT_CLEAR(bl, JSON_BOOL);
100 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo) {
102 if(!newo) newo = jsonNewObject(NULL);
103 JSON_INIT_CLEAR(o, JSON_ARRAY);
105 osrfListPush( o->value.l, newo );
106 o->size = o->value.l->size;
110 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj) {
112 if(!newObj) newObj = jsonNewObject(NULL);
113 JSON_INIT_CLEAR(dest, JSON_ARRAY);
114 newObj->parent = dest;
115 osrfListSet( dest->value.l, newObj, index );
116 dest->size = dest->value.l->size;
117 return dest->value.l->size;
120 unsigned long jsonObjectSetKey( jsonObject* o, const char* key, jsonObject* newo) {
122 if(!newo) newo = jsonNewObject(NULL);
123 JSON_INIT_CLEAR(o, JSON_HASH);
125 osrfHashSet( o->value.h, newo, key );
126 o->size = o->value.h->size;
130 jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ) {
131 if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
132 return osrfHashGet( obj->value.h, key);
135 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key ) {
136 if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
137 return osrfHashGet( obj->value.h, key);
140 char* jsonObjectToJSON( const jsonObject* obj ) {
141 jsonObject* obj2 = jsonObjectEncodeClass( (jsonObject*) obj);
142 char* json = jsonObjectToJSONRaw(obj2);
143 jsonObjectFree(obj2);
147 char* jsonObjectToJSONRaw( const jsonObject* obj ) {
148 if(!obj) return NULL;
149 growing_buffer* buf = buffer_init(32);
156 if(obj->value.b) OSRF_BUFFER_ADD(buf, "true");
157 else OSRF_BUFFER_ADD(buf, "false");
161 double x = obj->value.n;
163 INT_TO_STRING((int)x);
164 OSRF_BUFFER_ADD(buf, INTSTR);
168 OSRF_BUFFER_ADD(buf, DOUBLESTR);
174 OSRF_BUFFER_ADD(buf, "null");
178 OSRF_BUFFER_ADD_CHAR(buf, '"');
179 char* data = obj->value.s;
180 int len = strlen(data);
182 char* output = uescape(data, len, 1);
183 OSRF_BUFFER_ADD(buf, output);
185 OSRF_BUFFER_ADD_CHAR(buf, '"');
189 OSRF_BUFFER_ADD_CHAR(buf, '[');
191 for( i = 0; i != obj->value.l->size; i++ ) {
192 json = jsonObjectToJSONRaw(OSRF_LIST_GET_INDEX(obj->value.l, i));
193 if(i > 0) OSRF_BUFFER_ADD(buf, ",");
194 OSRF_BUFFER_ADD(buf, json);
198 OSRF_BUFFER_ADD_CHAR(buf, ']');
204 OSRF_BUFFER_ADD_CHAR(buf, '{');
205 osrfHashIterator* itr = osrfNewHashIterator(obj->value.h);
209 while( (item = osrfHashIteratorNext(itr)) ) {
210 if(i++ > 0) OSRF_BUFFER_ADD(buf, ",");
211 buffer_fadd(buf, "\"%s\":", itr->current);
212 char* json = jsonObjectToJSONRaw(item);
213 OSRF_BUFFER_ADD(buf, json);
217 osrfHashIteratorFree(itr);
218 OSRF_BUFFER_ADD_CHAR(buf, '}');
223 return buffer_release(buf);
227 jsonIterator* jsonNewIterator(const jsonObject* obj) {
228 if(!obj) return NULL;
230 OSRF_MALLOC(itr, sizeof(jsonIterator));
232 itr->obj = (jsonObject*) obj;
236 if( obj->type == JSON_HASH )
237 itr->hashItr = osrfNewHashIterator(obj->value.h);
242 void jsonIteratorFree(jsonIterator* itr) {
245 osrfHashIteratorFree(itr->hashItr);
249 jsonObject* jsonIteratorNext(jsonIterator* itr) {
250 if(!(itr && itr->obj)) return NULL;
251 if( itr->obj->type == JSON_HASH ) {
252 if(!itr->hashItr) return NULL;
253 jsonObject* item = osrfHashIteratorNext(itr->hashItr);
255 itr->key = strdup(itr->hashItr->current);
258 return jsonObjectGetIndex( itr->obj, itr->index++ );
262 int jsonIteratorHasNext(const jsonIterator* itr) {
263 if(!(itr && itr->obj)) return 0;
264 if( itr->obj->type == JSON_HASH )
265 return osrfHashIteratorHasNext( itr->hashItr );
266 return (itr->index < itr->obj->size) ? 1 : 0;
269 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index ) {
270 if(!obj) return NULL;
271 return (obj->type == JSON_ARRAY) ?
272 (OSRF_LIST_GET_INDEX(obj->value.l, index)) : NULL;
277 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index) {
278 if( dest && dest->type == JSON_ARRAY ) {
279 osrfListRemove(dest->value.l, index);
280 return dest->value.l->size;
286 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key) {
287 if( dest && key && dest->type == JSON_HASH ) {
288 osrfHashRemove(dest->value.h, key);
294 char* jsonObjectGetString(const jsonObject* obj) {
295 return (obj && obj->type == JSON_STRING) ? obj->value.s : NULL;
298 double jsonObjectGetNumber( const jsonObject* obj ) {
299 return (obj && obj->type == JSON_NUMBER) ? obj->value.n : 0;
302 void jsonObjectSetString(jsonObject* dest, const char* string) {
303 if(!(dest && string)) return;
304 JSON_INIT_CLEAR(dest, JSON_STRING);
306 dest->value.s = strdup(string);
309 void jsonObjectSetNumber(jsonObject* dest, double num) {
311 JSON_INIT_CLEAR(dest, JSON_NUMBER);
315 void jsonObjectSetClass(jsonObject* dest, const char* classname ) {
316 if(!(dest && classname)) return;
317 free(dest->classname);
318 dest->classname = strdup(classname);
320 const char* jsonObjectGetClass(const jsonObject* dest) {
321 if(!dest) return NULL;
322 return dest->classname;
325 jsonObject* jsonObjectClone( const jsonObject* o ) {
326 if(!o) return jsonNewObject(NULL);
333 jsonObject* result = NULL;
337 result = jsonNewObject(NULL);
340 result = jsonNewObject(jsonObjectGetString(o));
343 result = jsonNewNumberObject(jsonObjectGetNumber(o));
346 result = jsonNewBoolObject(jsonBoolIsTrue((jsonObject*) o));
349 arr = jsonNewObject(NULL);
350 arr->type = JSON_ARRAY;
351 for(i=0; i < o->size; i++)
352 jsonObjectPush(arr, jsonObjectClone(jsonObjectGetIndex(o, i)));
356 hash = jsonNewObject(NULL);
357 hash->type = JSON_HASH;
358 itr = jsonNewIterator(o);
359 while( (tmp = jsonIteratorNext(itr)) )
360 jsonObjectSetKey(hash, itr->key, jsonObjectClone(tmp));
361 jsonIteratorFree(itr);
366 jsonObjectSetClass(result, jsonObjectGetClass(o));
370 int jsonBoolIsTrue( jsonObject* boolObj ) {
371 if( boolObj && boolObj->type == JSON_BOOL && boolObj->value.b )
377 char* jsonObjectToSimpleString( const jsonObject* o ) {
386 if( o->value.n == (int) o->value.n ) {
387 INT_TO_STRING((int) o->value.n);
388 value = strdup(INTSTR);
391 DOUBLE_TO_STRING(o->value.n);
392 value = strdup(DOUBLESTR);
399 value = strdup(o->value.s);