Callisto4Bootloader: ARK/platform_encoder_json.c Source File

Callisto4Bootloader

platform_encoder_json.c
Go to the documentation of this file.
1 /*
2 * platform_json_encoder.c
3 *
4 * Created on: 27 Jul 2020
5 * Author: Nick Pelling
6 */
7
8 #include <stdio.h> // for snprintf() & sscanf()
9 #include <ctype.h> // for isspace()
10 #include <string.h> // for memcmp()
11
12 #include "platform_encoder.h"
13
20 static void OutputCharacter(stPayloadBuffer_t * pstPayload, uint8_t u8Character)
21 {
22 if (pstPayload->uiBufferLen < pstPayload->uiBufferSize)
23 {
24 pstPayload->pau8Buffer[pstPayload->uiBufferLen++] = u8Character;
25 }
26 }
27
33 static void EncodeStructStart(stPayloadBuffer_t * pstPayload)
34 {
35 OutputCharacter(pstPayload, '{');
36 }
37
43 static void EncodeStructEnd(stPayloadBuffer_t * pstPayload)
44 {
45 OutputCharacter(pstPayload, '}');
46 }
47
53 static void EncodeArrayStart(stPayloadBuffer_t * pstPayload)
54 {
55 OutputCharacter(pstPayload, '[');
56 }
57
63 static void EncodeArraySeparator(stPayloadBuffer_t * pstPayload)
64 {
65 OutputCharacter(pstPayload, ',');
66 }
67
73 static void EncodeArrayEnd(stPayloadBuffer_t * pstPayload)
74 {
75 OutputCharacter(pstPayload, ']');
76 }
77
84 static void EncodeFieldName(stPayloadBuffer_t * pstPayload, const uint8_t * pau8FieldName)
85 {
86 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
87 "\"%s\":", (const char *) pau8FieldName);
88 }
89
95 static void EncodeFieldSeparator(stPayloadBuffer_t * pstPayload)
96 {
97 OutputCharacter(pstPayload, ',');
98 }
99
106 static void EncodeBoolean(stPayloadBuffer_t * pstPayload, bool bValue)
107 {
108 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
109 bValue ? "true" : "false" );
110 }
111
118 static void EncodeReal(stPayloadBuffer_t * pstPayload, double dValue)
119 {
120 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
121 "%f", (double) dValue);
122 }
123
130 static void EncodeUnsignedInt(stPayloadBuffer_t * pstPayload, uint64_t ui64Value)
131 {
132 // JSON expects all numbers to be transported as doubles, so we cannot guarantee
133 // that numbers greater than 2^53 will be transported intact (i.e. without
134 // losing one or more of their LSBs). But the plan here is to migrate to CBOR,
135 // which has no such restrictions!
136 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
137 "%llu", ui64Value);
138 }
139
146 static void EncodeSignedInt(stPayloadBuffer_t * pstPayload, int64_t i64Value)
147 {
148 // JSON expects all numbers to be transported as doubles, so we cannot guarantee
149 // that numbers greater than 2^53 will be transported intact (i.e. without
150 // losing one or more of their LSBs). But the plan here is to migrate to CBOR,
151 // which has no such restrictions!
152 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
153 "%lld", i64Value);
154 }
155
162 static void EncodeString(stPayloadBuffer_t * pstPayload, const uint8_t * pau8String)
163 {
164 pstPayload->uiBufferLen += snprintf((char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], pstPayload->uiBufferSize - pstPayload->uiBufferLen,
165 "\"%s\"", (const char *) pau8String );
166 }
167
176 static bool SnoopNextCharacter(stPayloadBuffer_t * pstPayload, uint8_t *pu8Next)
177 {
178 bool bRetVal;
179
180 bRetVal = false;
181 if (pstPayload->uiBufferLen < pstPayload->uiBufferSize)
182 {
183 *pu8Next = pstPayload->pau8Buffer[pstPayload->uiBufferLen];
184 bRetVal = true;
185 }
186
187 return bRetVal;
188 }
189
197 static uint32_t PayloadRemaining(stPayloadBuffer_t * pstPayload)
198 {
199 return pstPayload->uiBufferSize - pstPayload->uiBufferLen;
200 }
201
207 static void IgnoreWhitespace(stPayloadBuffer_t * pstPayload)
208 {
209 uint8_t u8Next;
210 for (;;)
211 {
212 // If the payload has no more characters left, break out of this loop
213 if (SnoopNextCharacter(pstPayload, &u8Next) == false)
214 break;
215
216 // If the next character along is not whitespace, break out of this loop
217 if (!isspace((char) u8Next))
218 break;
219
220 // Advance the buffer pointer on by one
221 pstPayload->uiBufferLen++;
222 }
223 }
224
231 static bool ExpectCharacter(stPayloadBuffer_t * pstPayload, uint8_t u8CharacterExpected)
232 {
233 uint8_t u8Next;
234 bool bRetVal = false;
235
236 IgnoreWhitespace(pstPayload);
237 if (SnoopNextCharacter(pstPayload, &u8Next) == true)
238 {
239 if (u8Next == u8CharacterExpected)
240 {
241 pstPayload->uiBufferLen++;
242 bRetVal = true;
243 }
244 }
245
246 return bRetVal;
247 }
248
256 static bool DecodeStructStart(stPayloadBuffer_t * pstPayload)
257 {
258 return ExpectCharacter(pstPayload, '{');
259 }
260
268 static bool DecodeStructEnd(stPayloadBuffer_t * pstPayload)
269 {
270 return ExpectCharacter(pstPayload, '}');
271 }
272
280 static bool DecodeArrayStart(stPayloadBuffer_t * pstPayload)
281 {
282 return ExpectCharacter(pstPayload, '[');
283 }
284
292 static bool DecodeArraySeparator(stPayloadBuffer_t * pstPayload)
293 {
294 return ExpectCharacter(pstPayload, ',');
295 }
296
304 static bool DecodeArrayEnd(stPayloadBuffer_t * pstPayload)
305 {
306 return ExpectCharacter(pstPayload, ']');
307 }
308
316 static bool DecodeString(stPayloadBuffer_t * pstPayload, const uint8_t ** ppau8String, uint32_t *puiStringLength)
317 {
318 uint8_t u8Next;
319 bool bRetVal = false;
320
321 IgnoreWhitespace(pstPayload);
322 if (ExpectCharacter(pstPayload, '\"') == true)
323 {
324 *ppau8String = &pstPayload->pau8Buffer[pstPayload->uiBufferLen];
325 for (;;)
326 {
327 if (SnoopNextCharacter(pstPayload, &u8Next) == false)
328 {
329 break;
330 }
331 if (u8Next == '\"')
332 {
333 *puiStringLength = (uint32_t)( &pstPayload->pau8Buffer[pstPayload->uiBufferLen] - *ppau8String);
334 pstPayload->uiBufferLen++;
335 bRetVal = true;
336 break;
337 }
338 pstPayload->uiBufferLen++;
339 }
340 }
341 return bRetVal; // FIXME
342 }
343
353 static bool DecodeFieldName(stPayloadBuffer_t * pstPayload, const uint8_t ** pau8FieldName, uint32_t * puiNameLength)
354 {
355 // If there are no field names before the next closing struct, return a field name length of zero
356 if (ExpectCharacter(pstPayload, '}') == true)
357 {
358 *puiNameLength = 0;
359 return true;
360 }
361
362 // If we find a string match
363 if ( (DecodeString(pstPayload, pau8FieldName, puiNameLength))
364 && (ExpectCharacter(pstPayload, ':')) )
365 {
366 // Allowing a field name of "" would be problematic, so return false if that happens
367 return (*puiNameLength != 0);
368 }
369
370 // We didn't find the "label": field string pattern we were expecting, so return a failure code
371 return false;
372 }
373
381 static bool DecodeFieldSeparator(stPayloadBuffer_t * pstPayload)
382 {
383 return ExpectCharacter(pstPayload, ',');
384 }
385
394 static bool DecodeBoolean(stPayloadBuffer_t * pstPayload, bool * pbValue)
395 {
396 uint32_t uiRemaining;
397 bool bRetVal = false;
398
399 uiRemaining = PayloadRemaining(pstPayload);
400 if ((uiRemaining >= 4U) && memcmp(&pstPayload->pau8Buffer[pstPayload->uiBufferLen], "true", 4U) == 0)
401 {
402 pstPayload->uiBufferLen += 4U;
403 *pbValue = true;
404 bRetVal = true;
405 }
406 else
407 {
408 if ((uiRemaining >= 5U) && memcmp(&pstPayload->pau8Buffer[pstPayload->uiBufferLen], "false", 5U) == 0)
409 {
410 pstPayload->uiBufferLen += 5U;
411 *pbValue = false;
412 bRetVal = true;
413 }
414 }
415
416 return bRetVal;
417 }
418
427 static bool DecodeUnsignedInt(stPayloadBuffer_t * pstPayload, uint64_t * pui64Value)
428 {
429 uint32_t uiRemaining;
430 int iNumArgsRead;
431 int iNumCharactersRead;
432 bool bRetVal = false;
433 double d;
434
435 iNumArgsRead = sscanf((const char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], "%lf%n", &d, &iNumCharactersRead );
436 if ( iNumArgsRead >= 1 )
437 {
438 uiRemaining = PayloadRemaining(pstPayload);
439 if (iNumCharactersRead <= uiRemaining)
440 {
441 if (d >= -0.0)
442 {
443 *pui64Value = (uint64_t) d;
444 pstPayload->uiBufferLen += iNumCharactersRead;
445 bRetVal = true;
446 }
447 }
448 }
449
450 return bRetVal;
451 }
452
461 static bool DecodeSignedInt(stPayloadBuffer_t * pstPayload, int64_t * pi64Value)
462 {
463 uint32_t uiRemaining;
464 int iNumArgsRead;
465 int iNumCharactersRead;
466 bool bRetVal = false;
467 double d;
468
469 iNumArgsRead = sscanf((const char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], "%lf%n", &d, &iNumCharactersRead );
470 if ( iNumArgsRead >= 1 )
471 {
472 uiRemaining = PayloadRemaining(pstPayload);
473 if (iNumCharactersRead <= uiRemaining)
474 {
475 *pi64Value = (int64_t) d;
476 pstPayload->uiBufferLen += iNumCharactersRead;
477 bRetVal = true;
478 }
479 }
480
481 return bRetVal;
482
483 }
484
493 static bool DecodeReal(stPayloadBuffer_t * pstPayload, double * pdValue)
494 {
495 uint32_t uiRemaining;
496 int iNumArgsRead;
497 int iNumCharactersRead;
498 bool bRetVal = false;
499 double d;
500
501 iNumArgsRead = sscanf((const char *)&pstPayload->pau8Buffer[pstPayload->uiBufferLen], "%lf%n", &d, &iNumCharactersRead );
502 if ( iNumArgsRead >= 1 )
503 {
504 uiRemaining = PayloadRemaining(pstPayload);
505 if (iNumCharactersRead <= uiRemaining)
506 {
507 *pdValue = d;
508 pstPayload->uiBufferLen += iNumCharactersRead;
509 bRetVal = true;
510 }
511 }
512
513 return bRetVal;
514 }
515
516 const stPayloadEncoder_t stJSONEncoder =
517 {
518 // JSON Encoder virtual function implementations
519 .pfn_EncodeStructStart = EncodeStructStart,
520 .pfn_EncodeStructEnd = EncodeStructEnd,
521 .pfn_EncodeArrayStart = EncodeArrayStart,
522 .pfn_EncodeArraySeparator = EncodeArraySeparator,
523 .pfn_EncodeArrayEnd = EncodeArrayEnd,
524 .pfn_EncodeFieldName = EncodeFieldName,
525 .pfn_EncodeFieldSeparator = EncodeFieldSeparator,
526 .pfn_EncodeBoolean = EncodeBoolean,
527 .pfn_EncodeSignedInt = EncodeSignedInt,
528 .pfn_EncodeUnsignedInt = EncodeUnsignedInt,
529 .pfn_EncodeReal = EncodeReal,
530 .pfn_EncodeString = EncodeString
531 };
532
533 const stPayloadDecoder_t stJSONDecoder =
534 {
535 // JSON Decoder virtual function implementations
536 .pfn_DecodeStructStart = DecodeStructStart,
537 .pfn_DecodeStructEnd = DecodeStructEnd,
538 .pfn_DecodeArrayStart = DecodeArrayStart,
539 .pfn_DecodeArraySeparator = DecodeArraySeparator,
540 .pfn_DecodeArrayEnd = DecodeArrayEnd,
541 .pfn_DecodeFieldName = DecodeFieldName,
542 .pfn_DecodeFieldSeparator = DecodeFieldSeparator,
543 .pfn_DecodeBoolean = DecodeBoolean,
544 .pfn_DecodeSignedInt = DecodeSignedInt,
545 .pfn_DecodeUnsignedInt = DecodeUnsignedInt,
546 .pfn_DecodeReal = DecodeReal,
547 .pfn_DecodeString = DecodeString
548 };
stPayloadBuffer_t::uiBufferLen
uint32_t uiBufferLen
Definition: platform_encoder.h:23
EncodeBoolean
static void EncodeBoolean(stPayloadBuffer_t *pstPayload, bool bValue)
Definition: platform_encoder_json.c:106
DecodeReal
static bool DecodeReal(stPayloadBuffer_t *pstPayload, double *pdValue)
Definition: platform_encoder_json.c:493
ExpectCharacter
static bool ExpectCharacter(stPayloadBuffer_t *pstPayload, uint8_t u8CharacterExpected)
Definition: platform_encoder_json.c:231
EncodeReal
static void EncodeReal(stPayloadBuffer_t *pstPayload, double dValue)
Definition: platform_encoder_json.c:118
IgnoreWhitespace
static void IgnoreWhitespace(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:207
stPayloadBuffer_t
Definition: platform_encoder.h:20
EncodeArrayStart
static void EncodeArrayStart(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:53
DecodeBoolean
static bool DecodeBoolean(stPayloadBuffer_t *pstPayload, bool *pbValue)
Definition: platform_encoder_json.c:394
DecodeSignedInt
static bool DecodeSignedInt(stPayloadBuffer_t *pstPayload, int64_t *pi64Value)
Definition: platform_encoder_json.c:461
EncodeStructStart
static void EncodeStructStart(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:33
DecodeArrayStart
static bool DecodeArrayStart(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:280
DecodeString
static bool DecodeString(stPayloadBuffer_t *pstPayload, const uint8_t **ppau8String, uint32_t *puiStringLength)
Definition: platform_encoder_json.c:316
PayloadRemaining
static uint32_t PayloadRemaining(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:197
DecodeFieldName
static bool DecodeFieldName(stPayloadBuffer_t *pstPayload, const uint8_t **pau8FieldName, uint32_t *puiNameLength)
Definition: platform_encoder_json.c:353
EncodeString
static void EncodeString(stPayloadBuffer_t *pstPayload, const uint8_t *pau8String)
Definition: platform_encoder_json.c:162
EncodeStructEnd
static void EncodeStructEnd(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:43
DecodeArrayEnd
static bool DecodeArrayEnd(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:304
EncodeSignedInt
static void EncodeSignedInt(stPayloadBuffer_t *pstPayload, int64_t i64Value)
Definition: platform_encoder_json.c:146
EncodeArraySeparator
static void EncodeArraySeparator(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:63
EncodeFieldSeparator
static void EncodeFieldSeparator(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:95
stJSONEncoder
const stPayloadEncoder_t stJSONEncoder
Definition: platform_encoder_json.c:516
platform_encoder.h
stJSONDecoder
const stPayloadDecoder_t stJSONDecoder
Definition: platform_encoder_json.c:533
EncodeUnsignedInt
static void EncodeUnsignedInt(stPayloadBuffer_t *pstPayload, uint64_t ui64Value)
Definition: platform_encoder_json.c:130
SnoopNextCharacter
static bool SnoopNextCharacter(stPayloadBuffer_t *pstPayload, uint8_t *pu8Next)
Definition: platform_encoder_json.c:176
DecodeArraySeparator
static bool DecodeArraySeparator(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:292
DecodeStructEnd
static bool DecodeStructEnd(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:268
stPayloadBuffer_t::pau8Buffer
uint8_t * pau8Buffer
Definition: platform_encoder.h:22
stPayloadBuffer_t::uiBufferSize
uint32_t uiBufferSize
Definition: platform_encoder.h:24
DecodeUnsignedInt
static bool DecodeUnsignedInt(stPayloadBuffer_t *pstPayload, uint64_t *pui64Value)
Definition: platform_encoder_json.c:427
DecodeFieldSeparator
static bool DecodeFieldSeparator(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:381
stPayloadDecoder_t::pfn_DecodeStructStart
bool(* pfn_DecodeStructStart)(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder.h:52
stPayloadEncoder_t::pfn_EncodeStructStart
void(* pfn_EncodeStructStart)(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder.h:35
DecodeStructStart
static bool DecodeStructStart(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:256
stPayloadDecoder_t
Definition: platform_encoder.h:49
stPayloadEncoder_t
Definition: platform_encoder.h:32
EncodeArrayEnd
static void EncodeArrayEnd(stPayloadBuffer_t *pstPayload)
Definition: platform_encoder_json.c:73
OutputCharacter
static void OutputCharacter(stPayloadBuffer_t *pstPayload, uint8_t u8Character)
Definition: platform_encoder_json.c:20
EncodeFieldName
static void EncodeFieldName(stPayloadBuffer_t *pstPayload, const uint8_t *pau8FieldName)
Definition: platform_encoder_json.c:84