le_pack.h

1 /**
2  * @page c_pack Low-level Pack/Unpack API
3  *
4  * @ref le_pack.h "API Reference"
5  *
6  * <HR>
7  *
8  * This low-level pack/unpack API is intended to support the higher level
9  * IPC messaging system, specifically code generated by ifgen. But it
10  * can also be used to hand-pack messages if using the @ref c_messaging
11  * API directly.
12  *
13  * This low-level pack/unpack API supports:
14  * - Packing basic types supported by the IPC system.
15  * - Packing reference types
16  * - Packing arrays of the above types
17  * - Packing strings.
18  * It also supports unpacking any of the above.
19  */
20 
21 #ifndef LE_PACK_H_INCLUDE_GUARD
22 #define LE_PACK_H_INCLUDE_GUARD
23 
24 
25 // with ARM RVCT the max size of UINTPTR_MAX is signed.
26 #if UINT32_MAX == UINTPTR_MAX || INT32_MAX == UINTPTR_MAX
27 # define IFGEN_PTR32 1
28 #elif UINT64_MAX == UINTPTR_MAX || INT64_MAX == UINTPTR_MAX
29 # define IFGEN_PTR64 1
30 #else
31 # error "Unsupported pointer size -- only 32- and 64-bit are supported for local services."
32 #endif
33 
34 //--------------------------------------------------------------------------------------------------
35 /**
36  * Pack Definitions and Types
37  */
38 //--------------------------------------------------------------------------------------------------
39 
40 //semantic tag type:
41 typedef uint16_t le_pack_SemanticTag_t;
42 
43 // le_pack type:
44 typedef enum le_pack_Type
45 {
46  LE_PACK_TYPE_POS_INTEGER = 0,
47  LE_PACK_TYPE_NEG_INTEGER = 1,
48  LE_PACK_TYPE_BYTE_STRING = 2,
49  LE_PACK_TYPE_TEXT_STRING = 3,
50  LE_PACK_TYPE_ITEM_ARRAY = 4,
51  LE_PACK_TYPE_SEMANTIC_TAG = 5,
52  LE_PACK_TYPE_BOOLEAN = 6,
53  LE_PACK_TYPE_DOUBLE = 7,
54  LE_PACK_TYPE_INDEF_END = 8,
55  LE_PACK_TYPE_INVALID_TYPE = 9,
56 } le_pack_Type_t;
57 
58 
59 //--------------------------------------------------------------------------------------------------
60 /**
61  * The maximum size that a type would need when packed.
62  */
63 //--------------------------------------------------------------------------------------------------
64 #ifdef LE_CONFIG_RPC
65 #define LE_PACK_UINT8_MAX_SIZE (1 + sizeof(uint8_t))
66 #define LE_PACK_UINT16_MAX_SIZE (1 + sizeof(uint16_t))
67 #define LE_PACK_UINT32_MAX_SIZE (1 + sizeof(uint32_t))
68 #define LE_PACK_UINT64_MAX_SIZE (1 + sizeof(uint64_t))
69 #define LE_PACK_INT8_MAX_SIZE (1 + sizeof(int8_t))
70 #define LE_PACK_INT16_MAX_SIZE (1 + sizeof(int16_t))
71 #define LE_PACK_INT32_MAX_SIZE (1 + sizeof(int32_t))
72 #define LE_PACK_INT64_MAX_SIZE (1 + sizeof(int64_t))
73 #define LE_PACK_POS_INTEGER_MAX_SIZE (1 + sizeof(uint64_t))
74 #define LE_PACK_NEG_INTEGER_MAX_SIZE (1 + sizeof(int64_t))
75 #define LE_PACK_SEMANTIC_TAG_MAX_SIZE (1 + sizeof(le_pack_SemanticTag_t))
76 #define LE_PACK_BOOL_MAX_SIZE (1)
77 #define LE_PACK_DOUBLE_MAX_SIZE (9)
78 #define LE_PACK_INDEF_END_MAX_SIZE (1)
79 #define LE_PACK_STR_HEADER_MAX_SIZE (1 + sizeof(uint32_t))
80 #define LE_PACK_ARRAY_HEADER_MAX_SIZE (1 + sizeof(uint32_t))
81 #define LE_PACK_INDEF_ARRAY_HEADER_MAX_SIZE (1)
82 #define LE_PACK_SIZE_POINTER_TUPLE_MAX_SIZE (1 + 1 + sizeof(size_t) + 1 + sizeof(intptr_t))
83 
84 #else // no rpc:
85 #define LE_PACK_UINT8_MAX_SIZE (sizeof(uint8_t))
86 #define LE_PACK_UINT16_MAX_SIZE (sizeof(uint16_t))
87 #define LE_PACK_UINT32_MAX_SIZE (sizeof(uint32_t))
88 #define LE_PACK_UINT64_MAX_SIZE (sizeof(uint64_t))
89 #define LE_PACK_INT8_MAX_SIZE (sizeof(int8_t))
90 #define LE_PACK_INT16_MAX_SIZE (sizeof(int16_t))
91 #define LE_PACK_INT32_MAX_SIZE (sizeof(int32_t))
92 #define LE_PACK_INT64_MAX_SIZE (sizeof(int64_t))
93 #define LE_PACK_POS_INTEGER_MAX_SIZE (sizeof(uint64_t))
94 #define LE_PACK_NEG_INTEGER_MAX_SIZE (sizeof(int64_t))
95 #define LE_PACK_SEMANTIC_TAG_MAX_SIZE (0)
96 #define LE_PACK_BOOL_MAX_SIZE (sizeof(bool))
97 #define LE_PACK_DOUBLE_MAX_SIZE (sizeof(double))
98 #define LE_PACK_INDEF_END_MAX_SIZE (0)
99 #define LE_PACK_STR_HEADER_MAX_SIZE (sizeof(uint32_t))
100 #define LE_PACK_ARRAY_HEADER_MAX_SIZE (sizeof(uint32_t))
101 #define LE_PACK_INDEF_ARRAY_HEADER_MAX_SIZE (0)
102 #define LE_PACK_SIZE_POINTER_TUPLE_MAX_SIZE (sizeof(size_t) + sizeof(intptr_t))
103 #endif
104 
105 
106 //--------------------------------------------------------------------------------------------------
107 /**
108  * Semantic Tags:
109  */
110 //--------------------------------------------------------------------------------------------------
111 #define LE_PACK_REFERENCE (2001)
112 
113 #define LE_PACK_IN_STRING_POINTER (2002)
114 #define LE_PACK_OUT_STRING_POINTER (2003)
115 #define LE_PACK_IN_BYTE_STR_POINTER (2004)
116 #define LE_PACK_OUT_BYTE_STR_POINTER (2005)
117 
118 #define LE_PACK_CONTEXT_PTR_REFERENCE (2006)
119 #define LE_PACK_ASYNC_HANDLER_REFERENCE (2007)
120 
121 #define LE_PACK_FILESTREAM_ID (2008)
122 #define LE_PACK_FILESTREAM_FLAG (2009)
123 #define LE_PACK_FILESTREAM_REQUEST_SIZE (2010)
124 
125 #define LE_PACK_OUT_STRING_SIZE (2011)
126 #define LE_PACK_OUT_BYTE_STR_SIZE (2012)
127 
128 #define LE_PACK_OUT_STRING_RESPONSE (2013)
129 #define LE_PACK_OUT_BYTE_STR_RESPONSE (2014)
130 
131 
132 //--------------------------------------------------------------------------------------------------
133 /**
134  * Internal macros:
135  */
136 //--------------------------------------------------------------------------------------------------
137 #define _LE_PACK_CBOR_POS_INTEGER 0
138 #define _LE_PACK_CBOR_NEG_INTEGER 1
139 #define _LE_PACK_CBOR_BYTE_STRING 2
140 #define _LE_PACK_CBOR_TEXT_STRING 3
141 #define _LE_PACK_CBOR_ITEM_ARRAY 4
142 #define _LE_PACK_CBOR_PAIR_MAP 5
143 #define _LE_PACK_CBOR_SEMANTIC_TAG 6
144 #define _LE_PACK_CBOR_PRIMITVE 7
145 
146 #define _LE_PACK_CBOR_COMPLEX_THRESHOLD 24
147 
148 #define _LE_PACK_CBOR_PRIMITIVE_FALSE 20
149 #define _LE_PACK_CBOR_PRIMITIVE_TRUE 21
150 #define _LE_PACK_CBOR_PRIMITIVE_DOUBLE 27
151 #define _LE_PACK_CBOR_PRIMITIVE_BREAK 31
152 #define _LE_PACK_CBOR_PRIMITIVE_INDEFINITE 31
153 
154 
155 
156 
157 //--------------------------------------------------------------------------------------------------
158 // Pack functions
159 //--------------------------------------------------------------------------------------------------
160 
161 // Packing a simple value is basically the same regardless of type. But don't use this macro
162 // directly to get better verification that we're only packing the types we expect
163 #define LE_PACK_PACK_SIMPLE_VALUE(value) \
164  do { \
165  memcpy(*bufferPtr, &(value), sizeof(value)); \
166  *bufferPtr = *bufferPtr + sizeof(value); \
167  } while (0)
168 
169 
170 //--------------------------------------------------------------------------------------------------
171 /**
172  * write bytes
173  */
174 //--------------------------------------------------------------------------------------------------
175 #define LE_PACK_PACK_SIMPLE_BUFFER(desPtr, length) \
176  do { \
177  memcpy(*bufferPtr, desPtr, length); \
178  *bufferPtr += length; \
179  } while(0) \
180 
181 //--------------------------------------------------------------------------------------------------
182 /**
183  * pack tiny field
184  */
185 //--------------------------------------------------------------------------------------------------
186 #define LE_PACK_PACK_TINY_ITEM(major, additional) \
187  do { \
188  *(*bufferPtr) = ((major & 0x7) << 5) | (additional); \
189  *bufferPtr += 1; \
190  } while(0) \
191 
192 //--------------------------------------------------------------------------------------------------
193 /**
194  * Pack an integer:
195  */
196 //--------------------------------------------------------------------------------------------------
197 void _le_pack_packInteger
198 (
199  uint8_t **bufferPtr,
200  uint64_t value,
201  unsigned int major
202 );
203 
204 //--------------------------------------------------------------------------------------------------
205 /**
206  * Pack a negative integer
207  */
208 //--------------------------------------------------------------------------------------------------
209 void _le_pack_packNegativeInteger
210 (
211  uint8_t **bufferPtr,
212  uint64_t value
213 );
214 
215 //--------------------------------------------------------------------------------------------------
216 /**
217  * Pack a positive integer
218  */
219 //--------------------------------------------------------------------------------------------------
220 void _le_pack_packPositiveInteger
221 (
222  uint8_t **bufferPtr,
223  uint64_t value
224 );
225 
226 //--------------------------------------------------------------------------------------------------
227 /**
228  * Pack a TagID into a buffer, incrementing the buffer pointer and decrementing the
229  * available size, as appropriate.
230  *
231  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
232  * size is known at compile time.
233  */
234 //--------------------------------------------------------------------------------------------------
235 #if LE_CONFIG_RPC
236 bool le_pack_PackSemanticTag
237 (
238  uint8_t** bufferPtr,
239  le_pack_SemanticTag_t value
240 );
241 #else
242 LE_DECLARE_INLINE bool le_pack_PackSemanticTag
243 (
244  uint8_t **bufferPtr,
245  le_pack_SemanticTag_t value
246 )
247 {
248  LE_UNUSED(bufferPtr);
249  LE_UNUSED(value);
250 
251  return true;
252 }
253 #endif
254 
255 
256 #ifdef LE_CONFIG_RPC
257 //--------------------------------------------------------------------------------------------------
258 /**
259  * prototype of Out-of-line functions containing rpc specific implementation:
260  */
261 //--------------------------------------------------------------------------------------------------
262 bool le_pack_PackInt8_rpc(uint8_t** bufferPtr, int8_t value);
263 bool le_pack_PackInt16_rpc(uint8_t** bufferPtr, int16_t value);
264 bool le_pack_PackInt32_rpc(uint8_t** bufferPtr, int32_t value);
265 bool le_pack_PackInt64_rpc(uint8_t** bufferPtr, int64_t value);
266 bool le_pack_PackDouble_rpc(uint8_t** bufferPtr, double value);
267 bool le_pack_PackResult_rpc(uint8_t** bufferPtr, le_result_t value);
268 bool le_pack_PackTaggedSizeUint32Tuple_rpc(uint8_t** bufferPtr, size_t size, uint32_t value,
269  le_pack_SemanticTag_t tagId);
270 bool le_pack_PackTaggedSizeUint64Tuple_rpc(uint8_t** bufferPtr, size_t size, uint64_t value,
271  le_pack_SemanticTag_t tagId);
272 bool le_pack_PackString_rpc(uint8_t** bufferPtr, const char *stringPtr, uint32_t maxStringCount);
273 bool le_pack_PackIndefArrayHeader_rpc(uint8_t** bufferPtr);
274 bool le_pack_PackEndOfIndefArray_rpc(uint8_t** bufferPtr);
275 bool le_pack_PackBool_rpc(uint8_t** bufferPtr, bool value);
276 #endif
277 
278 //--------------------------------------------------------------------------------------------------
279 /**
280  * Pack a uint8_t into a buffer, incrementing the buffer pointer as appropriate.
281  *
282  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
283  * size is known at compile time.
284  */
285 //--------------------------------------------------------------------------------------------------
286 LE_DECLARE_INLINE bool le_pack_PackUint8
287 (
288  uint8_t** bufferPtr,
289  uint8_t value
290 )
291 {
292 #ifdef LE_CONFIG_RPC
293  _le_pack_packPositiveInteger(bufferPtr, value);
294 #else
295  LE_PACK_PACK_SIMPLE_VALUE(value);
296 #endif
297  return true;
298 }
299 
300 //--------------------------------------------------------------------------------------------------
301 /**
302  * Pack a uint8_t into a buffer using the specified TagID, incrementing the buffer pointer
303  * and decrementing the available size, as appropriate.
304  *
305  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
306  * size is known at compile time.
307  */
308 //--------------------------------------------------------------------------------------------------
309 LE_DECLARE_INLINE bool le_pack_PackTaggedUint8
310 (
311  uint8_t** bufferPtr,
312  uint8_t value,
313  le_pack_SemanticTag_t tagId
314 )
315 {
316 #ifdef LE_CONFIG_RPC
317  le_pack_PackSemanticTag(bufferPtr, tagId);
318 #else
319  LE_UNUSED(tagId);
320 #endif
321  le_pack_PackUint8(bufferPtr, value);
322  return true;
323 }
324 
325 //--------------------------------------------------------------------------------------------------
326 /**
327  * Pack a uint16_t into a buffer, incrementing the buffer pointer as appropriate.
328  */
329 //--------------------------------------------------------------------------------------------------
330 LE_DECLARE_INLINE bool le_pack_PackUint16
331 (
332  uint8_t** bufferPtr,
333  uint16_t value
334 )
335 {
336 #ifdef LE_CONFIG_RPC
337  _le_pack_packPositiveInteger(bufferPtr, value);
338 #else
339  LE_PACK_PACK_SIMPLE_VALUE(value);
340 #endif
341  return true;
342 }
343 
344 
345 //--------------------------------------------------------------------------------------------------
346 /**
347  * Pack a uint16_t into a buffer using the specified TagID, incrementing the buffer pointer
348  * and decrementing the available size, as appropriate.
349  *
350  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
351  * size is known at compile time.
352  */
353 //--------------------------------------------------------------------------------------------------
354 LE_DECLARE_INLINE bool le_pack_PackTaggedUint16
355 (
356  uint8_t** bufferPtr,
357  uint16_t value,
358  le_pack_SemanticTag_t tagId
359 )
360 {
361 #ifdef LE_CONFIG_RPC
362  le_pack_PackSemanticTag(bufferPtr, tagId);
363 #else
364  LE_UNUSED(tagId);
365 #endif
366  le_pack_PackUint16(bufferPtr, value);
367  return true;
368 }
369 
370 //--------------------------------------------------------------------------------------------------
371 /**
372  * Pack a uint32_t into a buffer, incrementing the buffer pointer as appropriate.
373  */
374 //--------------------------------------------------------------------------------------------------
375 LE_DECLARE_INLINE bool le_pack_PackUint32
376 (
377  uint8_t** bufferPtr,
378  uint32_t value
379 )
380 {
381 #ifdef LE_CONFIG_RPC
382  _le_pack_packPositiveInteger(bufferPtr, value);
383 #else
384  LE_PACK_PACK_SIMPLE_VALUE(value);
385 #endif
386  return true;
387 }
388 
389 
390 //--------------------------------------------------------------------------------------------------
391 /**
392  * Pack a uint32_t into a buffer using the specified TagID, incrementing the buffer pointer
393  * and decrementing the available size, as appropriate.
394  *
395  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
396  * size is known at compile time.
397  */
398 //--------------------------------------------------------------------------------------------------
399 LE_DECLARE_INLINE bool le_pack_PackTaggedUint32
400 (
401  uint8_t** bufferPtr,
402  uint32_t value,
403  le_pack_SemanticTag_t tagId
404 )
405 {
406 #ifdef LE_CONFIG_RPC
407  le_pack_PackSemanticTag(bufferPtr, tagId);
408 #else
409  LE_UNUSED(tagId);
410 #endif
411  le_pack_PackUint32(bufferPtr, value);
412  return true;
413 }
414 
415 //--------------------------------------------------------------------------------------------------
416 /**
417  * Pack a uint64_t into a buffer, incrementing the buffer pointer as appropriate.
418  */
419 //--------------------------------------------------------------------------------------------------
420 LE_DECLARE_INLINE bool le_pack_PackUint64
421 (
422  uint8_t** bufferPtr,
423  uint64_t value
424 )
425 {
426 #ifdef LE_CONFIG_RPC
427  _le_pack_packPositiveInteger(bufferPtr, value);
428 #else
429  LE_PACK_PACK_SIMPLE_VALUE(value);
430 #endif
431  return true;
432 }
433 
434 //--------------------------------------------------------------------------------------------------
435 /**
436  * Pack a uint64_t into a buffer using the specified TagID, incrementing the buffer pointer
437  * and decrementing the available size, as appropriate.
438  *
439  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
440  * size is known at compile time.
441  */
442 //--------------------------------------------------------------------------------------------------
443 LE_DECLARE_INLINE bool le_pack_PackTaggedUint64
444 (
445  uint8_t** bufferPtr,
446  uint64_t value,
447  le_pack_SemanticTag_t tagId
448 )
449 {
450 #ifdef LE_CONFIG_RPC
451  le_pack_PackSemanticTag(bufferPtr, tagId);
452 #else
453  LE_UNUSED(tagId);
454 #endif
455  le_pack_PackUint64(bufferPtr, value);
456  return true;
457 }
458 
459 //--------------------------------------------------------------------------------------------------
460 /**
461  * Pack a int8_t into a buffer, incrementing the buffer pointer as appropriate.
462  */
463 //--------------------------------------------------------------------------------------------------
464 LE_DECLARE_INLINE bool le_pack_PackInt8
465 (
466  uint8_t** bufferPtr,
467  int8_t value
468 )
469 {
470 #ifdef LE_CONFIG_RPC
471  return le_pack_PackInt8_rpc(bufferPtr, value);
472 #else
473  LE_PACK_PACK_SIMPLE_VALUE(value);
474  return true;
475 #endif
476 }
477 
478 //--------------------------------------------------------------------------------------------------
479 /**
480  * Pack a int8_t into a buffer using the specified TagID, incrementing the buffer pointer
481  * and decrementing the available size, as appropriate.
482  *
483  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
484  * size is known at compile time.
485  */
486 //--------------------------------------------------------------------------------------------------
487 LE_DECLARE_INLINE bool le_pack_PackTaggedInt8
488 (
489  uint8_t** bufferPtr,
490  int8_t value,
491  le_pack_SemanticTag_t tagId
492 )
493 {
494 #ifdef LE_CONFIG_RPC
495  le_pack_PackSemanticTag(bufferPtr, tagId);
496 #else
497  LE_UNUSED(tagId);
498 #endif
499  le_pack_PackInt8(bufferPtr, value);
500  return true;
501 }
502 
503 //--------------------------------------------------------------------------------------------------
504 /**
505  * Pack a int16_t into a buffer, incrementing the buffer pointer as appropriate.
506  */
507 //--------------------------------------------------------------------------------------------------
508 LE_DECLARE_INLINE bool le_pack_PackInt16
509 (
510  uint8_t** bufferPtr,
511  int16_t value
512 )
513 {
514 #ifdef LE_CONFIG_RPC
515  return le_pack_PackInt16_rpc(bufferPtr, value);
516 #else
517  LE_PACK_PACK_SIMPLE_VALUE(value);
518  return true;
519 #endif
520 }
521 
522 //--------------------------------------------------------------------------------------------------
523 /**
524  * Pack a int16_t into a buffer using the specified TagID, incrementing the buffer pointer
525  * and decrementing the available size, as appropriate.
526  *
527  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
528  * size is known at compile time.
529  */
530 //--------------------------------------------------------------------------------------------------
531 LE_DECLARE_INLINE bool le_pack_PackTaggedInt16
532 (
533  uint8_t** bufferPtr,
534  int16_t value,
535  le_pack_SemanticTag_t tagId
536 )
537 {
538 #ifdef LE_CONFIG_RPC
539  le_pack_PackSemanticTag(bufferPtr, tagId);
540 #else
541  LE_UNUSED(tagId);
542 #endif
543  le_pack_PackInt16(bufferPtr, value);
544  return true;
545 }
546 
547 //--------------------------------------------------------------------------------------------------
548 /**
549  * Pack a int32_t into a buffer, incrementing the buffer pointer as appropriate.
550  */
551 //--------------------------------------------------------------------------------------------------
552 LE_DECLARE_INLINE bool le_pack_PackInt32
553 (
554  uint8_t** bufferPtr,
555  int32_t value
556 )
557 {
558 #ifdef LE_CONFIG_RPC
559  return le_pack_PackInt32_rpc(bufferPtr, value);
560 #else
561  LE_PACK_PACK_SIMPLE_VALUE(value);
562  return true;
563 #endif
564 }
565 
566 //--------------------------------------------------------------------------------------------------
567 /**
568  * Pack a int32_t into a buffer using the specified TagID, incrementing the buffer pointer
569  * and decrementing the available size, as appropriate.
570  *
571  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
572  * size is known at compile time.
573  */
574 //--------------------------------------------------------------------------------------------------
575 LE_DECLARE_INLINE bool le_pack_PackTaggedInt32
576 (
577  uint8_t** bufferPtr,
578  int32_t value,
579  le_pack_SemanticTag_t tagId
580 )
581 {
582 #ifdef LE_CONFIG_RPC
583  le_pack_PackSemanticTag(bufferPtr, tagId);
584 #else
585  LE_UNUSED(tagId);
586 #endif
587  le_pack_PackInt32(bufferPtr, value);
588  return true;
589 }
590 
591 //--------------------------------------------------------------------------------------------------
592 /**
593  * Pack a int64_t into a buffer, incrementing the buffer pointer as appropriate.
594  */
595 //--------------------------------------------------------------------------------------------------
596 LE_DECLARE_INLINE bool le_pack_PackInt64
597 (
598  uint8_t** bufferPtr,
599  int64_t value
600 )
601 {
602 #ifdef LE_CONFIG_RPC
603  return le_pack_PackInt64_rpc(bufferPtr, value);
604 #else
605  LE_PACK_PACK_SIMPLE_VALUE(value);
606  return true;
607 #endif
608 }
609 
610 //--------------------------------------------------------------------------------------------------
611 /**
612  * Pack a int64_t into a buffer using the specified TagID, incrementing the buffer pointer
613  * and decrementing the available size, as appropriate.
614  *
615  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
616  * size is known at compile time.
617  */
618 //--------------------------------------------------------------------------------------------------
619 LE_DECLARE_INLINE bool le_pack_PackTaggedInt64
620 (
621  uint8_t** bufferPtr,
622  int64_t value,
623  le_pack_SemanticTag_t tagId
624 )
625 {
626 #ifdef LE_CONFIG_RPC
627  le_pack_PackSemanticTag(bufferPtr, tagId);
628 #else
629  LE_UNUSED(tagId);
630 #endif
631  le_pack_PackInt64(bufferPtr, value);
632  return true;
633 }
634 
635 //--------------------------------------------------------------------------------------------------
636 /**
637  * Pack a size_t into a buffer, incrementing the buffer pointer as appropriate.
638  *
639  * @note Packed sizes are limited to 2^32-1, regardless of platform
640  */
641 //--------------------------------------------------------------------------------------------------
642 LE_DECLARE_INLINE bool le_pack_PackSize
643 (
644  uint8_t **bufferPtr,
645  size_t value
646 )
647 {
648 #ifdef LE_CONFIG_RPC
649  _le_pack_packPositiveInteger(bufferPtr, value);
650  return true;
651 #else
652  return le_pack_PackUint32(bufferPtr, value);
653 #endif
654 }
655 
656 //--------------------------------------------------------------------------------------------------
657 /**
658  * Pack size_t and 32-bit integer tuple into a buffer using the specified TagID,
659  * incrementing the buffer pointer
660  * and decrementing the available size, as appropriate.
661  *
662  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
663  * size is known at compile time.
664  */
665 //--------------------------------------------------------------------------------------------------
666 LE_DECLARE_INLINE bool le_pack_PackTaggedSizeUint32Tuple
667 (
668  uint8_t** bufferPtr,
669  size_t size,
670  uint32_t value,
671  le_pack_SemanticTag_t tagId
672 )
673 {
674 #ifdef LE_CONFIG_RPC
675  return le_pack_PackTaggedSizeUint32Tuple_rpc(bufferPtr, size, value, tagId);
676 #else
677  LE_UNUSED(tagId);
678  bool result;
679  result = le_pack_PackSize(bufferPtr, size);
680  if (result)
681  {
682  result = le_pack_PackUint32(bufferPtr, value);
683  }
684  return result;
685 #endif
686 }
687 
688 //--------------------------------------------------------------------------------------------------
689 /**
690  * Pack size_t and 64-bit integer tuple into a buffer using the specified TagID,
691  * incrementing the buffer pointer
692  * and decrementing the available size, as appropriate.
693  *
694  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
695  * size is known at compile time.
696  */
697 //--------------------------------------------------------------------------------------------------
698 LE_DECLARE_INLINE bool le_pack_PackTaggedSizeUint64Tuple
699 (
700  uint8_t** bufferPtr,
701  size_t size,
702  uint64_t value,
703  le_pack_SemanticTag_t tagId
704 )
705 {
706 #ifdef LE_CONFIG_RPC
707  return le_pack_PackTaggedSizeUint64Tuple_rpc(bufferPtr, size, value, tagId);
708 #else
709  LE_UNUSED(tagId);
710  bool result;
711  result = le_pack_PackSize(bufferPtr, size);
712  if (result)
713  {
714  result = le_pack_PackUint64(bufferPtr, value);
715  }
716  return result;
717 #endif
718 }
719 
720 //--------------------------------------------------------------------------------------------------
721 /**
722  * pack a tuple of size and pointer.
723  */
724 //--------------------------------------------------------------------------------------------------
725 LE_DECLARE_INLINE bool le_pack_PackTaggedSizePointerTuple
726 (
727  uint8_t** bufferPtr,
728  size_t size,
729  void* value,
730  le_pack_SemanticTag_t tagId
731 )
732 {
733 #if IFGEN_PTR32
734  uint32_t rawValue = (uint32_t)value;
735  return le_pack_PackTaggedSizeUint32Tuple(bufferPtr, size, rawValue, tagId);
736 #elif IFGEN_PTR64
737  uint64_t rawValue = (uint64_t)value;
738  return le_pack_PackTaggedSizeUint64Tuple(bufferPtr, size, rawValue, tagId);
739 #else
740 # error "Unsupported pointer size -- only 32- and 64-bit are supported for local services."
741 #endif
742 }
743 
744 //--------------------------------------------------------------------------------------------------
745 /**
746  * Pack a size_t into a buffer using the specified TagID, incrementing the buffer pointer
747  * and decrementing the available size, as appropriate.
748  *
749  * @note Packed sizes are limited to 2^32-1, regardless of platform
750  */
751 //--------------------------------------------------------------------------------------------------
752 LE_DECLARE_INLINE bool le_pack_PackTaggedSize
753 (
754  uint8_t **bufferPtr,
755  size_t value,
756  le_pack_SemanticTag_t tagId
757 )
758 {
759  if (value > UINT32_MAX)
760  {
761  return false;
762  }
763 
764  return le_pack_PackTaggedUint32(bufferPtr, value, tagId);
765 }
766 
767 //--------------------------------------------------------------------------------------------------
768 /**
769  * Pack a bool into a buffer, incrementing the buffer pointer as appropriate.
770  */
771 //--------------------------------------------------------------------------------------------------
772 LE_DECLARE_INLINE bool le_pack_PackBool
773 (
774  uint8_t** bufferPtr,
775  bool value
776 )
777 {
778 #ifdef LE_CONFIG_RPC
779  return le_pack_PackBool_rpc(bufferPtr, value);
780 #else
781  // Force boolean to uint8_t 0 or 1 for packing, regarldess of underlying OS type.
782  // Underlying type has been int on some platforms in the past.
783  uint8_t simpleValue = ((value)?1:0);
784  LE_PACK_PACK_SIMPLE_VALUE(simpleValue);
785  return true;
786 #endif
787 }
788 
789 //--------------------------------------------------------------------------------------------------
790 /**
791  * Pack a bool into a buffer using the specified TagID, incrementing the buffer pointer
792  * and decrementing the available size, as appropriate.
793  *
794  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
795  * size is known at compile time.
796  */
797 //--------------------------------------------------------------------------------------------------
798 LE_DECLARE_INLINE bool le_pack_PackTaggedBool
799 (
800  uint8_t** bufferPtr,
801  bool value,
802  le_pack_SemanticTag_t tagId
803 )
804 {
805 #ifdef LE_CONFIG_RPC
806  le_pack_PackSemanticTag(bufferPtr, tagId);
807 #else
808  LE_UNUSED(tagId);
809 #endif
810  le_pack_PackBool(bufferPtr, value);
811  return true;
812 }
813 
814 //--------------------------------------------------------------------------------------------------
815 /**
816  * Pack a char into a buffer, incrementing the buffer pointer as appropriate.
817  */
818 //--------------------------------------------------------------------------------------------------
819 LE_DECLARE_INLINE bool le_pack_PackChar
820 (
821  uint8_t** bufferPtr,
822  char value
823 )
824 {
825 #ifdef LE_CONFIG_RPC
826  _le_pack_packPositiveInteger(bufferPtr, value);
827 #else
828  LE_PACK_PACK_SIMPLE_VALUE(value);
829 #endif
830  return true;
831 }
832 
833 //--------------------------------------------------------------------------------------------------
834 /**
835  * Pack a char into a buffer using the specified TagID, incrementing the buffer pointer
836  * and decrementing the available size, as appropriate.
837  *
838  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
839  * size is known at compile time.
840  */
841 //--------------------------------------------------------------------------------------------------
842 LE_DECLARE_INLINE bool le_pack_PackTaggedChar
843 (
844  uint8_t** bufferPtr,
845  char value,
846  le_pack_SemanticTag_t tagId
847 )
848 {
849 #ifdef LE_CONFIG_RPC
850  le_pack_PackSemanticTag(bufferPtr, tagId);
851 #else
852  LE_UNUSED(tagId);
853 #endif
854  le_pack_PackChar(bufferPtr, value);
855  return true;
856 }
857 
858 //--------------------------------------------------------------------------------------------------
859 /**
860  * Pack a double into a buffer, incrementing the buffer pointer as appropriate.
861  */
862 //--------------------------------------------------------------------------------------------------
863 LE_DECLARE_INLINE bool le_pack_PackDouble
864 (
865  uint8_t** bufferPtr,
866  double value
867 )
868 {
869 #ifdef LE_CONFIG_RPC
870  return le_pack_PackDouble_rpc(bufferPtr, value);
871 #else
872  LE_PACK_PACK_SIMPLE_VALUE(value);
873  return true;
874 #endif
875 }
876 
877 //--------------------------------------------------------------------------------------------------
878 /**
879  * Pack a double into a buffer using the specified TagID, incrementing the buffer pointer
880  * and decrementing the available size, as appropriate.
881  *
882  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
883  * size is known at compile time.
884  */
885 //--------------------------------------------------------------------------------------------------
886 LE_DECLARE_INLINE bool le_pack_PackTaggedDouble
887 (
888  uint8_t** bufferPtr,
889  double value,
890  le_pack_SemanticTag_t tagId
891 )
892 {
893 #ifdef LE_CONFIG_RPC
894  le_pack_PackSemanticTag(bufferPtr, tagId);
895 #else
896  LE_UNUSED(tagId);
897 #endif
898  le_pack_PackDouble(bufferPtr, value);
899  return true;
900 }
901 
902 //--------------------------------------------------------------------------------------------------
903 /**
904  * Pack a le_result_t into a buffer, incrementing the buffer pointer as appropriate.
905  */
906 //--------------------------------------------------------------------------------------------------
907 LE_DECLARE_INLINE bool le_pack_PackResult
908 (
909  uint8_t** bufferPtr,
910  le_result_t value
911 )
912 {
913 #ifdef LE_CONFIG_RPC
914  return le_pack_PackResult_rpc(bufferPtr, value);
915 #else
916  LE_PACK_PACK_SIMPLE_VALUE(value);
917  return true;
918 #endif
919 }
920 
921 //--------------------------------------------------------------------------------------------------
922 /**
923  * Pack a le_result_t into a buffer using the specified TagID, incrementing the buffer pointer
924  * and decrementing the available size, as appropriate.
925  *
926  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
927  * size is known at compile time.
928  */
929 //--------------------------------------------------------------------------------------------------
930 LE_DECLARE_INLINE bool le_pack_PackTaggedResult
931 (
932  uint8_t** bufferPtr,
933  le_result_t value,
934  le_pack_SemanticTag_t tagId
935 )
936 {
937 #ifdef LE_CONFIG_RPC
938  le_pack_PackSemanticTag(bufferPtr, tagId);
939 #else
940  LE_UNUSED(tagId);
941 #endif
942  le_pack_PackResult(bufferPtr, value);
943  return true;
944 }
945 
946 //--------------------------------------------------------------------------------------------------
947 /**
948  * Pack le_onoff_t into a buffer, incrementing the buffer pointer as appropriate.
949  */
950 //--------------------------------------------------------------------------------------------------
951 LE_DECLARE_INLINE bool le_pack_PackOnOff
952 (
953  uint8_t** bufferPtr,
954  le_onoff_t value
955 )
956 {
957 #ifdef LE_CONFIG_RPC
958  le_pack_PackUint8(bufferPtr, value);
959 #else
960  LE_PACK_PACK_SIMPLE_VALUE(value);
961 #endif
962  return true;
963 }
964 
965 //--------------------------------------------------------------------------------------------------
966 /**
967  * Pack le_onoff_t into a buffer using the specified TagID, incrementing the buffer pointer
968  * and decrementing the available size, as appropriate.
969  *
970  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
971  * size is known at compile time.
972  */
973 //--------------------------------------------------------------------------------------------------
974 LE_DECLARE_INLINE bool le_pack_PackTaggedOnOff
975 (
976  uint8_t** bufferPtr,
977  le_onoff_t value,
978  le_pack_SemanticTag_t tagId
979 )
980 {
981 #ifdef LE_CONFIG_RPC
982  le_pack_PackSemanticTag(bufferPtr, tagId);
983 #else
984  LE_UNUSED(tagId);
985 #endif
986  le_pack_PackOnOff(bufferPtr, value);
987  return true;
988 }
989 
990 #undef LE_PACK_PACK_SIMPLE_VALUE
991 
992 //--------------------------------------------------------------------------------------------------
993 /**
994  * Pack a reference into a buffer, incrementing the buffer pointer.
995  */
996 //--------------------------------------------------------------------------------------------------
997 LE_DECLARE_INLINE bool le_pack_PackReference
998 (
999  uint8_t** bufferPtr,
1000  const void* ref
1001 )
1002 {
1003  size_t refAsInt = (size_t)ref;
1004 
1005  // All references passed through an API must be safe references (or NULL), so
1006  // 0-bit will be set and reference will be <= UINT32_MAX. Size check
1007  // is performed in pack function.
1008  if ((refAsInt <= UINT32_MAX) &&
1009  ((refAsInt & 0x01) ||
1010  !refAsInt))
1011  {
1012 #ifdef LE_CONFIG_RPC
1013  return le_pack_PackTaggedUint32(bufferPtr, (uint32_t)refAsInt, LE_PACK_REFERENCE);
1014 #else
1015  return le_pack_PackUint32(bufferPtr, (uint32_t)refAsInt);
1016 #endif
1017  }
1018  else
1019  {
1020  return false;
1021  }
1022 }
1023 
1024 //--------------------------------------------------------------------------------------------------
1025 /**
1026  * Pack a reference into a buffer using the specified TagID, incrementing the buffer pointer
1027  * and decrementing the available size.
1028  */
1029 //--------------------------------------------------------------------------------------------------
1030 LE_DECLARE_INLINE bool le_pack_PackTaggedReference
1031 (
1032  uint8_t** bufferPtr,
1033  const void* ref,
1034  le_pack_SemanticTag_t tagId
1035 )
1036 {
1037  size_t refAsInt = (size_t)ref;
1038 
1039  // All references passed through an API must be safe references (or NULL), so
1040  // 0-bit will be set and reference will be <= UINT32_MAX. Size check
1041  // is performed in pack function.
1042  if ((refAsInt <= UINT32_MAX) &&
1043  ((refAsInt & 0x01) ||
1044  !refAsInt))
1045  {
1046  return le_pack_PackTaggedUint32(bufferPtr, (uint32_t)refAsInt, tagId);
1047  }
1048  else
1049  {
1050  return false;
1051  }
1052 }
1053 
1054 //--------------------------------------------------------------------------------------------------
1055 /**
1056  * Pack a string header
1057  */
1058 //--------------------------------------------------------------------------------------------------
1059 LE_DECLARE_INLINE bool le_pack_PackStringHeader
1060 (
1061  uint8_t** bufferPtr,
1062  size_t stringLen
1063 )
1064 {
1065 #ifdef LE_CONFIG_RPC
1066  _le_pack_packInteger(bufferPtr, stringLen, _LE_PACK_CBOR_TEXT_STRING);
1067  return true;
1068 #else
1069  return le_pack_PackUint32(bufferPtr, stringLen);
1070 #endif
1071 }
1072 
1073 
1074 //--------------------------------------------------------------------------------------------------
1075 /**
1076  * Pack a string into a buffer, incrementing the buffer pointer.
1077  */
1078 //--------------------------------------------------------------------------------------------------
1079 LE_DECLARE_INLINE bool le_pack_PackString
1080 (
1081  uint8_t** bufferPtr,
1082  const char *stringPtr,
1083  uint32_t maxStringCount
1084 )
1085 {
1086 #ifdef LE_CONFIG_RPC
1087  return le_pack_PackString_rpc(bufferPtr, stringPtr, maxStringCount);
1088 #else
1089  if (!stringPtr)
1090  {
1091  return false;
1092  }
1093 
1094  uint32_t stringLen = strnlen(stringPtr, maxStringCount);
1095  // String was too long to fit in the buffer -- return false.
1096  if (stringPtr[stringLen] != '\0')
1097  {
1098  return false;
1099  }
1100  le_pack_PackUint32(bufferPtr, stringLen);
1101  LE_PACK_PACK_SIMPLE_BUFFER(stringPtr, stringLen);
1102  return true;
1103 #endif
1104 }
1105 
1106 //--------------------------------------------------------------------------------------------------
1107 /**
1108  * Pack a string into a buffer using the specified TagID, incrementing the buffer pointer
1109  * and decrementing the available size.
1110  *
1111  * @note Always decrements available size according to the max possible size used, not actual size
1112  * used.
1113  */
1114 //--------------------------------------------------------------------------------------------------
1115 LE_DECLARE_INLINE bool le_pack_PackTaggedString
1116 (
1117  uint8_t** bufferPtr,
1118  const char *stringPtr,
1119  uint32_t maxStringCount,
1120  le_pack_SemanticTag_t tagId
1121 )
1122 {
1123 #ifdef LE_CONFIG_RPC
1124  le_pack_PackSemanticTag(bufferPtr, tagId);
1125 #else
1126  LE_UNUSED(tagId);
1127 #endif
1128  return le_pack_PackString(bufferPtr, stringPtr, maxStringCount);
1129 }
1130 
1131 //--------------------------------------------------------------------------------------------------
1132 /**
1133  * Pack the size information for an array into a buffer, incrementing the buffer pointer.
1134  *
1135  * @note Users of this API should generally use LE_PACK_PACKARRAY macro instead which also
1136  * packs the array data.
1137  */
1138 //--------------------------------------------------------------------------------------------------
1139 LE_DECLARE_INLINE bool le_pack_PackArrayHeader
1140 (
1141  uint8_t **bufferPtr,
1142  const void *arrayPtr,
1143  size_t elementSize,
1144  size_t arrayCount,
1145  size_t arrayMaxCount
1146 )
1147 {
1148  LE_UNUSED(arrayPtr);
1149  LE_UNUSED(elementSize);
1150 
1151  if (arrayCount > arrayMaxCount)
1152  {
1153  return false;
1154  }
1155 
1156 #ifdef LE_CONFIG_RPC
1157  _le_pack_packInteger(bufferPtr, arrayCount, _LE_PACK_CBOR_ITEM_ARRAY);
1158 #else
1159  LE_ASSERT(le_pack_PackSize(bufferPtr, arrayCount));
1160 #endif
1161  return true;
1162 }
1163 
1164 //--------------------------------------------------------------------------------------------------
1165 /**
1166  * Pack an array header with unknown number of elements (inifinite array)
1167  */
1168 //--------------------------------------------------------------------------------------------------
1169 LE_DECLARE_INLINE bool le_pack_PackIndefArrayHeader
1170 (
1171  uint8_t** bufferPtr
1172 )
1173 {
1174 #ifdef LE_CONFIG_RPC
1175  return le_pack_PackIndefArrayHeader_rpc(bufferPtr);
1176 #else
1177  LE_UNUSED(bufferPtr);
1178  return true;
1179 #endif
1180 }
1181 
1182 //--------------------------------------------------------------------------------------------------
1183 /**
1184  * Pack the end of an indefinite item array
1185  */
1186 //--------------------------------------------------------------------------------------------------
1187 LE_DECLARE_INLINE bool le_pack_PackEndOfIndefArray
1188 (
1189  uint8_t** bufferPtr
1190 )
1191 {
1192 #ifdef LE_CONFIG_RPC
1193  return le_pack_PackEndOfIndefArray_rpc(bufferPtr);
1194 #else
1195  LE_UNUSED(bufferPtr);
1196  return true;
1197 #endif
1198 }
1199 
1200 //--------------------------------------------------------------------------------------------------
1201 /**
1202  * Pack a string header
1203  */
1204 //--------------------------------------------------------------------------------------------------
1205 LE_DECLARE_INLINE bool le_pack_PackByteStringHeader
1206 (
1207  uint8_t** bufferPtr,
1208  size_t length
1209 )
1210 {
1211 #ifdef LE_CONFIG_RPC
1212  _le_pack_packInteger(bufferPtr, length, _LE_PACK_CBOR_BYTE_STRING);
1213  return true;
1214 #else
1215  return le_pack_PackUint32(bufferPtr, length);
1216 #endif
1217 }
1218 
1219 //--------------------------------------------------------------------------------------------------
1220 /**
1221  * pack a byte string (Array of uint8, int8, or char)
1222  */
1223 //--------------------------------------------------------------------------------------------------
1224 LE_DECLARE_INLINE bool le_pack_PackByteString
1225 (
1226  uint8_t** bufferPtr,
1227  const void* byteStringPtr,
1228  uint32_t byteStringCount
1229 )
1230 {
1231 #ifdef LE_CONFIG_RPC
1232  _le_pack_packInteger(bufferPtr, byteStringCount, _LE_PACK_CBOR_BYTE_STRING);
1233 #else
1234  le_pack_PackUint32(bufferPtr, byteStringCount);
1235 #endif
1236  LE_PACK_PACK_SIMPLE_BUFFER(byteStringPtr, byteStringCount);
1237  return true;
1238 }
1239 
1240 //--------------------------------------------------------------------------------------------------
1241 /**
1242  * Pack tagged inf array header
1243  */
1244 //--------------------------------------------------------------------------------------------------
1245 LE_DECLARE_INLINE bool le_pack_PackTaggedIndefArrayHeader
1246 (
1247  uint8_t** bufferPtr,
1248  le_pack_SemanticTag_t tagId
1249 )
1250 {
1251 #ifdef LE_CONFIG_RPC
1252  le_pack_PackSemanticTag(bufferPtr, tagId);
1253 #else
1254  LE_UNUSED(tagId);
1255 #endif
1256  return le_pack_PackIndefArrayHeader(bufferPtr);
1257 }
1258 
1259 //--------------------------------------------------------------------------------------------------
1260 /**
1261  * Pack the size information for an array into a buffer using the specified TagID,
1262  * incrementing the buffer pointer and decrementing the available size.
1263  *
1264  * @note Users of this API should generally use LE_PACK_PACKARRAY macro instead which also
1265  * packs the array data.
1266  */
1267 //--------------------------------------------------------------------------------------------------
1268 LE_DECLARE_INLINE bool le_pack_PackTaggedArrayHeader
1269 (
1270  uint8_t **bufferPtr,
1271  const void *arrayPtr,
1272  size_t elementSize,
1273  size_t arrayCount,
1274  size_t arrayMaxCount,
1275  le_pack_SemanticTag_t tagId
1276 )
1277 {
1278  LE_UNUSED(arrayPtr);
1279  LE_UNUSED(elementSize);
1280 
1281  if (arrayCount > arrayMaxCount)
1282  {
1283  return false;
1284  }
1285 #ifdef LE_CONFIG_RPC
1286  le_pack_PackSemanticTag(bufferPtr, tagId);
1287 #else
1288  LE_UNUSED(tagId);
1289 #endif
1290  LE_ASSERT(le_pack_PackArrayHeader(bufferPtr,arrayPtr, elementSize, arrayCount, arrayMaxCount));
1291  return true;
1292 }
1293 
1294 
1295 //--------------------------------------------------------------------------------------------------
1296 /**
1297  * pack a byte string (Array of uint8, int8, or char)
1298  */
1299 //--------------------------------------------------------------------------------------------------
1300 LE_DECLARE_INLINE bool le_pack_PackTaggedByteString
1301 (
1302  uint8_t** bufferPtr,
1303  void* byteStringPtr,
1304  uint32_t byteStringCount
1305 )
1306 {
1307 #ifdef LE_CONFIG_RPC
1308  _le_pack_packInteger(bufferPtr, byteStringCount, _LE_PACK_CBOR_BYTE_STRING);
1309 #else
1310  le_pack_PackUint32(bufferPtr, byteStringCount);
1311 #endif
1312  LE_PACK_PACK_SIMPLE_BUFFER(byteStringPtr, byteStringCount);
1313  return true;
1314 }
1315 
1316 //--------------------------------------------------------------------------------------------------
1317 /**
1318  * Pack an array into a buffer, incrementing the buffer pointer.
1319  *
1320  * @note Will assert if the resulted array exceeds the maximum size allowed.
1321  */
1322 //--------------------------------------------------------------------------------------------------
1323 #define LE_PACK_PACKARRAY(bufferPtr, \
1324  arrayPtr, \
1325  arrayCount, \
1326  arrayMaxCount, \
1327  packFunc, \
1328  resultPtr) \
1329  do { \
1330  *(resultPtr) = le_pack_PackArrayHeader((bufferPtr), \
1331  (arrayPtr), sizeof((arrayPtr)[0]), \
1332  (arrayCount), (arrayMaxCount)); \
1333  if (*(resultPtr)) \
1334  { \
1335  uint32_t i; \
1336  for (i = 0; i < (arrayCount); ++i) \
1337  { \
1338  LE_ASSERT(packFunc((bufferPtr), (arrayPtr)[i])); \
1339  } \
1340  *(resultPtr) = true; \
1341  } \
1342  } while (0)
1343 
1344 
1345 //--------------------------------------------------------------------------------------------------
1346 /**
1347  * Pack an array into a buffer, incrementing the buffer pointer.
1348  *
1349  * @note Will assert if the resulted array exceeds the maximum size allowed.
1350  */
1351 //--------------------------------------------------------------------------------------------------
1352 #define LE_PACK_PACKTAGGEDARRAY(bufferPtr, \
1353  arrayPtr, \
1354  arrayCount, \
1355  arrayMaxCount, \
1356  packFunc, \
1357  tagId, \
1358  resultPtr) \
1359  do { \
1360  *(resultPtr) = le_pack_PackTaggedArrayHeader((bufferPtr), \
1361  (arrayPtr), sizeof((arrayPtr)[0]), \
1362  (arrayCount), (arrayMaxCount), tagId); \
1363  if (*(resultPtr)) \
1364  { \
1365  uint32_t i; \
1366  for (i = 0; i < (arrayCount); ++i) \
1367  { \
1368  LE_ASSERT(packFunc((bufferPtr), (arrayPtr)[i])); \
1369  } \
1370  *(resultPtr) = true; \
1371  } \
1372  } while (0)
1373 
1374 //--------------------------------------------------------------------------------------------------
1375 /**
1376  * Pack an array of struct into a buffer, incrementing the buffer pointer.
1377  *
1378  * @note Will assert if the resulted array of struct exceeds the maximum size allowed.
1379  */
1380 //--------------------------------------------------------------------------------------------------
1381 #define LE_PACK_PACKSTRUCTARRAY(bufferPtr, \
1382  arrayPtr, \
1383  arrayCount, \
1384  arrayMaxCount, \
1385  packFunc, \
1386  resultPtr) \
1387  do { \
1388  *(resultPtr) = le_pack_PackArrayHeader((bufferPtr), \
1389  (arrayPtr), sizeof((arrayPtr)[0]), \
1390  (arrayCount), (arrayMaxCount)); \
1391  if (*(resultPtr)) \
1392  { \
1393  uint32_t i; \
1394  for (i = 0; i < (arrayCount); ++i) \
1395  { \
1396  LE_ASSERT(packFunc((bufferPtr), &((arrayPtr)[i]))); \
1397  } \
1398  *(resultPtr) = true; \
1399  } \
1400  } while (0)
1401 
1402 //--------------------------------------------------------------------------------------------------
1403 // Unpack functions
1404 //--------------------------------------------------------------------------------------------------
1405 
1406 #define LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr) \
1407  do { \
1408  memcpy((valuePtr), *bufferPtr, sizeof(*(valuePtr))); \
1409  *bufferPtr = (*bufferPtr) + sizeof(*(valuePtr)); \
1410  } while (0)
1411 
1412 
1413 //--------------------------------------------------------------------------------------------------
1414 /**
1415  * read bytes
1416  */
1417 //--------------------------------------------------------------------------------------------------
1418 #define LE_PACK_UNPACK_SIMPLE_BUFFER(srcPtr, length) \
1419  do { \
1420  memcpy((void*)(srcPtr), *bufferPtr, length); \
1421  *bufferPtr += length; \
1422  } while(0) \
1423 
1424 //--------------------------------------------------------------------------------------------------
1425 /**
1426  * Get type.
1427  *
1428  * @return
1429  * - an le_pack_Type_t enum.
1430  */
1431 //--------------------------------------------------------------------------------------------------
1432 le_pack_Type_t le_pack_GetType
1433 (
1434  uint8_t* buffer, ///< [IN] buffer pointer
1435  ssize_t* additionalBytes ///< [OUT] number of additional bytes
1436 );
1437 
1438 //--------------------------------------------------------------------------------------------------
1439 /**
1440  * unpack tiny field
1441  */
1442 //--------------------------------------------------------------------------------------------------
1443 #define LE_PACK_UNPACK_TINY_ITEM() \
1444  do { \
1445  uint8_t* buffer = *bufferPtr; \
1446  major = (buffer[0] >> 5) & 0x7; \
1447  additional = buffer[0] & 0x1F; \
1448  *bufferPtr += 1; \
1449  } while(0) \
1450 
1451 //--------------------------------------------------------------------------------------------------
1452 /**
1453  * unpack positive integer
1454  */
1455 //--------------------------------------------------------------------------------------------------
1456 bool _le_pack_unpackPositiveInteger(
1457  uint8_t** bufferPtr,
1458  uint64_t* valuePtr,
1459  unsigned int expectedMajor
1460 );
1461 
1462 
1463 //--------------------------------------------------------------------------------------------------
1464 /**
1465  * unpack integer(may be positive or negative)
1466  */
1467 //--------------------------------------------------------------------------------------------------
1468 bool _le_pack_unpackInteger
1469 (
1470  uint8_t** bufferPtr,
1471  int64_t* valuePtr
1472 );
1473 
1474 #ifdef LE_CONFIG_RPC
1475 //--------------------------------------------------------------------------------------------------
1476 /**
1477  * Protoype of out-of-line functions containing rpc specific implementations:
1478  */
1479 //--------------------------------------------------------------------------------------------------
1480 bool le_pack_UnpackUint8_rpc(uint8_t** bufferPtr, uint8_t* valuePtr);
1481 bool le_pack_UnpackUint16_rpc(uint8_t** bufferPtr, uint16_t* valuePtr);
1482 bool le_pack_UnpackUint32_rpc(uint8_t** bufferPtr, uint32_t* valuePtr);
1483 bool le_pack_UnpackUint64_rpc(uint8_t** bufferPtr, uint64_t* valuePtr);
1484 bool le_pack_UnpackInt8_rpc(uint8_t** bufferPtr, int8_t* valuePtr);
1485 bool le_pack_UnpackInt16_rpc(uint8_t** bufferPtr, int16_t* valuePtr);
1486 bool le_pack_UnpackInt32_rpc(uint8_t** bufferPtr, int32_t* valuePtr);
1487 bool le_pack_UnpackInt64_rpc(uint8_t** bufferPtr, int64_t* valuePtr);
1488 bool le_pack_UnpackBool_rpc(uint8_t** bufferPtr, bool* valuePtr);
1489 bool le_pack_UnpackChar_rpc(uint8_t** bufferPtr, char* valuePtr);
1490 bool le_pack_UnpackDouble_rpc(uint8_t** bufferPtr, double* valuePtr);
1491 bool le_pack_UnpackResult_rpc(uint8_t** bufferPtr, le_result_t* valuePtr);
1492 bool le_pack_UnpackOnOff_rpc(uint8_t** bufferPtr, le_onoff_t* valuePtr);
1493 bool le_pack_UnpackStringHeader_rpc(uint8_t** bufferPtr, size_t* stringSizePtr);
1494 bool le_pack_UnpackIndefArrayHeader_rpc(uint8_t** bufferPtr);
1495 bool le_pack_UnpackEndOfIndefArray_rpc(uint8_t** bufferPtr);
1496 bool le_pack_UnpackByteStringHeader_rpc(uint8_t** bufferPtr, size_t* lengthPtr);
1497 bool le_pack_UnpackSizeUint32Tuple_rpc(uint8_t** bufferPtr, size_t* sizePtr, uint32_t* valuePtr,
1498  le_pack_SemanticTag_t* semanticTagPtr);
1499 bool le_pack_UnpackSizeUint64Tuple_rpc(uint8_t** bufferPtr, size_t* sizePtr, uint64_t* valuePtr,
1500  le_pack_SemanticTag_t* semanticTagPtr);
1501 bool le_pack_UnpackReference_rpc(uint8_t** bufferPtr, void* refPtr,
1502  le_pack_SemanticTag_t* semanticTagPtr);
1503 bool le_pack_UnpackString_rpc(uint8_t** bufferPtr, char *stringPtr, uint32_t bufferSize,
1504  uint32_t maxStringCount);
1505 bool le_pack_UnpackStringHeader_rpc(uint8_t** bufferPtr, size_t* stringSizePtr);
1506 bool le_pack_UnpackArrayHeader_rpc(uint8_t **bufferPtr, const void *arrayPtr, size_t elementSize,
1507  size_t *arrayCountPtr, size_t arrayMaxCount);
1508 bool le_pack_UnpackIndefArrayHeader_rpc(uint8_t** bufferPtr);
1509 bool le_pack_UnpackEndOfIndefArray_rpc(uint8_t** bufferPtr);
1510 bool le_pack_UnpackByteStringHeader_rpc(uint8_t** bufferPtr, size_t* lengthPtr);
1511 bool le_pack_UnpackByteString_rpc(uint8_t** bufferPtr, void *arrayPtr, size_t *arrayCountPtr,
1512  size_t arrayMaxCount);
1513 #endif
1514 
1515 //--------------------------------------------------------------------------------------------------
1516 /**
1517  * Unpack a TagID from a buffer, incrementing the buffer pointer and decrementing the
1518  * available size, as appropriate.
1519  */
1520 //--------------------------------------------------------------------------------------------------
1521 #if LE_CONFIG_RPC
1522 bool le_pack_UnpackSemanticTag
1523 (
1524  uint8_t** bufferPtr,
1525  le_pack_SemanticTag_t* tagIdPtr
1526 );
1527 #else
1528 LE_DECLARE_INLINE bool le_pack_UnpackSemanticTag
1529 (
1530  uint8_t** bufferPtr,
1531  le_pack_SemanticTag_t *tagIdPtr
1532 )
1533 {
1534  LE_UNUSED(bufferPtr);
1535 
1536  if (tagIdPtr)
1537  {
1538  *tagIdPtr = 0;
1539  }
1540 
1541  return true;
1542 }
1543 #endif
1544 
1545 //--------------------------------------------------------------------------------------------------
1546 /**
1547  * Unpack a TagID from a buffer, incrementing the buffer pointer and decrementing the
1548  * available size, as appropriate, then check the tag matches the expected tag
1549  *
1550  * @note By making this an inline function, gcc can often optimize out the size check if the buffer
1551  * size is known at compile time.
1552  */
1553 //--------------------------------------------------------------------------------------------------
1554 LE_DECLARE_INLINE bool le_pack_CheckSemanticTag
1555 (
1556  uint8_t** bufferPtr,
1557  le_pack_SemanticTag_t expectedTagId
1558 )
1559 {
1560 #if LE_CONFIG_RPC
1561  le_pack_SemanticTag_t tagId;
1562  return le_pack_UnpackSemanticTag(bufferPtr, &tagId) && (tagId == expectedTagId);
1563 #else
1564  // No tagging, assume tags always match
1565  LE_UNUSED(bufferPtr);
1566  LE_UNUSED(expectedTagId);
1567  return true;
1568 #endif
1569 }
1570 
1571 
1572 //--------------------------------------------------------------------------------------------------
1573 /**
1574  * Unpack a uint8_t from a buffer, incrementing the buffer pointer as appropriate.
1575  */
1576 //--------------------------------------------------------------------------------------------------
1577 LE_DECLARE_INLINE bool le_pack_UnpackUint8
1578 (
1579  uint8_t** bufferPtr,
1580  uint8_t* valuePtr
1581 )
1582 {
1583 #ifdef LE_CONFIG_RPC
1584  return le_pack_UnpackUint8_rpc(bufferPtr, valuePtr);
1585 #else
1586  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1587  return true;
1588 #endif
1589 }
1590 
1591 //--------------------------------------------------------------------------------------------------
1592 /**
1593  * Unpack a uint16_t from a buffer, incrementing the buffer pointer as appropriate.
1594  */
1595 //--------------------------------------------------------------------------------------------------
1596 LE_DECLARE_INLINE bool le_pack_UnpackUint16
1597 (
1598  uint8_t** bufferPtr,
1599  uint16_t* valuePtr
1600 )
1601 {
1602 #ifdef LE_CONFIG_RPC
1603  return le_pack_UnpackUint16_rpc(bufferPtr, valuePtr);
1604 #else
1605  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1606  return true;
1607 #endif
1608 }
1609 
1610 //--------------------------------------------------------------------------------------------------
1611 /**
1612  * Unpack a uint32_t from a buffer, incrementing the buffer pointer as appropriate.
1613  */
1614 //--------------------------------------------------------------------------------------------------
1615 LE_DECLARE_INLINE bool le_pack_UnpackUint32
1616 (
1617  uint8_t** bufferPtr,
1618  uint32_t* valuePtr
1619 )
1620 {
1621 #ifdef LE_CONFIG_RPC
1622  return le_pack_UnpackUint32_rpc(bufferPtr, valuePtr);
1623 #else
1624  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1625  return true;
1626 #endif
1627 }
1628 
1629 //--------------------------------------------------------------------------------------------------
1630 /**
1631  * Unpack a uint64_t from a buffer, incrementing the buffer pointer as appropriate.
1632  */
1633 //--------------------------------------------------------------------------------------------------
1634 LE_DECLARE_INLINE bool le_pack_UnpackUint64
1635 (
1636  uint8_t** bufferPtr,
1637  uint64_t* valuePtr
1638 )
1639 {
1640 #ifdef LE_CONFIG_RPC
1641  return le_pack_UnpackUint64_rpc(bufferPtr, valuePtr);
1642 #else
1643  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1644  return true;
1645 #endif
1646 }
1647 
1648 //--------------------------------------------------------------------------------------------------
1649 /**
1650  * Unpack a int8_t from a buffer, incrementing the buffer pointer as appropriate.
1651  */
1652 //--------------------------------------------------------------------------------------------------
1653 LE_DECLARE_INLINE bool le_pack_UnpackInt8
1654 (
1655  uint8_t** bufferPtr,
1656  int8_t* valuePtr
1657 )
1658 {
1659 #ifdef LE_CONFIG_RPC
1660  return le_pack_UnpackInt8_rpc(bufferPtr, valuePtr);
1661 #else
1662  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1663  return true;
1664 #endif
1665 }
1666 
1667 //--------------------------------------------------------------------------------------------------
1668 /**
1669  * Unpack a int16_t from a buffer, incrementing the buffer pointer as appropriate.
1670  */
1671 //--------------------------------------------------------------------------------------------------
1672 LE_DECLARE_INLINE bool le_pack_UnpackInt16
1673 (
1674  uint8_t** bufferPtr,
1675  int16_t* valuePtr
1676 )
1677 {
1678 #ifdef LE_CONFIG_RPC
1679  return le_pack_UnpackInt16_rpc(bufferPtr, valuePtr);
1680 #else
1681  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1682  return true;
1683 #endif
1684 }
1685 
1686 //--------------------------------------------------------------------------------------------------
1687 /**
1688  * Unpack a int32_t from a buffer, incrementing the buffer pointer as appropriate.
1689  */
1690 //--------------------------------------------------------------------------------------------------
1691 LE_DECLARE_INLINE bool le_pack_UnpackInt32
1692 (
1693  uint8_t** bufferPtr,
1694  int32_t* valuePtr
1695 )
1696 {
1697 #ifdef LE_CONFIG_RPC
1698  return le_pack_UnpackInt32_rpc(bufferPtr, valuePtr);
1699 #else
1700  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1701  return true;
1702 #endif
1703 }
1704 
1705 //--------------------------------------------------------------------------------------------------
1706 /**
1707  * Unpack a int64_t from a buffer, incrementing the buffer pointer as appropriate.
1708  */
1709 //--------------------------------------------------------------------------------------------------
1710 LE_DECLARE_INLINE bool le_pack_UnpackInt64
1711 (
1712  uint8_t** bufferPtr,
1713  int64_t* valuePtr
1714 )
1715 {
1716 #ifdef LE_CONFIG_RPC
1717  return le_pack_UnpackInt64_rpc(bufferPtr, valuePtr);
1718 #else
1719  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1720  return true;
1721 #endif
1722 }
1723 
1724 
1725 //--------------------------------------------------------------------------------------------------
1726 /**
1727  * Pack a size_t into a buffer, incrementing the buffer pointer as appropriate.
1728  *
1729  * @note Packed sizes are limited to 2^32-1, regardless of platform
1730  */
1731 //--------------------------------------------------------------------------------------------------
1732 LE_DECLARE_INLINE bool le_pack_UnpackSize
1733 (
1734  uint8_t **bufferPtr,
1735  size_t *valuePtr
1736 )
1737 {
1738  uint32_t rawValue;
1739 
1740  if (!le_pack_UnpackUint32(bufferPtr, &rawValue))
1741  {
1742  return false;
1743  }
1744 
1745  *valuePtr = rawValue;
1746 
1747  return true;
1748 }
1749 
1750 //--------------------------------------------------------------------------------------------------
1751 /**
1752  * Unpack a uint8_t from a buffer, checking if the tag matches the expected semantic tag
1753  * and incrementing the buffer pointer as appropriate.
1754  */
1755 //--------------------------------------------------------------------------------------------------
1756 LE_DECLARE_INLINE bool le_pack_UnpackTaggedUint8
1757 (
1758  uint8_t** bufferPtr,
1759  uint8_t* valuePtr,
1760  le_pack_SemanticTag_t tagId
1761 )
1762 {
1763 #ifdef LE_CONFIG_RPC
1764  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1765  {
1766  return false;
1767  }
1768 
1769  return le_pack_UnpackUint8_rpc(bufferPtr, valuePtr);
1770 #else
1771  LE_UNUSED(bufferPtr);
1772  LE_UNUSED(tagId);
1773  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1774  return true;
1775 #endif
1776 }
1777 
1778 //--------------------------------------------------------------------------------------------------
1779 /**
1780  * Unpack a uint16_t from a buffer, checking if the tag matches the expected semantic tag
1781  * and incrementing the buffer pointer as appropriate.
1782  */
1783 //--------------------------------------------------------------------------------------------------
1784 LE_DECLARE_INLINE bool le_pack_UnpackTaggedUint16
1785 (
1786  uint8_t** bufferPtr,
1787  uint16_t* valuePtr,
1788  le_pack_SemanticTag_t tagId
1789 )
1790 {
1791 #ifdef LE_CONFIG_RPC
1792  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1793  {
1794  return false;
1795  }
1796 
1797  return le_pack_UnpackUint16_rpc(bufferPtr, valuePtr);
1798 #else
1799  LE_UNUSED(bufferPtr);
1800  LE_UNUSED(tagId);
1801  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1802  return true;
1803 #endif
1804 }
1805 
1806 //--------------------------------------------------------------------------------------------------
1807 /**
1808  * Unpack a uint32_t from a buffer, checking if the tag matches the expected semantic tag
1809  * and incrementing the buffer pointer as appropriate.
1810  */
1811 //--------------------------------------------------------------------------------------------------
1812 LE_DECLARE_INLINE bool le_pack_UnpackTaggedUint32
1813 (
1814  uint8_t** bufferPtr,
1815  uint32_t* valuePtr,
1816  le_pack_SemanticTag_t tagId
1817 )
1818 {
1819 #ifdef LE_CONFIG_RPC
1820  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1821  {
1822  return false;
1823  }
1824 
1825  return le_pack_UnpackUint32_rpc(bufferPtr, valuePtr);
1826 #else
1827  LE_UNUSED(bufferPtr);
1828  LE_UNUSED(tagId);
1829  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1830  return true;
1831 #endif
1832 }
1833 
1834 //--------------------------------------------------------------------------------------------------
1835 /**
1836  * Unpack a uint64_t from a buffer, checking if the tag matches the expected semantic tag
1837  * and incrementing the buffer pointer as appropriate.
1838  */
1839 //--------------------------------------------------------------------------------------------------
1840 LE_DECLARE_INLINE bool le_pack_UnpackTaggedUint64
1841 (
1842  uint8_t** bufferPtr,
1843  uint64_t* valuePtr,
1844  le_pack_SemanticTag_t tagId
1845 )
1846 {
1847 #ifdef LE_CONFIG_RPC
1848  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1849  {
1850  return false;
1851  }
1852 
1853  return le_pack_UnpackUint64_rpc(bufferPtr, valuePtr);
1854 #else
1855  LE_UNUSED(bufferPtr);
1856  LE_UNUSED(tagId);
1857  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1858  return true;
1859 #endif
1860 }
1861 
1862 //--------------------------------------------------------------------------------------------------
1863 /**
1864  * Unpack a int8_t from a buffer, checking if the tag matches the expected semantic tag and
1865  * incrementing the buffer pointer as appropriate.
1866  */
1867 //--------------------------------------------------------------------------------------------------
1868 LE_DECLARE_INLINE bool le_pack_UnpackTaggedInt8
1869 (
1870  uint8_t** bufferPtr,
1871  int8_t* valuePtr,
1872  le_pack_SemanticTag_t tagId
1873 )
1874 {
1875 #ifdef LE_CONFIG_RPC
1876  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1877  {
1878  return false;
1879  }
1880 
1881  return le_pack_UnpackInt8_rpc(bufferPtr, valuePtr);
1882 #else
1883  LE_UNUSED(bufferPtr);
1884  LE_UNUSED(tagId);
1885  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1886  return true;
1887 #endif
1888 }
1889 
1890 //--------------------------------------------------------------------------------------------------
1891 /**
1892  * Unpack a int16_t from a buffer, checking if the tag matches the expected semantic tag
1893  * and incrementing the buffer pointer as appropriate.
1894  */
1895 //--------------------------------------------------------------------------------------------------
1896 LE_DECLARE_INLINE bool le_pack_UnpackTaggedInt16
1897 (
1898  uint8_t** bufferPtr,
1899  int16_t* valuePtr,
1900  le_pack_SemanticTag_t tagId
1901 )
1902 {
1903 #ifdef LE_CONFIG_RPC
1904  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1905  {
1906  return false;
1907  }
1908 
1909  return le_pack_UnpackInt16_rpc(bufferPtr, valuePtr);
1910 #else
1911  LE_UNUSED(bufferPtr);
1912  LE_UNUSED(tagId);
1913  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1914  return true;
1915 #endif
1916 }
1917 
1918 //--------------------------------------------------------------------------------------------------
1919 /**
1920  * Unpack a int32_t from a buffer, checking if the tag matches the expected semantic tag
1921  * and incrementing the buffer pointer as appropriate.
1922  */
1923 //--------------------------------------------------------------------------------------------------
1924 LE_DECLARE_INLINE bool le_pack_UnpackTaggedInt32
1925 (
1926  uint8_t** bufferPtr,
1927  int32_t* valuePtr,
1928  le_pack_SemanticTag_t tagId
1929 )
1930 {
1931 #ifdef LE_CONFIG_RPC
1932  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1933  {
1934  return false;
1935  }
1936 
1937  return le_pack_UnpackInt32_rpc(bufferPtr, valuePtr);
1938 #else
1939  LE_UNUSED(bufferPtr);
1940  LE_UNUSED(tagId);
1941  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1942  return true;
1943 #endif
1944 }
1945 
1946 //--------------------------------------------------------------------------------------------------
1947 /**
1948  * Unpack a int64_t from a buffer, checking if the tag matches the expected semantic tag
1949  * and incrementing the buffer pointer as appropriate.
1950  */
1951 //--------------------------------------------------------------------------------------------------
1952 LE_DECLARE_INLINE bool le_pack_UnpackTaggedInt64
1953 (
1954  uint8_t** bufferPtr,
1955  int64_t* valuePtr,
1956  le_pack_SemanticTag_t tagId
1957 )
1958 {
1959 #ifdef LE_CONFIG_RPC
1960  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1961  {
1962  return false;
1963  }
1964 
1965  return le_pack_UnpackInt64_rpc(bufferPtr, valuePtr);
1966 #else
1967  LE_UNUSED(bufferPtr);
1968  LE_UNUSED(tagId);
1969  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
1970  return true;
1971 #endif
1972 }
1973 
1974 
1975 //--------------------------------------------------------------------------------------------------
1976 /**
1977  * Pack a size_t into a buffer, checking if the tag matches the expected semantic tag
1978  * and incrementing the buffer pointer as appropriate.
1979  *
1980  * @note Packed sizes are limited to 2^32-1, regardless of platform
1981  */
1982 //--------------------------------------------------------------------------------------------------
1983 LE_DECLARE_INLINE bool le_pack_UnpackTaggedSize
1984 (
1985  uint8_t **bufferPtr,
1986  size_t *valuePtr,
1987  le_pack_SemanticTag_t tagId
1988 )
1989 {
1990  uint32_t rawValue;
1991 
1992  if (!le_pack_CheckSemanticTag(bufferPtr, tagId))
1993  {
1994  return false;
1995  }
1996 
1997  if (!le_pack_UnpackUint32(bufferPtr, &rawValue))
1998  {
1999  return false;
2000  }
2001 
2002  *valuePtr = rawValue;
2003 
2004  return true;
2005 }
2006 
2007 //--------------------------------------------------------------------------------------------------
2008 /**
2009  * Unpack a size_t and 32-bit integer tuple from the buffer,
2010  * incrementing the buffer pointer as appropriate.
2011  */
2012 //--------------------------------------------------------------------------------------------------
2013 LE_DECLARE_INLINE bool le_pack_UnpackSizeUint32Tuple
2014 (
2015  uint8_t** bufferPtr,
2016  size_t* sizePtr,
2017  uint32_t* valuePtr,
2018  le_pack_SemanticTag_t* semanticTagPtr
2019 )
2020 {
2021 #ifdef LE_CONFIG_RPC
2022  return le_pack_UnpackSizeUint32Tuple_rpc(bufferPtr, sizePtr, valuePtr, semanticTagPtr);
2023 #else
2024  LE_UNUSED(semanticTagPtr);
2025  bool result;
2026  result = le_pack_UnpackSize(bufferPtr, sizePtr);
2027  if (result)
2028  {
2029  result = le_pack_UnpackUint32(bufferPtr, valuePtr);
2030  }
2031  return result;
2032 #endif
2033 }
2034 
2035 
2036 //--------------------------------------------------------------------------------------------------
2037 /**
2038  * Unpack a size_t and 64-bit integer tuple from the buffer,
2039  * incrementing the buffer pointer as appropriate.
2040  */
2041 //--------------------------------------------------------------------------------------------------
2042 LE_DECLARE_INLINE bool le_pack_UnpackSizeUint64Tuple
2043 (
2044  uint8_t** bufferPtr,
2045  size_t* sizePtr,
2046  uint64_t* valuePtr,
2047  le_pack_SemanticTag_t* semanticTagPtr
2048 )
2049 {
2050 #ifdef LE_CONFIG_RPC
2051  return le_pack_UnpackSizeUint64Tuple_rpc(bufferPtr, sizePtr, valuePtr, semanticTagPtr);
2052 #else
2053  LE_UNUSED(semanticTagPtr);
2054  bool result;
2055  result = le_pack_UnpackSize(bufferPtr, sizePtr);
2056  if (result)
2057  {
2058  result = le_pack_UnpackUint64(bufferPtr, valuePtr);
2059  }
2060  return result;
2061 #endif
2062 }
2063 
2064 //--------------------------------------------------------------------------------------------------
2065 /**
2066  * Unpack a size and pointer tuple from the buffer.
2067  */
2068 //--------------------------------------------------------------------------------------------------
2069 LE_DECLARE_INLINE bool le_pack_UnpackSizePointerTuple
2070 (
2071  uint8_t** bufferPtr,
2072  size_t* sizePtr,
2073  void** valuePtr,
2074  le_pack_SemanticTag_t* semanticTagPtr
2075 )
2076 {
2077 #if IFGEN_PTR32
2078  uint32_t* rawValuePtr = (uint32_t*)valuePtr;
2079  return le_pack_UnpackSizeUint32Tuple(bufferPtr, sizePtr, rawValuePtr, semanticTagPtr);
2080 #elif IFGEN_PTR64
2081  uint64_t* rawValuePtr = (uint64_t*)valuePtr;
2082  return le_pack_UnpackSizeUint64Tuple(bufferPtr, sizePtr, rawValuePtr, semanticTagPtr);
2083 #else
2084 # error "Unsupported pointer size -- only 32- and 64-bit are supported for local services."
2085 #endif
2086 }
2087 
2088 
2089 
2090 
2091 //--------------------------------------------------------------------------------------------------
2092 /**
2093  * Unpack a bool from a buffer, incrementing the buffer pointer as appropriate.
2094  */
2095 //--------------------------------------------------------------------------------------------------
2096 LE_DECLARE_INLINE bool le_pack_UnpackBool
2097 (
2098  uint8_t** bufferPtr,
2099  bool* valuePtr
2100 )
2101 {
2102 
2103 #ifdef LE_CONFIG_RPC
2104  return le_pack_UnpackBool_rpc(bufferPtr, valuePtr);
2105 #else
2106  // Treat boolean as uint8_t for packing, regardless of underlying OS type.
2107  // Underlying type has been int on some platforms in the past.
2108  uint8_t simpleValue;
2109 
2110  memcpy(&simpleValue, *bufferPtr, sizeof(simpleValue));
2111 
2112  *bufferPtr = ((uint8_t* )*bufferPtr) + sizeof(simpleValue);
2113 
2114  // force to true or false
2115  *valuePtr = !!simpleValue;
2116  return true;
2117 #endif
2118 }
2119 
2120 //--------------------------------------------------------------------------------------------------
2121 /**
2122  * Unpack a char from a buffer, incrementing the buffer pointer as appropriate.
2123  */
2124 //--------------------------------------------------------------------------------------------------
2125 LE_DECLARE_INLINE bool le_pack_UnpackChar
2126 (
2127  uint8_t** bufferPtr,
2128  char* valuePtr
2129 )
2130 {
2131 #ifdef LE_CONFIG_RPC
2132  return le_pack_UnpackChar_rpc(bufferPtr, valuePtr);
2133 #else
2134  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
2135  return true;
2136 #endif
2137 }
2138 
2139 //--------------------------------------------------------------------------------------------------
2140 /**
2141  * Unpack a double from a buffer, incrementing the buffer pointer as appropriate.
2142  */
2143 //--------------------------------------------------------------------------------------------------
2144 LE_DECLARE_INLINE bool le_pack_UnpackDouble
2145 (
2146  uint8_t** bufferPtr,
2147  double* valuePtr
2148 )
2149 {
2150 #ifdef LE_CONFIG_RPC
2151  return le_pack_UnpackDouble_rpc(bufferPtr, valuePtr);
2152 #else
2153  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
2154  return true;
2155 #endif
2156 }
2157 
2158 //--------------------------------------------------------------------------------------------------
2159 /**
2160  * Unpack a le_result_t from a buffer, incrementing the buffer pointer as appropriate.
2161  */
2162 //--------------------------------------------------------------------------------------------------
2163 LE_DECLARE_INLINE bool le_pack_UnpackResult
2164 (
2165  uint8_t** bufferPtr,
2166  le_result_t* valuePtr
2167 )
2168 {
2169 #ifdef LE_CONFIG_RPC
2170  return le_pack_UnpackResult_rpc(bufferPtr, valuePtr);
2171 #else
2172  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
2173  return true;
2174 #endif
2175 }
2176 
2177 //--------------------------------------------------------------------------------------------------
2178 /**
2179  * Pack le_onoff_t into a buffer, incrementing the buffer pointer as appropriate.
2180  */
2181 //--------------------------------------------------------------------------------------------------
2182 LE_DECLARE_INLINE bool le_pack_UnpackOnOff
2183 (
2184  uint8_t** bufferPtr,
2185  le_onoff_t* valuePtr
2186 )
2187 {
2188 #ifdef LE_CONFIG_RPC
2189  return le_pack_UnpackOnOff_rpc(bufferPtr, valuePtr);
2190 #else
2191  LE_PACK_UNPACK_SIMPLE_VALUE(valuePtr);
2192  return true;
2193 #endif
2194 }
2195 
2196 #undef LE_PACK_UNPACK_SIMPLE_VALUE
2197 
2198 //--------------------------------------------------------------------------------------------------
2199 /**
2200  * Unpack a reference from a buffer, incrementing the buffer pointer.
2201  */
2202 //--------------------------------------------------------------------------------------------------
2203 LE_DECLARE_INLINE bool le_pack_UnpackReference
2204 (
2205  uint8_t** bufferPtr, ///< Pointer to the reference. Declared as void * to allow implicit
2206  void* refPtr, ///< conversion from pointer to reference types.
2207  le_pack_SemanticTag_t* semanticTagPtr ///< [out] semantic tag found before reference.
2208 )
2209 {
2210 #ifdef LE_CONFIG_RPC
2211  return le_pack_UnpackReference_rpc(bufferPtr, refPtr, semanticTagPtr);
2212 #else
2213  LE_UNUSED(semanticTagPtr);
2214  uint32_t refAsInt;
2215  if (!le_pack_UnpackUint32(bufferPtr, &refAsInt))
2216  {
2217  return false;
2218  }
2219 
2220  // All references passed through an API must be safe references, so
2221  // 0-bit will be set. Check that here to be safe.
2222  if ((refAsInt & 0x01) ||
2223  (!refAsInt))
2224  {
2225  // Double cast to avoid warnings.
2226  *(void **)refPtr = (void *)(size_t)refAsInt;
2227  return true;
2228  }
2229  else
2230  {
2231  return false;
2232  }
2233 #endif
2234 }
2235 
2236 //--------------------------------------------------------------------------------------------------
2237 /**
2238  * Unpack a string header
2239  */
2240 //--------------------------------------------------------------------------------------------------
2241 LE_DECLARE_INLINE bool le_pack_UnpackStringHeader
2242 (
2243  uint8_t** bufferPtr,
2244  size_t* stringSizePtr
2245 )
2246 {
2247 #ifdef LE_CONFIG_RPC
2248  return le_pack_UnpackStringHeader_rpc(bufferPtr, stringSizePtr);
2249 #else
2250  if (!le_pack_UnpackSize(bufferPtr, stringSizePtr))
2251  {
2252  return false;
2253  }
2254  return true;
2255 #endif
2256 }
2257 
2258 //--------------------------------------------------------------------------------------------------
2259 /**
2260  * Unpack a string from a buffer, incrementing the buffer pointer.
2261  */
2262 //--------------------------------------------------------------------------------------------------
2263 LE_DECLARE_INLINE bool le_pack_UnpackString
2264 (
2265  uint8_t** bufferPtr,
2266  char *stringPtr,
2267  uint32_t bufferSize,
2268  uint32_t maxStringCount
2269 )
2270 {
2271 #ifdef LE_CONFIG_RPC
2272  return le_pack_UnpackString_rpc(bufferPtr, stringPtr, bufferSize, maxStringCount);
2273 #else
2274  // First get string size
2275  uint32_t stringSize;
2276  if (!le_pack_UnpackUint32(bufferPtr, &stringSize))
2277  {
2278  return false;
2279  }
2280  if ((stringSize > maxStringCount) ||
2281  (stringSize > bufferSize))
2282  {
2283  return false;
2284  }
2285 
2286  if (!stringPtr)
2287  {
2288  // Only allow unpacking into no output buffer if the string is zero sized.
2289  // Otherwise an output buffer is required.
2290  if (stringSize)
2291  {
2292  return false;
2293  }
2294  else
2295  {
2296  return true;
2297  }
2298  }
2299 
2300  memcpy(stringPtr, *bufferPtr, stringSize);
2301  stringPtr[stringSize] = '\0';
2302 
2303  *bufferPtr = *bufferPtr + stringSize;
2304 
2305  return true;
2306 #endif
2307 }
2308 
2309 //--------------------------------------------------------------------------------------------------
2310 /**
2311  * Pack the size information for an array into a buffer, incrementing the buffer pointer.
2312  *
2313  * @note Users of this API should generally use LE_PACK_PACKARRAY macro instead which also
2314  * packs the array data.
2315  */
2316 //--------------------------------------------------------------------------------------------------
2317 LE_DECLARE_INLINE bool le_pack_UnpackArrayHeader
2318 (
2319  uint8_t **bufferPtr,
2320  const void *arrayPtr,
2321  size_t elementSize,
2322  size_t *arrayCountPtr,
2323  size_t arrayMaxCount
2324 )
2325 {
2326 #ifdef LE_CONFIG_RPC
2327  return le_pack_UnpackArrayHeader_rpc(bufferPtr, arrayPtr, elementSize, arrayCountPtr,
2328  arrayMaxCount);
2329 #else
2330  LE_UNUSED(elementSize);
2331  LE_ASSERT(le_pack_UnpackSize(bufferPtr, arrayCountPtr));
2332  if (*arrayCountPtr > arrayMaxCount)
2333  {
2334  return false;
2335  }
2336  else if (!arrayPtr)
2337  {
2338  // Missing array pointer must match zero sized array.
2339  return (*arrayCountPtr == 0);
2340  }
2341 
2342  return true;
2343 #endif
2344 }
2345 
2346 //--------------------------------------------------------------------------------------------------
2347 /**
2348  * unpack infinite array header
2349  */
2350 //--------------------------------------------------------------------------------------------------
2351 LE_DECLARE_INLINE bool le_pack_UnpackIndefArrayHeader
2352 (
2353  uint8_t** bufferPtr
2354 )
2355 {
2356 #ifdef LE_CONFIG_RPC
2357  return le_pack_UnpackIndefArrayHeader_rpc(bufferPtr);
2358 #else
2359  LE_UNUSED(bufferPtr);
2360  return true;
2361 #endif
2362 }
2363 
2364 //--------------------------------------------------------------------------------------------------
2365 /**
2366  * unpack break
2367  */
2368 //--------------------------------------------------------------------------------------------------
2369 LE_DECLARE_INLINE bool le_pack_UnpackEndOfIndefArray
2370 (
2371  uint8_t** bufferPtr
2372 )
2373 {
2374 #ifdef LE_CONFIG_RPC
2375  return le_pack_UnpackEndOfIndefArray_rpc(bufferPtr);
2376 #else
2377  LE_UNUSED(bufferPtr);
2378  return true;
2379 #endif
2380 }
2381 
2382 //--------------------------------------------------------------------------------------------------
2383 /**
2384  * Unpack a string header
2385  */
2386 //--------------------------------------------------------------------------------------------------
2387 LE_DECLARE_INLINE bool le_pack_UnpackByteStringHeader
2388 (
2389  uint8_t** bufferPtr,
2390  size_t* lengthPtr
2391 )
2392 {
2393 #ifdef LE_CONFIG_RPC
2394  return le_pack_UnpackByteStringHeader_rpc(bufferPtr, lengthPtr);
2395 #else
2396  if (!le_pack_UnpackSize(bufferPtr, lengthPtr))
2397  {
2398  return false;
2399  }
2400  return true;
2401 #endif
2402 }
2403 
2404 //--------------------------------------------------------------------------------------------------
2405 /**
2406  * unpack a byte string (Array of uint8, int8, char)
2407  */
2408 //--------------------------------------------------------------------------------------------------
2409 LE_DECLARE_INLINE bool le_pack_UnpackByteString
2410 (
2411  uint8_t** bufferPtr,
2412  void *arrayPtr,
2413  size_t *arrayCountPtr,
2414  size_t arrayMaxCount
2415 )
2416 {
2417 #ifdef LE_CONFIG_RPC
2418  return le_pack_UnpackByteString_rpc(bufferPtr, arrayPtr, arrayCountPtr, arrayMaxCount);
2419 #else
2420  le_pack_UnpackSize(bufferPtr, arrayCountPtr);
2421  if (*arrayCountPtr > arrayMaxCount)
2422  {
2423  return false;
2424  }
2425  else if (!arrayPtr)
2426  {
2427  // Missing array pointer must match zero sized array.
2428  return (*arrayCountPtr == 0);
2429  }
2430  else
2431  {
2432  LE_PACK_UNPACK_SIMPLE_BUFFER(arrayPtr, *arrayCountPtr);
2433  return true;
2434  }
2435 #endif
2436 }
2437 
2438 //--------------------------------------------------------------------------------------------------
2439 /**
2440  * Unpack an array into from buffer, incrementing the buffer pointer and decrementing the available
2441  * size.
2442  *
2443  * @note Always decrements available size according to the max possible size used, not actual size
2444  * used. Will assert if the resulted array exceeds the maximum size allowed.
2445  */
2446 //--------------------------------------------------------------------------------------------------
2447 #define LE_PACK_UNPACKARRAY(bufferPtr, \
2448  arrayPtr, \
2449  arrayCountPtr, \
2450  arrayMaxCount, \
2451  unpackFunc, \
2452  resultPtr) \
2453  do { \
2454  if (!le_pack_UnpackArrayHeader((bufferPtr), \
2455  (arrayPtr), sizeof((arrayPtr)[0]), \
2456  (arrayCountPtr), (arrayMaxCount))) \
2457  { \
2458  *(resultPtr) = false; \
2459  } \
2460  else \
2461  { \
2462  uint32_t i; \
2463  for (i = 0; i < *(arrayCountPtr); ++i) \
2464  { \
2465  LE_ASSERT(unpackFunc((bufferPtr), &(arrayPtr)[i])); \
2466  } \
2467  *(resultPtr) = true; \
2468  } \
2469  } while (0)
2470 
2471 
2472 //--------------------------------------------------------------------------------------------------
2473 /**
2474  * Unpack an array of tagged items from buffer, incrementing the buffer pointer and decrementing the
2475  * available size.
2476  *
2477  * @note Always decrements available size according to the max possible size used, not actual size
2478  * used. Will assert if the resulted array exceeds the maximum size allowed.
2479  */
2480 //--------------------------------------------------------------------------------------------------
2481 #define LE_PACK_UNPACKTAGGEDARRAY(bufferPtr, \
2482  arrayPtr, \
2483  arrayCountPtr, \
2484  arrayMaxCount, \
2485  unpackFunc, \
2486  resultPtr) \
2487  do { \
2488  if (!le_pack_UnpackArrayHeader((bufferPtr), \
2489  (arrayPtr), sizeof((arrayPtr)[0]), \
2490  (arrayCountPtr), (arrayMaxCount))) \
2491  { \
2492  *(resultPtr) = false; \
2493  } \
2494  else \
2495  { \
2496  uint32_t i; \
2497  for (i = 0; i < *(arrayCountPtr); ++i) \
2498  { \
2499  LE_ASSERT(unpackFunc((bufferPtr), &(arrayPtr)[i]), NULL); \
2500  } \
2501  *(resultPtr) = true; \
2502  } \
2503  } while (0)
2504 
2505 
2506 //--------------------------------------------------------------------------------------------------
2507 /**
2508  * Unpack an array of struct from buffer. Since its logic is the same as that for unpacking an
2509  * array, here it calls LE_PACK_UNPACKSTRUCTARRAY() to do the work.
2510  */
2511 //--------------------------------------------------------------------------------------------------
2512 #define LE_PACK_UNPACKSTRUCTARRAY(bufferPtr, \
2513  arrayPtr, \
2514  arrayCountPtr, \
2515  arrayMaxCount, \
2516  unpackFunc, \
2517  resultPtr) \
2518  LE_PACK_UNPACKARRAY((bufferPtr), (arrayPtr), (arrayCountPtr), \
2519  (arrayMaxCount), (unpackFunc), (resultPtr))
2520 
2521 #endif /* LE_PACK_H_INCLUDE_GUARD */
le_result_t
Definition: le_basics.h:46
#define LE_UNUSED(v)
Definition: le_basics.h:369
#define LE_ASSERT(condition)
Definition: le_log.h:991
#define LE_DECLARE_INLINE
Definition: le_basics.h:320
le_onoff_t
Definition: le_basics.h:85