9#error "jsmn-find.h should be included after jsmn.h"
16#define JSMNF_PAIR_ATTRS_const \
18 OA_HASH_ATTRS(const); \
20 const struct jsmnf_pair *const fields; \
22 const jsmntok_t *const k; \
24 const jsmntok_t *const v
25#define JSMNF_PAIR_ATTRS_mut \
29 struct jsmnf_pair *fields; \
34#define JSMNF_PAIR_ATTRS(_qualifier) JSMNF_PAIR_ATTRS_##_qualifier
36typedef struct jsmnf_pair {
37 JSMNF_PAIR_ATTRS(
const);
42typedef struct jsmnf_loader {
48 const jsmnf_pair *root;
52typedef struct jsmnf_table {
55 const struct jsmnf_pair __;
64JSMN_API void jsmnf_init(jsmnf_loader *loader);
78JSMN_API long jsmnf_load(jsmnf_loader *loader,
82 const size_t table_len);
93JSMN_API const jsmnf_pair *jsmnf_find(
const jsmnf_pair *
const head,
106JSMN_API const jsmnf_pair *jsmnf_find_path(
const jsmnf_pair *
const head,
124JSMN_API long jsmnf_load_auto(jsmnf_loader *loader,
127 jsmnf_table **p_table,
146 unsigned *num_tokens);
169#define OA_HASH_STATIC
173struct _jsmnf_pair_mut {
174 JSMNF_PAIR_ATTRS(mut);
178jsmnf_init(jsmnf_loader *loader)
181 loader->pairnext = 0;
185_jsmnf_load_pairs(
struct jsmnf_loader *loader,
187 struct _jsmnf_pair_mut *curr,
188 const size_t num_tokens,
189 struct _jsmnf_pair_mut pairs[],
191 const size_t table_len)
195 if (!num_tokens)
return 0;
197 switch (curr->v->type) {
203 const unsigned value_size = (unsigned)curr->v->size,
204 top_idx = loader->pairnext + (1 + value_size),
205 bottom_idx = loader->pairnext;
208 if (value_size > (table_len - bottom_idx)
209 || top_idx > (table_len - bottom_idx))
214 loader->pairnext = top_idx;
217 top_idx - bottom_idx);
222 while (curr->length < value_size) {
223 struct _jsmnf_pair_mut *fields = pairs + bottom_idx,
224 *element = fields + curr->length;
225 element->k = curr->v + 1 + (offset++);
226 if (element->k->size > 0) {
227 element->v = curr->v + 1 + offset;
229 element->k->end - element->k->start, element);
230 if ((ret = _jsmnf_load_pairs(loader, js, element,
231 num_tokens - offset, pairs,
237 curr->fields = (
struct jsmnf_pair *)fields;
242 element->k->end - element->k->start, NULL);
247 for (; curr->length < value_size; ++curr->length) {
250 struct _jsmnf_pair_mut *fields = pairs + bottom_idx,
251 *element = fields + curr->length;
253 entry->
value = element;
254 element->v = curr->v + 1 + offset;
255 element->k = &empty_key;
256 if ((ret = _jsmnf_load_pairs(loader, js, element,
257 num_tokens - offset, pairs,
263 curr->fields = (
struct jsmnf_pair *)fields;
278jsmnf_load(
struct jsmnf_loader *loader,
281 struct jsmnf_table table[],
282 const size_t table_len)
285 struct _jsmnf_pair_mut
286 *pairs = (
struct _jsmnf_pair_mut *)(((
char *)tokens)
287 + (table_len *
sizeof *tokens)),
288 *mut_root = &pairs[0];
291 + (table_len *
sizeof *pairs));
294 if (loader->pairnext == 0) {
296 if (loader->parser.toknext == 0) {
297 memset(tokens, 0, table_len *
sizeof *tokens);
298 if ((ret =
jsmn_parse(&loader->parser, js, len, tokens, table_len))
304 memset(pairs, 0, table_len *
sizeof *pairs);
305 memset(buckets, 0, table_len *
sizeof *buckets);
306 mut_root->v = tokens + loader->pairnext++;
307 loader->root = (
struct jsmnf_pair *)mut_root;
309 if ((ret = _jsmnf_load_pairs(loader, js, mut_root, loader->parser.toknext,
310 pairs, buckets, table_len))
315 loader->pairnext = 0;
322jsmnf_find(
const struct jsmnf_pair *head,
326 if (!head || !head->v)
return NULL;
327 if (!key && !length)
return head;
334 const unsigned idx = (unsigned)strtoul(key, &endptr, 10);
335 if (endptr != key && (idx < head->length)
338 return head->buckets[idx].value;
345jsmnf_find_path(
const struct jsmnf_pair *head,
349 const struct jsmnf_pair *iter = head, *found = NULL;
351 for (i = 0; i < depth; ++i) {
352 if (!iter || !(found = jsmnf_find(iter, path[i], strlen(path[i]))))
359#define RECALLOC_OR_ERROR(ptr, prev_size) \
361 const unsigned new_size = *(prev_size) * 2; \
362 void *tmp = realloc((ptr), new_size * sizeof *(ptr)); \
363 if (!tmp) return JSMN_ERROR_NOMEM; \
365 memset((ptr) + *(prev_size), 0, \
366 (new_size - *(prev_size)) * sizeof *(ptr)); \
367 *(prev_size) = new_size; \
375 unsigned *num_tokens)
379 if (NULL == *p_tokens || 0 == *num_tokens) {
380 *p_tokens = calloc(1,
sizeof **p_tokens);
383 while ((ret =
jsmn_parse(parser, js, len, *p_tokens, *num_tokens))
386 RECALLOC_OR_ERROR(*p_tokens, num_tokens);
392jsmnf_load_auto(
struct jsmnf_loader *loader,
395 struct jsmnf_table **p_table,
400 if (NULL == *p_table || 0 == *table_len) {
401 if (!(*p_table = calloc(1,
sizeof **p_table))) {
406 while ((ret = jsmnf_load(loader, js, len, *p_table, *table_len))
409 RECALLOC_OR_ERROR(*p_table, table_len);
414#undef RECALLOC_OR_ERROR
417_jsmnf_read_4_digits(
char *s,
const char *end,
unsigned *p_hex)
424 for (i = 0; i < 4; i++) {
426 if ((
'0' <= s[i] && s[i] <=
'9') || (
'A' <= s[i] && s[i] <=
'F')
427 || (
'a' <= s[i] && s[i] <=
'f'))
434 *p_hex = (unsigned)strtoul(buf, NULL, 16);
439#define _JSMNF_UTF16_IS_FIRST_SURROGATE(c) \
440 (0xD800 <= (unsigned)c && (unsigned)c <= 0xDBFF)
441#define _JSMNF_UTF16_IS_SECOND_SURROGATE(c) \
442 (0xDC00 <= (unsigned)c && (unsigned)c <= 0xDFFF)
443#define _JSMNF_UTF16_JOIN_SURROGATE(c1, c2) \
444 (((((unsigned long)c1 & 0x3FF) << 10) | ((unsigned)c2 & 0x3FF)) + 0x10000)
445#define _JSMNF_UTF8_IS_VALID(c) \
446 (((unsigned long)c <= 0x10FFFF) \
447 && ((unsigned long)c < 0xD800 || (unsigned long)c > 0xDFFF))
448#define _JSMNF_UTF8_IS_TRAIL(c) (((unsigned char)c & 0xC0) == 0x80)
449#define _JSMNF_UTF_ILLEGAL 0xFFFFFFFFu
452_jsmnf_utf8_trail_length(
unsigned char c)
454 if (c < 128)
return 0;
455 if (c < 194)
return -1;
456 if (c < 224)
return 1;
457 if (c < 240)
return 2;
458 if (c <= 244)
return 3;
463_jsmnf_utf8_width(
unsigned long value)
465 if (value <= 0x7F)
return 1;
466 if (value <= 0x7FF)
return 2;
467 if (value <= 0xFFFF)
return 3;
474_jsmnf_utf8_next(
char **p,
const char *end)
476 unsigned char lead, tmp;
480 if (*p == end)
return _JSMNF_UTF_ILLEGAL;
486 trail_size = _jsmnf_utf8_trail_length(lead);
488 if (trail_size < 0)
return _JSMNF_UTF_ILLEGAL;
491 if (trail_size == 0)
return lead;
493 c = lead & ((1 << (6 - trail_size)) - 1);
496 switch (trail_size) {
498 if (*p == end)
return _JSMNF_UTF_ILLEGAL;
501 if (!_JSMNF_UTF8_IS_TRAIL(tmp))
return _JSMNF_UTF_ILLEGAL;
502 c = (c << 6) | (tmp & 0x3F);
505 if (*p == end)
return _JSMNF_UTF_ILLEGAL;
508 if (!_JSMNF_UTF8_IS_TRAIL(tmp))
return _JSMNF_UTF_ILLEGAL;
509 c = (c << 6) | (tmp & 0x3F);
512 if (*p == end)
return _JSMNF_UTF_ILLEGAL;
515 if (!_JSMNF_UTF8_IS_TRAIL(tmp))
return _JSMNF_UTF_ILLEGAL;
516 c = (c << 6) | (tmp & 0x3F);
520 if (!_JSMNF_UTF8_IS_VALID(c))
return _JSMNF_UTF_ILLEGAL;
523 if (_jsmnf_utf8_width(c) != trail_size + 1)
return _JSMNF_UTF_ILLEGAL;
529_jsmnf_utf8_validate(
char *p,
const char *end)
531 const char *start = p;
533 if (_jsmnf_utf8_next(&p, end) == _JSMNF_UTF_ILLEGAL)
536 return (
long)(end - start);
540_jsmnf_utf8_encode(
unsigned long value,
char utf8_seq[4])
546 if (value <= 0x7FF) {
547 utf8_seq[0] = (value >> 6) | 0xC0;
548 utf8_seq[1] = (value & 0x3F) | 0x80;
551 if (value <= 0xFFFF) {
552 utf8_seq[0] = (value >> 12) | 0xE0;
553 utf8_seq[1] = ((value >> 6) & 0x3F) | 0x80;
554 utf8_seq[2] = (value & 0x3F) | 0x80;
557 utf8_seq[0] = (value >> 18) | 0xF0;
558 utf8_seq[1] = ((value >> 12) & 0x3F) | 0x80;
559 utf8_seq[2] = ((value >> 6) & 0x3F) | 0x80;
560 utf8_seq[3] = (value & 0x3F) | 0x80;
565_jsmnf_utf8_append(
unsigned long hex,
char *buf_tok,
const char *buf_end)
568 unsigned utf8_seqlen = _jsmnf_utf8_encode(hex, utf8_seq);
573 for (i = 0; i < utf8_seqlen; ++i)
574 buf_tok[i] = utf8_seq[i];
578#define BUF_PUSH(buf_tok, c, buf_end) \
580 if (buf_tok >= buf_end) return JSMN_ERROR_NOMEM; \
585jsmnf_unescape(
char buf[],
size_t bufsize,
const char src[],
size_t len)
587 char *src_tok = (
char *)src, *
const src_end = src_tok + len;
588 char *buf_tok = buf, *
const buf_end = buf + bufsize;
589 int second_surrogate_expected = 0;
590 unsigned first_surrogate = 0;
592 while (*src_tok && src_tok < src_end) {
599 BUF_PUSH(buf_tok, c, buf_end);
614 BUF_PUSH(buf_tok, c, buf_end);
617 BUF_PUSH(buf_tok,
'\b', buf_end);
620 BUF_PUSH(buf_tok,
'\f', buf_end);
623 BUF_PUSH(buf_tok,
'\n', buf_end);
626 BUF_PUSH(buf_tok,
'\r', buf_end);
629 BUF_PUSH(buf_tok,
'\t', buf_end);
633 int ret = _jsmnf_read_4_digits(src_tok, src_end, &hex);
635 if (ret != 4)
return ret;
639 if (second_surrogate_expected) {
640 if (!_JSMNF_UTF16_IS_SECOND_SURROGATE(hex))
643 ret = _jsmnf_utf8_append(
644 _JSMNF_UTF16_JOIN_SURROGATE(first_surrogate, hex), buf_tok,
646 if (ret < 0)
return ret;
650 second_surrogate_expected = 0;
652 else if (_JSMNF_UTF16_IS_FIRST_SURROGATE(hex)) {
653 second_surrogate_expected = 1;
654 first_surrogate = hex;
657 ret = _jsmnf_utf8_append(hex, buf_tok, buf_end);
658 if (ret < 0)
return ret;
667 return _jsmnf_utf8_validate(buf, buf_tok);
675#undef JSMNF_PAIR_ATTRS_const
676#undef JSMNF_PAIR_ATTRS_mut
677#undef JSMNF_PAIR_ATTRS
@ 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
void jsmn_init(jsmn_parser *parser)
Definition: jsmn.h:459
#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
void * oa_hash_set(struct oa_hash *ht, const char key[], const size_t len, void *value)
Insert or update entry (wrapper around oa_hash_set_entry)
Definition: oa_hash.h:266
void * oa_hash_get(const struct oa_hash *ht, const char key[], const size_t len)
Retrieve value by key (wrapper around oa_hash_get_entry)
Definition: oa_hash.h:213
@ OA_HASH_ENTRY_OCCUPIED
Definition: oa_hash.h:19
void oa_hash_init(struct oa_hash *ht, struct oa_hash_entry buckets[], const size_t capacity)
Initialize hash table with given buckets array.
Definition: oa_hash.h:151
Entry holding key-value pair in hash table.
Definition: oa_hash.h:24
void * value
Definition: oa_hash.h:30
size_t length
Definition: oa_hash.h:28
enum oa_hash_entry_state state
Definition: oa_hash.h:25
struct oa_hash_entry::@14 key
const char * buf
Definition: oa_hash.h:27
Open addressing hash table.
Definition: oa_hash.h:45