Skip to content

Commit 3a4ebff

Browse files
author
Suhel Chakraborty
authored
Key based element lookup (#11)
* Hash table implemented * Updated README
1 parent 6cab4b0 commit 3a4ebff

File tree

12 files changed

+935
-597
lines changed

12 files changed

+935
-597
lines changed

.vscode/settings.json

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,6 @@
11
{
2-
"files.associations": {
3-
"*.x": "linkerscript",
4-
"typeinfo": "c",
5-
"__bit_reference": "c",
6-
"__functional_base": "c",
7-
"__node_handle": "c",
8-
"algorithm": "c",
9-
"atomic": "c",
10-
"bitset": "c",
11-
"chrono": "c",
12-
"cstddef": "c",
13-
"__memory": "c",
14-
"functional": "c",
15-
"iterator": "c",
16-
"limits": "c",
17-
"locale": "c",
18-
"memory": "c",
19-
"optional": "c",
20-
"ratio": "c",
21-
"system_error": "c",
22-
"tuple": "c",
23-
"type_traits": "c",
24-
"vector": "c",
25-
"__config": "c",
26-
"__hash_table": "c",
27-
"__split_buffer": "c",
28-
"array": "c",
29-
"initializer_list": "c",
30-
"string": "c",
31-
"string_view": "c",
32-
"unordered_map": "c",
33-
"utility": "c"
34-
},
352
"[json]": {
363
"editor.formatOnSave": false
37-
}
4+
},
5+
"C_Cpp.clang_format_style": "LLVM"
386
}

