blob: e23d934c3e3b73f505c5a4632bf2aecd6e491665 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
#ifndef DC_REALLOC_K
#define DC_REALLOC_K 1.5
#endif
struct dc_json { /* does not care about syntax, only purpose is to detect objects for libcjson */
char * buf; /* internal buffer */
size_t bufcap; /* internal buffer capacity */
size_t nest; /* internal nesting depth of whatevery type: object or array */
size_t instr; /* internal if we are currently in a string */
size_t start; /* internal starting offset in buffer of first byte of object - { */
char backup; /* internal we store byte we overwrote with \0 when we were ready */
int ready; /* internal we indicate to the next call that we were ready previous time */
}; /* note that no memory is transfered. in is copied and return mustn't be freed. */
char * dc_json (struct dc_json * j, char * in) { /* detects start/end of a cat objects JSON stream */
size_t i; /* input a null terminated string - a chunk of the json stream */
if (!j->buf)
(j->buf = malloc((j->bufcap = 1024) * sizeof(char)))[0] = '\0';
if (j->ready) {
if (j->ready > 0)
memmove(j->buf, j->buf+j->ready, strlen(j->buf+j->ready)+1);
j->buf[0] = j->backup;
}
size_t bufstrlen = strlen(j->buf); /* could optimize and cache it into the struct */
size_t instrlen = strlen(in);
i = bufstrlen;
if (bufstrlen + instrlen > j->bufcap)
j->buf = realloc(j->buf, (j->bufcap=(bufstrlen+instrlen)*DC_REALLOC_K)*sizeof(char));
strcpy(j->buf+bufstrlen, in);
bufstrlen += instrlen;
while (i < bufstrlen) {
if (j->instr) {
if (j->buf[i] == '"') {
int escaped = 0;
int index = 0;
while (j->buf[i-++index] == '\\') {
if (escaped)
escaped = 0;
else
escaped++;
}
if (!escaped) {
j->instr = 0;
fprintf(stderr, "dc_json: j->instr = 0\n");
} else
fprintf(stderr, "dc_json: escaped\n");
}
goto next;
}
switch (j->buf[i]) {
case '{':
case '[':
if (!j->nest++)
j->start = i;
break;
case '"':
j->instr++;
fprintf(stderr, "dc_json: j->instr++\n");
break;
case '}':
case ']':
if (!--j->nest) {
j->backup = j->buf[++i];
j->ready = i;
if (!j->backup)
j->ready = -1;
j->buf[i] = '\0';
return j->buf+j->start;
}
break;
default:
break;
}
next:
i++;
}
return NULL;
} /* returns pointer to null terminated string when there's an object to be parsed or NULL. */
void dc_json_free (struct dc_json * s) {
free(s->buf);
free(s);
}
|