GitHub - lcsmuller/jsmn-find: Tiny, zero-allocation JSON tokenizer written in ANSI C (original) (raw)
JSMN-FIND
jsmn-find is an ANSI C add-on for the minimalistic JSON tokenizerjsmn, it offers a familiar and zero-allocation design. Its serializer counterpart can be found at json-build.
Dependencies
- jsmn - Minimalistic JSON parser
- oa_hash - A lightweight single-header open-addressing hashtable implementation in ANSI C
Design
jsmn-find organizes jsmn's JSON tokens under a hashtable so that they can be searched for in linear time.
Usage
Download jsmn-find.h and the dependencies should be visible to your linker search path:
load (zero-allocation)
#include "jsmn.h" #include "jsmn-find.h"
... jsmnf_table table[256]; jsmnf_loader loader;
jsmnf_init(&loader); long r = jsmnf_load(&loader, json, strlen(json), table, 256); if (r < 0) error();
auto load (allocate memory for jsmnf_table automatically)
jsmn_parse_auto
jsmn_parser parser; jsmntok_t *toks = NULL; unsigned num_tokens = 0;
jsmn_init(&parser); long r = jsmn_parse_auto(&parser, json, strlen(json), &toks, &num_tokens); if (r <= 0) error();
free(toks);
jsmnf_load_auto
jsmnf_loader loader; jsmnf_table *table = NULL; size_t table_len = 0;
jsmnf_init(&loader); long r = jsmnf_load_auto(&loader, json, strlen(json), &table, &table_len); if (r <= 0) error();
free(table);
find by key
const jsmnf_pair *f;
// assume the JSON : { "foo": { "bar": [ true, null, null ] } } if ((f = jsmnf_find(loader.root, "foo", strlen("foo")))) { // Found: { "bar" : [ true, null, null ] } printf("Found: %.*s\n", f->v->end - f->v->start, json + f->v->start); if ((f = jsmnf_find(f, "bar", 3))) { // Found: [ true, null, null ] printf("Found: %.*s\n", f->v->end - f->v->start, json + f->v->start); if ((f = jsmnf_find(f, "0", 1))) { // Found: true printf("Found: %.*s\n", f->v->end - f->v->start, json + f->v->start); } } }
index access for arrays
const jsmnf_pair *f;
// assume the JSON : [ false, [ true ] ] f = &loader.root->fields[1]; printf("Found: %.*s\n", f->v->end - f->v->start, json + f->v->start); // Found: [ true ] f = &f->fields[0]; // get nested array printf("Found: %.*s\n", f->v->end - f->v->start, json + f->v->start); // Found: true
// looping over array for (int i = 0; loader.root->size; ++i) { f = &loader.root->fields[i]; printf("%.*s ", f->v->end - f->v->start, json + f->v->start); }
find by path
// assume the JSON : [ false, false, [ false, [ { "b":true } ] ] ] char *path[] = { "2", "1", "0", "b" }; // array keys are the same as its indexes const jsmnf_pair *f;
if ((f = jsmnf_find_path(&loader.root, path, sizeof(path) / sizeof *path))) { // Found: true printf("Found: %.*s\n", (int)f->v->end - f->v->start, json + f->v->start); }
jsmn-find is single-header and should be compatible with jsmn additional macros for more complex uses cases. #define JSMN_STATIC hides all jsmn-find API symbols by making them static. Also, if you want to include jsmn-find.h from multiple C files, to avoid duplication of symbols you may define JSMN_HEADER macro.
/* In every .c file that uses jsmn include only declarations: */ #define JSMN_HEADER #include "jsmn.h" #include "jsmn-find.h"
/* Additionally, create one jsmn-find.c file for jsmn-find implementation: */ #include "jsmn.h" #include "jsmn-find.h"
API
jsmnf_init()- initialize ajsmnf_loaderjsmnf_load()- populatejsmnf_tabletable with JSMN tokensjsmnf_find()- locate ajsmnf_pairby its associated keyjsmnf_find_path()- locate ajsmnf_pairby its full key path
Misc
jsmn_parse_auto()-jsmn_parse()counterpart that automatically allocates the necessary amount of tokensjsmnf_load_auto()-jsmnf_load()counterpart that automatically allocates the necessary amount of pairsjsmnf_unescape()- unescape a Unicode string
Other Info
This software is distributed under MIT license, so feel free to integrate it in your commercial products.