-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
190 lines (149 loc) · 7.23 KB
/
README
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
json
----
CURRENTLY NO ERROR CHECKING - don't use for projects that could receive incorrect data.
A simple JSON library in C with no dependencies other than the C standard
library. Comes with a hashmap implementation. To use the hashmap implementation,
read the last part of this document.
Include json.h and add json.c to your project. The following functions, macros,
and structs are provided:
typedef enum json_t {
json_bool,
json_string,
json_array,
json_dict,
json_number,
json_null
} json_t;
typedef union {
double number;
char *string;
bool boolean;
struct json *json_data;
struct json **json_data_array;
HashMap *json_data_dict;
} json_data;
struct json {
json_t type;
char *key; /* If a dictionary item */
int n_data_items; /* Length (if applicable) */
size_t data_list_capacity; /* Capacity (if applicable) */
json_data data;
};
struct json * json_parse(char *)
void free_json_item(struct json *)
/* READ BELOW ABOUT THESE TWO FUNCTIONS */
struct json * json_access(struct json *, ...)
struct json * json_safe_access(struct json *, char *, ...);
/*
* The following will access json data with a key or array index.
* You must use json_get_TYPE to access the data in the appropriate
* type, or use the json_get_array_TYPE or json_get_dict_TYPE family
* of functions.
*/
struct json * json_get_array_item(struct json *, int)
struct json * json_get_dict_item(struct json *, char *)
/* Use these to access information about a dictionary or an array. */
int json_get_size(struct json *)
int json_get_capacity(struct json *)
/* Access functions */
char * json_get_string(struct json *)
bool json_get_bool(struct json *)
double json_get_number(struct json *)
struct json * json_get_data(struct json *)
struct json * json_get_array(struct json *)
struct json * json_get_dict(struct json *)
/*
* Function to read a file into a (char *) buffer.
* Note that there is no limit on file size, and the buffer will be
* grown infinitely. This function is used for testing, but it is left
* in for user convenience.
*/
char * json_read_file(char *)
/*
* The following macros are equivalent to
* json_get_TYPE(json_get_array_item(j, idx or key))
*/
char * json_get_array_string(struct json *, int)
bool json_get_array_bool(struct json *, int)
double json_get_array_number(struct json *, int)
struct json * json_get_array_data(struct json *, int)
struct json * json_get_array_array(struct json *, int)
struct json * json_get_array_dict(struct json *, int)
/*
* These functions also have a corresponding json_get_dict_TYPE()
* function for accessing dictionaries. Just replace int with a key
* of type (char *) as follows:
*/
char * json_get_dict_string(struct json *, char *)
bool json_get_dict_bool(struct json *, char *)
double json_get_dict_number(struct json *, char *)
struct json * json_get_dict_data(struct json *, char *)
struct json * json_get_dict_array(struct json *, char *)
struct json * json_get_dict_dict(struct json *, char *)
Macros beginning with json_get_ are used to access the data of a parsed JSON
item. For example:
struct json *j = json_parse("\"abc\"");
char *data = json_get_string(j); /* data now equals "abc" */
json_access() is a bit of a strange function. I added it to easily access deeply
nested information. Generally, the function works like this:
json_access(j, "index1", "index2", "0", "1", NULL);
as opposed to:
json_get_array_item(json_get_array_item(
json_get_dict_item(
json_get_dict_item(j, "index1"), "index2"), 0), 1
);
The list of arguments to json_access() MUST end with NULL. You may notice that
array indices are also strings. This is because you can not mix types within
va_list. This will also result in conflicts if you have a dictionary with keys
that are numbers.
The only way around this would be to provide a format string similar to the one
used by printf() and its various related functions, but this further complicates
the function. If you would like to guarantee that everything behaves as expected
or if you are working with dictionaries that use integers as keys, use the
json_safe_access() function. It works as follows:
json_safe_access(j, "%s %s %d %d", "index1", "index2", 0, 1);
There is no need for NULL at the end. Only the %d and %s formatters are
supported.
Further information can be obtained by reading the source code. Read below
to use the hashmap implementation.
hashmap
-------
This library comes with a builtin hashmap implementation. The following
functions, macros, and structs are provided:
typedef struct HMItem HMItem;
struct HMItem {
char *key;
char *val;
/* Free functions for key and val, respectively. */
void (*k_free_func)(void *);
void (*v_free_func)(void *);
};
/*
* This will cast a free() function for your items into a function
* that can be passed to new_item().
*/
hashmap_item_free_func(f)
HMItem *new_item(char *key, void *val,
void (*k_free_func)(void *), void (*v_free_func)(void *))
void free_item(HMItem *item)
HashMap *new_hashmap(size_t capacity);
void free_hashmap(HashMap *map);
/*
* Will check if the hashmap can hold N more entries. If not, resize.
* Returns 0 on success, 1 on failure.
*/
int check_hashmap_capacity(HashMap *map, size_t n);
int hashmap_set(HashMap *map, HMItem *item);
uint64_t hashmap_hash_func(char *key);
void *hashmap_index(HashMap *map, char *key);
void hashmap_remove(HashMap *map, char *key);
This may look like a lot, but I will explain it.
Create a new hashmap with the new_hashmap() function. To add items,
create an HMItem with the new_item() function. k_free_func and v_free_func can
be NULL, which means your item does not need to be freed along with the hashmap.
The free_functions are only necessary if you are using a struct for your items
with elements that need to be freed to avoid memory leaks.
Use free() for the key's free function.
Once you have an HMItem, use hashmap_set() to add it to the hashmap. There is
no need to check for overflow yourself, the function will do it automatically.
Once you are done, use free_hashmap() to free the hashmap.