+# --------------------------------------------------------------------
+# Copyright (C) 2005 Georgia Public Library Service
+# Bill Erickson <highfalutin@gmail.com>
+# Mike Rylander <mrylander@gmail.com>
+
+# 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.
+# --------------------------------------------------------------------
+
+
OBJS = object.o json_parser.o utils.o
UTIL_DIR = ../utils
DEST_INCLUDE = objson
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin@gmail.com>
+
+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.
+*/
+
+
#include "json_parser.h"
/* keep a copy of the length of the current json string so we don't
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
- /* This was taken directly from json-c http://oss.metaparadigm.com/json-c/ */
+ /* The following chunk was borrowed with permission from
+ json-c http://oss.metaparadigm.com/json-c/ */
unsigned char utf_out[3];
memset(utf_out,0,3);
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
-
(*index) += 3;
in_escape = 0;
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin@gmail.com>
+
+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.
+*/
+
+
+
+
/* ---------------------------------------------------------------------------------------
JSON parser.
* --------------------------------------------------------------------------------------- */
-
-
#include <stdio.h>
#include "object.h"
#include "utils.h"
#define JSON_PARSER_H
+/* Parses the given JSON string and returns the built object.
+ * returns NULL (and prints parser error to stderr) on error.
+ * if string is NULL, returns an object whose is_null flag is set to true.
+ */
+object* json_parse_string(char* string);
+
-/* returns NULL on error. if string is NULL, returns an object whose is_null flag
- * is set to true */
-object* json_parse_string(char* string);
/* does the actual parsing work. returns 0 on success. -1 on error and
* -2 if there was no object to build (string was all comments)
/* returns 0 on success and turns obj into a number or double object */
int json_parse_json_number(char* string, unsigned long* index, object* obj);
+/* returns 0 on success and turns obj into an 'object' object */
int json_parse_json_object(char* string, unsigned long* index, object* obj);
/* returns 0 on success and turns object into an array object */
int json_parse_json_array(char* string, unsigned long* index, object* obj);
/* churns through whitespace and increments index as it goes.
- * eat_all means we should eat newlines, tabs
+ * eat_all == true means we should eat newlines, tabs
*/
void json_eat_ws(char* string, unsigned long* index, int eat_all);
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin@gmail.com>
+
+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.
+*/
+
#include "object.h"
#include "json_parser.h"
#include <fcntl.h>
obj->data = NULL;
obj->push = &object_push;
- obj->add_index = &object_add_index;
+ obj->set_index = &object_set_index;
obj->add_key = &object_add_key;
obj->get_index = &object_get_index;
obj->get_key = &object_get_key;
return obj->size;
}
-unsigned long object_add_index(object* obj, unsigned long index, object* new_obj) {
+unsigned long object_set_index(object* obj, unsigned long index, object* new_obj) {
assert(obj != NULL && index <= MAX_OBJECT_NODES);
object_clear_type(obj);
obj->is_array = 1;
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin@gmail.com>
+
+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.
+*/
+
/* ---------------------------------------------------------------------------------------
Generic object framework for C. An object can be either a string, boolean, null,
number, array or hash (think Perl hash, dictionary, etc.).
#include <assert.h>
#include "utils.h"
-/* does we need this? */
#define MAX_OBJECT_NODES 1000000
#ifndef OBJECT_H
#define OBJECT_H
-/* top leve generic object structuure */
+/* top level generic object structuure */
struct object_struct {
/* how many sub-objects do we contain. Note that this includes null
/* attached accessor/mutator methods for the OO inclined*/
unsigned long (*push) (struct object_struct* src, struct object_struct*);
- unsigned long (*add_index) (struct object_struct* src, unsigned long index, struct object_struct*);
+ unsigned long (*set_index) (struct object_struct* src, unsigned long index, struct object_struct*);
unsigned long (*add_key) (struct object_struct* src, char* key, struct object_struct*);
struct object_struct* (*get_index) (struct object_struct*, unsigned long index);
struct object_struct* (*get_key) (struct object_struct*, char* key);
int object_iterator_has_next(object_iterator*);
-/* allocates a new object. classname is optional */
+/* allocates a new object. 'string' is the string data if this object
+ is to be a string. if not, string should be NULL */
object* new_object(char* string);
/* utility method for initing an object */
/* returns a pointer to the object with the given key */
object* object_get_key( object* obj, char* key );
-/* de-allocates a object */
+/* de-allocates a object ( * should only be called on objects that are not
+ children of other objects ) */
void free_object(object*);
/* allocates a new object node */
/* de-allocates a object node */
void free_object_node(object_node*);
+
/* pushes the given object onto the end of the list,
* returns the size on success, -1 on error
+ * If obj is NULL, inserts a new object into the list with is_null set to true
*/
unsigned long object_push(object*, object* obj);
-/* removes the object at the given index (if one exists) and inserts
+/* removes (and deallocates) the object at the given index (if one exists) and inserts
* the new one. returns the size on success, -1 on error
+ * If obj is NULL, inserts a new object into the list with is_null set to true
*/
-unsigned long object_add_index(object*, unsigned long index, object* obj);
+unsigned long object_set_index(object*, unsigned long index, object* obj);
-/* inserts the new object, overwriting any previous object with the given key
+/* inserts the new object, overwriting (removing, deallocating) any
+ * previous object with the given key.
* returns the size on success, -1 on error
* if 'obj' is NULL, a new object is inserted at key 'key' with 'is_null'
* set to true
*/
unsigned long object_remove_index(object*, unsigned long index);
-/* de-allocates the object at index 'index' and sets the field to null.
- * this will *not* change the object size */
-//unsigned long object_clear_index(object*, unsigned long index);
-
-/* removes the object with key 'key' if it exists */
+/* removes (and deallocates) the object with key 'key' if it exists */
unsigned long object_remove_key(object*, char* key);
/* returns a pointer to the string data held by this object */
/* set this object's comment string */
void object_set_comment(object*, char*);
-/* starting at index 'index', shifts all indices down by one and
+/* utility method. starting at index 'index', shifts all indices down by one and
* decrements the objects size by 1
*/
void object_shift_index(object*, unsigned long index);
-#include <stdio.h>
-#include "utils.h"
-#include <fcntl.h>
+/*
+Copyright (C) 2005 Georgia Public Library Service
+Bill Erickson <highfalutin@gmail.com>
+
+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.
+*/
+
+//#include "utils.h"
#include "object.h"
#include "json_parser.h"
-#include <wchar.h>
-#include <locale.h>
-
+#include <stdio.h>
+#include <fcntl.h>
/* ---------------------------------------------------------------------- */
/* See object.h for function info */
/* ---------------------------------------------------------------------- */
int main() {
+ /* sample JSON string with some encoded UTF8 */
char* jsons = "/*--S mvr--*/[null,null,null,\"Griswold del Castillo, Richard\",[],null,\"1405676\",null,null,\"1558853243 (alk. paper) :\",\"c2002\",\"Pin\\u0303ata Books\",null,[],[[\"Chavez, Cesar 1927-\",\"Juvenile literature\"],[\"Labor leaders\",\"United States\",\"Biography\",\"Juvenile literature\"],[\"Mexican Americans\",\"Biography\",\"Juvenile literature\"],[\"Agricultural laborers\",\"Labor unions\",\"United States\",\"History\",\"Juvenile literature\"],[\"United Farm Workers\",\"History\",\"Juvenile literature\"],[\"Chavez, Cesar 1927-\"],[\"Labor leaders\"],[\"Mexican Americans\",\"Biography\"],[\"United Farm Workers.\"],[\"Spanish language materials\",\"Bilingual\"],[\"Chavez, Cesar 1927-\",\"Literatura juvenil\"],[\"Li\\u0301deres obreros\",\"Estados Unidos\",\"Biografi\\u0301a\",\"Literatura juvenil\"],[\"Mexicano-americanos\",\"Biografi\\u0301a\",\"Literatura juvenil\"],[\"Sindicatos\",\"Trabajadores agri\\u0301colas\",\"Estados Unidos\",\"Historia\",\"Literatura juvenil\"],[\"Unio\\u0301n de Trabajadores Agri\\u0301colas\",\"Historia\",\"Literatura juvenil\"]],\"ocm48083852 \",\"Ce\\u0301sar Cha\\u0301vez : the struggle for justice = Ce\\u0301sar Cha\\u0301vez : la lucha por la justicia\",[\"text\"], { \"hi\":\"you\"} ]/*--E mvr--*/";
- //char* jsons = buffer_data(buffer);
printf("\nOriginal JSON\n%s\n", jsons);
+ /* parse the JSON string */
object* yuk = json_parse_string(jsons);
+
+ /* grab the class name from the object */
+ printf("\nParsed object with class %s\n", yuk->classname );
+
+ /* turn the resulting object back into JSON */
char* ccc = yuk->to_json(yuk);
+ /* extract a sub-object from the object and print its data*/
object* o = yuk->get_index(yuk, 11);
printf("\nRandom unicode string => %s\n", o->string_data);
+ /* parse the new JSON string to build yet another object */
object* yuk2 = json_parse_string(ccc);
- char* cccc = yuk2->to_json(yuk2);
+ /* turn that one back into JSON and print*/
+ char* cccc = yuk2->to_json(yuk2);
printf("\nFinal JSON: \n%s\n", cccc);
+ char* string2 = strdup(jsons);
+
int x = 0;
- printf("\nParsing 10,000 round trips at %f...\n", get_timestamp_millis());
+ int count = 10000;
+ printf("\nParsing %d round trips at %f...\n", count, get_timestamp_millis());
- char* string2 = strdup(jsons);
- while(x++ < 10000) {
+ /* parse and stringify many times in a loop to check speed */
+ while(x++ < count) {
object* o = json_parse_string(string2);
free(string2);
string2 = o->to_json(o);
free_object(o);
- if(!(x%1000))
+ if(!(x % 500))
fprintf(stderr, "Round trip at %d\n", x);
}
- printf("\nAfter Loop: %f\n", get_timestamp_millis());
+ printf("After Loop: %f\n", get_timestamp_millis());
+ /* to_json() generates a string that must be freed by the caller */
free(string2);
free(ccc);
free(cccc);
+
+ /* only free the top level objects. objects that are 'children'
+ of other objects should not be freed */
free_object(yuk);
free_object(yuk2);
- //buffer_free(buffer);
- return 0;
+
+ /* ------------------------------------------------------------------------ */
+
+ /* parse a big JSON file */
+ FILE* F = fopen("test.json", "r");
+ if(!F) {
+ perror("unable to open test.json for testing");
+ exit(99);
+ }
+
+ char buf[10240];
+ char smallbuf[512];
+ bzero(buf, 10240);
+ bzero(smallbuf, 512);
+
+ while(fgets(smallbuf, 512, F))
+ strcat(buf, smallbuf);
+
+ /* dig our way into the JSON object we parsed, see test.json to get
+ an idea of the object structure */
+ object* big = json_parse_string(buf);
+ object* k = big->get_key(big,"web-app");
+ object* k2 = k->get_key(k,"servlet");
+ object* k3 = k2->get_index(k2, 0);
+ object* k4 = k3->get_key(k3,"servlet-class");
+
+ printf("\nValue for object with key 'servlet-class' in the JSON file => %s\n", k4->get_string(k4));
+
+ return 0;
}