1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**
12  * @file nx_azure_iot_json_writer.h
13  *
14  */
15 
16 #ifndef NX_AZURE_IOT_JSON_WRITER_H
17 #define NX_AZURE_IOT_JSON_WRITER_H
18 
19 #include "azure/core/az_json.h"
20 #include "nx_api.h"
21 
22 #ifdef __cplusplus
23 extern   "C" {
24 #endif
25 
26 /**
27  * @brief Provides forward-only, non-cached writing of UTF-8 encoded JSON text into the provided
28  * buffer.
29  *
30  * @remarks #az_json_writer builds the text sequentially with no caching and by default adheres to
31  * the JSON RFC: https://tools.ietf.org/html/rfc8259.
32  *
33  */
34 typedef struct NX_AZURE_IOT_JSON_WRITER_STRUCT
35 {
36     NX_PACKET *packet_ptr;
37     az_json_writer json_writer;
38     UINT wait_option;
39     ULONG nx_tail_packet_offset;
40     ULONG nx_packet_init_length;
41 } NX_AZURE_IOT_JSON_WRITER;
42 
43 /**
44  * @brief Initializes an #NX_AZURE_IOT_JSON_WRITER which writes JSON text into a NX_PACKET.
45  *
46  * @param[out] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER the instance to initialize.
47  * @param[in] packet_ptr A pointer to #NX_PACKET.
48  * @param[in] wait_option Ticks to wait for allocating next packet
49  *
50  * @return An `UINT` value indicating the result of the operation.
51  * @retval #NX_AZURE_IOT_SUCCESS Successfully initialized JSON writer.
52  */
53 UINT nx_azure_iot_json_writer_init(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
54                                    NX_PACKET *packet_ptr, UINT wait_option);
55 
56 /**
57  * @brief Initializes an #NX_AZURE_IOT_JSON_WRITER which writes JSON text into a buffer passed.
58  *
59  * @param[out] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER the instance to initialize.
60  * @param[in] buffer_ptr A buffer pointer to which JSON text will be written.
61  * @param[in] buffer_len Length of buffer.
62  *
63  * @return An `UINT` value indicating the result of the operation.
64  * @retval #NX_AZURE_IOT_SUCCESS Successfully initialized JSON writer.
65  */
66 UINT nx_azure_iot_json_writer_with_buffer_init(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
67                                                UCHAR *buffer_ptr, UINT buffer_len);
68 
69 /**
70  * @brief Deinitializes an #NX_AZURE_IOT_JSON_WRITER.
71  *
72  * @param[out] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER the instance to de-initialize.
73  *
74  * @return An `UINT` value indicating the result of the operation.
75  * @retval #NX_AZURE_IOT_SUCCESS Successfully de-initialized JSON writer.
76  */
77 UINT nx_azure_iot_json_writer_deinit(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
78 
79 /**
80  * @brief Appends the UTF-8 property name and value where value is int32
81  *
82  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
83  * @param[in] property_name The UTF-8 encoded property name of the JSON value to be written. The name is
84  * escaped before writing.
85  * @param[in] property_name_len Length of property_name.
86  * @param[in] value The value to be written as a JSON number.
87  *
88  * @return An `UINT` value indicating the result of the operation.
89  * @retval #NX_AZURE_IOT_SUCCESS The property name and int32 value was appended successfully.
90  */
91 UINT nx_azure_iot_json_writer_append_property_with_int32_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
92                                                                const UCHAR *property_name, UINT property_name_len,
93                                                                int32_t value);
94 
95 /**
96  * @brief Appends the UTF-8 property name and value where value is double
97  *
98  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
99  * @param[in] property_name The UTF-8 encoded property name of the JSON value to be written. The name is
100  * escaped before writing.
101  * @param[in] property_name_len Length of property_name.
102  * @param[in] value The value to be written as a JSON number.
103  * @param[in] fractional_digits The number of digits of the value to write after the decimal point and truncate the rest.
104  *
105  * @return An `UINT` value indicating the result of the operation.
106  * @retval #NX_AZURE_IOT_SUCCESS The property name and double value was appended successfully.
107  */
108 UINT nx_azure_iot_json_writer_append_property_with_double_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
109                                                                 const UCHAR *property_name, UINT property_name_len,
110                                                                 double value, UINT fractional_digits);
111 
112 /**
113  * @brief Appends the UTF-8 property name and value where value is boolean
114  *
115  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
116  * @param[in] property_name The UTF-8 encoded property name of the JSON value to be written. The name is
117  * escaped before writing.
118  * @param[in] property_name_len Length of property_name.
119  * @param[in] value The value to be written as a JSON literal `true` or `false`.
120  *
121  * @return An `UINT` value indicating the result of the operation.
122  * @retval #NX_AZURE_IOT_SUCCESS The property name and bool value was appended successfully.
123  */
124 UINT nx_azure_iot_json_writer_append_property_with_bool_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
125                                                               const UCHAR *property_name, UINT property_name_len,
126                                                               UINT value);
127 
128 /**
129  * @brief Appends the UTF-8 property name and value where value is string
130  *
131  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
132  * @param[in] property_name The UTF-8 encoded property name of the JSON value to be written. The name is
133  * escaped before writing.
134  * @param[in] property_name_len Length of property_name.
135  * @param[in] value The UTF-8 encoded property name of the JSON value to be written. The name is
136  * escaped before writing.
137  * @param[in] value_len Length of value.
138  *
139  * @return An `UINT` value indicating the result of the operation.
140  * @retval #NX_AZURE_IOT_SUCCESS The property name and string value was appended successfully.
141  */
142 UINT nx_azure_iot_json_writer_append_property_with_string_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
143                                                                 const UCHAR *property_name, UINT property_name_len,
144                                                                 const UCHAR *value, UINT value_len);
145 
146 /**
147  * @brief Returns the length containing the JSON text written to the underlying buffer.
148  *
149  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
150  *
151  * @return An UINT containing the length of JSON text built so far.
152  */
153 UINT nx_azure_iot_json_writer_get_bytes_used(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
154 
155 /**
156  * @brief Appends the UTF-8 text value (as a JSON string) into the buffer.
157  *
158  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
159  * @param[in] value Pointer of UCHAR buffer that contains UTF-8 encoded value to be written as a JSON string.
160  * The value is escaped before writing.
161  * @param[in] value_len Length of value.
162  *
163  * @return An `UINT` value indicating the result of the operation.
164  * @retval #NX_AZURE_IOT_SUCCESS The string value was appended successfully.
165  */
166 UINT nx_azure_iot_json_writer_append_string(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
167                                             const UCHAR *value, UINT value_len);
168 
169 /**
170  * @brief Appends an existing UTF-8 encoded JSON text into the buffer, useful for appending nested
171  * JSON.
172  *
173  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
174  * @param[in] json A pointer to single, possibly nested, valid, UTF-8 encoded, JSON value to be written as
175  * is, without any formatting or spacing changes. No modifications are made to this text, including
176  * escaping.
177  * @param[in] json_len Length of json
178  *
179  * @remarks A single, possibly nested, JSON value is one that starts and ends with {} or [] or is a
180  * single primitive token. The JSON cannot start with an end object or array, or a property name, or
181  * be incomplete.
182  *
183  * @remarks The function validates that the provided JSON to be appended is valid and properly
184  * escaped, and fails otherwise.
185  *
186  * @return An `UINT` value indicating the result of the operation.
187  * @retval #NX_AZURE_IOT_SUCCESS The provided json_text was appended successfully.
188  */
189 UINT nx_azure_iot_json_writer_append_json_text(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
190                                                const UCHAR *json, UINT json_len);
191 
192 /**
193  * @brief Appends the UTF-8 property name (as a JSON string) which is the first part of a name/value
194  * pair of a JSON object.
195  *
196  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
197  * @param[in] value The UTF-8 encoded property name of the JSON value to be written. The name is
198  * escaped before writing.
199  * @param[in] value_len Length of name.
200  *
201  * @return An `UINT` value indicating the result of the operation.
202  * @retval #NX_AZURE_IOT_SUCCESS The property name was appended successfully.
203  */
204 UINT nx_azure_iot_json_writer_append_property_name(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
205                                                    const UCHAR *value, UINT value_len);
206 
207 /**
208  * @brief Appends a boolean value (as a JSON literal `true` or `false`).
209  *
210  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
211  * @param[in] value The value to be written as a JSON literal `true` or `false`.
212  *
213  * @return An `UINT` value indicating the result of the operation.
214  * @retval #NX_AZURE_IOT_SUCCESS The bool was appended successfully.
215  */
216 UINT nx_azure_iot_json_writer_append_bool(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, UINT value);
217 
218 /**
219  * @brief Appends an `int32_t` number value.
220  *
221  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
222  * @param[in] value The value to be written as a JSON number.
223  *
224  * @return An `UINT` value indicating the result of the operation.
225  * @retval #NX_AZURE_IOT_SUCCESS The number was appended successfully.
226  */
227 UINT nx_azure_iot_json_writer_append_int32(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, int32_t value);
228 
229 /**
230  * @brief Appends a `double` number value.
231  *
232  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
233  * @param[in] value The value to be written as a JSON number.
234  * @param[in] fractional_digits The number of digits of the \p value to write after the decimal
235  * point and truncate the rest.
236  *
237  * @return An `UINT` value indicating the result of the operation.
238  * @retval #NX_AZURE_IOT_SUCCESS The number was appended successfully.
239  *
240  * @remark Only finite double values are supported. Values such as `NAN` and `INFINITY` are not
241  * allowed and would lead to invalid JSON being written.
242  *
243  * @remark Non-significant trailing zeros (after the decimal point) are not written, even if \p
244  * fractional_digits is large enough to allow the zero padding.
245  *
246  * @remark The \p fractional_digits must be between 0 and 15 (inclusive). Any value passed in that
247  * is larger will be clamped down to 15.
248  */
249 UINT nx_azure_iot_json_writer_append_double(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
250                                             double value, int32_t fractional_digits);
251 
252 /**
253  * @brief Appends the JSON literal `null`.
254  *
255  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
256  *
257  * @return An `UINT` value indicating the result of the operation.
258  * @retval #NX_AZURE_IOT_SUCCESS `null` was appended successfully.
259  */
260 UINT nx_azure_iot_json_writer_append_null(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
261 
262 /**
263  * @brief Appends the beginning of a JSON object (i.e. `{`).
264  *
265  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
266  *
267  * @return An `UINT` value indicating the result of the operation.
268  * @retval #NX_AZURE_IOT_SUCCESS Object start was appended successfully.
269  */
270 UINT nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
271 
272 /**
273  * @brief Appends the beginning of a JSON array (i.e. `[`).
274  *
275  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
276  *
277  * @return An `UINT` value indicating the result of the operation.
278  * @retval #NX_AZURE_IOT_SUCCESS Array start was appended successfully.
279  */
280 UINT nx_azure_iot_json_writer_append_begin_array(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
281 
282 /**
283  * @brief Appends the end of the current JSON object (i.e. `}`).
284  *
285  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
286  *
287  * @return An `UINT` value indicating the result of the operation.
288  * @retval #NX_AZURE_IOT_SUCCESS Object end was appended successfully.
289  */
290 UINT nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
291 
292 /**
293  * @brief Appends the end of the current JSON array (i.e. `]`).
294  *
295  * @param[in] json_writer_ptr A pointer to an #NX_AZURE_IOT_JSON_WRITER.
296  *
297  * @return An `UINT` value indicating the result of the operation.
298  * @retval #NX_AZURE_IOT_SUCCESS Array end was appended successfully.
299  */
300 UINT nx_azure_iot_json_writer_append_end_array(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr);
301 
302 #ifdef __cplusplus
303 }
304 #endif
305 #endif /* NX_AZURE_IOT_JSON_WRITER_H */
306