Directory: | ./ |
---|---|
File: | src/util.c |
Date: | 2021-09-04 00:13:15 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 67 | 68 | 98.5% |
Branches: | 47 | 52 | 90.4% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /***************************************************************************/ /** | ||
2 | |||
3 | @file util.c | ||
4 | |||
5 | @author Stephen Brennan | ||
6 | |||
7 | @date Created Wednesday, 9 December 2015 | ||
8 | |||
9 | @brief JSON manipulation utilities. | ||
10 | |||
11 | @copyright Copyright (c) 2015, Stephen Brennan. Released under the | ||
12 | Revised BSD License. See LICENSE.txt for details. | ||
13 | |||
14 | *******************************************************************************/ | ||
15 | |||
16 | #include <stdio.h> | ||
17 | #include <stdlib.h> | ||
18 | |||
19 | #include "nosj.h" | ||
20 | |||
21 | 22 | size_t json_object_get(const char *json, const struct json_token *tokens, | |
22 | size_t index, const char *key) | ||
23 | { | ||
24 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (tokens[index].type != JSON_OBJECT) |
25 | ✗ | return 0; | |
26 | |||
27 | 22 | index = tokens[index].child; | |
28 | |||
29 |
2/2✓ Branch 0 taken 173 times.
✓ Branch 1 taken 2 times.
|
175 | while (index != 0) { |
30 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 153 times.
|
173 | if (json_string_match(json, tokens, index, key)) { |
31 | 20 | return tokens[index].child; | |
32 | } | ||
33 | 153 | index = tokens[index].next; | |
34 | } | ||
35 | |||
36 | 2 | return 0; | |
37 | } | ||
38 | |||
39 | 14 | size_t json_array_get(const char *json, const struct json_token *tokens, | |
40 | size_t index, size_t array_index) | ||
41 | { | ||
42 | (void)json; | ||
43 | |||
44 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11 times.
|
14 | if (array_index >= tokens[index].length) { |
45 | 3 | return 0; | |
46 | } | ||
47 | |||
48 | 11 | index = tokens[index].child; | |
49 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 11 times.
|
35 | while (array_index--) { |
50 | 24 | index = tokens[index].next; | |
51 | } | ||
52 | |||
53 | 11 | return index; | |
54 | } | ||
55 | |||
56 | 17 | double json_number_get(const char *json, const struct json_token *tokens, | |
57 | size_t index) | ||
58 | { | ||
59 | double result; | ||
60 | 17 | sscanf(json + tokens[index].start, "%lf", &result); | |
61 | 17 | return result; | |
62 | } | ||
63 | |||
64 | /** | ||
65 | * Lookup key within the parsed json_token buffer. Note that in this case, "key" | ||
66 | * is not simply an object key. It can express a dotted notation for traversing | ||
67 | * JSON objects: | ||
68 | * | ||
69 | * keyname.nextkey[123].blah | ||
70 | */ | ||
71 | 10 | size_t json_lookup(const char *json, const struct json_token *arr, size_t tok, | |
72 | const char *key) | ||
73 | { | ||
74 | 10 | size_t start = 0, i = 0; | |
75 | 10 | int state = 0; | |
76 | long index; | ||
77 | 10 | char *keymut = strdup(key); | |
78 | char c; | ||
79 | |||
80 | 159 | for (i = 0;; i++) { | |
81 | 159 | c = keymut[i]; | |
82 |
8/8✓ Branch 0 taken 141 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 123 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 120 times.
|
159 | if (state == 0 && (c == '.' || c == '[' || c == '\0')) { |
83 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
21 | if (i == 0 && c == '[') { |
84 | /* Exception: allow the string to start with | ||
85 | * [indexing] */ | ||
86 | 1 | state = 1; | |
87 | 1 | start = 1; | |
88 | 1 | continue; | |
89 | } | ||
90 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 19 times.
|
20 | if (arr[tok].type != JSON_OBJECT) { |
91 | 1 | tok = 0; | |
92 | 1 | goto out; | |
93 | } | ||
94 | 19 | keymut[i] = '\0'; | |
95 | // printf("Get key \"%s\"\n", &keymut[start]); | ||
96 | 19 | tok = json_object_get(json, arr, tok, &keymut[start]); | |
97 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
|
19 | if (tok == 0) { |
98 | // printf("not found\n"); | ||
99 | 1 | goto out; | |
100 | } | ||
101 | 18 | start = i + 1; | |
102 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 11 times.
|
18 | if (c == '[') |
103 | 7 | state = 1; | |
104 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | else if (c == '\0') |
105 | 1 | goto out; | |
106 | // else if (c == '.') stay in state 0 | ||
107 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 120 times.
|
138 | } else if (state == 0) { |
108 | // do nothing | ||
109 |
3/4✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 10 times.
|
18 | } else if (state == 1 && c == ']') { |
110 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
|
8 | if (arr[tok].type != JSON_ARRAY) { |
111 | 1 | tok = 0; | |
112 | 1 | goto out; | |
113 | } | ||
114 | 7 | keymut[i] = '\0'; | |
115 | 7 | index = strtol(&keymut[start], NULL, 10); | |
116 | // printf("Get ix %ld\n", index); | ||
117 | 7 | tok = json_array_get(json, arr, tok, (size_t)index); | |
118 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
|
7 | if (tok == 0) { |
119 | // printf("Not found\n"); | ||
120 | 1 | goto out; | |
121 | } | ||
122 | 6 | i += 1; | |
123 | 6 | start = i + 1; | |
124 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
|
6 | if (keymut[i] == '.') { |
125 | 1 | state = 0; | |
126 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
5 | } else if (keymut[i] == '[') { |
127 | 1 | state = 1; | |
128 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
|
4 | } else if (keymut[i] == '\0') { |
129 | 3 | goto out; | |
130 | } else { | ||
131 | 1 | tok = 0; | |
132 | 1 | goto out; | |
133 | } | ||
134 |
4/6✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
|
10 | } else if (state == 1 && (c < '0' || c > '9')) { |
135 | // bad character | ||
136 | 1 | tok = 0; | |
137 | 1 | goto out; | |
138 | } | ||
139 | } | ||
140 | |||
141 | 10 | out: | |
142 | 10 | free(keymut); | |
143 | 10 | return tok; | |
144 | } | ||
145 |