9#error "jsmn-find.h should be included after jsmn.h"
124 unsigned *num_pairs);
142 unsigned *num_tokens);
166#define CHASH_KEY_FIELD k
168#define CHASH_VALUE_FIELD v
170#define CHASH_BUCKETS_FIELD fields
172#define CHASH_LENGTH_FIELD size
176#define _jsmnf_key_hash(key, hash) \
179 unsigned __CHASH_HINDEX; \
180 for (__CHASH_HINDEX = 0; __CHASH_HINDEX < (key).len; \
181 ++__CHASH_HINDEX) { \
182 (hash) = (((hash) << 1) + (hash)) \
183 + _JSMNF_STRING_B[(key).pos + __CHASH_HINDEX]; \
188#define _jsmnf_key_compare(cmp_a, cmp_b) \
189 ((cmp_a).len == (cmp_b).len \
190 && !strncmp(_JSMNF_STRING_B + (cmp_a).pos, \
191 _JSMNF_STRING_A + (cmp_b).pos, (cmp_a).len))
193#define _JSMNF_TABLE_HEAP 0
194#define _JSMNF_TABLE_BUCKET struct jsmnf_pair
195#define _JSMNF_TABLE_FREE_KEY(_key)
196#define _JSMNF_TABLE_HASH(_key, _hash) _jsmnf_key_hash(_key, _hash)
197#define _JSMNF_TABLE_FREE_VALUE(_value)
198#define _JSMNF_TABLE_COMPARE(_cmp_a, _cmp_b) _jsmnf_key_compare(_cmp_a, _cmp_b)
199#define _JSMNF_TABLE_INIT(_bucket, _key, _value) \
200 chash_default_init(_bucket, _key, _value)
208#define _JSMNF_STRING_A js
209#define _JSMNF_STRING_B js
222 if (!num_tokens)
return 0;
230 const unsigned top_idx = loader->
pairnext + (1 + tok->
size),
234 if (tok->
size > (
int)(num_pairs - bottom_idx)
235 || top_idx > (num_pairs - bottom_idx))
247 const struct jsmntok *_key = tok + 1 + offset;
257 if (_key->
size > 0) {
258 const struct jsmntok *_value = tok + 1 + offset;
267 ret = _jsmnf_load_pairs(loader, js, found, _value,
268 num_tokens - offset, pairs,
270 if (ret < 0)
return ret;
281 const struct jsmntok *_value = tok + 1 + offset;
295 ret = _jsmnf_load_pairs(loader, js, element, _value,
296 num_tokens - offset, pairs, num_pairs);
297 if (ret < 0)
return ret;
306 fputs(
"Error: JSMN_UNDEFINED token detected, jsmn_parse() failure\n",
316#undef _JSMNF_STRING_A
317#undef _JSMNF_STRING_B
330 static const struct jsmnf_pair blank_pair = { 0 };
333 for (; i < num_pairs; ++i)
334 pairs[i] = blank_pair;
342 ret = _jsmnf_load_pairs(loader, js, pairs, tokens, num_tokens, pairs,
351#define _JSMNF_STRING_A js
352#define _JSMNF_STRING_B key
362 if (!key || !head)
return NULL;
378 int idx = (int)strtol(key, &endptr, 10);
379 if (endptr != key && idx < head->size) found = head->
fields + idx;
384#undef _JSMNF_STRING_A
385#undef _JSMNF_STRING_B
397 for (i = 0; i < depth; ++i) {
399 found =
jsmnf_find(iter, js, path[i], strlen(path[i]));
406#define RECALLOC_OR_ERROR(ptr, prev_size) \
408 const unsigned new_size = *prev_size * 2; \
409 void *tmp = realloc((ptr), new_size * sizeof *(ptr)); \
410 if (!tmp) return JSMN_ERROR_NOMEM; \
412 *prev_size = new_size; \
413 memset((ptr) + *(prev_size), 0, \
414 (new_size - *(prev_size)) * sizeof *(ptr)); \
423 unsigned *num_tokens)
427 if (NULL == *p_tokens || !*num_tokens) {
428 *p_tokens = calloc(1,
sizeof **p_tokens);
433 ret =
jsmn_parse(parser, js, length, *p_tokens, *num_tokens);
452 if (NULL == *p_pairs || !*num_pairs) {
453 *p_pairs = calloc(1,
sizeof **p_pairs);
458 ret =
jsmnf_load(loader, js, tokens, num_tokens, *p_pairs, *num_pairs);
467#undef RECALLOC_OR_ERROR
470_jsmnf_read_4_digits(
char *s,
const char *end,
unsigned *p_hex)
477 for (i = 0; i < 4; i++) {
479 if ((
'0' <= s[i] && s[i] <=
'9') || (
'A' <= s[i] && s[i] <=
'F')
480 || (
'a' <= s[i] && s[i] <=
'f'))
487 *p_hex = (unsigned)strtoul(buf, NULL, 16);
492#define _JSMNF_UTF16_IS_FIRST_SURROGATE(c) \
493 (0xD800 <= (unsigned)c && (unsigned)c <= 0xDBFF)
494#define _JSMNF_UTF16_IS_SECOND_SURROGATE(c) \
495 (0xDC00 <= (unsigned)c && (unsigned)c <= 0xDFFF)
496#define _JSMNF_UTF16_JOIN_SURROGATE(c1, c2) \
497 (((((unsigned long)c1 & 0x3FF) << 10) | ((unsigned)c2 & 0x3FF)) + 0x10000)
498#define _JSMNF_UTF8_IS_VALID(c) \
499 (((unsigned long)c <= 0x10FFFF) \
500 && ((unsigned long)c < 0xD800 || (unsigned long)c > 0xDFFF))
501#define _JSMNF_UTF8_IS_TRAIL(c) (((unsigned char)c & 0xC0) == 0x80)
502#define _JSMNF_UTF_ILLEGAL 0xFFFFFFFFu
505_jsmnf_utf8_trail_length(
unsigned char c)
507 if (c < 128)
return 0;
508 if (c < 194)
return -1;
509 if (c < 224)
return 1;
510 if (c < 240)
return 2;
511 if (c <= 244)
return 3;
516_jsmnf_utf8_width(
unsigned long value)
518 if (value <= 0x7F)
return 1;
519 if (value <= 0x7FF)
return 2;
520 if (value <= 0xFFFF)
return 3;
527_jsmnf_utf8_next(
char **p,
const char *end)
529 unsigned char lead, tmp;
539 trail_size = _jsmnf_utf8_trail_length(lead);
544 if (trail_size == 0)
return lead;
546 c = lead & ((1 << (6 - trail_size)) - 1);
549 switch (trail_size) {
555 c = (c << 6) | (tmp & 0x3F);
562 c = (c << 6) | (tmp & 0x3F);
569 c = (c << 6) | (tmp & 0x3F);
582_jsmnf_utf8_validate(
char *p,
const char *end)
584 const char *start = p;
589 return (
long)(end - start);
593_jsmnf_utf8_encode(
unsigned long value,
char utf8_seq[4])
599 if (value <= 0x7FF) {
600 utf8_seq[0] = (value >> 6) | 0xC0;
601 utf8_seq[1] = (value & 0x3F) | 0x80;
604 if (value <= 0xFFFF) {
605 utf8_seq[0] = (value >> 12) | 0xE0;
606 utf8_seq[1] = ((value >> 6) & 0x3F) | 0x80;
607 utf8_seq[2] = (value & 0x3F) | 0x80;
610 utf8_seq[0] = (value >> 18) | 0xF0;
611 utf8_seq[1] = ((value >> 12) & 0x3F) | 0x80;
612 utf8_seq[2] = ((value >> 6) & 0x3F) | 0x80;
613 utf8_seq[3] = (value & 0x3F) | 0x80;
618_jsmnf_utf8_append(
unsigned long hex,
char *buf_tok,
const char *buf_end)
621 unsigned utf8_seqlen = _jsmnf_utf8_encode(hex, utf8_seq);
626 for (i = 0; i < utf8_seqlen; ++i)
627 buf_tok[i] = utf8_seq[i];
631#define BUF_PUSH(buf_tok, c, buf_end) \
633 if (buf_tok >= buf_end) return JSMN_ERROR_NOMEM; \
640 char *src_tok = (
char *)src, *
const src_end = src_tok + len;
641 char *buf_tok = buf, *
const buf_end = buf + bufsize;
642 int second_surrogate_expected = 0;
643 unsigned first_surrogate = 0;
645 while (*src_tok && src_tok < src_end) {
686 int ret = _jsmnf_read_4_digits(src_tok, src_end, &hex);
688 if (ret != 4)
return ret;
692 if (second_surrogate_expected) {
696 ret = _jsmnf_utf8_append(
699 if (ret < 0)
return ret;
703 second_surrogate_expected = 0;
706 second_surrogate_expected = 1;
707 first_surrogate = hex;
710 ret = _jsmnf_utf8_append(hex, buf_tok, buf_end);
711 if (ret < 0)
return ret;
720 return _jsmnf_utf8_validate(buf, buf_tok);
#define chash_init_stack(hashtable, buffer, _length, namespace)
Definition: chash.h:282
#define chash_contains(hashtable, _key, storage, namespace)
Definition: chash.h:378
#define CHASH_FILLED
Definition: chash.h:104
#define chash_lookup_bucket(hashtable, _key, storage, namespace)
Definition: chash.h:396
#define chash_assign(hashtable, _key, _value, namespace)
Definition: chash.h:297
struct jsmnf_pair jsmnf_pair
JSON object.
JSMN_API void jsmnf_init(jsmnf_loader *loader)
Initialize a jsmnf_loader.
Definition: jsmn-find.h:203
#define RECALLOC_OR_ERROR(ptr, prev_size)
Definition: jsmn-find.h:406
#define _JSMNF_UTF_ILLEGAL
Definition: jsmn-find.h:502
#define BUF_PUSH(buf_tok, c, buf_end)
Definition: jsmn-find.h:631
JSMN_API int jsmnf_load(jsmnf_loader *loader, const char *js, const jsmntok_t tokens[], unsigned num_tokens, jsmnf_pair pairs[], unsigned num_pairs)
Populate the jsmnf_pair pairs from jsmn tokens.
Definition: jsmn-find.h:320
struct jsmnf_loader jsmnf_loader
Bucket (jsmnf_pair) loader, keeps track of pair array position.
JSMN_API jsmnf_pair * jsmnf_find_path(const jsmnf_pair *head, const char *js, char *const path[], unsigned depth)
Find a jsmnf_pair token by its full key path.
#define _JSMNF_UTF16_JOIN_SURROGATE(c1, c2)
Definition: jsmn-find.h:496
JSMN_API jsmnf_pair * jsmnf_find(const jsmnf_pair *head, const char *js, const char key[], int length)
Find a jsmnf_pair token by its associated key.
JSMN_API int jsmnf_load_auto(jsmnf_loader *loader, const char *js, const jsmntok_t tokens[], unsigned num_tokens, jsmnf_pair **p_pairs, unsigned *num_pairs)
Populate and automatically allocate the jsmnf_pair pairs from jsmn tokens.
Definition: jsmn-find.h:443
#define _JSMNF_UTF16_IS_SECOND_SURROGATE(c)
Definition: jsmn-find.h:494
#define _JSMNF_UTF8_IS_VALID(c)
Definition: jsmn-find.h:498
JSMN_API int jsmn_parse_auto(jsmn_parser *parser, const char *js, size_t length, jsmntok_t **p_tokens, unsigned *num_tokens)
jsmn_parse() counterpart that automatically allocates the necessary amount of tokens necessary for pa...
Definition: jsmn-find.h:419
JSMN_API long jsmnf_unescape(char buf[], size_t bufsize, const char src[], size_t length)
Utility function for unescaping a Unicode string.
Definition: jsmn-find.h:638
#define _JSMNF_UTF16_IS_FIRST_SURROGATE(c)
Definition: jsmn-find.h:492
#define _JSMNF_UTF8_IS_TRAIL(c)
Definition: jsmn-find.h:501
jsmntype_t
Definition: jsmn.h:46
@ JSMN_PRIMITIVE
Definition: jsmn.h:51
@ JSMN_OBJECT
Definition: jsmn.h:48
@ JSMN_UNDEFINED
Definition: jsmn.h:47
@ JSMN_ARRAY
Definition: jsmn.h:49
@ JSMN_STRING
Definition: jsmn.h:50
#define JSMN_API
Definition: jsmn.h:36
int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, jsmntok_t *tokens, const unsigned int num_tokens)
Definition: jsmn.h:268
@ JSMN_ERROR_INVAL
Definition: jsmn.h:58
@ JSMN_ERROR_PART
Definition: jsmn.h:60
@ JSMN_ERROR_NOMEM
Definition: jsmn.h:56
Bucket (jsmnf_pair) loader, keeps track of pair array position.
Definition: jsmn-find.h:40
unsigned pairnext
Definition: jsmn-find.h:42
JSON object.
Definition: jsmn-find.h:21
int state
Definition: jsmn-find.h:35
int size
Definition: jsmn-find.h:25
struct jsmnftok k
Definition: jsmn-find.h:31
jsmntype_t type
Definition: jsmn-find.h:23
struct jsmnf_pair * fields
Definition: jsmn-find.h:29
int capacity
Definition: jsmn-find.h:27
struct jsmnftok v
Definition: jsmn-find.h:33
JSON token description.
Definition: jsmn-find.h:13
int pos
Definition: jsmn-find.h:15
size_t len
Definition: jsmn-find.h:17
int end
Definition: jsmn.h:72
int size
Definition: jsmn.h:73
int start
Definition: jsmn.h:71
jsmntype_t type
Definition: jsmn.h:70