#include <stdio.h>
#include "kson.h"
-kson_node_t *kson_parse(const char *json, int *_n, int *error, int *parsed_len)
+kson_node_t *kson_parse_core(const char *json, long *_n, int *error, long *parsed_len)
{
- int *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;
kson_node_t *a = 0, *u;
const char *p, *q;
#define __push_back(y) do { \
if (top == max) { \
max = max? max<<1 : 4; \
- stack = (int*)realloc(stack, sizeof(int) * max); \
+ stack = (long*)realloc(stack, sizeof(long) * max); \
} \
stack[top++] = (y); \
} while (0)
#define __new_node(z) do { \
if (n_a == m_a) { \
- int old_m = m_a; \
+ long old_m = m_a; \
m_a = m_a? m_a<<1 : 4; \
a = (kson_node_t*)realloc(a, sizeof(kson_node_t) * m_a); \
memset(a + old_m, 0, sizeof(kson_node_t) * (m_a - old_m)); \
*(z) = &a[n_a++]; \
} while (0)
+ *error = KSON_OK;
for (p = json; *p; ++p) {
while (*p && isblank(*p)) ++p;
if (*p == 0) break;
__push_back(t);
} else stack[top-1] = t; // named internal node
} else if (*p == ']' || *p == '}') {
- int i, start, t = *p == ']'? -1 : -2;
+ long i, start, t = *p == ']'? -1 : -2;
for (i = top - 1; i >= 0 && stack[i] != t; --i);
if (i < 0) { // error: an extra right bracket
*error = KSON_ERR_EXTRA_RIGHT;
u = &a[stack[start-1]];
u->key = u->v.str;
u->n = top - 1 - start;
- u->v.child = (int*)malloc(u->n * sizeof(int));
+ u->v.child = (long*)malloc(u->n * sizeof(long));
for (i = start + 1; i < top; ++i)
u->v.child[i - start - 1] = stack[i];
u->type = *p == ']'? KSON_TYPE_BRACKET : KSON_TYPE_BRACE;
return a;
}
-void kson_destroy(int n_nodes, kson_node_t *nodes)
+void kson_destroy(kson_t *kson)
{
- int i;
- for (i = 0; i < n_nodes; ++i) {
- free(nodes[i].key); free(nodes[i].v.str);
+ if (kson) {
+ long i;
+ for (i = 0; i < kson->n_nodes; ++i) {
+ free(kson->nodes[i].key); free(kson->nodes[i].v.str);
+ }
+ free(kson->nodes); free(kson);
+ }
+}
+
+kson_t *kson_parse(const char *json, int *error)
+{
+ kson_t *ks;
+ ks = (kson_t*)calloc(1, sizeof(kson_t));
+ ks->nodes = kson_parse_core(json, &ks->n_nodes, error, 0);
+ if (*error) {
+ kson_destroy(ks);
+ return 0;
}
- free(nodes);
+ return ks;
}
void kson_print_recur(kson_node_t *nodes, kson_node_t *p)
if (p->v.str) putchar(':');
}
if (p->type == KSON_TYPE_BRACKET || p->type == KSON_TYPE_BRACE) {
- int i;
+ long i;
putchar(p->type == KSON_TYPE_BRACKET? '[' : '{');
- for (i = 0; i < p->n; ++i) {
+ for (i = 0; i < (long)p->n; ++i) {
if (i) putchar(',');
kson_print_recur(nodes, &nodes[p->v.child[i]]);
}
}
}
+void kson_print(kson_t *kson)
+{
+ kson_print_recur(kson->nodes, kson->nodes);
+}
+
#ifdef KSON_MAIN
int main(int argc, char *argv[])
{
- kson_node_t *nodes;
- int n_nodes, error, parsed_len;
- nodes = kson_parse("{'a' : 1, 'b':[0,'isn\\'t',true],'d':[{}]}", &n_nodes, &error, &parsed_len);
+ kson_t *kson;
+ int error;
+ kson = kson_parse("{'a' : 1, 'b':[0,'isn\\'t',true],'d':[{}]}", &error);
if (error == 0) {
- kson_print_recur(nodes, &nodes[0]);
+ kson_print(kson);
putchar('\n');
} else {
printf("Error code: %d\n", error);
}
- kson_destroy(n_nodes, nodes);
+ kson_destroy(kson);
return 0;
}
#endif
uint64_t type:3, n:61;
char *key;
union {
- int *child;
+ long *child;
char *str;
} v;
} kson_node_t;
+typedef struct {
+ long n_nodes;
+ kson_node_t *nodes;
+} kson_t;
+
#ifdef __cplusplus
extern "C" {
#endif
/**
- * Parse a JSON string
+ * Parse a JSON string into nodes
*
* @param json JSON string
* @param n_nodes number of nodes
*
* @return An array of size $n_nodes keeping parsed nodes
*/
- kson_node_t *kson_parse(const char *json, int *n_nodes, int *error, int *parsed_len);
+ kson_node_t *kson_parse_core(const char *json, long *n_nodes, int *error, long *parsed_len);
- void kson_destroy(int n_nodes, kson_node_t *nodes);
+ // Equivalent to: { kson->nodes = kson_parse_core(json, &kson->n_nodes, &error, 0); return *error? 0 : kson; }
+ kson_t *kson_parse(const char *json, int *error);
- void kson_print_recur(kson_node_t *nodes, kson_node_t *root);
+ void kson_destroy(kson_t *ks);
+ void kson_print(kson_t *kson);
#ifdef __cplusplus
}