mirror of
https://github.com/rafagafe/tiny-json.git
synced 2024-11-17 11:35:30 +00:00
Implement custom pool API
Now it's poosible to use any custom pool allocation, i.e preallocated pools or dymamic allocation on fly.
This commit is contained in:
parent
9052ef2473
commit
b3804dcf50
121
example-03.c
Normal file
121
example-03.c
Normal file
@ -0,0 +1,121 @@
|
||||
|
||||
/*
|
||||
|
||||
<https://github.com/rafagafe/tiny-json>
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright (c) 2016-2018 Rafa Garcia <rafagarcia77@gmail.com>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
typedef struct jsonStaticPool_s {
|
||||
json_t mem[32];
|
||||
unsigned int nextFree;
|
||||
jsonPool_t pool;
|
||||
} jsonStaticPool_t;
|
||||
|
||||
static json_t* poolInit( jsonPool_t* pool ) {
|
||||
jsonStaticPool_t* spool = json_container_of(pool, jsonStaticPool_t, pool);
|
||||
spool->nextFree = 1;
|
||||
return &spool->mem[0];
|
||||
}
|
||||
|
||||
static json_t* poolNew( jsonPool_t* pool ) {
|
||||
jsonStaticPool_t* spool = json_container_of(pool, jsonStaticPool_t, pool);
|
||||
if ( spool->nextFree >= sizeof spool->mem / sizeof spool->mem[0] ) return 0;
|
||||
return &spool->mem[spool->nextFree++];
|
||||
}
|
||||
|
||||
/* Parser a json string. */
|
||||
int main( void ) {
|
||||
char str[] = "{\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";
|
||||
puts( str );
|
||||
jsonStaticPool_t spool = { .pool = { .init = poolInit, .new = poolNew } };
|
||||
json_t const* json = json_create_pool( str, &spool.pool );
|
||||
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 );
|
||||
printf( "Fist Name: %s.\n", firstNameVal );
|
||||
|
||||
char const* lastName = json_getPropertyValue( json, "lastName" );
|
||||
if ( !lastName ) {
|
||||
puts("Error, the last name property is not found.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf( "Last Name: %s.\n", lastName );
|
||||
|
||||
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 ) ) {
|
||||
char const* phoneNumber = json_getPropertyValue( phone, "number" );
|
||||
if ( phoneNumber ) printf( "Number: %s.\n", phoneNumber );
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
8
makefile
8
makefile
@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
build: example-01.exe example-02.exe
|
||||
build: example-01.exe example-02.exe example-03.exe
|
||||
|
||||
clean:
|
||||
rm -rf *.o
|
||||
@ -17,6 +17,9 @@ example-01.exe: example-01.o tiny-json.o
|
||||
example-02.exe: example-02.o tiny-json.o
|
||||
gcc -std=c99 -Wall -o example-02.exe example-02.o tiny-json.o
|
||||
|
||||
example-03.exe: example-03.o tiny-json.o
|
||||
gcc -std=c99 -Wall -o example-03.exe example-03.o tiny-json.o
|
||||
|
||||
test.exe: tests.o tiny-json.o
|
||||
gcc -std=c99 -Wall -o test.exe tests.o tiny-json.o
|
||||
|
||||
@ -29,5 +32,8 @@ example-01.o: example-01.c tiny-json.h
|
||||
example-02.o: example-02.c tiny-json.h
|
||||
gcc -std=c99 -Wall -c example-02.c
|
||||
|
||||
example-03.o: example-03.c tiny-json.h
|
||||
gcc -std=c99 -Wall -c example-03.c
|
||||
|
||||
tests.o: tests.c tiny-json.h
|
||||
gcc -std=c99 -Wall -c tests.c
|
||||
|
33
tiny-json.c
33
tiny-json.c
@ -32,11 +32,12 @@
|
||||
#include "tiny-json.h"
|
||||
|
||||
/** Structure to handle a heap of JSON properties. */
|
||||
typedef struct jsonPool_s {
|
||||
typedef struct jsonStaticPool_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;
|
||||
jsonPool_t pool;
|
||||
} jsonStaticPool_t;
|
||||
|
||||
/* Search a property by its name in a JSON object. */
|
||||
json_t const* json_getProperty( json_t const* obj, char const* property ) {
|
||||
@ -66,19 +67,27 @@ static char* setToNull( char* ch );
|
||||
static bool isEndOfPrimitive( char ch );
|
||||
|
||||
/* Parse a string to get a json. */
|
||||
json_t const* json_create( char* str, json_t mem[], unsigned int qty ) {
|
||||
json_t const* json_create_pool( char* str, jsonPool_t* pool ) {
|
||||
char* ptr = goBlank( str );
|
||||
if ( !ptr || *ptr != '{' ) return 0;
|
||||
jsonPool_t pool = { .mem = mem, .qty = qty };
|
||||
json_t* obj = poolInit( &pool );
|
||||
json_t* obj = pool->init( pool );
|
||||
obj->name = 0;
|
||||
obj->sibling = 0;
|
||||
obj->u.c.child = 0;
|
||||
ptr = objValue( ptr, obj, &pool );
|
||||
ptr = objValue( ptr, obj, pool );
|
||||
if ( !ptr ) return 0;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* Parse a string to get a json. */
|
||||
json_t const* json_create( char* str, json_t mem[], unsigned int qty ) {
|
||||
jsonStaticPool_t spool = {
|
||||
.mem = mem, .qty = qty,
|
||||
.pool = { .init = poolInit, .new = poolNew }
|
||||
};
|
||||
return json_create_pool( str, &spool.pool );
|
||||
}
|
||||
|
||||
/** Get a special character with its escape character. Examples:
|
||||
* 'b' -> '\b', 'n' -> '\n', 't' -> '\t'
|
||||
* @param ch The escape character.
|
||||
@ -335,7 +344,7 @@ static char* objValue( char* ptr, json_t* obj, jsonPool_t* pool ) {
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
json_t* property = poolNew( pool );
|
||||
json_t* property = pool->new( pool );
|
||||
if ( !property ) return 0;
|
||||
if( obj->type != JSON_ARRAY ) {
|
||||
if ( *ptr != '\"' ) return 0;
|
||||
@ -374,8 +383,9 @@ static char* objValue( char* ptr, json_t* obj, jsonPool_t* pool ) {
|
||||
* @param pool The handler of the pool.
|
||||
* @return a instance of a json. */
|
||||
static json_t* poolInit( jsonPool_t* pool ) {
|
||||
pool->nextFree = 1;
|
||||
return &pool->mem[0];
|
||||
jsonStaticPool_t* spool = json_container_of(pool, jsonStaticPool_t, pool);
|
||||
spool->nextFree = 1;
|
||||
return &spool->mem[0];
|
||||
}
|
||||
|
||||
/** Create an instance of a json from a pool.
|
||||
@ -383,8 +393,9 @@ static json_t* poolInit( jsonPool_t* 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++];
|
||||
jsonStaticPool_t* spool = json_container_of(pool, jsonStaticPool_t, pool);
|
||||
if ( spool->nextFree >= spool->qty ) return 0;
|
||||
return &spool->mem[spool->nextFree++];
|
||||
}
|
||||
|
||||
/** Checks whether an character belongs to set.
|
||||
|
20
tiny-json.h
20
tiny-json.h
@ -34,10 +34,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define json_container_of(ptr, type, member) ({ \
|
||||
void *__mptr = (void *)(ptr); \
|
||||
((type *)(__mptr - offsetof(type, member))); })
|
||||
|
||||
/** @defgroup tinyJson Tiny JSON parser.
|
||||
* @{ */
|
||||
|
||||
@ -61,6 +66,13 @@ typedef struct json_s {
|
||||
jsonType_t type;
|
||||
} json_t;
|
||||
|
||||
/** Structure to handle a heap of JSON properties. */
|
||||
typedef struct jsonPool_s jsonPool_t;
|
||||
typedef struct jsonPool_s {
|
||||
json_t* (*init) ( jsonPool_t* pool );
|
||||
json_t* (*new) ( jsonPool_t* pool );
|
||||
} jsonPool_t;
|
||||
|
||||
/** Parse a string to get a json.
|
||||
* @param str String pointer with a JSON object. It will be modified.
|
||||
* @param mem Array of json properties to allocate.
|
||||
@ -70,6 +82,14 @@ typedef struct json_s {
|
||||
* This property is always unnamed and its type is JSON_OBJ. */
|
||||
json_t const* json_create( char* str, json_t mem[], unsigned int qty );
|
||||
|
||||
/** Parse a string to get a json.
|
||||
* @param str String pointer with a JSON object. It will be modified.
|
||||
* @param pool Custom json pool pointer.
|
||||
* @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_pool( char* str, jsonPool_t *pool );
|
||||
|
||||
/** 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.
|
||||
|
Loading…
Reference in New Issue
Block a user