kson_node_t *kson_parse_core(const char *json, long *_n, int *error, long *parsed_len)
{
- long *stack = 0, top = 0, max = 0, n_a = 0, m_a = 0;
+ long *stack = 0, top = 0, max = 0, n_a = 0, m_a = 0, i, j;
kson_node_t *a = 0, *u;
const char *p, *q;
u = &a[stack[start-1]];
u->key = u->v.str;
u->n = top - 1 - start;
- u->v.child = (long*)malloc(u->n * sizeof(long));
+ u->v.child = (kson_ptr_t*)malloc(u->n * sizeof(kson_ptr_t));
for (i = start + 1; i < top; ++i)
- u->v.child[i - start - 1] = stack[i];
+ u->v.child[i - start - 1].i = stack[i];
u->type = *p == ']'? KSON_TYPE_BRACKET : KSON_TYPE_BRACE;
if ((top = start) == 1) break; // completed one object; remaining characters discarded
} else if (*p == ':') {
if (parsed_len) *parsed_len = p - json;
if (top != 1) *error = KSON_ERR_EXTRA_LEFT;
+ for (i = 0; i < n_a; ++i) {
+ u = &a[i];
+ for (j = 0; j < (long)u->n; ++j)
+ u->v.child[j].p = &a[u->v.child[j].i];
+ }
+
free(stack);
*_n = n_a;
return a;
*** Query ***
*************/
-const kson_node_t *kson_query(const kson_t *kson, int depth, ...)
+const kson_node_t *kson_query(const kson_node_t *p, int depth, ...)
{
- const kson_node_t *p = kson->nodes;
va_list ap;
va_start(ap, depth);
while (p && depth > 0) {
if (p->type == KSON_TYPE_BRACE) {
- p = kson_by_key(kson->nodes, p, va_arg(ap, const char*));
+ p = kson_by_key(p, va_arg(ap, const char*));
} else if (p->type == KSON_TYPE_BRACKET) {
- p = kson_by_index(kson->nodes, p, va_arg(ap, long));
+ p = kson_by_index(p, va_arg(ap, long));
} else break;
--depth;
}
*** Fromat ***
**************/
-void kson_format_recur(const kson_node_t *nodes, int depth, const kson_node_t *p)
+void kson_format_recur(const kson_node_t *p, int depth)
{
long i;
if (p->key) {
putchar(',');
putchar('\n'); for (i = 0; i <= depth; ++i) fputs(" ", stdout);
}
- kson_format_recur(nodes, depth + 1, &nodes[p->v.child[i]]);
+ kson_format_recur(p->v.child[i].p, depth + 1);
}
putchar('\n'); for (i = 0; i < depth; ++i) fputs(" ", stdout);
}
}
}
-void kson_format(const kson_t *kson)
+void kson_format(const kson_node_t *root)
{
- kson_format_recur(kson->nodes, 0, kson->nodes);
+ kson_format_recur(root, 0);
putchar('\n');
}
const kson_node_t *p = kson->nodes;
for (i = 2; i < argc && p; ++i) {
if (p->type == KSON_TYPE_BRACKET)
- p = kson_by_index(kson->nodes, p, atoi(argv[i]));
+ p = kson_by_index(p, atoi(argv[i]));
else if (p->type == KSON_TYPE_BRACE)
- p = kson_by_key(kson->nodes, p, argv[i]);
+ p = kson_by_key(p, argv[i]);
else p = 0;
}
if (p) {
} else {
kson = kson_parse("{'a' : 1,'b':[0,'isn\\'t',true],'d':[{\n}]}", &error);
if (error == 0) {
- const kson_node_t *p = kson_query(kson, 2, "b", 1);
+ const kson_node_t *p = kson_query(kson->nodes, 2, "b", 1);
if (p) printf("*** %s\n", p->v.str);
else printf("!!! not found\n");
kson_format(kson);
#define KSON_ERR_EXTRA_RIGHT 2
#define KSON_ERR_NO_KEY 3
-typedef struct {
+struct kson_node_s;
+
+typedef union {
+ long i; // this is a temporary variable; don't use it!
+ struct kson_node_s *p;
+} kson_ptr_t;
+
+typedef struct kson_node_s {
uint64_t type:3, n:61;
char *key;
union {
- long *child;
+ kson_ptr_t *child;
char *str;
} v;
} kson_node_t;
typedef struct {
long n_nodes;
- kson_node_t *nodes;
+ kson_node_t *nodes; // nodes[0] is the root
} kson_t;
#define kson_is_internal(p) ((p)->type == KSON_TYPE_BRACKET || (p)->type == KSON_TYPE_BRACE)
/** Destroy a kson_t object */
void kson_destroy(kson_t *kson);
- const kson_node_t *kson_query(const kson_t *kson, int max_depth, ...);
+ const kson_node_t *kson_query(const kson_node_t *root, int max_depth, ...);
- void kson_format(const kson_t *kson);
+ void kson_format(const kson_node_t *root);
#ifdef __cplusplus
}
#endif
-static inline const kson_node_t *kson_by_key(const kson_node_t *nodes, const kson_node_t *p, const char *key)
+static inline const kson_node_t *kson_by_key(const kson_node_t *p, const char *key)
{
long i;
for (i = 0; i < (long)p->n; ++i) {
- const kson_node_t *q = &nodes[p->v.child[i]];
+ const kson_node_t *q = p->v.child[i].p;
if (q->key && strcmp(q->key, key) == 0)
return q;
}
return 0;
}
-static inline const kson_node_t *kson_by_index(const kson_node_t *nodes, const kson_node_t *p, long i)
+static inline const kson_node_t *kson_by_index(const kson_node_t *p, long i)
{
- return 0 <= i && i < (long)p->n? &nodes[p->v.child[i]] : 0;
+ return 0 <= i && i < (long)p->n? p->v.child[i].p : 0;
}
#endif