Skip to content

Commit 0c7f7af

Browse files
committed
adding (optional) j0g set of utilities, safer handling of index pointer, and can be dropped into arduino projects as a lib easily now
1 parent 0746461 commit 0c7f7af

File tree

8 files changed

+105
-15
lines changed

8 files changed

+105
-15
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
all:
2-
gcc -Wall -o js0n_test js0n_test.c js0n.c
2+
gcc -Wall -o js0n_test test/js0n_test.c js0n.c j0g.c

README

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ Parsing this:
88

99
Would result in:
1010

11-
2,3,8,3,14,6,22,7,30,3,35,9
11+
2,3,8,3,14,6,22,7,30,3,35,9,0
1212

13+
Also includes a collection utility functions for handy ways of using js0n quickly/easily.

j0g.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include "js0n.h"
5+
#include "j0g.h"
6+
7+
// dumbed down parser, expects null terminated json, if fails the *index is 0 (and safe to pass into j0g_*)
8+
char *j0g(char *json, unsigned short *index, int ilen)
9+
{
10+
int ret, len;
11+
if(!json) return NULL;
12+
len = strlen(json);
13+
ret = js0n((unsigned char*)json, len, index, ilen);
14+
if(ret) *index = 0;
15+
return json;
16+
}
17+
18+
// return the null-terminated string value matching the given key
19+
char *j0g_str(char *key, char *json, unsigned short *index)
20+
{
21+
char *str, *cursor;
22+
int val = j0g_val(key, json, index);
23+
if(!val) return NULL;
24+
*(json+(index[val]+index[val+1])) = 0; // null terminate
25+
// unescape stuff
26+
for(cursor=str=json+index[val]; *cursor; cursor++,str++)
27+
{
28+
if(*cursor == '\\' && *(cursor+1) == 'n')
29+
{
30+
*str = '\n';
31+
cursor++;
32+
}else if(*cursor == '\\' && *(cursor+1) == '"'){
33+
*str = '"';
34+
cursor++;
35+
}else{
36+
*str = *cursor;
37+
}
38+
}
39+
*str = *cursor; // copy null terminator too
40+
return (char*)json+index[val];
41+
}
42+
43+
// return 1 if the value is the bool value true, number 1, or even the string "true", false otherwise
44+
int j0g_test(char *key, char *json, unsigned short *index)
45+
{
46+
char *val = j0g_str(key, json, index);
47+
if(!val) return 0;
48+
if(strcmp(val, "true") == 0) return 1;
49+
if(strcmp(val, "1") == 0) return 1;
50+
return 0;
51+
}
52+
53+
// return the index offset of the value matching the given key
54+
int j0g_val(char *key, char *json, unsigned short *index)
55+
{
56+
if(!key || !json) return 0;
57+
int i, klen = strlen(key);
58+
for(i=0;index[i];i+=4)
59+
{
60+
if(klen == index[i+1] && strncmp(key,(char*)json+index[i],klen) == 0) return i+2;
61+
}
62+
return 0;
63+
}
64+

j0g.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// these are handy utility functions to make working with js0n easier
2+
3+
// dumbed down parser, expects null terminated json, if fails the *index is 0 (and safe to pass into j0g_*)
4+
// returns json, for chaining
5+
char *j0g(char *json, unsigned short *index, int ilen);
6+
7+
// for the rest -
8+
// first arg is the key to find in the json
9+
// second is the original json passed to js0n
10+
// third is the array returned by js0n
11+
// these functions will modify the json arg in place (to null terminate strings)
12+
13+
// return the null-terminated string value matching the given key
14+
char *j0g_str(char *key, char *json, unsigned short *index);
15+
16+
// return 1 if the value is the bool value true, number 1, or even the string "true", false otherwise
17+
int j0g_test(char *key, char *json, unsigned short *index);
18+
19+
// return the index offset of the value matching the given key
20+
int j0g_val(char *key, char *json, unsigned short *index);

js0n.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#define PUSH(i) if(depth == 1) prev = *out++ = ((cur+i) - js)
66
#define CAP(i) if(depth == 1) prev = *out++ = ((cur+i) - (js + prev) + 1)
77

8-
int js0n(unsigned char *js, unsigned int len, unsigned short *out)
8+
int js0n(unsigned char *js, unsigned int len, unsigned short *out, unsigned int olen)
99
{
10-
unsigned short prev = 0;
10+
unsigned short prev = 0, *oend;
1111
unsigned char *cur, *end;
1212
int depth=0;
1313
int utf8_remain=0;
@@ -55,12 +55,13 @@ int js0n(unsigned char *js, unsigned int len, unsigned short *out)
5555
};
5656
static void **go = gostruct;
5757

58-
for(cur=js,end=js+len; cur<end; cur++)
58+
for(cur=js,end=js+len,oend=out+olen; cur<end && out<oend; cur++)
5959
{
6060
goto *go[*cur];
6161
l_loop:;
6262
}
6363

64+
if(out < oend) *out = 0;
6465
return depth; // 0 if successful full parse, >0 for incomplete data
6566

6667
l_bad:

js0n.h

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
// pass it a raw json string and length, it will return an array of unsigned shorts, see js0n.c for more
3-
int js0n(unsigned char *js, unsigned int len, unsigned short *out);
4-
5-
// TODO: decode a string value, copy into new while unescaping things and unicode stuffs
6-
// int js0n(unsigned char *in, unsigned int len, unsigned char *out);
1+
// pass it a raw json string and length, and it will tag all the key/value offsets in the out argument (size it same as js to be safe)
2+
// returns 0 if successful, >0 if not
3+
int js0n(unsigned char *js, unsigned int len, unsigned short *out, unsigned int olen);

test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
"bar":[1,2,3],
44
"baz":{"a":"b"},
55
"num":123.45,
6-
"obj":{"true":false}
6+
"key":"value\n\"newline\"",
7+
"obj":{"true":true}
78
}

js0n_test.c renamed to test/js0n_test.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <string.h>
4-
#include "js0n.h"
4+
#include "../js0n.h"
5+
#include "../j0g.h"
56

67
int main(int argc, char **argv)
78
{
@@ -24,13 +25,18 @@ int main(int argc, char **argv)
2425
fclose(f);
2526
printf("got[%.*s]\n",lastlen,json);
2627
res = malloc(lastlen); // way more than enough
27-
memset(res,0,lastlen);
28-
ret = js0n(json,lastlen,res);
28+
ret = js0n(json,lastlen,res,lastlen);
2929
printf("returned %d\n",ret);
3030
for(i=0;res[i];i+=2)
3131
{
3232
printf("%d: at %d len %d is %.*s\n",i,res[i],res[i+1],res[i+1],json+res[i]);
3333
}
34+
35+
// j0g tests
36+
printf("j0g_val 'key' val offset %d\n", j0g_val("key",(char*)json,res));
37+
printf("j0g_str 'key' val '%s'\n", j0g_str("key",(char*)json,res));
38+
printf("j0g_str 'num' val '%0.2f'\n", (j0g_str("num",(char*)json,res)!=NULL)?strtof(j0g_str("num",(char*)json,res), NULL):0);
39+
printf("j0g_test obj->true %d\n", j0g_test("true",j0g(j0g_str("obj",(char*)json,res),res,16),res));
3440
return 0;
3541
}
3642

0 commit comments

Comments
 (0)