.vscode/tasks.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"args": [
88
"-fdiagnostics-color=always",
99
"-g",
10+
"-O0",
11+
"-DJSON_DEBUG",
1012
"${workspaceFolder}/*.c",
1113
"-o",
1214
"${workspaceFolder}/bin/a.out"

README.md

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ An easy to use, very fast JSON parsing implementation written in pure C
55
## Features
66

77
* Fully [RFC-8259](https://datatracker.ietf.org/doc/html/rfc8259) compliant
8-
* Simple 2 file library
8+
* Small 2 file library
99
* Support for all data types
10+
* Simple and efficient hash table implementation to search element by key
1011
* Rust like `result` type used throughout fallible calls
1112
* Compile with `-DJSON_SCRAPE_WHITESPACE` to parse non-minified JSON with whitespace in between
1213

@@ -46,7 +47,12 @@ result(json_element) // json_element_result_t
4647
result(json_element) json_parse(typed(json_string) json_str);
4748
```
4849
49-
### Print JSON with specific indentation
50+
### Find an element by key
51+
```C
52+
result(json_element) json_object_find(typed(json_object) * object, typed(json_string) key);
53+
```
54+
55+
### Print JSON with specified indentation
5056
```C
5157
void json_print(typed(json_element) *element, int indent);
5258
```
@@ -176,8 +182,18 @@ int main() {
176182

177183
// Extract the data
178184
typed(json_element) element = result_unwrap(json_element)(&element_result);
185+
186+
// Fetch the "hello" key value
187+
result(json_element) hello_element_result = json_object_find(&element, "hello");
188+
if(result_is_err(json_element)(&hello_element_result)) {
189+
typed(json_error) error = result_unwrap_err(json_element)(&hello_element_result);
190+
fprintf(stderr, "Error getting element \"hello\": %s\n", json_error_to_string(error));
191+
return -1;
192+
}
193+
typed(json_element) hello_element = result_unwrap(json_element)(&hello_element_result);
194+
179195
// Use the element
180-
printf("Value is \"%s\"\n", element.value.as_object->entries[1].element.value.as_string);
196+
printf("\"hello\": \"%s\"\n", hello_element.value.as_string);
181197
json_print(&element, 2);
182198
json_free(&element);
183199

@@ -187,7 +203,7 @@ int main() {
187203
Outputs
188204

189205
```
190-
Value is "value"
206+
"hello": "world"
191207
{
192208
"hello": "world",
193209
"key": "value"
@@ -212,23 +228,23 @@ At each Key-Value pair `typed(json_entry_t)`, there is a member `type`
212228
...
213229

214230
typed(json_element) element = ...; // See example above
215-
typed(json_entry) entry = element->value.as_object->entries[0];
231+
typed(json_entry) entry = element.value.as_object->entries[0];
216232

217-
switch(entry.type) {
233+
switch(entry.element.type) {
218234
case JSON_TYPE_STRING:
219-
// `entry.value.as_string` is a `json_string_t`
235+
// `entry.element.value.as_string` is a `json_string_t`
220236
break;
221237
case JSON_TYPE_NUMBER:
222-
// `entry.value.as_number` is a `json_number_t`
238+
// `entry.element.value.as_number` is a `json_number_t`
223239
break;
224240
case JSON_TYPE_OBJECT:
225-
// `entry.value.as_object` is a `json_object_t *`
241+
// `entry.element.value.as_object` is a `json_object_t *`
226242
break;
227243
case JSON_TYPE_ARRAY:
228-
// `entry.value.as_array` is a `json_array_t *`
244+
// `entry.element.value.as_array` is a `json_array_t *`
229245
break;
230246
case JSON_TYPE_BOOLEAN:
231-
// `entry.value.as_boolean` is a `json_boolean_t`
247+
// `entry.element.value.as_boolean` is a `json_boolean_t`
232248
break;
233249
}
234250
```
@@ -245,14 +261,14 @@ In each `typed(json_object)`, there is a member `count`
245261
int i;
246262
247263
typed(json_element) element = ...; // See example above
248-
typed(json_object) *obj = element->value.as_object;
264+
typed(json_object) *obj = element.value.as_object;
249265
250266
for(i = 0; i < obj->count; i++) {
251267
typed(json_entry) entry = obj->entries[i];
252268
253269
typed(json_string) key = entry.key;
254-
typed(json_element_type) type = entry.type;
255-
typed(json_element_value) value = entry.value;
270+
typed(json_element_type) type = entry.element.type;
271+
typed(json_element_value) value = entry.element.value;
256272
// Do something with `key`, `type` and `value`
257273
}
258274
```
@@ -269,10 +285,10 @@ In each `typed(json_array)`, there is a member `count`
269285
int i;
270286

271287
typed(json_element) element = ...; // See example above
272-
typed(json_array) *arr = element->value.as_array;
288+
typed(json_array) *arr = element.value.as_array;
273289

274-
for(i = 0; i < obj->count; i++) {
275-
typed(json_element) element = obj->elements[i];
290+
for(i = 0; i < arr->count; i++) {
291+
typed(json_element) element = arr->elements[i];
276292

277293
typed(json_element_type) type = element.type;
278294
typed(json_element_value) value = element.value;

example.c

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,58 @@
11
#include <stdio.h>
22
#include <stdlib.h>
33
#include <string.h>
4+
#include <time.h>
45

56
#include "json.h"
67

78
const char *read_file(const char *path) {
8-
FILE *file = fopen(path, "r");
9-
if (file == NULL) {
10-
fprintf(stderr, "Expected file \"%s\" not found", path);
11-
return NULL;
12-
}
13-
fseek(file, 0, SEEK_END);
14-
long len = ftell(file);
15-
fseek(file, 0, SEEK_SET);
16-
char *buffer = malloc(len);
17-
18-
if (buffer == NULL) {
19-
fprintf(stderr, "Unable to allocate memory for file");
20-
fclose(file);
21-
return NULL;
22-
}
23-
24-
fread(buffer, 1, len, file);
25-
26-
return (const char *)buffer;
9+
FILE *file = fopen(path, "r");
10+
if (file == NULL) {
11+
fprintf(stderr, "Expected file \"%s\" not found", path);
12+
return NULL;
13+
}
14+
fseek(file, 0, SEEK_END);
15+
long len = ftell(file);
16+
fseek(file, 0, SEEK_SET);
17+
char *buffer = malloc(len + 1);
18+
19+
if (buffer == NULL) {
20+
fprintf(stderr, "Unable to allocate memory for file");
21+
fclose(file);
22+
return NULL;
23+
}
24+
25+
fread(buffer, 1, len, file);
26+
buffer[len] = '\0';
27+
28+
return (const char *)buffer;
2729
}
2830

2931
int main() {
30-
const char *json = read_file("../reddit.json");
31-
if (json == NULL) {
32-
return -1;
33-
}
34-
35-
result(json_element) element_result = json_parse(json);
36-
free((void *)json);
37-
38-
if (result_is_err(json_element)(&element_result)) {
39-
typed(json_error) error = result_unwrap_err(json_element)(&element_result);
40-
fprintf(stderr, "Error parsing JSON: %s\n", json_error_to_string(error));
41-
return -1;
42-
}
43-
typed(json_element) element = result_unwrap(json_element)(&element_result);
44-
json_print(&element, 2);
45-
json_free(&element);
46-
47-
return 0;
32+
const char *json = read_file("../sample/reddit.json");
33+
if (json == NULL) {
34+
return -1;
35+
}
36+
37+
clock_t start, end;
38+
start = clock();
39+
result(json_element) element_result = json_parse(json);
40+
end = clock();
41+
42+
printf("Time taken %fs\n", (double)(end - start) / (double)CLOCKS_PER_SEC);
43+
44+
free((void *)json);
45+
46+
if (result_is_err(json_element)(&element_result)) {
47+
typed(json_error) error = result_unwrap_err(json_element)(&element_result);
48+
fprintf(stderr, "Error parsing JSON: %s\n", json_error_to_string(error));
49+
return -1;
50+
}
51+
typed(json_element) element = result_unwrap(json_element)(&element_result);
52+
typed(json_object) *obj = element.value.as_object;
53+
54+
// json_print(&element, 2);
55+
json_free(&element);
56+
57+
return 0;
4858
}

0 commit comments

Comments
 (0)