|
@@ -0,0 +1,1502 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <stdarg.h>
|
|
|
+#include "common.h"
|
|
|
+#include "json.h"
|
|
|
+
|
|
|
+/**
|
|
|
+ * TODO: 1. Redo the json_obj structure to be able to hold several.
|
|
|
+ * Now only hols several members and pairs. Can hold several.
|
|
|
+ * 2. Save to file
|
|
|
+ * 3. Encoding of values; e.g unicode values and special chars.
|
|
|
+ * 4. json_from_file; parser?
|
|
|
+ **/
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_type
|
|
|
+ * Typedef: json_type_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Type of an JSON-entry.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Holds the type of an JSON-entry.
|
|
|
+ **/
|
|
|
+struct json_type {
|
|
|
+ json_types_t type;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * JSON-entry types
|
|
|
+ **/
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure:
|
|
|
+ * Typedef:
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST)
|
|
|
+ * json_mem_t *members: JSON-meners entries.
|
|
|
+ * print_type_t ptype: Print type, eg Pretty print.
|
|
|
+ * int code: Status code.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Defines an JSON-object.
|
|
|
+ **/
|
|
|
+struct json_obj {
|
|
|
+ json_types_t type;
|
|
|
+ json_mem_t *members;
|
|
|
+ print_type_t ptype;
|
|
|
+ json_printf_t *pfunc;
|
|
|
+ FILE *jfile;
|
|
|
+ int code;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_mem
|
|
|
+ * Typedef: json_mem_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST)
|
|
|
+ * void *entry: Containing entry. Either pair or new member
|
|
|
+ * void *next: Simblings; other members or pairs in parent.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Defines an JSON-member entry
|
|
|
+ **/
|
|
|
+struct json_mem {
|
|
|
+ json_types_t type;
|
|
|
+ void *entry;
|
|
|
+ void *next;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_elem
|
|
|
+ * Typedef: json_elem_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST).
|
|
|
+ * void *entry: Containing entry. Either value or new element.
|
|
|
+ * void *next: Simblings; other elements in parent.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Defines an JSON-element entry.
|
|
|
+ **/
|
|
|
+struct json_elem {
|
|
|
+ json_types_t type;
|
|
|
+ void *entry;
|
|
|
+ void *next;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_pair
|
|
|
+ * Typedef: json_pair_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST).
|
|
|
+ * char *str: String specifier.
|
|
|
+ * json_val_t *value; Containing entry, only value.
|
|
|
+ * void *next: Simblings; other members or pairs in parent.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ **/
|
|
|
+struct json_pair {
|
|
|
+ json_types_t type;
|
|
|
+ char *str;
|
|
|
+ json_val_t *value;
|
|
|
+ void *next;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_arr
|
|
|
+ * Typedef: json_arr_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST).
|
|
|
+ * void *entry: Containing entry, only elements.
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Defines a JSON-array entry.
|
|
|
+ **/
|
|
|
+struct json_arr {
|
|
|
+ json_types_t type;
|
|
|
+ json_elem_t *entry;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Structure: json_val
|
|
|
+ * Typedef: json_val_t
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Sections:
|
|
|
+ * json_types_t type: Entry type (MUST BE FIRST).
|
|
|
+ * json_types_t sub_type: Type of the sub entry, eg JSON_INT, _CHAR etc
|
|
|
+ * void *value: The actual entry
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ *
|
|
|
+ **/
|
|
|
+struct json_val {
|
|
|
+ json_types_t type;
|
|
|
+ json_types_t sub_type;
|
|
|
+ void *value;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_ptype
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - print_type_t ptype: Print type
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Validates and sets the print type, e.g
|
|
|
+ * Pretty Print, Print etc. (File save not implemented)
|
|
|
+ *
|
|
|
+ * Returns: int, the print type value
|
|
|
+ **/
|
|
|
+static int json_ptype( print_type_t ptype );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_set_code
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object to set status for
|
|
|
+ * - int code: The status code to set
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Sets the status code of the last event
|
|
|
+ * of types related to the JSON-object.
|
|
|
+ *
|
|
|
+ * Returns: int, the newly set code
|
|
|
+ **/
|
|
|
+static int json_set_code( json_obj_t *jobj, int code );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_get_type
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - void *entry: The JSON-entry to read type of
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Returns the type of the JSON-entry.
|
|
|
+ *
|
|
|
+ * Returns: json_types_t, the type
|
|
|
+ **/
|
|
|
+static json_types_t json_get_type( void *entry );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_is_type
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - void *entry: The JSON-entry to check
|
|
|
+ * - json_types_t: The JSON-type compare against
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks the equality of the type of the entry
|
|
|
+ * agains the given type.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on success, 0 on failure
|
|
|
+ **/
|
|
|
+static int json_is_type( void *entry, json_types_t jtype );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_uninit_obj
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: The JSON-object (parent of obj)
|
|
|
+ * - void *obj: Any kind of object within parent
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks if the JSON-object is uninitialized. Checks
|
|
|
+ * both the root (jobj) and sub obj.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on failure, 0 on success
|
|
|
+ **/
|
|
|
+static int json_uninit_obj( json_obj_t *jobj, void *obj );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_val_vtype
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: Parent JSON-object
|
|
|
+ * - json_types_t *vtype: The value type
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks if the given type is valid as a value, for
|
|
|
+ * the value entry.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on success, 0 on failure
|
|
|
+ **/
|
|
|
+static int json_val_vtype( json_obj_t *jobj, json_types_t vtype );
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_insert
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: Parent JSON-obj
|
|
|
+ * - void *root: Root-entry, an JSON-entry
|
|
|
+ * - void *entry: New entry, valid for root-entry
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Inserts an entry into the root, which is related
|
|
|
+ * to the parent JSON-obj. Insertion method and possibilities
|
|
|
+ * depends on the root-entry.
|
|
|
+ *
|
|
|
+ * Returns: void *, address to newly inserte entry
|
|
|
+ **/
|
|
|
+static void *json_insert( json_obj_t *jobj, void *root, void *entry );
|
|
|
+
|
|
|
+/** Recursice functions to print the tree **/
|
|
|
+static void _json_out( json_obj_t *jobj, int height );
|
|
|
+static void _print_( json_obj_t *jobj, ... );
|
|
|
+static void _print_mem( json_obj_t *jobj, json_mem_t *jmem, int height );
|
|
|
+static void _print_pair( json_obj_t *jobj, json_pair_t *jpair, int height );
|
|
|
+static void _print_arr( json_obj_t *jobj, json_arr_t *jarr, int height );
|
|
|
+static void _print_elem( json_obj_t *jobj, json_elem_t *jelem, int height );
|
|
|
+static void _print_value( json_obj_t *jobj, json_val_t *jval, int height );
|
|
|
+static char *_print_set_newline( json_obj_t *jobj );
|
|
|
+static void _print_tabs_release( char *tabs );
|
|
|
+static char *_print_tabs( json_obj_t *jobj, int height );
|
|
|
+/** Silence in comments is like nothing was here */
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - char *fname: The filename; on saving
|
|
|
+ and possible parsing - in the future.
|
|
|
+ * - print_type_t ptype: Store/print type
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates the main root of the JSON-structure.
|
|
|
+ *
|
|
|
+ * Returns: json_obj_t *, the mother root
|
|
|
+ **/
|
|
|
+json_obj_t *json_create( char *fname, print_type_t ptype ) {
|
|
|
+
|
|
|
+ json_obj_t *jobj = ( json_obj_t *) malloc( sizeof( json_obj_t ) );
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ errandend( "Could not allocate memory for JSON object" );
|
|
|
+
|
|
|
+ jobj->type = JSON_OBJ;
|
|
|
+ jobj->members = NULL;
|
|
|
+ jobj->ptype = json_ptype( ptype );
|
|
|
+
|
|
|
+ if ( (jobj->ptype & JSON_SAVE_FILE) == JSON_SAVE_FILE ) {
|
|
|
+ jobj->jfile = fopen( fname, "w+" );
|
|
|
+
|
|
|
+ if ( jobj->jfile == NULL ) {
|
|
|
+ printf("%s\n", fname );
|
|
|
+ errandend( "Could not open file for reading/writing." );
|
|
|
+ }
|
|
|
+
|
|
|
+ jobj->pfunc = (json_printf_t *)fprintf;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ jobj->jfile = NULL;
|
|
|
+ jobj->pfunc = (json_printf_t *)printf;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ json_set_code( jobj, jobj->ptype );
|
|
|
+
|
|
|
+ return jobj;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroys any kind of JSON-objects
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ( jobj->members != NULL )
|
|
|
+ json_destroy_mem( jobj->members );
|
|
|
+
|
|
|
+ if ( jobj->jfile != NULL )
|
|
|
+ fclose( jobj->jfile );
|
|
|
+
|
|
|
+ free( jobj );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create_obj
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ * - json_val_t *jval: JSON-value to insert to
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a new JSON-object to insert into the
|
|
|
+ * JSON-structure (only into JSON-value.).
|
|
|
+ *
|
|
|
+ * Works recursivly on children.
|
|
|
+ *
|
|
|
+ * Returns: json_obj_t *, JSON-object
|
|
|
+ **/
|
|
|
+json_obj_t *json_create_obj( json_obj_t *jobj, json_val_t *jval ) {
|
|
|
+
|
|
|
+ json_obj_t *jcobj;
|
|
|
+
|
|
|
+ if ( json_uninit_obj( jobj, jval ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jcobj = json_create( "", jobj->ptype );
|
|
|
+
|
|
|
+ if ( json_insert( jobj, jval, jobj ) != NULL )
|
|
|
+ return jcobj;
|
|
|
+
|
|
|
+ json_destroy( jcobj );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create_mem
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object to insert to
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a new JSON-member and inserts it into the
|
|
|
+ * JSON-object. May be any kind of JSON-object, both
|
|
|
+ * root or children.
|
|
|
+ *
|
|
|
+ * Returns: json_mem_t *, JSON-member
|
|
|
+ **/
|
|
|
+json_mem_t *json_create_mem( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ json_mem_t *jmem;
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jmem = ( json_mem_t *) malloc( sizeof( json_mem_t ) );
|
|
|
+
|
|
|
+ if ( jmem == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_NOMEM );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jmem->type = JSON_MEM;
|
|
|
+ jmem->entry = NULL;
|
|
|
+ jmem->next = NULL;
|
|
|
+
|
|
|
+ if ( json_insert( jobj, jobj, jmem ) != NULL )
|
|
|
+ return jmem;
|
|
|
+
|
|
|
+ json_destroy_mem( jmem );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy_mem
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_mem_t *jmem: JSON-member to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroy a JSON-member, works recursively on both simblings
|
|
|
+ * and children.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy_mem( json_mem_t *jmem ) {
|
|
|
+
|
|
|
+ if ( jmem == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ( jmem->entry != NULL ) {
|
|
|
+ if ( json_is_type( jmem->entry, JSON_PAIR ) )
|
|
|
+ json_destroy_pair( jmem->entry );
|
|
|
+ else
|
|
|
+ json_destroy_mem( jmem->entry );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( jmem->next != NULL ) {
|
|
|
+ if ( json_is_type( jmem->next, JSON_PAIR ) )
|
|
|
+ json_destroy_pair( jmem->next );
|
|
|
+ else
|
|
|
+ json_destroy_mem( jmem->next );
|
|
|
+ }
|
|
|
+
|
|
|
+ free( jmem );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create_pair
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ * - json_mem_t *jmem: JSON-member to insert to
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a new JSON-pair and inserts it into a JSON-member.
|
|
|
+ *
|
|
|
+ * Returns: json_pair_t *, JSON-pair
|
|
|
+ **/
|
|
|
+json_pair_t *json_create_pair( json_obj_t *jobj, json_mem_t *jmem, char *str ) {
|
|
|
+
|
|
|
+ json_pair_t *jpair;
|
|
|
+
|
|
|
+ if ( json_uninit_obj( jobj, jmem ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jpair = ( json_pair_t *) malloc( sizeof( json_pair_t ) );
|
|
|
+
|
|
|
+ if ( jpair == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_NOMEM );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jpair->type = JSON_PAIR;
|
|
|
+ jpair->str = strdup( str );
|
|
|
+ jpair->value = NULL;
|
|
|
+ jpair->next = NULL;
|
|
|
+
|
|
|
+ if ( json_insert( jobj, jmem, jpair ) != NULL )
|
|
|
+ return jpair;
|
|
|
+
|
|
|
+ json_destroy_pair( jpair );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy_pair
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_pair_t *jpair: JSON-pair to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroys a JSON-pair. Works recursively on both the simblings
|
|
|
+ * and children.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy_pair( json_pair_t *jpair ) {
|
|
|
+
|
|
|
+ if ( jpair == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ( jpair->value != NULL )
|
|
|
+ json_destroy_value( jpair->value );
|
|
|
+
|
|
|
+ if ( jpair->next != NULL ) {
|
|
|
+ if ( json_is_type( jpair->next, JSON_PAIR ) )
|
|
|
+ json_destroy_pair( jpair->next );
|
|
|
+ else
|
|
|
+ json_destroy_mem( jpair->next );
|
|
|
+ }
|
|
|
+
|
|
|
+ free( jpair->str );
|
|
|
+ free( jpair );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create_arr
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ * - json_val_t *jval: JSON-value to insert to
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a new JSON-array and inserts it into JSON-value.
|
|
|
+ *
|
|
|
+ * Returns: json_arr_t *, JSON-array
|
|
|
+ **/
|
|
|
+json_arr_t *json_create_arr( json_obj_t *jobj, json_val_t *jval ) {
|
|
|
+
|
|
|
+ json_arr_t *jarr;
|
|
|
+
|
|
|
+ if ( json_uninit_obj( jobj, jval ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jarr = ( json_arr_t *) malloc( sizeof( json_arr_t ) );
|
|
|
+
|
|
|
+ if ( jarr == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_NOMEM );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jarr->type = JSON_ARR;
|
|
|
+ jarr->entry = NULL;
|
|
|
+
|
|
|
+ if ( json_insert( jobj, jval, jarr ) != NULL )
|
|
|
+ return jarr;
|
|
|
+
|
|
|
+ json_destroy_arr( jarr );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy_arr
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_arr_t *jarr: JSON-array to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroys a JSON-array. Works recursively on the children.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy_arr( json_arr_t *jarr ) {
|
|
|
+
|
|
|
+ if ( jarr == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ( jarr->entry != NULL )
|
|
|
+ json_destroy_elem( jarr->entry );
|
|
|
+
|
|
|
+ free( jarr );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_create_elem
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ * - json_arr_t *jarr: JSON-array to insert into
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a JSON-element and inserts it int an JSON-array.
|
|
|
+ *
|
|
|
+ * Returns: json_elem_t *, JSON-element
|
|
|
+ **/
|
|
|
+json_elem_t *json_create_elem( json_obj_t *jobj, json_arr_t *jarr ) {
|
|
|
+
|
|
|
+ json_elem_t *jelem;
|
|
|
+
|
|
|
+ if ( json_uninit_obj( jobj, jarr ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jelem = ( json_elem_t *) malloc( sizeof( json_elem_t ) );
|
|
|
+
|
|
|
+ if ( jelem == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_NOMEM );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jelem->type = JSON_ELEM;
|
|
|
+ jelem->entry = NULL;
|
|
|
+ jelem->next = NULL;
|
|
|
+
|
|
|
+ if ( json_insert( jobj, jarr, jelem ) != NULL )
|
|
|
+ return jelem;
|
|
|
+
|
|
|
+ json_destroy_elem( jelem );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy_elem
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_elem_t *jelem: JSON-element to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroys a JSON-element. Works recursively on both simblings
|
|
|
+ * and children.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy_elem( json_elem_t *jelem ) {
|
|
|
+
|
|
|
+ if ( jelem == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if ( jelem->entry != NULL )
|
|
|
+ json_destroy_value( jelem->entry );
|
|
|
+
|
|
|
+ if ( jelem->next != NULL )
|
|
|
+ json_destroy_elem( jelem->next );
|
|
|
+
|
|
|
+ free( jelem );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_insert_value
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ * - void *ins_obj: Object or element to insert into
|
|
|
+ * - json_types_t vtype: Type of the held element in value
|
|
|
+ * - void *entry: Entry to store in value
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Creates a new JSON-value and inserts it into a JSON-element or
|
|
|
+ * a JSON-pair. The value must also be specified. JSON-object and
|
|
|
+ * JSON-array can be insert upon creation by setting entry as NULL.
|
|
|
+ *
|
|
|
+ * Ex:
|
|
|
+ *
|
|
|
+ * // Insert this value into a JSON-pair, will contain an JSON-array
|
|
|
+ * json_val_t *jvalue = json_insert_value( jobj, jpair, JSON_ARR, NULL );
|
|
|
+ *
|
|
|
+ * // Create the JSON-array and insert it into the above value
|
|
|
+ * json_arr_t *jarr = json_create_arr( jobj, jval );
|
|
|
+ *
|
|
|
+ * Returns: json_val_t *, JSON-value
|
|
|
+ **/
|
|
|
+json_val_t *json_insert_value( json_obj_t *jobj, void *ins_obj, json_types_t vtype, void *entry ) {
|
|
|
+
|
|
|
+ json_val_t *jval;
|
|
|
+
|
|
|
+ if ( vtype != JSON_NULL && ( ( vtype != JSON_OBJ && vtype != JSON_ARR && json_uninit_obj( jobj, entry ) ) || json_val_vtype( jobj, vtype ) < 0 ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ jval = ( json_val_t *) malloc( sizeof( json_val_t ) );
|
|
|
+
|
|
|
+ if ( jval == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_NOMEM );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ jval->type = JSON_VAL;
|
|
|
+ jval->sub_type = vtype;
|
|
|
+
|
|
|
+ if ( vtype == JSON_OBJ || vtype == JSON_ARR ) {
|
|
|
+ /* By now; nothing to do */
|
|
|
+ } else {
|
|
|
+
|
|
|
+ switch( vtype ) {
|
|
|
+ case JSON_CHAR:
|
|
|
+ jval->value = strdup( (char *)entry );
|
|
|
+ break;
|
|
|
+ case JSON_INT:
|
|
|
+ jval->value = (int *) malloc( sizeof( int ) );
|
|
|
+ memcpy( jval->value, ((const void *)entry), sizeof( int ) );
|
|
|
+ break;
|
|
|
+ case JSON_FLOAT:
|
|
|
+ jval->value = (float *) malloc( sizeof( int ) );
|
|
|
+ memcpy( jval->value, ((const void *)entry), sizeof( float ) );
|
|
|
+ break;
|
|
|
+ case JSON_BOOL:
|
|
|
+ jval->value = strdup( *((bool *)entry) == true ? "true" : "false" );
|
|
|
+ break;
|
|
|
+ case JSON_NULL:
|
|
|
+ jval->value = strdup( entry == NULL ? "null" : "" );
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ json_set_code( jobj, JSON_INVALID_VAL_TYPE );
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_VAL_VAL );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( json_insert( jobj, ins_obj, jval ) != NULL )
|
|
|
+ return jval;
|
|
|
+
|
|
|
+ json_destroy_value( jval );
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_destroy_value
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_val_t *jval: JSON-value to destroy
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Destroys a JSON-value. Works recursively on children.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_destroy_value( json_val_t *jval ) {
|
|
|
+
|
|
|
+ if ( jval == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ switch( jval->sub_type ) {
|
|
|
+
|
|
|
+ case JSON_OBJ:
|
|
|
+ json_destroy( jval->value );;
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_ARR:
|
|
|
+ json_destroy_arr( jval->value );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_CHAR:
|
|
|
+ case JSON_INT:
|
|
|
+ case JSON_FLOAT:
|
|
|
+ case JSON_BOOL:
|
|
|
+ case JSON_NULL:
|
|
|
+ free( jval->value );
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ free( jval );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_has_err
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Returns whether or not there was an error present on last event.
|
|
|
+ *
|
|
|
+ * Returns: int 0 on non errors 1 on errors
|
|
|
+ **/
|
|
|
+int json_has_err( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ return JSON_UNINITALIZED_OJB;
|
|
|
+
|
|
|
+ return ( jobj->code >= 0 ? 0 : 1 );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_last_err
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Returns the last error code present.
|
|
|
+ *
|
|
|
+ * Returns: int, >= 0 on non errors <= 0 on errors
|
|
|
+ **/
|
|
|
+int json_last_err( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ return JSON_UNINITALIZED_OJB;
|
|
|
+
|
|
|
+ return jobj->code;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_last_errmsg
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Returns the error message related to the error code
|
|
|
+ * stored in the JSON-object (remember to check for errors; json_has_err).
|
|
|
+ *
|
|
|
+ * Returns: char *, error message
|
|
|
+ **/
|
|
|
+const char *json_last_errmsg( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ char *errmsg;
|
|
|
+ int errcode = json_last_err( jobj );
|
|
|
+
|
|
|
+ switch( errcode ) {
|
|
|
+
|
|
|
+ case JSON_NO_REPORT:
|
|
|
+ errmsg = "Not an error";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_UNKNOWN_PTYPE:
|
|
|
+ errmsg = "Unknown print type";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_UNINITALIZED_OJB:
|
|
|
+ errmsg = "Un-initialized JSON object";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_NOMEM:
|
|
|
+ errmsg = "Out of memory";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_INVALID_VAL_TYPE:
|
|
|
+ errmsg = "Invalid type to insert within value object";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_INVALID_ROOT_ENT:
|
|
|
+ case JSON_INVALID_OBJ_ENT:
|
|
|
+ case JSON_INVALID_MEM_ENT:
|
|
|
+ case JSON_INVALID_PAIR_ENT:
|
|
|
+ case JSON_INVALID_ELE_MENT:
|
|
|
+ case JSON_INVALID_VAL_ENT:
|
|
|
+ case JSON_INVALID_ELEM_ENT:
|
|
|
+ case JSON_INVALID_ARR_ENT:
|
|
|
+ errmsg = "Invalid object to insert within parent object";
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_MIXED_VAL_AND_TYPE:
|
|
|
+ errmsg = "Mixed value and type.";
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ errmsg = "Error code unknown or not implemented";
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return (const char *)errmsg;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_out
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object which is the main-root
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Recursively prints the JSON-object.
|
|
|
+ *
|
|
|
+ * Returns: void
|
|
|
+ **/
|
|
|
+void json_out( json_obj_t *jobj ) {
|
|
|
+
|
|
|
+ int height = 1;
|
|
|
+
|
|
|
+ _print_( jobj, "[%s", _print_set_newline(jobj) );
|
|
|
+ _json_out( jobj, height );
|
|
|
+ _print_( jobj, "]%s", _print_set_newline(jobj) );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_ptype
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - print_type_t ptype: Print type
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Validates and sets the print type, e.g
|
|
|
+ * Pretty Print, Print etc. (File save not implemented)
|
|
|
+ *
|
|
|
+ * Returns: int, the print type value
|
|
|
+ **/
|
|
|
+static int json_ptype( print_type_t ptype ) {
|
|
|
+ return ( ptype > JSON_SAVE_FILE - 1 && ptype < JSON_TYPE ? ptype : JSON_UNKNOWN_PTYPE );
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_set_code
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: JSON-object to set status for
|
|
|
+ * - int code: The status code to set
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Sets the status code of the last event
|
|
|
+ * of types related to the JSON-object.
|
|
|
+ *
|
|
|
+ * Returns: int, the newly set code
|
|
|
+ **/
|
|
|
+static int json_set_code( json_obj_t *jobj, int code ) {
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ return jobj->code = JSON_UNINITALIZED_OJB;
|
|
|
+
|
|
|
+ return jobj->code = code;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_get_type
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - void *entry: The JSON-entry to read type of
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Returns the type of the JSON-entry.
|
|
|
+ *
|
|
|
+ * Returns: json_types_t, the type
|
|
|
+ **/
|
|
|
+static json_types_t json_get_type( void *entry ) {
|
|
|
+
|
|
|
+ json_type_t *type = (json_type_t *)entry;
|
|
|
+
|
|
|
+ return type->type;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_is_type
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - void *entry: The JSON-entry to check
|
|
|
+ * - json_types_t: The JSON-type compare against
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks the equality of the type of the entry
|
|
|
+ * agains the given type.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on success, 0 on failure
|
|
|
+ **/
|
|
|
+static int json_is_type( void *entry, json_types_t jtype ) {
|
|
|
+ return json_get_type( entry ) == jtype;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_uninit_obj
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: The JSON-object (parent of obj)
|
|
|
+ * - void *obj: Any kind of object within parent
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks if the JSON-object is uninitialized. Checks
|
|
|
+ * both the root (jobj) and sub obj.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on failure, 0 on success
|
|
|
+ **/
|
|
|
+static int json_uninit_obj( json_obj_t *jobj, void *obj ) {
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if ( obj == NULL ) {
|
|
|
+ json_set_code( jobj, JSON_UNINITALIZED_OJB );
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_val_vtype
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: Parent JSON-object
|
|
|
+ * - json_types_t *vtype: The value type
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Checks if the given type is valid as a value, for
|
|
|
+ * the value entry.
|
|
|
+ *
|
|
|
+ * Returns: int, 1 on success, 0 on failure
|
|
|
+ **/
|
|
|
+static int json_val_vtype( json_obj_t *jobj, json_types_t vtype ) {
|
|
|
+
|
|
|
+ int i;
|
|
|
+ json_types_t val_types[7] = {
|
|
|
+ JSON_OBJ, JSON_ARR, JSON_CHAR, JSON_INT, JSON_FLOAT, JSON_BOOL, JSON_NULL
|
|
|
+ };
|
|
|
+
|
|
|
+ for ( i = 0; i < sizeof( val_types ); i++ ) {
|
|
|
+ if ( vtype == val_types[ i ] )
|
|
|
+ return ( jobj == NULL ? JSON_INS_TYPE_VAL : json_set_code( jobj, JSON_INS_TYPE_VAL ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ return ( jobj == NULL ? JSON_INVALID_VAL_TYPE : json_set_code( jobj, JSON_INVALID_VAL_TYPE ) );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Function: json_insert
|
|
|
+ * Author: Joachim M. Giæver
|
|
|
+ *
|
|
|
+ * Parameters:
|
|
|
+ * - json_obj_t *jobj: Parent JSON-obj
|
|
|
+ * - void *root: Root-entry, an JSON-entry
|
|
|
+ * - void *entry: New entry, valid for root-entry
|
|
|
+ *
|
|
|
+ * Description:
|
|
|
+ * Inserts an entry into the root, which is related
|
|
|
+ * to the parent JSON-obj. Insertion method and possibilities
|
|
|
+ * depends on the root-entry.
|
|
|
+ *
|
|
|
+ * Returns: void *, address to newly inserte entry
|
|
|
+ **/
|
|
|
+static void *json_insert( json_obj_t *jobj, void *root, void *entry ) {
|
|
|
+
|
|
|
+ void *tmp;
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ switch( json_get_type( root ) ) {
|
|
|
+
|
|
|
+ case JSON_OBJ:
|
|
|
+
|
|
|
+ if ( !json_is_type( entry, JSON_MEM ) ) {
|
|
|
+ json_set_code( jobj, JSON_INVALID_OBJ_ENT );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ tmp = ((json_obj_t *)root)->members;
|
|
|
+
|
|
|
+ while( tmp != NULL && ((json_mem_t *)tmp)->next != NULL )
|
|
|
+ tmp = ((json_mem_t *)tmp)->next;
|
|
|
+
|
|
|
+ if ( tmp == NULL )
|
|
|
+ ((json_obj_t *)root)->members = (json_mem_t *)entry;
|
|
|
+ else
|
|
|
+ ((json_mem_t *)tmp)->next = (json_mem_t *)entry;
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_MEM_OBJ );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_MEM:
|
|
|
+
|
|
|
+ switch( json_get_type( entry ) ) {
|
|
|
+
|
|
|
+ case JSON_PAIR:
|
|
|
+ case JSON_MEM:
|
|
|
+
|
|
|
+ tmp = ((json_mem_t *)root)->entry;
|
|
|
+
|
|
|
+ if ( tmp == NULL )
|
|
|
+ ((json_mem_t *)root)->entry = entry;
|
|
|
+
|
|
|
+ while( tmp != NULL && ( ( json_is_type( entry, JSON_MEM ) && ((json_mem_t *)tmp)->next != NULL ) || ( json_is_type( entry, JSON_PAIR ) && ((json_pair_t *)tmp)->next != NULL ) ) ) {
|
|
|
+ tmp = ( json_is_type( entry, JSON_MEM ) ? ((json_mem_t *)tmp)->next : ((json_pair_t *)tmp)->next );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( tmp != NULL ) {
|
|
|
+ if ( json_is_type( entry, JSON_MEM ) )
|
|
|
+ ((json_mem_t *)tmp)->next = entry;
|
|
|
+ else
|
|
|
+ ((json_pair_t *)tmp)->next = entry;
|
|
|
+ }
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_PAIR_MEM );
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ json_set_code( jobj, JSON_INVALID_MEM_ENT );
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_PAIR:
|
|
|
+
|
|
|
+ if ( !json_is_type( entry, JSON_VAL ) ) {
|
|
|
+ json_set_code( jobj, JSON_INVALID_PAIR_ENT );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ((json_pair_t *)root)->value = entry;
|
|
|
+ json_set_code( jobj, JSON_INS_VAL_PAIR );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_ELEM:
|
|
|
+
|
|
|
+ if ( !json_is_type( entry, JSON_VAL ) ) {
|
|
|
+ json_set_code( jobj, JSON_INVALID_ELEM_ENT );
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ tmp = ((json_elem_t *)root)->entry;
|
|
|
+
|
|
|
+ if ( tmp != NULL )
|
|
|
+ json_destroy_value( tmp );
|
|
|
+
|
|
|
+ ((json_elem_t *)root)->entry = entry;
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_VAL_ELEM );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_ARR:
|
|
|
+
|
|
|
+ if ( !json_is_type( entry, JSON_ELEM ) ) {
|
|
|
+ json_set_code( jobj, JSON_INVALID_ARR_ENT );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ tmp = ((json_arr_t *)root)->entry;
|
|
|
+
|
|
|
+ if ( tmp == NULL )
|
|
|
+ ((json_arr_t *)root)->entry = entry;
|
|
|
+ else {
|
|
|
+
|
|
|
+ while( tmp != NULL && ((json_elem_t *)tmp)->next != NULL )
|
|
|
+ tmp = ((json_elem_t *)tmp)->next;
|
|
|
+
|
|
|
+ ((json_elem_t *)tmp)->next = entry;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_ELEM_ARR );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_VAL:
|
|
|
+
|
|
|
+ switch( json_get_type( entry ) ) {
|
|
|
+
|
|
|
+ case JSON_OBJ:
|
|
|
+ case JSON_ARR:
|
|
|
+
|
|
|
+ ((json_val_t *)root)->value = entry;
|
|
|
+
|
|
|
+ json_set_code( jobj, JSON_INS_VAL_VAL );
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ json_set_code( jobj, JSON_INVALID_VAL_ENT );
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ json_set_code( jobj, JSON_INVALID_ROOT_ENT );
|
|
|
+ return NULL;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return entry;
|
|
|
+}
|
|
|
+
|
|
|
+/** Recursice functions to print the tree **/
|
|
|
+static void _json_out( json_obj_t *jobj, int height ) {
|
|
|
+
|
|
|
+ if ( jobj == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ _print_mem( jobj, jobj->members, height );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_( json_obj_t *jobj, ... ) {
|
|
|
+
|
|
|
+ va_list vargs;
|
|
|
+ char *format;
|
|
|
+
|
|
|
+ va_start( vargs, jobj );
|
|
|
+
|
|
|
+ if ( jobj->jfile == NULL || (jobj->ptype & JSON_PRINT) == JSON_PRINT ) {
|
|
|
+
|
|
|
+ format = va_arg( vargs, char * );
|
|
|
+ vprintf( format, vargs );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ va_end( vargs );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_mem( json_obj_t *jobj, json_mem_t *jmem, int height ) {
|
|
|
+
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( jmem == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ tabs = _print_tabs( jobj, height );
|
|
|
+
|
|
|
+ _print_( jobj, "%s{%s", tabs, _print_set_newline( jobj ) );
|
|
|
+
|
|
|
+ if ( json_is_type( jmem->entry, JSON_PAIR ) )
|
|
|
+ _print_pair( jobj, jmem->entry, height + 1 );
|
|
|
+ else
|
|
|
+ _print_mem( jobj, jmem->entry, height + 1 );
|
|
|
+
|
|
|
+ _print_( jobj, "%s}%s%s", tabs, ( jmem->next != NULL ? "," : "" ), _print_set_newline( jobj ) );
|
|
|
+
|
|
|
+ _print_tabs_release( tabs );
|
|
|
+
|
|
|
+ _print_mem( jobj, jmem->next, height );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_pair( json_obj_t *jobj, json_pair_t *jpair, int height ) {
|
|
|
+
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( jpair == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ tabs = _print_tabs( jobj, height );
|
|
|
+
|
|
|
+ _print_( jobj, "%s\"%s\":", tabs, jpair->str );
|
|
|
+ _print_value( jobj, jpair->value, height + 1 );
|
|
|
+ _print_( jobj, "%s%s", ( jpair->next != NULL ? "," : "" ), _print_set_newline( jobj ) );
|
|
|
+
|
|
|
+ _print_tabs_release( tabs );
|
|
|
+
|
|
|
+ if ( jpair->next != NULL ) {
|
|
|
+
|
|
|
+ if ( json_is_type( jpair->next, JSON_PAIR ) )
|
|
|
+ _print_pair( jobj, jpair->next, height );
|
|
|
+ else if ( json_is_type( jpair->next, JSON_MEM ) )
|
|
|
+ _print_mem( jobj, jpair->next, height );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_arr( json_obj_t *jobj, json_arr_t *jarr, int height ) {
|
|
|
+
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( jarr == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ tabs = _print_tabs( jobj, height - 1 );
|
|
|
+
|
|
|
+ _print_( jobj, "[%s", _print_set_newline( jobj ) );
|
|
|
+ _print_elem( jobj, jarr->entry, height );
|
|
|
+ _print_( jobj, "%s]", tabs );
|
|
|
+
|
|
|
+ _print_tabs_release( tabs );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_elem( json_obj_t *jobj, json_elem_t *jelem, int height ) {
|
|
|
+
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( jelem == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ tabs = _print_tabs( jobj, height );
|
|
|
+
|
|
|
+ _print_( jobj, "%s", tabs );
|
|
|
+ _print_value( jobj, jelem->entry, height );
|
|
|
+ _print_( jobj, "%s%s", ( jelem->next != NULL ? "," : "" ), _print_set_newline( jobj ) );
|
|
|
+
|
|
|
+ _print_elem( jobj, jelem->next, height );
|
|
|
+
|
|
|
+ _print_tabs_release( tabs );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_value( json_obj_t *jobj, json_val_t *jval, int height ) {
|
|
|
+
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( jval == NULL ) {
|
|
|
+ _print_( jobj, "\"\"" );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ tabs = _print_tabs( jobj, height + 1 );
|
|
|
+
|
|
|
+ switch( jval->sub_type ) {
|
|
|
+
|
|
|
+ case JSON_OBJ:
|
|
|
+ _json_out( jval->value, height );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_ARR:
|
|
|
+ _print_arr( jobj, jval->value, height );
|
|
|
+ break;
|
|
|
+ case JSON_CHAR:
|
|
|
+ case JSON_BOOL:
|
|
|
+ case JSON_NULL:
|
|
|
+ _print_( jobj, "\"%s\"", (char *)jval->value );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_INT:
|
|
|
+ _print_( jobj, "%d", *(int *)jval->value );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case JSON_FLOAT:
|
|
|
+ _print_( jobj, "%f", *(float *)jval->value );
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ _print_( jobj, "\"\"");
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ _print_tabs_release( tabs );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static char *_print_set_newline( json_obj_t *jobj ) {
|
|
|
+ return (jobj->ptype & JSON_PPRINT) == JSON_PPRINT ? "\n": "";
|
|
|
+}
|
|
|
+
|
|
|
+static void _print_tabs_release( char *tabs ) {
|
|
|
+
|
|
|
+ if ( tabs == NULL )
|
|
|
+ return;
|
|
|
+
|
|
|
+ free( tabs );
|
|
|
+}
|
|
|
+
|
|
|
+static char *_print_tabs( json_obj_t *jobj, int height ) {
|
|
|
+
|
|
|
+ int i;
|
|
|
+ char *tabs;
|
|
|
+
|
|
|
+ if ( (jobj->ptype & JSON_PPRINT) == JSON_PPRINT ) {
|
|
|
+ tabs = ( char *) malloc( sizeof( char * ) );
|
|
|
+ tabs[0] = 0;
|
|
|
+ return tabs;
|
|
|
+ }
|
|
|
+
|
|
|
+ tabs = ( char *) malloc( sizeof( char * ) * height );
|
|
|
+
|
|
|
+ for ( i = 0; i < height; i++ )
|
|
|
+ tabs[ i ] = '\t';
|
|
|
+
|
|
|
+ tabs[i] = 0;
|
|
|
+
|
|
|
+ return tabs;
|
|
|
+
|
|
|
+}
|
|
|
+/** Silence in comments is like nothing was here */
|
|
|
+
|
|
|
+/***
|
|
|
+ * THIS IS FOR DEBUGGING OF THE JSON-IMPLEMENTATION;
|
|
|
+ * To run this make project as:
|
|
|
+ * $ make json-test
|
|
|
+ * and run by
|
|
|
+ * $ ./json-test
|
|
|
+ **/
|
|
|
+
|
|
|
+#ifdef _DEBUG_JSON
|
|
|
+
|
|
|
+int main(int argc, char const *argv[]) {
|
|
|
+
|
|
|
+ int i = 18848;
|
|
|
+ float f = 154.4848;
|
|
|
+ bool b = true;
|
|
|
+
|
|
|
+ json_obj_t *jobj = json_create( "", JSON_PRINT | JSON_PPRINT );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_mem_t *jmem = json_create_mem( jobj );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_pair_t *jpair = json_create_pair( jobj, jmem, "Test" );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_pair_t *jpair2 = json_create_pair( jobj, jmem, "Test" );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_pair_t *jpair3 = json_create_pair( jobj, jmem, "Test" );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_val_t *jval = json_insert_value( jobj, jpair, JSON_CHAR, "Litt text" );
|
|
|
+ jval = json_insert_value( jobj, jpair2, JSON_CHAR, "Litt mer test" );
|
|
|
+ jval = json_insert_value( jobj, jpair3, JSON_CHAR, "Litt test" );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_mem_t *jmem2 = json_create_mem( jobj );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ jpair2 = json_create_pair( jobj, jmem2, "array" );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_val_t *jval2 = json_insert_value( jobj, jpair2, JSON_ARR, NULL );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_arr_t *jarr = json_create_arr( jobj, jval2 );
|
|
|
+
|
|
|
+ if ( json_has_err( jobj ) )
|
|
|
+ printf("ERR: %s\n\n", json_last_errmsg( jobj ) );
|
|
|
+
|
|
|
+ json_elem_t *elem = json_create_elem( jobj, jarr );
|
|
|
+
|
|
|
+ json_val_t *val = json_insert_value( jobj, elem, JSON_INT, &i );
|
|
|
+
|
|
|
+ elem = json_create_elem( jobj, jarr );
|
|
|
+ val = json_insert_value( jobj, elem, JSON_BOOL, &b );
|
|
|
+
|
|
|
+ elem = json_create_elem( jobj, jarr );
|
|
|
+ val = json_insert_value( jobj, elem, JSON_CHAR, "FUCK YOU" );
|
|
|
+
|
|
|
+ elem = json_create_elem( jobj, jarr );
|
|
|
+ val = json_insert_value( jobj, elem, JSON_FLOAT, &f );
|
|
|
+
|
|
|
+ elem = json_create_elem( jobj, jarr );
|
|
|
+ val = json_insert_value( jobj, elem, JSON_NULL, NULL );
|
|
|
+
|
|
|
+ json_out( jobj );
|
|
|
+
|
|
|
+ json_destroy( jobj );
|
|
|
+
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|