• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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