12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502 |
- #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
|