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.
17 #include <opensrf/osrf_json.h>
18 #include <opensrf/osrf_json_utils.h>
20 /* cleans up an object if it is morphing another object, also
21 * verifies that the appropriate storage container exists where appropriate */
22 #define JSON_INIT_CLEAR(_obj_, newtype) \
23 if( _obj_->type == JSON_HASH && newtype != JSON_HASH ) { \
24 osrfHashFree(_obj_->value.h); \
25 _obj_->value.h = NULL; \
26 } else if( _obj_->type == JSON_ARRAY && newtype != JSON_ARRAY ) { \
27 osrfListFree(_obj_->value.l); \
28 _obj_->value.l = NULL; \
29 } else if( _obj_->type == JSON_STRING && newtype != JSON_STRING ) { \
30 free(_obj_->value.s); \
31 _obj_->value.s = NULL; \
33 _obj_->type = newtype;\
34 if( newtype == JSON_HASH && _obj_->value.h == NULL ) { \
35 _obj_->value.h = osrfNewHash(); \
36 _obj_->value.h->freeItem = _jsonFreeHashItem; \
37 } else if( newtype == JSON_ARRAY && _obj_->value.l == NULL ) { \
38 _obj_->value.l = osrfNewList(); \
39 _obj_->value.l->freeItem = _jsonFreeListItem;\
42 static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf );
44 jsonObject* jsonNewObject(const char* data) {
47 OSRF_MALLOC(o, sizeof(jsonObject));
51 o->type = JSON_STRING;
52 o->value.s = strdup(data);
58 jsonObject* jsonNewObjectFmt(const char* data, ...) {
61 OSRF_MALLOC(o, sizeof(jsonObject));
65 VA_LIST_TO_STRING(data);
66 o->type = JSON_STRING;
67 o->value.s = strdup(VA_BUF);
73 jsonObject* jsonNewNumberObject( double num ) {
74 jsonObject* o = jsonNewObject(NULL);
75 o->type = JSON_NUMBER;
80 jsonObject* jsonNewBoolObject(int val) {
81 jsonObject* o = jsonNewObject(NULL);
87 jsonObject* jsonNewObjectType(int type) {
88 jsonObject* o = jsonNewObject(NULL);
93 void jsonObjectFree( jsonObject* o ) {
95 if(!o || o->parent) return;
99 case JSON_HASH : osrfHashFree(o->value.h); break;
100 case JSON_ARRAY : osrfListFree(o->value.l); break;
101 case JSON_STRING : free(o->value.s); break;
106 static void _jsonFreeHashItem(char* key, void* item){
108 jsonObject* o = (jsonObject*) item;
109 o->parent = NULL; /* detach the item */
112 static void _jsonFreeListItem(void* item){
114 jsonObject* o = (jsonObject*) item;
115 o->parent = NULL; /* detach the item */
119 void jsonSetBool(jsonObject* bl, int val) {
121 JSON_INIT_CLEAR(bl, JSON_BOOL);
125 unsigned long jsonObjectPush(jsonObject* o, jsonObject* newo) {
127 if(!newo) newo = jsonNewObject(NULL);
128 JSON_INIT_CLEAR(o, JSON_ARRAY);
130 osrfListPush( o->value.l, newo );
131 o->size = o->value.l->size;
135 unsigned long jsonObjectSetIndex(jsonObject* dest, unsigned long index, jsonObject* newObj) {
137 if(!newObj) newObj = jsonNewObject(NULL);
138 JSON_INIT_CLEAR(dest, JSON_ARRAY);
139 newObj->parent = dest;
140 osrfListSet( dest->value.l, newObj, index );
141 dest->size = dest->value.l->size;
142 return dest->value.l->size;
145 unsigned long jsonObjectSetKey( jsonObject* o, const char* key, jsonObject* newo) {
147 if(!newo) newo = jsonNewObject(NULL);
148 JSON_INIT_CLEAR(o, JSON_HASH);
150 osrfHashSet( o->value.h, newo, key );
151 o->size = o->value.h->size;
155 jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ) {
156 if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
157 return osrfHashGet( obj->value.h, key);
160 const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key ) {
161 if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL;
162 return osrfHashGet( obj->value.h, key);
165 char* jsonObjectToJSON( const jsonObject* obj ) {
166 jsonObject* obj2 = jsonObjectEncodeClass( obj );
167 char* json = jsonObjectToJSONRaw(obj2);
168 jsonObjectFree(obj2);
172 char* jsonObjectToJSONRaw( const jsonObject* obj ) {
173 if(!obj) return NULL;
174 growing_buffer* buf = buffer_init(32);
175 add_json_to_buffer( obj, buf );
176 return buffer_release( buf );
179 static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf ) {
184 if(obj->value.b) OSRF_BUFFER_ADD(buf, "true");
185 else OSRF_BUFFER_ADD(buf, "false");
189 double x = obj->value.n;
190 if( x <= INT_MAX && x >= INT_MIN && x == (int) x ) {
191 INT_TO_STRING((int)x);
192 OSRF_BUFFER_ADD(buf, INTSTR);
196 OSRF_BUFFER_ADD(buf, DOUBLESTR);
202 OSRF_BUFFER_ADD(buf, "null");
206 OSRF_BUFFER_ADD_CHAR(buf, '"');
207 char* data = obj->value.s;
208 int len = strlen(data);
210 char* output = uescape(data, len, 1);
211 OSRF_BUFFER_ADD(buf, output);
213 OSRF_BUFFER_ADD_CHAR(buf, '"');
217 OSRF_BUFFER_ADD_CHAR(buf, '[');
220 for( i = 0; i != obj->value.l->size; i++ ) {
221 if(i > 0) OSRF_BUFFER_ADD(buf, ",");
222 add_json_to_buffer( OSRF_LIST_GET_INDEX(obj->value.l, i), buf );
225 OSRF_BUFFER_ADD_CHAR(buf, ']');
231 OSRF_BUFFER_ADD_CHAR(buf, '{');
232 osrfHashIterator* itr = osrfNewHashIterator(obj->value.h);
236 while( (item = osrfHashIteratorNext(itr)) ) {
237 if(i++ > 0) OSRF_BUFFER_ADD(buf, ",");
238 buffer_fadd(buf, "\"%s\":", itr->current);
239 add_json_to_buffer( item, buf );
242 osrfHashIteratorFree(itr);
243 OSRF_BUFFER_ADD_CHAR(buf, '}');
250 jsonIterator* jsonNewIterator(const jsonObject* obj) {
251 if(!obj) return NULL;
253 OSRF_MALLOC(itr, sizeof(jsonIterator));
255 itr->obj = (jsonObject*) obj;
259 if( obj->type == JSON_HASH )
260 itr->hashItr = osrfNewHashIterator(obj->value.h);
265 void jsonIteratorFree(jsonIterator* itr) {
268 osrfHashIteratorFree(itr->hashItr);
272 jsonObject* jsonIteratorNext(jsonIterator* itr) {
273 if(!(itr && itr->obj)) return NULL;
274 if( itr->obj->type == JSON_HASH ) {
275 if(!itr->hashItr) return NULL;
276 jsonObject* item = osrfHashIteratorNext(itr->hashItr);
278 itr->key = strdup(itr->hashItr->current);
281 return jsonObjectGetIndex( itr->obj, itr->index++ );
285 int jsonIteratorHasNext(const jsonIterator* itr) {
286 if(!(itr && itr->obj)) return 0;
287 if( itr->obj->type == JSON_HASH )
288 return osrfHashIteratorHasNext( itr->hashItr );
289 return (itr->index < itr->obj->size) ? 1 : 0;
292 jsonObject* jsonObjectGetIndex( const jsonObject* obj, unsigned long index ) {
293 if(!obj) return NULL;
294 return (obj->type == JSON_ARRAY) ?
295 (OSRF_LIST_GET_INDEX(obj->value.l, index)) : NULL;
300 unsigned long jsonObjectRemoveIndex(jsonObject* dest, unsigned long index) {
301 if( dest && dest->type == JSON_ARRAY ) {
302 osrfListRemove(dest->value.l, index);
303 return dest->value.l->size;
309 unsigned long jsonObjectRemoveKey( jsonObject* dest, const char* key) {
310 if( dest && key && dest->type == JSON_HASH ) {
311 osrfHashRemove(dest->value.h, key);
317 char* jsonObjectGetString(const jsonObject* obj) {
318 return (obj && obj->type == JSON_STRING) ? obj->value.s : NULL;
321 double jsonObjectGetNumber( const jsonObject* obj ) {
322 return (obj && obj->type == JSON_NUMBER) ? obj->value.n : 0;
325 void jsonObjectSetString(jsonObject* dest, const char* string) {
326 if(!(dest && string)) return;
327 JSON_INIT_CLEAR(dest, JSON_STRING);
329 dest->value.s = strdup(string);
332 void jsonObjectSetNumber(jsonObject* dest, double num) {
334 JSON_INIT_CLEAR(dest, JSON_NUMBER);
338 void jsonObjectSetClass(jsonObject* dest, const char* classname ) {
339 if(!(dest && classname)) return;
340 free(dest->classname);
341 dest->classname = strdup(classname);
343 const char* jsonObjectGetClass(const jsonObject* dest) {
344 if(!dest) return NULL;
345 return dest->classname;
348 jsonObject* jsonObjectClone( const jsonObject* o ) {
349 if(!o) return jsonNewObject(NULL);
356 jsonObject* result = NULL;
360 result = jsonNewObject(NULL);
363 result = jsonNewObject(jsonObjectGetString(o));
366 result = jsonNewNumberObject(jsonObjectGetNumber(o));
369 result = jsonNewBoolObject(jsonBoolIsTrue((jsonObject*) o));
372 arr = jsonNewObject(NULL);
373 arr->type = JSON_ARRAY;
374 for(i=0; i < o->size; i++)
375 jsonObjectPush(arr, jsonObjectClone(jsonObjectGetIndex(o, i)));
379 hash = jsonNewObject(NULL);
380 hash->type = JSON_HASH;
381 itr = jsonNewIterator(o);
382 while( (tmp = jsonIteratorNext(itr)) )
383 jsonObjectSetKey(hash, itr->key, jsonObjectClone(tmp));
384 jsonIteratorFree(itr);
389 jsonObjectSetClass(result, jsonObjectGetClass(o));
393 int jsonBoolIsTrue( jsonObject* boolObj ) {
394 if( boolObj && boolObj->type == JSON_BOOL && boolObj->value.b )
400 char* jsonObjectToSimpleString( const jsonObject* o ) {
409 if( o->value.n == (int) o->value.n ) {
410 INT_TO_STRING((int) o->value.n);
411 value = strdup(INTSTR);
414 DOUBLE_TO_STRING(o->value.n);
415 value = strdup(DOUBLESTR);
422 value = strdup(o->value.s);