2 Copyright (C) 2005 Georgia Public Library Service
3 Bill Erickson <highfalutin@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 "json_parser.h"
22 /* ---------------------------------------------------------------------- */
23 /* See object.h for function info */
24 /* ---------------------------------------------------------------------- */
26 object* new_object(char* string_value) {
27 return _init_object(string_value);
30 object* _init_object(char* string_value) {
32 object* obj = (object*) safe_malloc(sizeof(object));
36 obj->push = &object_push;
37 obj->set_index = &object_set_index;
38 obj->add_key = &object_add_key;
39 obj->get_index = &object_get_index;
40 obj->get_key = &object_get_key;
41 obj->get_string = &object_get_string;
42 obj->set_string = &object_set_string;
43 obj->set_number = &object_set_number;
44 obj->set_class = &object_set_class;
45 obj->set_double = &object_set_double;
46 obj->remove_index = &object_remove_index;
47 obj->remove_key = &object_remove_key;
48 obj->to_json = &object_to_json;
49 obj->set_comment = &object_set_comment;
53 obj->string_data = strdup(string_value);
60 object_node* new_object_node(object* obj) {
61 object_node* node = (object_node*) safe_malloc(sizeof(object_node));
68 unsigned long object_push(object* obj, object* new_obj) {
70 object_clear_type(obj);
74 new_obj = new_object(NULL);
78 object_node* node = new_object_node(new_obj);
79 node->index = obj->size++;
81 if( obj->size > MAX_OBJECT_NODES )
84 if(obj->data == NULL) {
88 /* append the node onto the end */
89 object_node* tmp = obj->data;
91 if(tmp->next == NULL) break;
99 unsigned long object_set_index(object* obj, unsigned long index, object* new_obj) {
100 assert(obj != NULL && index <= MAX_OBJECT_NODES);
101 object_clear_type(obj);
104 if(obj->size <= index)
105 obj->size = index + 1;
107 if(new_obj == NULL) {
108 new_obj = new_object(NULL);
109 new_obj->is_null = 1;
112 object_node* node = new_object_node(new_obj);
115 if( obj->data == NULL ) {
120 if(obj->data->index == index) {
121 object_node* tmp = obj->data->next;
122 free_object_node(obj->data);
128 object_node* prev = obj->data;
129 object_node* cur = prev->next;
134 /* replace an existing node */
135 if( cur->index == index ) {
136 object_node* tmp = cur->next;
137 free_object_node(cur);
143 /* instert between two nodes */
144 } else if( prev->index < index && cur->index > index ) {
154 /* shove on to the end */
164 void object_shift_index(object* obj, unsigned long index) {
165 assert(obj && index <= MAX_OBJECT_NODES);
166 if(obj->data == NULL) {
171 object_node* data = obj->data;
173 if(data->index >= index)
180 unsigned long object_remove_index(object* obj, unsigned long index) {
181 assert(obj != NULL && index <= MAX_OBJECT_NODES);
182 if(obj->data == NULL) return 0;
184 /* removing the first item in the list */
185 if(obj->data->index == index) {
186 object_node* tmp = obj->data->next;
187 free_object_node(obj->data);
189 object_shift_index(obj,index);
194 object_node* prev = obj->data;
195 object_node* cur = prev->next;
198 if(cur->index == index) {
199 object_node* tmp = cur->next;
200 free_object_node(cur);
202 object_shift_index(obj,index);
213 unsigned long object_remove_key(object* obj, char* key) {
215 if(obj->data == NULL) return 0;
217 /* removing the first item in the list */
218 if(!strcmp(obj->data->key, key)) {
219 object_node* tmp = obj->data->next;
220 free_object_node(obj->data);
228 object_node* prev = obj->data;
229 object_node* cur = prev->next;
232 if(!strcmp(cur->key,key)) {
233 object_node* tmp = cur->next;
234 free_object_node(cur);
247 unsigned long object_add_key(object* obj, char* key, object* new_obj) {
249 assert(obj != NULL && key != NULL);
250 object_clear_type(obj);
254 if(new_obj == NULL) {
255 new_obj = new_object(NULL);
256 new_obj->is_null = 1;
259 object_node* node = new_object_node(new_obj);
260 node->key = strdup(key);
262 if( obj->data == NULL ) {
268 /* replace the first node */
269 if(!strcmp(obj->data->key, key)) {
270 object_node* tmp = obj->data->next;
271 free_object_node(obj->data);
277 object_node* prev = obj->data;
278 object_node* cur = prev->next;
283 /* replace an existing node */
284 if( !strcmp(cur->key, key) ) {
285 object_node* tmp = cur->next;
286 free_object_node(cur);
297 /* shove on to the end */
309 void free_object(object* obj) {
311 if(obj == NULL) return;
312 if(obj->classname) free(obj->classname);
313 if(obj->comment) free(obj->comment);
316 object_node* tmp = obj->data->next;
317 free_object_node(obj->data);
322 free(obj->string_data);
326 void free_object_node(object_node* node) {
327 if(node == NULL) return;
328 if(node->key) free(node->key);
329 free_object(node->item);
333 object* object_get_index( object* obj, unsigned long index ) {
334 assert(obj != NULL && index <= MAX_OBJECT_NODES);
335 object_node* node = obj->data;
337 if(node->index == index)
344 object* object_get_key( object* obj, char* key ) {
346 object_node* node = obj->data;
349 if(node->key && !strcmp(node->key, key))
357 char* object_get_string(object* obj) {
359 return obj->string_data;
362 void object_set_string(object* obj, char* string) {
364 object_clear_type(obj);
367 obj->string_data = strdup(string);
371 void object_set_number(object* obj, long num) {
373 object_clear_type(obj);
375 obj->num_value = num;
378 void object_set_double(object* obj, double num) {
380 object_clear_type(obj);
382 obj->double_value = num;
386 void object_set_class(object* obj, char* classname) {
387 assert(obj && classname);
388 obj->classname = strdup(classname);
393 char* object_to_json(object* obj) {
396 return strdup("null");
398 growing_buffer* buf = buffer_init(64);
400 /* add class hints if we have a class name */
402 buffer_add(buf,"/*--S ");
403 buffer_add(buf,obj->classname);
404 buffer_add(buf, "--*/");
407 if(obj->is_bool && obj->bool_value)
408 buffer_add(buf, "true");
410 else if(obj->is_bool && ! obj->bool_value)
411 buffer_add(buf, "false");
413 else if(obj->is_number) {
416 sprintf(b, "%ld", obj->num_value);
420 else if(obj->is_double) {
423 sprintf(b, "%lf", obj->double_value);
428 buffer_add(buf, "null");
430 else if (obj->is_string) {
432 buffer_add(buf, "\"");
433 char* data = obj->string_data;
434 int len = strlen(data);
436 char* output = uescape(data, len, 1);
437 buffer_add(buf, output);
439 buffer_add(buf, "\"");
441 } else if(obj->is_array) {
443 buffer_add(buf, "[");
445 for( i = 0; i!= obj->size; i++ ) {
446 char* data = object_to_json(obj->get_index(obj,i));
447 buffer_add(buf, data);
449 if(i != obj->size - 1)
450 buffer_add(buf, ",");
452 buffer_add(buf, "]");
454 } else if(obj->is_hash) {
455 buffer_add(buf, "{");
456 object_iterator* itr = new_iterator(obj);
458 while( (tmp = itr->next(itr)) ) {
459 buffer_add(buf, "\"");
460 buffer_add(buf, tmp->key);
461 buffer_add(buf, "\":");
462 char* data = object_to_json(tmp->item);
463 buffer_add(buf, data);
464 if(itr->has_next(itr))
465 buffer_add(buf, ",");
469 buffer_add(buf, "}");
472 /* close out the object hint */
474 buffer_add(buf, "/*--E ");
475 buffer_add(buf, obj->classname);
476 buffer_add(buf, "--*/");
480 buffer_add(buf, " /*");
481 buffer_add(buf, obj->comment);
482 buffer_add(buf, "*/");
485 char* data = buffer_data(buf);
492 void object_clear_type(object* obj) {
493 if(obj == NULL) return;
502 void object_set_comment(object* obj, char* com) {
504 obj->comment = strdup(com);
509 /* ---------------------------------------------------------------------- */
512 object_iterator* new_iterator(object* obj) {
513 object_iterator* iter = safe_malloc(sizeof(object_iterator));
515 iter->current = obj->data;
516 iter->next = &object_iterator_next;
517 iter->has_next = &object_iterator_has_next;
521 object_node* object_iterator_next(object_iterator* itr) {
522 assert( itr != NULL );
524 object_node* tmp = itr->current;
525 if(tmp == NULL) return NULL;
526 itr->current = itr->current->next;
531 void free_iterator(object_iterator* iter) {
532 if(iter == NULL) return;
536 int object_iterator_has_next(object_iterator* itr) {
538 if(itr->current) return 1;