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 #include "nx_azure_iot_json_writer.h"
12 
13 #include "nx_azure_iot.h"
14 
nx_azure_iot_json_wirter_packet_allocator_cb(az_span_allocator_context * allocator_context,az_span * out_next_destination)15 static az_result nx_azure_iot_json_wirter_packet_allocator_cb(az_span_allocator_context* allocator_context,
16                                                               az_span* out_next_destination)
17 {
18 NX_AZURE_IOT_JSON_WRITER *writer_ptr = (NX_AZURE_IOT_JSON_WRITER *)allocator_context -> user_context;
19 NX_PACKET *packet_ptr = writer_ptr -> packet_ptr;
20 NX_PACKET *new_paket_ptr;
21 NX_PACKET *tail_packet_ptr;
22 
23     /* Allocate a new packet.  */
24     if (nx_packet_allocate(packet_ptr -> nx_packet_pool_owner,
25                            &new_paket_ptr, 0, writer_ptr -> wait_option))
26     {
27         return(AZ_ERROR_OUT_OF_MEMORY);
28     }
29 
30     if (allocator_context -> minimum_required_size > (INT)(new_paket_ptr -> nx_packet_data_end -
31                                                            new_paket_ptr -> nx_packet_data_start))
32     {
33         nx_packet_release(new_paket_ptr);
34         return(AZ_ERROR_OUT_OF_MEMORY);
35     }
36 
37     if (packet_ptr -> nx_packet_last)
38     {
39         tail_packet_ptr = packet_ptr -> nx_packet_last;
40     }
41     else
42     {
43         tail_packet_ptr = packet_ptr;
44     }
45 
46     NX_ASSERT((tail_packet_ptr -> nx_packet_data_start + writer_ptr -> nx_tail_packet_offset +
47                (ULONG)(allocator_context -> bytes_used)) <=
48               tail_packet_ptr -> nx_packet_data_end);
49 
50     /* Update tail.  */
51     tail_packet_ptr -> nx_packet_append_ptr =
52         tail_packet_ptr -> nx_packet_data_start + writer_ptr -> nx_tail_packet_offset +
53         (ULONG)(allocator_context -> bytes_used);
54     tail_packet_ptr -> nx_packet_next = new_paket_ptr;
55 
56     /* Update head.  */
57     packet_ptr -> nx_packet_length += (ULONG)(allocator_context -> bytes_used);
58     packet_ptr -> nx_packet_last = new_paket_ptr;
59 
60     writer_ptr -> nx_tail_packet_offset = 0;
61 
62     *out_next_destination = az_span_create(new_paket_ptr -> nx_packet_data_start,
63                                            (INT)(new_paket_ptr -> nx_packet_data_end -
64                                                  new_paket_ptr -> nx_packet_data_start));
65 
66     return(AZ_OK);
67 }
68 
nx_azure_iot_json_writer_packet_update(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)69 static VOID nx_azure_iot_json_writer_packet_update(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
70 {
71 NX_PACKET *tail_packet_ptr;
72 UINT last_chunk_size =
73     (UINT)az_span_size(az_json_writer_get_bytes_used_in_destination(&(json_writer_ptr -> json_writer)));
74 
75     if (json_writer_ptr -> packet_ptr == NX_NULL)
76     {
77         return;
78     }
79 
80     if (json_writer_ptr -> packet_ptr -> nx_packet_last)
81     {
82         tail_packet_ptr = json_writer_ptr -> packet_ptr -> nx_packet_last;
83     }
84     else
85     {
86         tail_packet_ptr = json_writer_ptr -> packet_ptr;
87     }
88 
89     NX_ASSERT((tail_packet_ptr -> nx_packet_data_start + json_writer_ptr -> nx_tail_packet_offset +
90                last_chunk_size) <= tail_packet_ptr -> nx_packet_data_end);
91 
92     tail_packet_ptr -> nx_packet_append_ptr =
93         tail_packet_ptr -> nx_packet_data_start + json_writer_ptr -> nx_tail_packet_offset + last_chunk_size;
94     json_writer_ptr -> packet_ptr -> nx_packet_length =
95         json_writer_ptr -> nx_packet_init_length + (UINT)json_writer_ptr -> json_writer.total_bytes_written;
96 }
97 
nx_azure_iot_json_writer_init(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,NX_PACKET * packet_ptr,UINT wait_option)98 UINT nx_azure_iot_json_writer_init(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
99                                    NX_PACKET *packet_ptr, UINT wait_option)
100 {
101 az_span span;
102 NX_PACKET *tail_packet_ptr;
103 
104     if ((json_writer_ptr == NX_NULL) ||
105         (packet_ptr == NX_NULL))
106     {
107         LogError(LogLiteralArgs("Json writer init fail: INVALID POINTER"));
108         return(NX_AZURE_IOT_INVALID_PARAMETER);
109     }
110 
111     memset((VOID *)json_writer_ptr, 0, sizeof(NX_AZURE_IOT_JSON_WRITER));
112 
113     if (packet_ptr -> nx_packet_last)
114     {
115         tail_packet_ptr = packet_ptr -> nx_packet_last;
116     }
117     else
118     {
119         tail_packet_ptr = packet_ptr;
120     }
121 
122     span = az_span_create(tail_packet_ptr -> nx_packet_append_ptr,
123                           (INT)(tail_packet_ptr -> nx_packet_data_end - tail_packet_ptr -> nx_packet_append_ptr));
124 
125     if (az_result_failed(az_json_writer_chunked_init(&(json_writer_ptr -> json_writer), span,
126                                                      nx_azure_iot_json_wirter_packet_allocator_cb,
127                                                      (VOID *)json_writer_ptr, NX_NULL)))
128     {
129         LogError(LogLiteralArgs("Json writer failed to init chunked writer"));
130         return(NX_AZURE_IOT_SDK_CORE_ERROR);
131     }
132 
133     json_writer_ptr -> packet_ptr = packet_ptr;
134     json_writer_ptr -> wait_option = wait_option;
135     json_writer_ptr -> nx_tail_packet_offset =
136         (ULONG)(tail_packet_ptr -> nx_packet_append_ptr - tail_packet_ptr -> nx_packet_data_start);
137     json_writer_ptr -> nx_packet_init_length = packet_ptr -> nx_packet_length;
138 
139     return(NX_AZURE_IOT_SUCCESS);
140 }
141 
nx_azure_iot_json_writer_with_buffer_init(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,UCHAR * buffer_ptr,UINT buffer_len)142 UINT nx_azure_iot_json_writer_with_buffer_init(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
143                                                UCHAR *buffer_ptr, UINT buffer_len)
144 {
145 az_span span;
146 
147     if ((json_writer_ptr == NX_NULL) ||
148         (buffer_ptr == NX_NULL))
149     {
150         LogError(LogLiteralArgs("Json writer init fail: INVALID POINTER"));
151         return(NX_AZURE_IOT_INVALID_PARAMETER);
152     }
153 
154     memset((VOID *)json_writer_ptr, 0, sizeof(NX_AZURE_IOT_JSON_WRITER));
155 
156     span = az_span_create(buffer_ptr, (INT)(buffer_len));
157 
158     if (az_result_failed(az_json_writer_init(&(json_writer_ptr -> json_writer), span, NX_NULL)))
159     {
160         LogError(LogLiteralArgs("Json writer failed to init writer"));
161         return(NX_AZURE_IOT_SDK_CORE_ERROR);
162     }
163 
164     return(NX_AZURE_IOT_SUCCESS);
165 }
166 
nx_azure_iot_json_writer_deinit(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)167 UINT nx_azure_iot_json_writer_deinit(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
168 {
169     if (json_writer_ptr == NX_NULL)
170     {
171         LogError(LogLiteralArgs("Json writer deinit fail: INVALID POINTER"));
172         return(NX_AZURE_IOT_INVALID_PARAMETER);
173     }
174 
175     if (json_writer_ptr -> packet_ptr)
176     {
177         json_writer_ptr -> packet_ptr = NX_NULL;
178     }
179 
180     return(NX_AZURE_IOT_SUCCESS);
181 }
182 
nx_azure_iot_json_writer_get_bytes_used(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)183 UINT nx_azure_iot_json_writer_get_bytes_used(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
184 {
185     if (json_writer_ptr == NX_NULL)
186     {
187         LogError(LogLiteralArgs("Json writer get bytes used fail: INVALID POINTER"));
188         return(NX_AZURE_IOT_INVALID_PARAMETER);
189     }
190 
191     return((UINT)json_writer_ptr -> json_writer.total_bytes_written);
192 }
193 
nx_azure_iot_json_writer_append_string(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * value,UINT value_len)194 UINT nx_azure_iot_json_writer_append_string(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
195                                             const UCHAR *value, UINT value_len)
196 {
197 az_span span = az_span_create((UCHAR *)value, (INT)value_len);
198 
199     if (json_writer_ptr == NX_NULL)
200     {
201         LogError(LogLiteralArgs("Json writer append string fail: INVALID POINTER"));
202         return(NX_AZURE_IOT_INVALID_PARAMETER);
203     }
204 
205     if (az_result_failed(az_json_writer_append_string(&(json_writer_ptr -> json_writer), span)))
206     {
207         return(NX_AZURE_IOT_SDK_CORE_ERROR);
208     }
209 
210     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
211 
212     return(NX_AZURE_IOT_SUCCESS);
213 }
214 
nx_azure_iot_json_writer_append_json_text(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * json,UINT json_len)215 UINT nx_azure_iot_json_writer_append_json_text(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
216                                                const UCHAR *json, UINT json_len)
217 {
218 az_span span = az_span_create((UCHAR *)json, (INT)json_len);
219 
220     if (json_writer_ptr == NX_NULL)
221     {
222         LogError(LogLiteralArgs("Json writer append text fail: INVALID POINTER"));
223         return(NX_AZURE_IOT_INVALID_PARAMETER);
224     }
225 
226     if (az_result_failed(az_json_writer_append_json_text(&(json_writer_ptr -> json_writer), span)))
227     {
228         return(NX_AZURE_IOT_SDK_CORE_ERROR);
229     }
230 
231     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
232 
233     return(NX_AZURE_IOT_SUCCESS);
234 }
235 
nx_azure_iot_json_writer_append_property_name(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * value,UINT value_len)236 UINT nx_azure_iot_json_writer_append_property_name(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
237                                                    const UCHAR *value, UINT value_len)
238 {
239 az_span span = az_span_create((UCHAR *)value, (INT)value_len);
240 
241     if (json_writer_ptr == NX_NULL)
242     {
243         LogError(LogLiteralArgs("Json writer append property name fail: INVALID POINTER"));
244         return(NX_AZURE_IOT_INVALID_PARAMETER);
245     }
246 
247     if (az_result_failed(az_json_writer_append_property_name(&(json_writer_ptr -> json_writer), span)))
248     {
249         return(NX_AZURE_IOT_SDK_CORE_ERROR);
250     }
251 
252     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
253 
254     return(NX_AZURE_IOT_SUCCESS);
255 }
256 
nx_azure_iot_json_writer_append_bool(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,UINT value)257 UINT nx_azure_iot_json_writer_append_bool(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, UINT value)
258 {
259     if (json_writer_ptr == NX_NULL)
260     {
261         LogError(LogLiteralArgs("Json writer append bool fail: INVALID POINTER"));
262         return(NX_AZURE_IOT_INVALID_PARAMETER);
263     }
264 
265     if (az_result_failed(az_json_writer_append_bool(&(json_writer_ptr -> json_writer), value)))
266     {
267         return(NX_AZURE_IOT_SDK_CORE_ERROR);
268     }
269 
270     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
271 
272     return(NX_AZURE_IOT_SUCCESS);
273 }
274 
nx_azure_iot_json_writer_append_int32(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,int32_t value)275 UINT nx_azure_iot_json_writer_append_int32(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, int32_t value)
276 {
277     if (json_writer_ptr == NX_NULL)
278     {
279         LogError(LogLiteralArgs("Json writer append int32 fail: INVALID POINTER"));
280         return(NX_AZURE_IOT_INVALID_PARAMETER);
281     }
282 
283     if (az_result_failed(az_json_writer_append_int32(&(json_writer_ptr -> json_writer), value)))
284     {
285         return(NX_AZURE_IOT_SDK_CORE_ERROR);
286     }
287 
288     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
289 
290     return(NX_AZURE_IOT_SUCCESS);
291 }
292 
nx_azure_iot_json_writer_append_double(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,double value,int32_t fractional_digits)293 UINT nx_azure_iot_json_writer_append_double(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
294                                             double value, int32_t fractional_digits)
295 {
296     if (json_writer_ptr == NX_NULL)
297     {
298         LogError(LogLiteralArgs("Json writer append double fail: INVALID POINTER"));
299         return(NX_AZURE_IOT_INVALID_PARAMETER);
300     }
301 
302     if (az_result_failed(az_json_writer_append_double(&(json_writer_ptr -> json_writer), value, fractional_digits)))
303     {
304         return(NX_AZURE_IOT_SDK_CORE_ERROR);
305     }
306 
307     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
308 
309     return(NX_AZURE_IOT_SUCCESS);
310 }
311 
nx_azure_iot_json_writer_append_null(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)312 UINT nx_azure_iot_json_writer_append_null(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
313 {
314     if (json_writer_ptr == NX_NULL)
315     {
316         LogError(LogLiteralArgs("Json writer append null fail: INVALID POINTER"));
317         return(NX_AZURE_IOT_INVALID_PARAMETER);
318     }
319 
320     if (az_result_failed(az_json_writer_append_null(&(json_writer_ptr -> json_writer))))
321     {
322         return(NX_AZURE_IOT_SDK_CORE_ERROR);
323     }
324 
325     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
326 
327     return(NX_AZURE_IOT_SUCCESS);
328 }
329 
nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)330 UINT nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
331 {
332     if (json_writer_ptr == NX_NULL)
333     {
334         LogError(LogLiteralArgs("Json writer append begin object fail: INVALID POINTER"));
335         return(NX_AZURE_IOT_INVALID_PARAMETER);
336     }
337 
338     if (az_result_failed(az_json_writer_append_begin_object(&(json_writer_ptr -> json_writer))))
339     {
340         return(NX_AZURE_IOT_SDK_CORE_ERROR);
341     }
342 
343     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
344 
345     return(NX_AZURE_IOT_SUCCESS);
346 }
347 
nx_azure_iot_json_writer_append_begin_array(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)348 UINT nx_azure_iot_json_writer_append_begin_array(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
349 {
350     if (json_writer_ptr == NX_NULL)
351     {
352         LogError(LogLiteralArgs("Json writer append begin array fail: INVALID POINTER"));
353         return(NX_AZURE_IOT_INVALID_PARAMETER);
354     }
355 
356     if (az_result_failed(az_json_writer_append_begin_array(&(json_writer_ptr -> json_writer))))
357     {
358         return(NX_AZURE_IOT_SDK_CORE_ERROR);
359     }
360 
361     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
362 
363     return(NX_AZURE_IOT_SUCCESS);
364 }
365 
nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)366 UINT nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
367 {
368     if (json_writer_ptr == NX_NULL)
369     {
370         LogError(LogLiteralArgs("Json writer append end object fail: INVALID POINTER"));
371         return(NX_AZURE_IOT_INVALID_PARAMETER);
372     }
373 
374     if (az_result_failed(az_json_writer_append_end_object(&(json_writer_ptr -> json_writer))))
375     {
376         return(NX_AZURE_IOT_SDK_CORE_ERROR);
377     }
378 
379     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
380 
381     return(NX_AZURE_IOT_SUCCESS);
382 }
383 
nx_azure_iot_json_writer_append_end_array(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr)384 UINT nx_azure_iot_json_writer_append_end_array(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr)
385 {
386     if (json_writer_ptr == NX_NULL)
387     {
388         LogError(LogLiteralArgs("Json writer append end array fail: INVALID POINTER"));
389         return(NX_AZURE_IOT_INVALID_PARAMETER);
390     }
391 
392     if (az_result_failed(az_json_writer_append_end_array(&(json_writer_ptr -> json_writer))))
393     {
394         return(NX_AZURE_IOT_SDK_CORE_ERROR);
395     }
396 
397     nx_azure_iot_json_writer_packet_update(json_writer_ptr);
398 
399     return(NX_AZURE_IOT_SUCCESS);
400 }
401 
nx_azure_iot_json_writer_append_property_with_int32_value(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * property_name,UINT property_name_len,int32_t value)402 UINT nx_azure_iot_json_writer_append_property_with_int32_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
403                                                                const UCHAR *property_name, UINT property_name_len,
404                                                                int32_t value)
405 {
406     return ((UINT)(nx_azure_iot_json_writer_append_property_name(json_writer_ptr, property_name, property_name_len) ||
407                    nx_azure_iot_json_writer_append_int32(json_writer_ptr, value)));
408 }
409 
nx_azure_iot_json_writer_append_property_with_double_value(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * property_name,UINT property_name_len,double value,UINT fractional_digits)410 UINT nx_azure_iot_json_writer_append_property_with_double_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
411                                                                 const UCHAR *property_name, UINT property_name_len,
412                                                                 double value, UINT fractional_digits)
413 {
414     return ((UINT)(nx_azure_iot_json_writer_append_property_name(json_writer_ptr, property_name, property_name_len) ||
415                    nx_azure_iot_json_writer_append_double(json_writer_ptr, value, (int32_t)fractional_digits)));
416 }
417 
nx_azure_iot_json_writer_append_property_with_bool_value(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * property_name,UINT property_name_len,UINT value)418 UINT nx_azure_iot_json_writer_append_property_with_bool_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
419                                                               const UCHAR *property_name, UINT property_name_len,
420                                                               UINT value)
421 {
422     return ((UINT)(nx_azure_iot_json_writer_append_property_name(json_writer_ptr, property_name, property_name_len) ||
423                    nx_azure_iot_json_writer_append_bool(json_writer_ptr, value)));
424 }
425 
nx_azure_iot_json_writer_append_property_with_string_value(NX_AZURE_IOT_JSON_WRITER * json_writer_ptr,const UCHAR * property_name,UINT property_name_len,const UCHAR * value,UINT value_len)426 UINT nx_azure_iot_json_writer_append_property_with_string_value(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr,
427                                                                 const UCHAR *property_name, UINT property_name_len,
428                                                                 const UCHAR *value, UINT value_len)
429 {
430     return ((UINT)(nx_azure_iot_json_writer_append_property_name(json_writer_ptr, property_name, property_name_len) ||
431                    nx_azure_iot_json_writer_append_string(json_writer_ptr, value, value_len)));
432 }
433