1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3 * Copyright (C) 2021-2024 Cyril Hrubis <metan@ucw.cz>
4 */
5
6 /**
7 * @file ujson_writer.h
8 * @brief A JSON writer.
9 *
10 * All the function that add values return zero on success and non-zero on a
11 * failure. Once an error has happened all subsequent attempts to add more
12 * values return with non-zero exit status immediatelly. This is designed
13 * so that we can add several values without checking each return value
14 * and only check if error has happened at the end of the sequence.
15 *
16 * Failures may occur:
17 * - if we call the functions out of order, e.g. attempt to finish array when
18 * we are not writing out an array.
19 * - if we run out of recursion stack
20 * - may be propagated from the writer function, e.g. allocation failure, no
21 * space on disk, etc.
22 */
23
24 #ifndef UJSON_WRITER_H
25 #define UJSON_WRITER_H
26
27 #include <ujson_common.h>
28
29 /** @brief A JSON writer */
30 struct ujson_writer {
31 unsigned int depth;
32 char depth_type[UJSON_RECURSION_MAX/8];
33 char depth_first[UJSON_RECURSION_MAX/8];
34
35 /** Handler to print errors and warnings */
36 void (*err_print)(void *err_print_priv, const char *line);
37 void *err_print_priv;
38 char err[UJSON_ERR_MAX];
39
40 /** Handler to produce JSON output */
41 int (*out)(struct ujson_writer *self, const char *buf, size_t buf_size);
42 void *out_priv;
43 };
44
45 /**
46 * @brief An ujson_writer initializer with default values.
47 *
48 * @param vout A pointer to function to write out the data.
49 * @param vout_priv An user pointer passed to the out function.
50 *
51 * @return An ujson_writer initialized with default values.
52 */
53 #define UJSON_WRITER_INIT(vout, vout_priv) { \
54 .err_print = UJSON_ERR_PRINT, \
55 .err_print_priv = UJSON_ERR_PRINT_PRIV, \
56 .out = vout, \
57 .out_priv = vout_priv \
58 }
59
60 /**
61 * @brief Allocates a JSON file writer.
62 *
63 * The call may fail either when file cannot be opened for writing or if
64 * allocation has failed. In all cases errno should be set correctly.
65 *
66 * @param path A path to the file, file is opened for writing and created if it
67 * does not exist.
68 *
69 * @return A ujson_writer pointer or NULL in a case of failure.
70 */
71 ujson_writer *ujson_writer_file_open(const char *path);
72
73 /**
74 * @brief Closes and frees a JSON file writer.
75 *
76 * @param self A ujson_writer file writer.
77 *
78 * @return Zero on success, non-zero on a failure and errno is set.
79 */
80 int ujson_writer_file_close(ujson_writer *self);
81
82 /**
83 * @brief Returns true if writer error happened.
84 *
85 * @param self A JSON writer.
86 *
87 * @return True if error has happened.
88 */
ujson_writer_err(ujson_writer * self)89 static inline int ujson_writer_err(ujson_writer *self)
90 {
91 return !!self->err[0];
92 }
93
94 /**
95 * @brief Starts a JSON object.
96 *
97 * For a top level object the id must be NULL, every other object has to have
98 * non-NULL id. The call will also fail if maximal recursion depth
99 * UJSON_RECURSION_MAX has been reached.
100 *
101 * @param self A JSON writer.
102 * @param id An object name.
103 *
104 * @return Zero on a success, non-zero otherwise.
105 */
106 int ujson_obj_start(ujson_writer *self, const char *id);
107
108 /**
109 * @brief Finishes a JSON object.
110 *
111 * The call will fail if we are currenlty not writing out an object.
112 *
113 * @param self A JSON writer.
114 *
115 * @return Zero on success, non-zero otherwise.
116 */
117 int ujson_obj_finish(ujson_writer *self);
118
119 /**
120 * @brief Starts a JSON array.
121 *
122 * For a top level array the id must be NULL, every other array has to have
123 * non-NULL id. The call will also fail if maximal recursion depth
124 * UJSON_RECURSION_MAX has been reached.
125 *
126 * @param self A JSON writer.
127 * @param id An array name.
128 *
129 * @return Zero on success, non-zero otherwise.
130 */
131 int ujson_arr_start(ujson_writer *self, const char *id);
132
133 /**
134 * @brief Finishes a JSON array.
135 *
136 * The call will fail if we are currenlty not writing out an array.
137 *
138 * @param self A JSON writer.
139 *
140 * @return Zero on success, non-zero otherwise.
141 */
142 int ujson_arr_finish(ujson_writer *self);
143
144 /**
145 * @brief Adds a null value.
146 *
147 * The id must be NULL inside of an array, and must be non-NULL inside of an
148 * object.
149 *
150 * @param self A JSON writer.
151 * @param id A null value name.
152 *
153 * @return Zero on success, non-zero otherwise.
154 */
155 int ujson_null_add(ujson_writer *self, const char *id);
156
157 /**
158 * @brief Adds an integer value.
159 *
160 * The id must be NULL inside of an array, and must be non-NULL inside of an
161 * object.
162 *
163 * @param self A JSON writer.
164 * @param id An integer value name.
165 * @param val An integer value.
166 *
167 * @return Zero on success, non-zero otherwise.
168 */
169 int ujson_int_add(ujson_writer *self, const char *id, long val);
170
171 /**
172 * @brief Adds a bool value.
173 *
174 * The id must be NULL inside of an array, and must be non-NULL inside of an
175 * object.
176 *
177 * @param self A JSON writer.
178 * @param id An boolean value name.
179 * @param val A boolean value.
180 *
181 * @return Zero on success, non-zero otherwise.
182 */
183 int ujson_bool_add(ujson_writer *self, const char *id, int val);
184
185 /**
186 * @brief Adds a float value.
187 *
188 * The id must be NULL inside of an array, and must be non-NULL inside of an
189 * object.
190 *
191 * @param self A JSON writer.
192 * @param id A floating point value name.
193 * @param val A floating point value.
194 *
195 * @return Zero on success, non-zero otherwise.
196 */
197 int ujson_float_add(ujson_writer *self, const char *id, double val);
198
199 /**
200 * @brief Adds a string value.
201 *
202 * The id must be NULL inside of an array, and must be non-NULL inside of an
203 * object.
204 *
205 * @param self A JSON writer.
206 * @param id A string value name.
207 * @param str An UTF8 string value.
208 *
209 * @return Zero on success, non-zero otherwise.
210 */
211 int ujson_str_add(ujson_writer *self, const char *id, const char *str);
212
213 /**
214 * @brief Finalizes json writer.
215 *
216 * Finalizes the json writer, throws possible errors through the error printing
217 * function.
218 *
219 * @param self A JSON writer.
220 * @return Overall error value.
221 */
222 int ujson_writer_finish(ujson_writer *self);
223
224 #endif /* UJSON_WRITER_H */
225