mirror of
https://github.com/rafagafe/tiny-json.git
synced 2025-03-12 19:25:30 +00:00
All files are added.
This commit is contained in:
parent
3231433c14
commit
fb3ef655bd
114
example1.c
Normal file
114
example1.c
Normal file
@ -0,0 +1,114 @@
|
||||
|
||||
/*
|
||||
* example1.c 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* example1.c 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* In this example the JSON library is used to scan an object that nothing is
|
||||
* known about its properties.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "tiny-json.h"
|
||||
|
||||
/** Get the name of a json type code.
|
||||
* @param type the json type code.
|
||||
* @return A null-terminated string with the name. */
|
||||
static char const* getJsonTypeName( jsonType_t type ) {
|
||||
static struct { jsonType_t type; char const* name; } const pair[] = {
|
||||
{ JSON_OBJ, "object" },
|
||||
{ JSON_TEXT, "text" },
|
||||
{ JSON_BOOLEAN, "boolean" },
|
||||
{ JSON_INTEGER, "integer" },
|
||||
{ JSON_NULL, "null" },
|
||||
{ JSON_ARRAY, "array" },
|
||||
};
|
||||
unsigned int i;
|
||||
for( i = 0; i < sizeof pair / sizeof *pair; ++i )
|
||||
if ( pair[i].type == type )
|
||||
return pair[i].name;
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/** Print the value os a json object or array.
|
||||
* @param json The handler of the json object or array. */
|
||||
static void print( json_t const* json ) {
|
||||
|
||||
jsonType_t const type = json_getType( json );
|
||||
if ( type != JSON_OBJ && type != JSON_ARRAY ) {
|
||||
puts("error");
|
||||
return;
|
||||
}
|
||||
|
||||
printf( "%s", type == JSON_OBJ? " {": " [" );
|
||||
|
||||
json_t const* child;
|
||||
for( child = json_getChild( json ); child != 0; child = json_getSibling( child ) ) {
|
||||
|
||||
jsonType_t propertyType = json_getType( child );
|
||||
char const* name = json_getName( child );
|
||||
if ( name ) printf(" \"%s\": ", name );
|
||||
|
||||
if ( propertyType == JSON_OBJ || propertyType == JSON_ARRAY )
|
||||
print( child );
|
||||
|
||||
else {
|
||||
char const* value = json_getValue( child );
|
||||
if ( value ) {
|
||||
bool const text = JSON_TEXT == json_getType( child );
|
||||
char const* fmt = text? " \"%s\"": " %s";
|
||||
printf( fmt, value );
|
||||
bool const last = !json_getSibling( child );
|
||||
if ( !last ) putchar(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf( "%s", type == JSON_OBJ? " }": " ]" );
|
||||
|
||||
}
|
||||
|
||||
/* Parser a json string. */
|
||||
int main( void ) {
|
||||
char const* msg = "{\n"
|
||||
"\t\"firstName\": \"Bidhan\",\n"
|
||||
"\t\"lastName\": \"Chatterjee\",\n"
|
||||
"\t\"age\": 40,\n"
|
||||
"\t\"address\": {\n"
|
||||
"\t\t\"streetAddress\": \"144 J B Hazra Road\",\n"
|
||||
"\t\t\"city\": \"Burdwan\",\n"
|
||||
"\t\t\"state\": \"Paschimbanga\",\n"
|
||||
"\t\t\"postalCode\": \"713102\"\n"
|
||||
"\t},\n"
|
||||
"\t\"phoneList\": [\n"
|
||||
"\t\t{ \"type\": \"personal\", \"number\": \"09832209761\" },\n"
|
||||
"\t\t{ \"type\": \"fax\", \"number\": \"91-342-2567692\" }\n"
|
||||
"\t]\n"
|
||||
"}\n";
|
||||
char aux[512];
|
||||
strcpy( aux, msg );
|
||||
puts( aux );
|
||||
json_t mem[32];
|
||||
json_t const* json = json_create( aux, mem, sizeof mem / sizeof *mem );
|
||||
if ( !json ) {
|
||||
puts("Error json create.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
puts("Print JSON:");
|
||||
print( json );
|
||||
return EXIT_SUCCESS;
|
||||
}
|
98
example2.c
Normal file
98
example2.c
Normal file
@ -0,0 +1,98 @@
|
||||
|
||||
/*
|
||||
* example2.c 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* example2.c 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* In this example the JSON library is used to analyze an object that some
|
||||
* properties are expected.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "tiny-json.h"
|
||||
|
||||
/* Parser a json string. */
|
||||
int main( void ) {
|
||||
char const* msg = "{\n"
|
||||
"\t\"firstName\": \"Bidhan\",\n"
|
||||
"\t\"lastName\": \"Chatterjee\",\n"
|
||||
"\t\"age\": 40,\n"
|
||||
"\t\"address\": {\n"
|
||||
"\t\t\"streetAddress\": \"144 J B Hazra Road\",\n"
|
||||
"\t\t\"city\": \"Burdwan\",\n"
|
||||
"\t\t\"state\": \"Paschimbanga\",\n"
|
||||
"\t\t\"postalCode\": \"713102\"\n"
|
||||
"\t},\n"
|
||||
"\t\"phoneList\": [\n"
|
||||
"\t\t{ \"type\": \"personal\", \"number\": \"09832209761\" },\n"
|
||||
"\t\t{ \"type\": \"fax\", \"number\": \"91-342-2567692\" }\n"
|
||||
"\t]\n"
|
||||
"}\n";
|
||||
char aux[512];
|
||||
strcpy( aux, msg );
|
||||
puts( aux );
|
||||
json_t mem[32];
|
||||
json_t const* json = json_create( aux, mem, sizeof mem / sizeof *mem );
|
||||
if ( !json ) {
|
||||
puts("Error json create.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
json_t const* firstName = json_getProperty( json, "firstName" );
|
||||
if ( !firstName || JSON_TEXT != json_getType( firstName ) ) {
|
||||
puts("Error, the first name property is not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
char const* firstNameVal = json_getValue( firstName );
|
||||
if ( firstNameVal ) printf( "Fist Name: %s.\n", firstNameVal );
|
||||
|
||||
json_t const* lastName = json_getProperty( json, "lastName" );
|
||||
if ( !lastName || JSON_TEXT != json_getType( lastName ) ) {
|
||||
puts("Error, the last name property is not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
char const* lastNameVal = json_getValue( lastName );
|
||||
if ( lastName ) printf( "Last Name: %s.\n", lastNameVal );
|
||||
|
||||
json_t const* age = json_getProperty( json, "age" );
|
||||
if ( !age || JSON_INTEGER != json_getType( age ) ) {
|
||||
puts("Error, the age property is not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
int const ageVal = (int)json_getInteger( age );
|
||||
printf( "Age: %d.\n", ageVal );
|
||||
|
||||
json_t const* phoneList = json_getProperty( json, "phoneList" );
|
||||
if ( !phoneList || JSON_ARRAY != json_getType( phoneList ) ) {
|
||||
puts("Error, the phone list property is not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
json_t const* phone;
|
||||
for( phone = json_getChild( phoneList ); phone != 0; phone = json_getSibling( phone ) ) {
|
||||
if ( JSON_OBJ == json_getType( phone ) ) {
|
||||
json_t const* number = json_getProperty( phone, "number" );
|
||||
if ( number ) {
|
||||
char const* numberVal = json_getValue( number );
|
||||
if ( numberVal ) printf( "Number: %s.\n", numberVal );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
24
makefile
Normal file
24
makefile
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
build: example1.exe example2.exe
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
rm -rf *.exe
|
||||
|
||||
all: clean build
|
||||
|
||||
example1.exe: example1.o tiny-json.o
|
||||
gcc -o example1.exe example1.o tiny-json.o
|
||||
|
||||
example2.exe: example2.o tiny-json.o
|
||||
gcc -o example2.exe example2.o tiny-json.o
|
||||
|
||||
tiny-json.o: tiny-json.c tiny-json.h
|
||||
gcc -c tiny-json.c
|
||||
|
||||
example1.o: example1.c tiny-json.h
|
||||
gcc -c example1.c
|
||||
|
||||
example2.o: example2.c tiny-json.h
|
||||
gcc -c example2.c
|
380
tiny-json.c
Normal file
380
tiny-json.c
Normal file
@ -0,0 +1,380 @@
|
||||
|
||||
/*
|
||||
* tiny-json.c 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* tiny-json.c 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "tiny-json.h"
|
||||
|
||||
/** Structure to handle a heap of JSON properties. */
|
||||
typedef struct jsonPool_s {
|
||||
json_t* const mem; /**< Pointer to array of json properties. */
|
||||
unsigned int const qty; /**< Length of the array of json properties. */
|
||||
unsigned int nextFree; /**< The index of the next free json property. */
|
||||
} jsonPool_t;
|
||||
|
||||
/* Search a property by its name in a JSON object. */
|
||||
json_t const* json_getProperty( json_t const* obj, char const* property ) {
|
||||
json_t const* sibling;
|
||||
for( sibling = obj->u.child; sibling; sibling = sibling->sibling )
|
||||
if ( sibling->name && !strcmp( sibling->name, property ) )
|
||||
return sibling;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Internal prototypes: */
|
||||
static char* _goWhiteSpace( char* str );
|
||||
static char* _goNum( char* str );
|
||||
static json_t* _poolInit( jsonPool_t* pool );
|
||||
static json_t* _poolNew( jsonPool_t* pool );
|
||||
static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool );
|
||||
static char* _setToNull( char* ch );
|
||||
|
||||
/* Parse a string to get a json. */
|
||||
json_t const* json_create( char* str, json_t mem[], unsigned int qty ) {
|
||||
char* ptr = _goWhiteSpace( str );
|
||||
if ( *ptr != '{') return 0;
|
||||
jsonPool_t pool = { .mem = mem, .qty = qty };
|
||||
json_t* obj = _poolInit( &pool );
|
||||
obj->name = 0;
|
||||
obj->sibling = 0;
|
||||
obj->u.child = 0;
|
||||
ptr = _objValue( ptr, obj, &pool );
|
||||
if ( !ptr ) return 0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/** Get a special character with its escape character. Examples:
|
||||
* 'b' -> '\b', 'n' -> '\n', 't' -> '\t'
|
||||
* @param ch The escape character.
|
||||
* @return The character code. */
|
||||
static char _getEscape( char ch ) {
|
||||
static struct { char ch; char code; } const pair[] = {
|
||||
{ '\"', '\"' },
|
||||
{ '\\', '\\' },
|
||||
{ '/', '/' },
|
||||
{ 'b', '\b' },
|
||||
{ 'f', '\f' },
|
||||
{ 'n', '\n' },
|
||||
{ 'r', '\r' },
|
||||
{ 't', '\t' },
|
||||
};
|
||||
unsigned int i;
|
||||
for( i = 0; i < sizeof pair / sizeof *pair; ++i )
|
||||
if ( pair[i].ch == ch )
|
||||
return pair[i].code;
|
||||
return '\0';
|
||||
}
|
||||
|
||||
/** Check if a character is a hexadecimal digit. */
|
||||
static bool _isHexaDigit( unsigned char nibble ) {
|
||||
if ( nibble < '0' ) return false;
|
||||
if ( nibble <= '9' ) return true;
|
||||
if ( nibble < 'A' ) return false;
|
||||
if ( nibble <= 'F' ) return true;
|
||||
if ( nibble < 'a' ) return false;
|
||||
if ( nibble <= 'f' ) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Parse 4 charcters.
|
||||
* @Param str Pointer to first digit.
|
||||
* @retval '?' If the four characters are hexadecimal digits.
|
||||
* @retcal '\0' In other cases. */
|
||||
static char _getCharFromUnicode( char const* str ) {
|
||||
unsigned int i;
|
||||
for( i = 0; i < 4; ++i )
|
||||
if ( !_isHexaDigit( str[i] ) )
|
||||
return '\0';
|
||||
return '?';
|
||||
}
|
||||
|
||||
/** Parse a string and replace the scape characters by their meaning characters.
|
||||
* This parser stops when finds the character '\"'. Then replaces '\"' by '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _parseString( char* str ) {
|
||||
char* head = str;
|
||||
char* tail = str;
|
||||
for( ; *head >= ' '; ++head, ++tail ) {
|
||||
if ( *head == '\"' ) {
|
||||
*tail = '\0';
|
||||
return ++head;
|
||||
}
|
||||
if ( *head == '\\' ) {
|
||||
if ( *++head == 'u' ) {
|
||||
char const ch = _getCharFromUnicode( ++head );
|
||||
if ( ch == '\0' ) return 0;
|
||||
*tail = ch;
|
||||
head += 3;
|
||||
}
|
||||
else {
|
||||
char const esc = _getEscape( *head );
|
||||
if ( esc == '\0' ) return 0;
|
||||
*tail = esc;
|
||||
}
|
||||
}
|
||||
else *tail = *head;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Parse a string to get the name of a property.
|
||||
* @param str Pointer to first character.
|
||||
* @param property The property to assign the name.
|
||||
* @retval Pointer to first of property value. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _propertyName( char* ptr, json_t* property ) {
|
||||
property->name = ++ptr;
|
||||
ptr = _parseString( ptr );
|
||||
if ( !ptr ) return 0;
|
||||
ptr = _goWhiteSpace( ptr );
|
||||
if ( !ptr ) return 0;
|
||||
if ( *ptr++ != ':' ) return 0;
|
||||
return _goWhiteSpace( ptr );
|
||||
}
|
||||
|
||||
/** Parse a string to get the value of a property when its type is JSON_TEXT.
|
||||
* @param str Pointer to first character ('\"').
|
||||
* @param property The property to assign the name.
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _textValue( char* ptr, json_t* property ) {
|
||||
++property->u.value;
|
||||
ptr = _parseString( ++ptr );
|
||||
if ( !ptr ) return 0;
|
||||
property->type = JSON_TEXT;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** Compare two strings until get the null character in the second one.
|
||||
* @param ptr
|
||||
* @param str
|
||||
* @retval
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _checkStr( char* ptr, char const* str ) {
|
||||
while( *str )
|
||||
if ( *ptr++ != *str++ )
|
||||
return 0;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** Parser a string to get a primitive value.
|
||||
* If the first character after the value is diferent of '}' or ']' is set to '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @param property Property handler to set the value and the type, (true, false or null).
|
||||
* @param value String with the primitive literal.
|
||||
* @param type The code of the type. ( JSON_BOOLEAN or JSON_NULL )
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _primitiveValue( char* ptr, json_t* property, char const* value, jsonType_t type ) {
|
||||
ptr = _checkStr( ptr, value );
|
||||
if ( !ptr ) return 0;
|
||||
ptr = _setToNull( ptr );
|
||||
property->type = type;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** Parser a string to get a true value.
|
||||
* If the first character after the value is diferent of '}' or ']' is set to '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @param property Property handler to set the value and the type, (true, false or null).
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _trueValue( char* ptr, json_t* property ) {
|
||||
return _primitiveValue( ptr, property, "true", JSON_BOOLEAN );
|
||||
}
|
||||
|
||||
/** Parser a string to get a false value.
|
||||
* If the first character after the value is diferent of '}' or ']' is set to '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @param property Property handler to set the value and the type, (true, false or null).
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _falseValue( char* ptr, json_t* property ) {
|
||||
return _primitiveValue( ptr, property, "false", JSON_BOOLEAN );
|
||||
}
|
||||
|
||||
/** Parser a string to get a null value.
|
||||
* If the first character after the value is diferent of '}' or ']' is set to '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @param property Property handler to set the value and the type, (true, false or null).
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _nullValue( char* ptr, json_t* property ) {
|
||||
return _primitiveValue( ptr, property, "null", JSON_NULL );
|
||||
}
|
||||
|
||||
/** Parser a string to get a integer value.
|
||||
* If the first character after the value is diferent of '}' or ']' is set to '\0'.
|
||||
* @param str Pointer to first character.
|
||||
* @param property Property handler to set the value and the type, (true, false or null).
|
||||
* @retval Pointer to first non white space after the string. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _integerValue( char* ptr, json_t* property ) {
|
||||
if ( *ptr == '-' ) ++ptr;
|
||||
ptr = _goNum( ptr );
|
||||
if ( !ptr ) return 0;
|
||||
ptr = _setToNull( ptr );
|
||||
property->type = JSON_INTEGER;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/** Add a property to a JSON object or array.
|
||||
* @param obj The handler of the JSON object or array.
|
||||
* @param property The handler of the property to be added. */
|
||||
static void _add( json_t* obj, json_t* property ) {
|
||||
property->sibling = 0;
|
||||
if ( !obj->u.child ) obj->u.child = property;
|
||||
else {
|
||||
json_t* iter;
|
||||
for( iter = obj->u.child; iter->sibling; iter = iter->sibling );
|
||||
iter->sibling = property;
|
||||
}
|
||||
}
|
||||
|
||||
/** Parser a string to get a json object value.
|
||||
* @param str Pointer to first character.
|
||||
* @param pool The handler of a json pool for creating json instances.
|
||||
* @retval Pointer to first character after the value. If success.
|
||||
* @retval Null pointer if any error occur. */
|
||||
static char* _objValue( char* ptr, json_t* obj, jsonPool_t* pool ) {
|
||||
obj->type = JSON_OBJ;
|
||||
obj->u.child = 0;
|
||||
obj->sibling = 0;
|
||||
ptr++;
|
||||
for(;;) {
|
||||
ptr = _goWhiteSpace( ptr );
|
||||
if ( !ptr ) return 0;
|
||||
char const endchar = ( obj->type == JSON_OBJ )? '}': ']';
|
||||
if ( *ptr == endchar ) {
|
||||
*ptr = '\0';
|
||||
json_t* parentObj = obj->sibling;
|
||||
if ( !parentObj ) return ++ptr;
|
||||
obj->sibling = 0;
|
||||
obj = parentObj;
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
if ( *ptr == ',' ) {
|
||||
ptr = _goWhiteSpace( ++ptr );
|
||||
if ( !ptr ) return 0;
|
||||
}
|
||||
json_t* property = _poolNew( pool );
|
||||
if ( !property ) return 0;
|
||||
if( obj->type != JSON_ARRAY ) {
|
||||
if ( *ptr != '\"' ) return 0;
|
||||
ptr = _propertyName( ptr, property );
|
||||
if ( !ptr ) return 0;
|
||||
}
|
||||
else property->name = 0;
|
||||
_add( obj, property );
|
||||
property->u.value = ptr;
|
||||
switch( *ptr ) {
|
||||
case '{':
|
||||
property->type = JSON_OBJ;
|
||||
property->u.child = 0;
|
||||
property->sibling = obj;
|
||||
obj = property;
|
||||
++ptr;
|
||||
break;
|
||||
case '[':
|
||||
property->type = JSON_ARRAY;
|
||||
property->u.child = 0;
|
||||
property->sibling = obj;
|
||||
obj = property;
|
||||
++ptr;
|
||||
break;
|
||||
case '\"': ptr = _textValue( ptr, property ); break;
|
||||
case 't': ptr = _trueValue( ptr, property ); break;
|
||||
case 'f': ptr = _falseValue( ptr, property ); break;
|
||||
case 'n': ptr = _nullValue( ptr, property ); break;
|
||||
default: ptr = _integerValue( ptr, property ); break;
|
||||
}
|
||||
if ( !ptr ) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize a json pool.
|
||||
* @param pool The handler of the pool.
|
||||
* @return a instace of a json. */
|
||||
static json_t* _poolInit( jsonPool_t* pool ) {
|
||||
pool->nextFree = 1;
|
||||
return &pool->mem[0];
|
||||
}
|
||||
|
||||
/** Create an instance of a json from a pool.
|
||||
* @param pool The handler of the pool.
|
||||
* @retval The handler of the new instance if success.
|
||||
* @retval Null pointer if the pool was empty. */
|
||||
static json_t* _poolNew( jsonPool_t* pool ) {
|
||||
if ( pool->nextFree >= pool->qty ) return 0;
|
||||
return &pool->mem[pool->nextFree++];
|
||||
}
|
||||
|
||||
/** Checks whether an character belongs to set.
|
||||
* @param ch Character value to be checked.
|
||||
* @param set Set of characters. It is just a null-terminated string.
|
||||
* @return true or false there is membership or not. */
|
||||
static bool _isOneOfThem( char ch, char const* set ) {
|
||||
while( *set != '\0' )
|
||||
if ( ch == *set++ )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Increases a pointer while it points to a character that belongs to a set.
|
||||
* @param str The initial pointer value.
|
||||
* @param set Set of characters. It is just a null-terminated string.
|
||||
* @return The final pointer value or null pointer if the null character was found. */
|
||||
static char* _goWhile( char* str, char const* set ) {
|
||||
for(; *str != '\0'; ++str ) {
|
||||
if ( !_isOneOfThem( *str, set ) )
|
||||
return str;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Increases a pointer while it points to a white space character.
|
||||
* @param str The initial pointer value.
|
||||
* @return The final pointer value or null pointer if the null character was found. */
|
||||
static char* _goWhiteSpace( char* str ) {
|
||||
return _goWhile( str, " \n\r\t\f" );
|
||||
}
|
||||
|
||||
/** Checks if a character is a decimal digit. */
|
||||
static bool _isNum( unsigned char ch ) {
|
||||
return ch >= '0' && ch <= '9';
|
||||
}
|
||||
|
||||
/** Increases a pointer while it points to a decimal digit character.
|
||||
* @param str The initial pointer value.
|
||||
* @return The final pointer value or null pointer if the null character was found. */
|
||||
static char* _goNum( char* str ) {
|
||||
for( ; *str != '\0'; ++str ) {
|
||||
if ( !_isNum( *str ) )
|
||||
return str;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Set a char to '\0' and increase its pointer if the char is diferent to '}' or ']'.
|
||||
* @param ch Pointer to character.
|
||||
* @return Final value pointer. */
|
||||
static char* _setToNull( char* ch ) {
|
||||
if ( !_isOneOfThem( *ch, "}]" ) ) *ch++ = '\0';
|
||||
return ch;
|
||||
}
|
125
tiny-json.h
Normal file
125
tiny-json.h
Normal file
@ -0,0 +1,125 @@
|
||||
|
||||
/*
|
||||
* tiny-json.h 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* tiny-json.h 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TINY_JSON_H_
|
||||
#define _TINY_JSON_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** @defgroup tinyJson Tiny JSON parser.
|
||||
* @{ */
|
||||
|
||||
/** Enumeration of codes of suported JSON properties types. */
|
||||
typedef enum {
|
||||
JSON_OBJ, JSON_ARRAY, JSON_TEXT, JSON_BOOLEAN, JSON_INTEGER, JSON_NULL
|
||||
} jsonType_t;
|
||||
|
||||
/** Structure to handle JSON properties. */
|
||||
typedef struct json_s {
|
||||
struct json_s* sibling;
|
||||
char const* name;
|
||||
union {
|
||||
char const* value;
|
||||
struct json_s* child;
|
||||
} u;
|
||||
jsonType_t type;
|
||||
} json_t;
|
||||
|
||||
/** Parse a string to get a json.
|
||||
* @param str String pointer with a JSON object. It will be modified.
|
||||
* @param mem
|
||||
* @param qty
|
||||
* @retval Null pointer if any was wrong in the parse process.
|
||||
* @retval If the parser process was successfully a valid handler of a json.
|
||||
* This property is always unnamed and its type is JSON_OBJ. */
|
||||
json_t const* json_create( char* str, json_t mem[], unsigned int qty );
|
||||
|
||||
/** Get the name of a json property.
|
||||
* @param json A valid handler of a json property.
|
||||
* @retval Pointer to null-terminated if property has name.
|
||||
* @retval Null pointer if the property is unnamed. */
|
||||
static inline char const* json_getName( json_t const* json ) {
|
||||
return json->name;
|
||||
}
|
||||
|
||||
/** Get the value of a json property.
|
||||
* The type of property cannot be JSON_OBJ or JSON_ARRAY.
|
||||
* @param json A valid handler of a json property.
|
||||
* @return Pointer to null-terminated string with the value. */
|
||||
static inline char const* json_getValue( json_t const* property ) {
|
||||
return property->u.value;
|
||||
}
|
||||
|
||||
/** Get the type of a json property.
|
||||
* @param json A valid handler of a json property.
|
||||
* @return The code of type.*/
|
||||
static inline jsonType_t json_getType( json_t const* json ) {
|
||||
return json->type;
|
||||
}
|
||||
|
||||
/** Get the next sibling of a JSON property that is within a JSON object or array.
|
||||
* @param json A valid handler of a json property.
|
||||
* @retval The handler of the next sbling if found.
|
||||
* @retval Null pointer if the json property is the last one. */
|
||||
static inline json_t const* json_getSibling( json_t const* json ) {
|
||||
return json->sibling;
|
||||
}
|
||||
|
||||
/** Search a property by its name in a JSON object.
|
||||
* @param obj A valid handler of a json object. Its type must be JSON_OBJ.
|
||||
* @param property The name of property to get.
|
||||
* @retval The handler of the json property if found.
|
||||
* @retval Null pointer if not found. */
|
||||
json_t const* json_getProperty( json_t const* obj, char const* property );
|
||||
|
||||
/** Get the first property of a JSON object or array.
|
||||
* @param json A valid handler of a json property.
|
||||
* Its type must be JSON_OBJ or JSON_ARRAY.
|
||||
* @retval The handler of the first property if there is.
|
||||
* @retval Null pointer if the json object has not porperties. */
|
||||
static inline json_t const* json_getChild( json_t const* json ) {
|
||||
return json->u.child;
|
||||
}
|
||||
|
||||
/** Get the value of a json boolean property.
|
||||
* @param property A valid handler of a json object. Its type must be JSON_BOOLEAN.
|
||||
* @return The value stdbool. */
|
||||
static inline bool json_getBoolean( json_t const* property ) {
|
||||
return *property->u.value == 't';
|
||||
}
|
||||
|
||||
/** Get the value of a json integer property.
|
||||
* @param property A valid handler of a json object. Its type must be JSON_INTEGER.
|
||||
* @return The value stdint. */
|
||||
static inline int64_t json_getInteger( json_t const* property ) {
|
||||
return (int64_t)atoll( property->u.value );
|
||||
}
|
||||
|
||||
/** @ } */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TINY_JSON_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user