blob: 2c74f889695caad4d4590e26376bb07de894b033 [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018-2020, Laurence Lundblade.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above
11 copyright notice, this list of conditions and the following
12 disclaimer in the documentation and/or other materials provided
13 with the distribution.
14 * Neither the name of The Linux Foundation nor the names of its
15 contributors, nor the name "Laurence Lundblade" may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 =============================================================================*/
31
32/*============================================================================
33 FILE: UsefulBuf.h
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42 when who what, where, why
43 -------- ---- --------------------------------------------------
44 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
45 5/21/2019 llundblade #define configs for efficient endianness handling.
46 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
47 3/23/2019 llundblade Big documentation & style update. No interface
48 change.
49 3/6/2019 llundblade Add UsefulBuf_IsValue()
50 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
51 12/13/2018 llundblade Documentation improvements
52 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
53 UsefulBufC.
54 02/02/18 llundbla Full support for integers in and out; fix pointer
55 alignment bug. Incompatible change: integers
56 in/out are now in network byte order.
57 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
58 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
59 comparison for < or > for unequal length buffers.
60 Added UsefulBuf_Set() function.
61 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
62 11/13/16 llundbla Initial Version.
63
64 =============================================================================*/
65
66#ifndef _UsefulBuf_h
67#define _UsefulBuf_h
68
69
70/*
71 Configuration Options
72
73 This code is designed so it will work correctly and completely by
74 default. No configuration is necessary to make it work. None of the
75 following #defines need to be enabled. The code works and is very
76 portable with them all turned off.
77
78 All configuration options (USEFULBUF_CONFIG_XXX)
79 1) Reduce code size
80 2) Improve efficiency
81 3) Both of the above
82
83 The efficiency improvements are not large, so the main reason really
84 is to reduce code size.
85
86 */
87
88
89/*
90 Endianness Configuration
91
92 By default, UsefulBuf does not need to know what the endianness of
93 the device is. All the code will run correctly on either big or
94 little endian CPUs.
95
96 Here's the recipe for configuring the endianness-related #defines
97 to use more efficient CPU/OS/compiler dependent features to reduce
98 code size. Note these only affect the integer arrays (tagged
99 arrays) feature of QCBOR. All other endianness handling in
100 QCBOR is integrated with code that also handles alignment and
101 preferred encoding.
102
103 The first option is to not define anything. This will work fine on
104 with all CPU's, OS's and compilers. The code for encoding
105 integers will be a little larger and slower.
106
107 If your CPU is big-endian then define USEFULBUF_CONFIG_BIG_ENDIAN. This
108 will give the most efficient code for big-endian CPUs. It will be small
109 and efficient because there will be no byte swapping.
110
111 Try defining USEFULBUF_CONFIG_HTON. This will work on most CPU's,
112 OS's and compilers, but not all. On big-endian CPUs this should give
113 the most efficient code, the same as USEFULBUF_CONFIG_BIG_ENDIAN
114 does. On little-endian CPUs it should call the system-defined byte
115 swapping method which is presumably implemented efficiently. In some
116 cases, this will be a dedicated byte swap instruction like Intel's
117 bswap.
118
119 If USEFULBUF_CONFIG_HTON works and you know your CPU is
120 little-endian, it is also good to define
121 USEFULBUF_CONFIG_LITTLE_ENDIAN.
122
123 if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
124 little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
125 USEFULBUF_CONFIG_BSWAP. This should call the most efficient
126 system-defined byte swap method. However, note
127 https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
128 this is fixed now. Often hton() and ntoh() will call the built-in
129 __builtin_bswapXX()() function, so this size issue could affect
130 USEFULBUF_CONFIG_HTON.
131
132 Last, run the tests. They must all pass.
133
134 These #define config options affect the inline implementation of
135 UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
136 also affect the 16-, 32-bit, float and double versions of these
Laurence Lundblade4c0883e2020-04-21 18:33:39 -0700137 instructions. Since they are inline, the size effect is not in the
Michael Eckel5c531332020-03-02 01:35:30 +0100138 UsefulBuf object code, but in the calling code.
139
140 Summary:
141 USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
142 USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
143 USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
144 handle big and little-endian with system option.
145 USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
146 use __builtin_bswapXX().
147 */
148
149#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
150#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
151#endif
152
153
154#include <stdint.h> // for uint8_t, uint16_t....
155#include <string.h> // for strlen, memcpy, memmove, memset
156#include <stddef.h> // for size_t
157
158
159#ifdef USEFULBUF_CONFIG_HTON
160#include <arpa/inet.h> // for htons, htonl, htonll, ntohs...
161#endif
162
163#ifdef __cplusplus
164extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700165#if 0
166} // Keep editor indention formatting happy
167#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100168#endif
169
170/**
171 @file UsefulBuf.h
172
173 The goal of this code is to make buffer and pointer manipulation
174 easier and safer when working with binary data.
175
176 The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
177 structures are used to represent buffers rather than ad hoc pointers and
178 lengths.
179
180 With these it will often be possible to write code that does little
181 or no direct pointer manipulation for copying and formatting
182 data. For example, the QCBOR encoder was written using these and
183 has no less pointer manipulation.
184
185 While it is true that object code using these functions will be a
186 little larger and slower than a white-knuckle clever use of pointers
187 might be, but not by that much or enough to have an effect for most
188 use cases. For security-oriented code this is highly
189 worthwhile. Clarity, simplicity, reviewability and are more
190 important.
191
192 There are some extra sanity and double checks in this code to help
193 catch coding errors and simple memory corruption. They are helpful,
194 but not a substitute for proper code review, input validation and
195 such.
196
197 This code consists of a lot of inline functions and a few that are
198 not. It should not generate very much object code, especially with
199 the optimizer turned up to @c -Os or @c -O3.
200 */
201
202
203/**
204 @ref UsefulBufC and @ref UsefulBuf are simple data structures to hold
205 a pointer and length for binary data. In C99 this data structure can
206 be passed on the stack making a lot of code cleaner than carrying
207 around a pointer and length as two parameters.
208
209 This is also conducive to secure coding practice as the length is
210 always carried with the pointer and the convention for handling a
211 pointer and a length is clear.
212
213 While it might be possible to write buffer and pointer code more
214 efficiently in some use cases, the thought is that unless there is an
215 extreme need for performance (e.g., you are building a
216 gigabit-per-second IP router), it is probably better to have cleaner
217 code you can be most certain about the security of.
218
219 The non-const @ref UsefulBuf is usually used to refer a buffer to be
220 filled in. The length is the size of the buffer.
221
222 The const @ref UsefulBufC is usually used to refer to some data that
223 has been filled in. The length is amount of valid data pointed to.
224
225 A common use is to pass a @ref UsefulBuf to a function, the function
226 fills it in, the function returns a @ref UsefulBufC. The pointer is
227 the same in both.
228
229 A @ref UsefulBuf is null, it has no value, when @c ptr in it is @c NULL.
230
231 There are utility functions for the following:
232 - Initializing
233 - Create initialized const @ref UsefulBufC from compiler literals
234 - Create initialized const @ref UsefulBufC from NULL-terminated string
235 - Make an empty @ref UsefulBuf on the stack
236 - Checking whether a @ref UsefulBuf is null, empty or both
237 - Copying, copying with offset, copying head or tail
238 - Comparing and finding substrings
239
240 See also @ref UsefulOutBuf. It is a richer structure that has both
241 the size of the valid data and the size of the buffer.
242
243 @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it
244 can go on the stack and be a function parameter or return value.
245
246 Another way to look at it is this. C has the NULL-terminated string
247 as a means for handling text strings, but no means or convention for
248 binary strings. Other languages do have such means, Rust, an
249 efficient compiled language, for example.
250
251 @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his
252 birthday. Eeyore's balloon fits beautifully, "it goes in and out
253 like anything".
254*/
255typedef struct q_useful_buf_c {
256 const void *ptr;
257 size_t len;
258} UsefulBufC;
259
260
261/**
262 This non-const @ref UsefulBuf is typically used for some allocated
263 memory that is to be filled in. The @c len is the amount of memory,
264 not the length of the valid data in the buffer.
265 */
266typedef struct q_useful_buf {
267 void *ptr;
268 size_t len;
269} UsefulBuf;
270
271
272/**
273 A null @ref UsefulBufC is one that has no value in the same way a @c
274 NULL pointer has no value. A @ref UsefulBufC is @c NULL when the @c
275 ptr field is @c NULL. It doesn't matter what @c len is. See
276 UsefulBuf_IsEmpty() for the distinction between null and empty.
277 */
278#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
279
280
281/**
282 A null @ref UsefulBuf is one that has no memory associated the same
283 way @c NULL points to nothing. It does not matter what @c len is.
284 */
285#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
286
287
288/**
289 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
290
291 @param[in] UB The UsefulBuf to check.
292
293 @return 1 if it is @ref NULLUsefulBuf, 0 if not.
294 */
295static inline int UsefulBuf_IsNULL(UsefulBuf UB);
296
297
298/**
299 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
300
301 @param[in] UB The @ref UsefulBufC to check.
302
303 @return 1 if it is @c NULLUsefulBufC, 0 if not.
304 */
305static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
306
307
308/**
309 @brief Check if a @ref UsefulBuf is empty or not.
310
311 @param[in] UB The @ref UsefulBuf to check.
312
313 @return 1 if it is empty, 0 if not.
314
315 An "empty" @ref UsefulBuf is one that has a value and can be
316 considered to be set, but that value is of zero length. It is empty
317 when @c len is zero. It doesn't matter what the @c ptr is.
318
319 A lot of uses will not need to clearly distinguish a @c NULL @ref
320 UsefulBuf from an empty one and can have the @c ptr @c NULL and the
321 @c len 0. However if a use of @ref UsefulBuf needs to make a
322 distinction then @c ptr should not be @c NULL when the @ref UsefulBuf
323 is considered empty, but not @c NULL.
324 */
325static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
326
327
328/**
329 @brief Check if a @ref UsefulBufC is empty or not.
330
331 @param[in] UB The @ref UsefulBufC to check.
332
333 @return 1 if it is empty, 0 if not.
334 */
335static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
336
337
338/**
339 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
340
341 @param[in] UB The @ref UsefulBuf to check.
342
343 @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
344 */
345static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
346
347
348/**
349 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
350
351 @param[in] UB The @ref UsefulBufC to check.
352
353 @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
354 */
355static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
356
357
358/**
359 @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
360
361 @param[in] UB The @ref UsefulBuf to convert.
362
363 @return A @ref UsefulBufC struct.
364 */
365static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
366
367
368/**
369 @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
370
371 @param[in] UBC The @ref UsefulBuf to convert.
372
373 @return A non-const @ref UsefulBuf struct.
374 */
375static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
376
377
378/**
379 Convert a literal string to a @ref UsefulBufC.
380
381 @c szString must be a literal string that @c sizeof() works on. This
382 is better for literal strings than UsefulBuf_FromSZ() because it
383 generates less code. It will not work on non-literal strings.
384
385 The terminating \0 (NULL) is NOT included in the length!
386 */
387#define UsefulBuf_FROM_SZ_LITERAL(szString) \
388 ((UsefulBufC) {(szString), sizeof(szString)-1})
389
390
391/**
392 Convert a literal byte array to a @ref UsefulBufC.
393
394 @c pBytes must be a literal string that @c sizeof() works on. It
395 will not work on non-literal arrays.
396 */
397#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
398 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
399
400
401/**
402 Make an automatic variable named @c name of type @ref UsefulBuf and
403 point it to a stack variable of the given @c size.
404 */
405#define UsefulBuf_MAKE_STACK_UB(name, size) \
406 uint8_t __pBuf##name[(size)];\
407 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
408
409
410/**
411 Make a byte array in to a @ref UsefulBuf. This is usually used on
412 stack variables or static variables. Also see @ref
413 UsefulBuf_MAKE_STACK_UB.
414 */
415#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
416 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
417
418
419/**
420 @brief Convert a NULL-terminated string to a @ref UsefulBufC.
421
422 @param[in] szString The string to convert.
423
424 @return A @ref UsefulBufC struct.
425
426 @c UsefulBufC.ptr points to the string so its lifetime must be
427 maintained.
428
429 The terminating \0 (NULL) is NOT included in the length.
430 */
431static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
432
433
434/**
435 @brief Copy one @ref UsefulBuf into another at an offset.
436
437 @param[in] Dest Destination buffer to copy into.
438 @param[in] uOffset The byte offset in @c Dest at which to copy to.
439 @param[in] Src The bytes to copy.
440
441 @return Pointer and length of the copy or @ref NULLUsefulBufC.
442
443 This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
444 size of @c Dest.
445
446 This fails and returns @ref NULLUsefulBufC if the @c Src length plus
447 @c uOffset is greater than the length of @c Dest.
448
449 The results are undefined if @c Dest and @c Src overlap.
450
451 This assumes that there is valid data in @c Dest up to @c
452 uOffset. The @ref UsefulBufC returned starts at the beginning of @c
453 Dest and goes to @c Src.len @c + @c uOffset.
454 */
455UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
456
457
458/**
459 @brief Copy one @ref UsefulBuf into another.
460
461 @param[in] Dest The destination buffer to copy into.
462 @param[out] Src The source to copy from.
463
464 @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
465 on failure.
466
467 This fails if @c Src.len is greater than @c Dest.len.
468
469 Note that like @c memcpy(), the pointers are not checked and this
470 will crash rather than return @ref NULLUsefulBufC if they are @c
471 NULL or invalid.
472
473 The results are undefined if @c Dest and @c Src overlap.
474 */
475static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
476
477
478/**
479 @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
480
481 @param[in] pDest The destination buffer to copy into.
482 @param[in] value The value to set the bytes to.
483
484 Note that like @c memset(), the pointer in @c pDest is not checked
485 and this will crash if @c NULL or invalid.
486 */
487static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
488
489
490/**
491 @brief Copy a pointer into a @ref UsefulBuf.
492
493 @param[in,out] Dest The destination buffer to copy into.
494 @param[in] ptr The source to copy from.
495 @param[in] uLen Length of the source; amount to copy.
496
497 @return 0 on success, 1 on failure.
498
499 This fails and returns @ref NULLUsefulBufC if @c uLen is greater than
500 @c pDest->len.
501
502 Note that like @c memcpy(), the pointers are not checked and this
503 will crash, rather than return 1 if they are @c NULL or invalid.
504 */
505static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
506 const void *ptr,
507 size_t uLen);
508
509
510/**
511 @brief Returns a truncation of a @ref UsefulBufC.
512
513 @param[in] UB The buffer to get the head of.
514 @param[in] uAmount The number of bytes in the head.
515
516 @return A @ref UsefulBufC that is the head of UB.
517 */
518static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
519
520
521/**
522 @brief Returns bytes from the end of a @ref UsefulBufC.
523
524 @param[in] UB The buffer to get the tail of.
525 @param[in] uAmount The offset from the start where the tail is to begin.
526
527 @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
528 if @c uAmount is greater than the length of the @ref UsefulBufC.
529
530 If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
531 be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
532 of the tail.
533 */
534static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
535
536
537/**
538 @brief Compare one @ref UsefulBufC to another.
539
540 @param[in] UB1 The first buffer to compare.
541 @param[in] UB2 The second buffer to compare.
542
543 @return 0, positive or negative value.
544
545 Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
546 less than @c UB2 if it is shorter or the first byte that is not the
547 same is less.
548
549 Returns 0 if the inputs are the same.
550
551 Returns a positive value if @c UB2 is less than @c UB1.
552
553 All that is of significance is that the result is positive, negative
554 or 0. (This doesn't return the difference between the first
555 non-matching byte like @c memcmp() ).
556 */
557int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
558
559
560/**
561 @brief Find first byte that is not a particular byte value.
562
563 @param[in] UB The destination buffer for byte comparison.
564 @param[in] uValue The byte value to compare to.
565
566 @return Offset of first byte that isn't @c uValue or
567 @c SIZE_MAX if all bytes are @c uValue.
568
569 Note that unlike most comparison functions, 0
570 does not indicate a successful comparison, so the
571 test for match is:
572
573 UsefulBuf_IsValue(...) == SIZE_MAX
574
575 If @c UB is null or empty, there is no match
576 and 0 is returned.
577 */
578size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
579
580
581/**
582 @brief Find one @ref UsefulBufC in another.
583
584 @param[in] BytesToSearch Buffer to search through.
585 @param[in] BytesToFind Buffer with bytes to be found.
586
587 @return Position of found bytes or @c SIZE_MAX if not found.
588 */
589size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
590
591
592#if 1 // NOT_DEPRECATED
593/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
594#define SZLiteralToUsefulBufC(szString) \
595 ((UsefulBufC) {(szString), sizeof(szString)-1})
596
597/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
598#define MakeUsefulBufOnStack(name, size) \
599 uint8_t __pBuf##name[(size)];\
600 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
601
602/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
603#define ByteArrayLiteralToUsefulBufC(pBytes) \
604 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
605
606/** Deprecated function; use UsefulBuf_Unconst() instead */
607static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
608{
609 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
610}
611#endif
612
613
614
615
616/**
617 @brief Copy a @c float to a @c uint32_t.
618
619 @param[in] f Float value to copy.
620
621 @return A @c uint32_t with the float bits.
622
623 Convenience function to avoid type punning, compiler warnings and
624 such. The optimizer usually reduces this to a simple assignment. This
625 is a crusty corner of C.
626 */
627static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
628
629
630/**
631 @brief Copy a @c double to a @c uint64_t.
632
633 @param[in] d Double value to copy.
634
635 @return A @c uint64_t with the double bits.
636
637 Convenience function to avoid type punning, compiler warnings and
638 such. The optimizer usually reduces this to a simple assignment. This
639 is a crusty corner of C.
640 */
641static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
642
643
644/**
645 @brief Copy a @c uint32_t to a @c float.
646
647 @param[in] u32 Integer value to copy.
648
649 @return The value as a @c float.
650
651 Convenience function to avoid type punning, compiler warnings and
652 such. The optimizer usually reduces this to a simple assignment. This
653 is a crusty corner of C.
654 */
655static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
656
657
658/**
659 @brief Copy a @c uint64_t to a @c double.
660
661 @param[in] u64 Integer value to copy.
662
663 @return The value as a @c double.
664
665 Convenience function to avoid type punning, compiler warnings and
666 such. The optimizer usually reduces this to a simple assignment. This
667 is a crusty corner of C.
668 */
669static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
670
671
672
673
674/**
675 UsefulOutBuf is a structure and functions (an object) for serializing
676 data into a buffer when encoding a network protocol or writing data
677 to file.
678
679 The main idea is that all the pointer manipulation is performed by
680 @ref UsefulOutBuf functions so the caller doesn't have to do any
681 pointer manipulation. The pointer manipulation is centralized. This
682 code will have been reviewed and written carefully so it spares the
683 caller of much of this work and results in safer code with less work.
684
685 The @ref UsefulOutBuf methods that add data to the output buffer
686 always check the length and will never write off the end of the
687 output buffer. If an attempt to add data that will not fit is made,
688 an internal error flag will be set and further attempts to add data
689 will not do anything.
690
691 There is no way to ever write off the end of that buffer when calling
692 the @c UsefulOutBuf_AddXxx() and @c UsefulOutBuf_InsertXxx()
693 functions.
694
695 The functions to add data do not return an error. The working model
696 is that all calls to add data are made without an error check. Errors
697 are just checked for once after all the data has been added before the
698 and before serialized data is to be used. This makes the calling code
699 cleaner.
700
701 There is a utility function to get the error status anytime along the
702 way for a special circumstance. There are functions to see how much
703 room is left and see if some data will fit too, but their use is
704 generally not necessary.
705
706 The general call flow is:
707
708 - Initialize by calling @ref UsefulOutBuf_Init(). The output
709 buffer given to it can be from the heap, stack or
710 otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience macro
711 that makes a buffer on the stack and initializes it.
712
713 - Call methods like UsefulOutBuf_InsertString(),
714 UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
715 to output data. The append calls add data to the end of the
716 valid data. The insert calls take a position argument.
717
718 - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
719 there were no errors and to get the serialized output bytes.
720
721 @ref UsefulOutBuf can be used in a size calculation mode to calculate
722 the size of output that would be generated. This is useful to
723 calculate the size of a buffer that is to be allocated to hold the
724 output. To use @ref UsefulOutBuf in this mode, call
725 UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
726 @c (UsefulBuf){NULL,MAX_UINT32}. Then call all the Insert and Add
727 functions. No attempt will made to actually copy data, so only the
728 lengths have to be valid for these calls.
729
730 Methods like UsefulOutBuf_InsertUint64() always output in network
731 bytes order (big endian).
732
733 The possible errors are:
734 - The @ref UsefulOutBuf was not initialized or was corrupted.
735
736 - An attempt was made to add data that will not fit.
737
738 - An attempt was made to insert data at a position beyond the end of
739 the buffer.
740
741 - An attempt was made to insert data at a position beyond the valid
742 data in the buffer.
743
744 Some inexpensive simple sanity checks are performed before every data
745 addition to guard against use of an uninitialized or corrupted
746 UsefulOutBuf.
747
748 This has been used to create a CBOR encoder. The CBOR encoder has
749 almost no pointer manipulation in it, is easier to read, and easier
750 to review.
751
752 A @ref UsefulOutBuf is small and can go on the stack:
753 - 32 bytes (27 bytes plus alignment padding) on a 64-bit machine
754 - 16 bytes (15 bytes plus alignment padding) on a 32-bit machines
755 */
756typedef struct useful_out_buf {
757 // PRIVATE DATA STRUCTURE
758 UsefulBuf UB; // Memory that is being output to
759 size_t data_len; // length of the data
760 uint16_t magic; // Used to detect corruption and lack of initialization
761 uint8_t err;
762} UsefulOutBuf;
763
764
765/**
766 @brief Initialize and supply the actual output buffer.
767
768 @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
769 @param[in] Storage Buffer to output into.
770
771 Initializes the @ref UsefulOutBuf with storage. Sets the current
772 position to the beginning of the buffer clears the error.
773
774 This must be called before the @ref UsefulOutBuf is used.
775 */
776void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
777
778
779/**
780 Convenience macro to make a @ref UsefulOutBuf on the stack and
781 initialize it with a stack buffer of the given size. The variable
782 will be named @c name.
783 */
784#define UsefulOutBuf_MakeOnStack(name, size) \
785 uint8_t __pBuf##name[(size)];\
786 UsefulOutBuf name;\
787 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
788
789
790/**
791 @brief Reset a @ref UsefulOutBuf for re use
792
793 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
794
795 This sets the amount of data in the output buffer to none and clears
796 the error state.
797
798 The output buffer is still the same one and size as from the
799 UsefulOutBuf_Init() call.
800
801 This doesn't zero the data, just resets to 0 bytes of valid data.
802 */
803static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
804
805
806/**
807 @brief Returns position of end of data in the @ref UsefulOutBuf.
808
809 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
810
811 @return position of end of data.
812
813 On a freshly initialized @ref UsefulOutBuf with no data added, this
814 will return 0. After 10 bytes have been added, it will return 10 and
815 so on.
816
817 Generally callers will not need this function for most uses of @ref
818 UsefulOutBuf.
819 */
820static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
821
822
823/**
824 @brief Returns whether any data has been added to the @ref UsefulOutBuf.
825
826 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
827
828 @return 1 if output position is at start.
829 */
830static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
831
832
833/**
834 @brief Inserts bytes into the @ref UsefulOutBuf.
835
836 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
837 @param[in] NewData The bytes to insert.
838 @param[in] uPos Index in output buffer at which to insert.
839
840 @c NewData is the pointer and length for the bytes to be added to the
841 output buffer. There must be room in the output buffer for all of @c
842 NewData or an error will occur.
843
844 The insertion point must be between 0 and the current valid data. If
845 not, an error will occur. Appending data to the output buffer is
846 achieved by inserting at the end of the valid data. This can be
847 retrieved by calling UsefulOutBuf_GetEndPosition().
848
849 When insertion is performed, the bytes between the insertion point
850 and the end of data previously added to the output buffer are slid to
851 the right to make room for the new data.
852
853 Overlapping buffers are OK. @c NewData can point to data in the
854 output buffer.
855
856 If an error occurs an error state is set in the @ref UsefulOutBuf. No
857 error is returned. All subsequent attempts to add data will do
858 nothing.
859
860 The intended use is that all additions are made without checking for
861 an error. The error will be taken into account when
862 UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
863 UsefulOutBuf_GetError() can also be called to check for an error.
864 */
865void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
866 UsefulBufC NewData,
867 size_t uPos);
868
869
870/**
871 @brief Insert a data buffer into the @ref UsefulOutBuf.
872
873 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
874 @param[in] pBytes Pointer to the bytes to insert
875 @param[in] uLen Length of the bytes to insert
876 @param[in] uPos Index in output buffer at which to insert
877
878 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
879 the difference being a pointer and length is passed in rather than an
880 @ref UsefulBufC.
881 */
882static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
883 const void *pBytes,
884 size_t uLen,
885 size_t uPos);
886
887
888/**
889 @brief Insert a NULL-terminated string into the UsefulOutBuf.
890
891 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
892 @param[in] szString NULL-terminated string to insert.
893 @param[in] uPos Index in output buffer at which to insert.
894 */
895static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
896 const char *szString,
897 size_t uPos);
898
899
900/**
901 @brief Insert a byte into the @ref UsefulOutBuf.
902
903 @param[in] pUOutBuf Pointer to the UsefulOutBuf.
904 @param[in] byte Bytes to insert.
905 @param[in] uPos Index in output buffer at which to insert.
906
907 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
908 the difference being a single byte is to be inserted.
909 */
910static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
911 uint8_t byte,
912 size_t uPos);
913
914
915/**
916 @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
917
918 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
919 @param[in] uInteger16 Integer to insert.
920 @param[in] uPos Index in output buffer at which to insert.
921
922 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
923 the difference being a two-byte integer is to be inserted.
924
925 The integer will be inserted in network byte order (big endian).
926 */
927static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
928 uint16_t uInteger16,
929 size_t uPos);
930
931
932/**
933 @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
934
935 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
936 @param[in] uInteger32 Integer to insert.
937 @param[in] uPos Index in output buffer at which to insert.
938
939 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
940 the difference being a four-byte integer is to be inserted.
941
942 The integer will be inserted in network byte order (big endian).
943 */
944static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
945 uint32_t uInteger32,
946 size_t uPos);
947
948
949/**
950 @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
951
952 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
953 @param[in] uInteger64 Integer to insert.
954 @param[in] uPos Index in output buffer at which to insert.
955
956 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
957 the difference being an eight-byte integer is to be inserted.
958
959 The integer will be inserted in network byte order (big endian).
960 */
961static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
962 uint64_t uInteger64,
963 size_t uPos);
964
965
966/**
967 @brief Insert a @c float into the @ref UsefulOutBuf.
968
969 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
970 @param[in] f @c float to insert.
971 @param[in] uPos Index in output buffer at which to insert.
972
973 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
974 the difference being a @c float is to be inserted.
975
976 The @c float will be inserted in network byte order (big endian).
977 */
978static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
979 float f,
980 size_t uPos);
981
982
983/**
984 @brief Insert a @c double into the @ref UsefulOutBuf.
985
986 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
987 @param[in] d @c double to insert.
988 @param[in] uPos Index in output buffer at which to insert.
989
990 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
991 the difference being a @c double is to be inserted.
992
993 The @c double will be inserted in network byte order (big endian).
994 */
995static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
996 double d,
997 size_t uPos);
998
999
1000/**
1001 @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1002
1003 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1004 @param[in] NewData The @ref UsefulBuf with the bytes to append.
1005
1006 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1007 with the insertion point at the end of the valid data.
1008*/
1009static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1010 UsefulBufC NewData);
1011
1012
1013/**
1014 @brief Append bytes to the @ref UsefulOutBuf.
1015
1016 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1017 @param[in] pBytes Pointer to bytes to append.
1018 @param[in] uLen Length of @c pBytes to append.
1019
1020 See UsefulOutBuf_InsertData() for details. This does the same
1021 with the insertion point at the end of the valid data.
1022 */
1023static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1024 const void *pBytes,
1025 size_t uLen);
1026
1027
1028/**
1029 @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1030
1031 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1032 @param[in] szString NULL-terminated string to append.
1033 */
1034static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1035 const char *szString);
1036
1037
1038/**
1039 @brief Append a byte to the @ref UsefulOutBuf
1040
1041 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1042 @param[in] byte Bytes to append.
1043
1044 See UsefulOutBuf_InsertByte() for details. This does the same
1045 with the insertion point at the end of the valid data.
1046 */
1047static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1048 uint8_t byte);
1049
1050
1051/**
1052 @brief Append an integer to the @ref UsefulOutBuf
1053
1054 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1055 @param[in] uInteger16 Integer to append.
1056
1057 See UsefulOutBuf_InsertUint16() for details. This does the same
1058 with the insertion point at the end of the valid data.
1059
1060 The integer will be appended in network byte order (big endian).
1061 */
1062static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1063 uint16_t uInteger16);
1064
1065
1066/**
1067 @brief Append an integer to the @ref UsefulOutBuf
1068
1069 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1070 @param[in] uInteger32 Integer to append.
1071
1072 See UsefulOutBuf_InsertUint32() for details. This does the same
1073 with the insertion point at the end of the valid data.
1074
1075 The integer will be appended in network byte order (big endian).
1076 */
1077static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1078 uint32_t uInteger32);
1079
1080
1081/**
1082 @brief Append an integer to the @ref UsefulOutBuf
1083
1084 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1085 @param[in] uInteger64 Integer to append.
1086
1087 See UsefulOutBuf_InsertUint64() for details. This does the same
1088 with the insertion point at the end of the valid data.
1089
1090 The integer will be appended in network byte order (big endian).
1091 */
1092static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1093 uint64_t uInteger64);
1094
1095
1096/**
1097 @brief Append a @c float to the @ref UsefulOutBuf
1098
1099 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1100 @param[in] f @c float to append.
1101
1102 See UsefulOutBuf_InsertFloat() for details. This does the same
1103 with the insertion point at the end of the valid data.
1104
1105 The float will be appended in network byte order (big endian).
1106 */
1107static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1108 float f);
1109
1110
1111/**
1112 @brief Append a @c double to the @ref UsefulOutBuf
1113
1114 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1115 @param[in] d @c double to append.
1116
1117 See UsefulOutBuf_InsertDouble() for details. This does the same
1118 with the insertion point at the end of the valid data.
1119
1120 The double will be appended in network byte order (big endian).
1121 */
1122static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1123 double d);
1124
1125
1126/**
1127 @brief Returns the current error status.
1128
1129 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1130
1131 @return 0 if all OK, 1 on error.
1132
1133 This is the error status since the call to either
1134 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1135 state it will stay until one of those functions is called.
1136
1137 Possible error conditions are:
1138 - bytes to be inserted will not fit
1139 - insertion point is out of buffer or past valid data
1140 - current position is off end of buffer (probably corrupted or uninitialized)
1141 - detect corruption / uninitialized by bad magic number
1142 */
1143static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1144
1145
1146/**
1147 @brief Returns number of bytes unused used in the output buffer.
1148
1149 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1150
1151 @return Number of unused bytes or zero.
1152
1153 Because of the error handling strategy and checks in
1154 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1155 this.
1156 */
1157static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1158
1159
1160/**
1161 @brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1162
1163 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1164 @param[in] uLen Number of bytes for which to check
1165
1166 @return 1 if @c uLen bytes will fit, 0 if not.
1167
1168 Because of the error handling strategy and checks in
1169 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1170 this.
1171 */
1172static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1173
1174
1175 /**
1176 @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1177
1178 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1179
1180 @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1181
1182 Giving a @c NULL output buffer to UsefulOutBuf_Init() is used
1183 when just calculating the length of the encoded data.
1184 */
1185static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1186
1187
1188/**
1189 @brief Returns the resulting valid data in a UsefulOutBuf
1190
1191 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1192
1193 @return The valid data in @ref UsefulOutBuf or
1194 @ref NULLUsefulBufC if there was an error adding data.
1195
1196 The storage for the returned data is the @c Storage parameter passed
1197 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1198
1199 This can be called anytime and many times to get intermediate
1200 results. It doesn't change the data or reset the current position
1201 so you can keep adding data.
1202 */
1203UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1204
1205
1206/**
1207 @brief Copies the valid data into a supplied buffer
1208
1209 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1210 @param[out] Dest The destination buffer to copy into.
1211
1212 @return Pointer and length of copied data or @c NULLUsefulBufC
1213 if it will not fit in the @c Dest buffer.
1214
1215 This is the same as UsefulOutBuf_OutUBuf() except it copies the data
1216 to @c Dest.
1217*/
1218UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1219
1220
1221
1222
1223/**
1224 @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf and is
1225 for parsing data read or received. Initialize it with the data from
1226 the network. Then use the functions here to get data chunks of
1227 various types. A position cursor is maintained internally.
1228
1229 As long as the functions here are used, there will never be a
1230 reference off the end of the given buffer. This is true even if they
1231 care called incorrectly, an attempt is made to seek of the end of the
1232 buffer, etc. This makes it easier to write safe and correct code.
1233 For example, the QCBOR decoder implementation is safer and easier to
1234 review through its use of @ref UsefulInputBuf.
1235
1236 @ref UsefulInputBuf maintains an internal error state. The
1237 intended use is that data chunks can be fetched without error
1238 checking until the end. Once data has been requested off the end of
1239 the buffer, the error state is entered. In the error state the
1240 @c UsefulInputBuf_GetXxxx() functions return 0, or @c NULL or
1241 @ref NULLUsefulBufC. As long as null are not dereferenced, the
1242 error check can be put off until the end, simplifying the calling
1243 code.
1244
1245 The integer and float parsing expects network byte order (big
1246 endian). Network byte order is what is used by TCP/IP, CBOR and most
1247 internet protocols.
1248
1249 Lots of inline functions are used to keep code size down. The code
1250 optimizer, particularly with the @c -Os or @c -O3, also reduces code
1251 size a lot. The only non-inline code is UsefulInputBuf_GetBytes()
1252 which is less than 100 bytes so use of @ref UsefulInputBuf doesn't
1253 add much code for all the messy hard-to-get right issues with parsing
1254 in C that is solves.
1255
1256 The parse context size is:
1257 - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1258 - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1259 */
1260typedef struct useful_input_buf {
1261 // PRIVATE DATA STRUCTURE
1262 UsefulBufC UB; // Data being parsed
1263 size_t cursor; // Current offset in data being parse
1264 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1265 uint8_t err; // Set request goes off end or magic number is bad
1266} UsefulInputBuf;
1267
1268#define UIB_MAGIC (0xB00F)
1269
1270
1271/**
1272 @brief Initialize the UsefulInputBuf structure before use.
1273
1274 @param[in] pUInBuf Pointer to the UsefulInputBuf instance.
1275 @param[in] UB The data to parse.
1276 */
1277static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1278
1279
1280/**
1281 @brief Returns current position in input buffer.
1282
1283 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1284
1285 @return Integer position of the cursor.
1286
1287 The position that the next bytes will be returned from.
1288 */
1289static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1290
1291
1292/**
1293 @brief Sets the current position in input buffer.
1294
1295 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1296 @param[in] uPos Position to set to.
1297
1298 If the position is off the end of the input buffer, the error state
1299 is entered, and all functions will do nothing.
1300
1301 Seeking to a valid position in the buffer will not reset the error
1302 state. Only re initialization will do that.
1303 */
1304static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1305
1306
1307/**
1308 @brief Returns the number of bytes from the cursor to the end of the buffer,
1309 the unconsumed bytes.
1310
1311 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1312
1313 @return Number of bytes unconsumed or 0 on error.
1314
1315 This is a critical function for input length validation.
1316
1317 Returns 0 if the cursor it invalid or corruption of the structure is
1318 detected.
1319 */
1320static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1321
1322
1323/**
1324 @brief Check if there are any unconsumed bytes.
1325
1326 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1327 @param[in] uLen Number of bytes to check availability for.
1328
1329 @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
1330 */
1331static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1332
1333
1334/**
1335 @brief Get pointer to bytes out of the input buffer.
1336
1337 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1338 @param[in] uNum Number of bytes to get.
1339
1340 @return Pointer to bytes.
1341
1342 This consumes @c uNum bytes from the input buffer. It returns a
1343 pointer to the start of the @c uNum bytes.
1344
1345 If there are not @c uNum bytes in the input buffer, @c NULL will be
1346 returned and an error will be set.
1347
1348 It advances the current position by @c uNum bytes.
1349 */
1350const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1351
1352
1353/**
1354 @brief Get @ref UsefulBuf out of the input buffer.
1355
1356 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1357 @param[in] uNum Number of bytes to get.
1358
1359 @return A @ref UsefulBufC with ptr and length of bytes consumed.
1360
1361 This consumes @c uNum bytes from the input buffer and returns the
1362 pointer and length for them as a @ref UsefulBufC. The length returned
1363 will always be @c uNum.
1364
1365 If there are not @c uNum bytes in the input buffer, @ref NULLUsefulBufC
1366 will be returned and the error state is set.
1367
1368 It advances the current position by @c uNum bytes.
1369 */
1370static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1371
1372
1373/**
1374 @brief Get a byte out of the input buffer.
1375
1376 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1377
1378 @return The byte.
1379
1380 This consumes 1 byte from the input buffer. It returns the byte.
1381
1382 If there is not 1 byte in the buffer, 0 will be returned for the byte
1383 and an error set internally. You must check the error at some point
1384 to know whether the 0 was the real value or just returned in error,
1385 but you may not have to do that right away. Check the error state
1386 with UsefulInputBuf_GetError(). You can also know you are in the
1387 error state if UsefulInputBuf_GetBytes() returns @c NULL or the @c
1388 ptr from UsefulInputBuf_GetUsefulBuf() is @c NULL.
1389
1390 It advances the current position by 1 byte.
1391 */
1392static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1393
1394
1395/**
1396 @brief Get a @c uint16_t out of the input buffer.
1397
1398 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1399
1400 @return The @c uint16_t.
1401
1402 See UsefulInputBuf_GetByte(). This works the same, except it returns
1403 a @c uint16_t and two bytes are consumed.
1404
1405 The input bytes must be in network order (big endian).
1406 */
1407static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1408
1409
1410/**
1411 @brief Get a uint32_t out of the input buffer.
1412
1413 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1414
1415 @return The @c uint32_t.
1416
1417 See UsefulInputBuf_GetByte(). This works the same, except it returns
1418 a @c uint32_t and four bytes are consumed.
1419
1420 The input bytes must be in network order (big endian).
1421 */
1422static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1423
1424
1425/**
1426 @brief Get a uint64_t out of the input buffer.
1427
1428 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1429
1430 @return The uint64_t.
1431
1432 See UsefulInputBuf_GetByte(). This works the same, except it returns
1433 a @c uint64_t and eight bytes are consumed.
1434
1435 The input bytes must be in network order (big endian).
1436 */
1437static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1438
1439
1440/**
1441 @brief Get a float out of the input buffer.
1442
1443 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1444
1445 @return The float.
1446
1447 See UsefulInputBuf_GetByte(). This works the same, except it returns
1448 a float and four bytes are consumed.
1449
1450 The input bytes must be in network order (big endian).
1451 */
1452static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1453
1454
1455/**
1456 @brief Get a double out of the input buffer.
1457
1458 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1459
1460 @return The double.
1461
1462 See UsefulInputBuf_GetByte(). This works the same, except it returns
1463 a double and eight bytes are consumed.
1464
1465 The input bytes must be in network order (big endian).
1466 */
1467static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1468
1469
1470/**
1471 @brief Get the error status.
1472
1473 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1474
1475 @return 0 if there is no error, 1 if there is.
1476
1477 The error state is entered for one of these reasons:
1478 - Attempt to fetch data past the end of the buffer
1479 - Attempt to seek to a position past the end of the buffer
1480 - Attempt to get data from an uninitialized or corrupt instance
1481 of @ref UsefulInputBuf
1482
1483 Once in the error state, it can only be cleared by calling
1484 UsefulInputBuf_Init().
1485
1486 You may be able to only check the error state at the end after all
1487 the UsefulInputBuf_GetXxxx() calls have been made, but if what you
1488 get later depends on what you get sooner you cannot. For example,
1489 if you get a length or count of following items you will have to
1490 check the error.
1491 */
1492static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1493
1494
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001495/**
1496 @brief Sets the input buffer length (use with caution)
1497
1498 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1499
1500 This changes the internal remembered length of the input buffer
1501 set when UsefulInputBuf_Init() was called. It is used by QCBOR
1502 to handle CBOR that is wrapped and embedded in CBOR.
1503
1504 Since this allows setting the length beyond the length of the
1505 original input buffer it allows the overall safety to
1506 be undermined.
1507
1508 The new length given here should always be equal to or less than
1509 the length given when UsefulInputBuf_Init() was called.
1510
1511 */
1512static void UsefulInputBuf_SetBufferLen(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001513
1514
1515/*----------------------------------------------------------
1516 Inline implementations.
1517 */
1518static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1519{
1520 return !UB.ptr;
1521}
1522
1523
1524static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1525{
1526 return !UB.ptr;
1527}
1528
1529
1530static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1531{
1532 return !UB.len;
1533}
1534
1535
1536static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1537{
1538 return !UB.len;
1539}
1540
1541
1542static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1543{
1544 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1545}
1546
1547
1548static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1549{
1550 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1551}
1552
1553
1554static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1555{
1556 return (UsefulBufC){UB.ptr, UB.len};
1557}
1558
1559
1560static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1561{
1562 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
1563}
1564
1565
1566static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1567{
1568 return ((UsefulBufC) {szString, strlen(szString)});
1569}
1570
1571
1572static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1573{
1574 return UsefulBuf_CopyOffset(Dest, 0, Src);
1575}
1576
1577
1578static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
1579{
1580 memset(pDest.ptr, value, pDest.len);
1581 return (UsefulBufC){pDest.ptr, pDest.len};
1582}
1583
1584
1585static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1586{
1587 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
1588}
1589
1590
1591static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1592{
1593 if(uAmount > UB.len) {
1594 return NULLUsefulBufC;
1595 }
1596 return (UsefulBufC){UB.ptr, uAmount};
1597}
1598
1599
1600static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1601{
1602 UsefulBufC ReturnValue;
1603
1604 if(uAmount > UB.len) {
1605 ReturnValue = NULLUsefulBufC;
1606 } else if(UB.ptr == NULL) {
1607 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
1608 } else {
1609 ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
1610 }
1611
1612 return ReturnValue;
1613}
1614
1615
1616
1617static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1618{
1619 uint32_t u32;
1620 memcpy(&u32, &f, sizeof(uint32_t));
1621 return u32;
1622}
1623
1624static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1625{
1626 uint64_t u64;
1627 memcpy(&u64, &d, sizeof(uint64_t));
1628 return u64;
1629}
1630
1631static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1632{
1633 double d;
1634 memcpy(&d, &u64, sizeof(uint64_t));
1635 return d;
1636}
1637
1638static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1639{
1640 float f;
1641 memcpy(&f, &u32, sizeof(uint32_t));
1642 return f;
1643}
1644
1645
1646
1647
1648static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1649{
1650 pMe->data_len = 0;
1651 pMe->err = 0;
1652}
1653
1654
1655static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1656{
1657 return pMe->data_len;
1658}
1659
1660
1661static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1662{
1663 return 0 == pMe->data_len;
1664}
1665
1666
1667static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1668 const void *pBytes,
1669 size_t uLen,
1670 size_t uPos)
1671{
1672 UsefulBufC Data = {pBytes, uLen};
1673 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1674}
1675
1676
1677static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1678 const char *szString,
1679 size_t uPos)
1680{
1681 UsefulOutBuf_InsertUsefulBuf(pMe,
1682 (UsefulBufC){szString, strlen(szString)},
1683 uPos);
1684}
1685
1686
1687static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1688 uint8_t byte,
1689 size_t uPos)
1690{
1691 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1692}
1693
1694
1695static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1696 uint16_t uInteger16,
1697 size_t uPos)
1698{
1699 // See UsefulOutBuf_InsertUint64() for comments on this code
1700
1701 const void *pBytes;
1702
1703#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1704 pBytes = &uInteger16;
1705
1706#elif defined(USEFULBUF_CONFIG_HTON)
1707 uint16_t uTmp = htons(uInteger16);
1708 pBytes = &uTmp;
1709
1710#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1711 uint16_t uTmp = __builtin_bswap16(uInteger16);
1712 pBytes = &uTmp;
1713
1714#else
1715 uint8_t aTmp[2];
1716
1717 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1718 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1719
1720 pBytes = aTmp;
1721#endif
1722
1723 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1724}
1725
1726
1727static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1728 uint32_t uInteger32,
1729 size_t uPos)
1730{
1731 // See UsefulOutBuf_InsertUint64() for comments on this code
1732
1733 const void *pBytes;
1734
1735#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1736 pBytes = &uInteger32;
1737
1738#elif defined(USEFULBUF_CONFIG_HTON)
1739 uint32_t uTmp = htonl(uInteger32);
1740 pBytes = &uTmp;
1741
1742#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1743 uint32_t uTmp = __builtin_bswap32(uInteger32);
1744
1745 pBytes = &uTmp;
1746
1747#else
1748 uint8_t aTmp[4];
1749
1750 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1751 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1752 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1753 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1754
1755 pBytes = aTmp;
1756#endif
1757
1758 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1759}
1760
1761static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
1762 uint64_t uInteger64,
1763 size_t uPos)
1764{
1765 const void *pBytes;
1766
1767#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1768 // We have been told explicitly we are running on a big-endian
1769 // machine. Network byte order is big endian, so just copy. There
1770 // is no issue with alignment here because uInter64 is always
1771 // aligned (and it doesn't matter if pBytes is aligned).
1772 pBytes = &uInteger64;
1773
1774#elif defined(USEFULBUF_CONFIG_HTON)
1775 // Use system function to handle big- and little-endian. This works
1776 // on both big- and little-endian machines, but hton() is not
1777 // always available or in a standard place so it is not used by
1778 // default. With some compilers and CPUs the code for this is very
1779 // compact through use of a special swap instruction and on
1780 // big-endian machines hton() will reduce to nothing.
1781 uint64_t uTmp = htonll(uInteger64);
1782
1783 pBytes = &uTmp;
1784
1785#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1786 // Use built-in function for byte swapping. This usually compiles
1787 // to an efficient special byte swap instruction. Unlike hton() it
1788 // does not do this conditionally on the CPU endianness, so this
1789 // code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1790 uint64_t uTmp = __builtin_bswap64(uInteger64);
1791
1792 pBytes = &uTmp;
1793
1794#else
1795 // Default which works on every CPU with no dependency on anything
1796 // from the CPU, compiler, libraries or OS. This always works, but
1797 // it is usually a little larger and slower than hton().
1798 uint8_t aTmp[8];
1799
1800 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1801 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1802 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1803 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1804 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1805 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1806 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1807 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
1808
1809 pBytes = aTmp;
1810#endif
1811
1812 // Do the insert
1813 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
1814}
1815
1816
1817static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1818 float f,
1819 size_t uPos)
1820{
1821 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
1822}
1823
1824
1825static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1826 double d,
1827 size_t uPos)
1828{
1829 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
1830}
1831
1832
1833static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
1834 UsefulBufC NewData)
1835{
1836 // An append is just a insert at the end
1837 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
1838}
1839
1840
1841static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
1842 const void *pBytes,
1843 size_t uLen)
1844{
1845 UsefulBufC Data = {pBytes, uLen};
1846 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
1847}
1848
1849
1850static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
1851 const char *szString)
1852{
1853 UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
1854}
1855
1856
1857static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
1858 uint8_t byte)
1859{
1860 UsefulOutBuf_AppendData(pMe, &byte, 1);
1861}
1862
1863
1864static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
1865 uint16_t uInteger16)
1866{
1867 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
1868}
1869
1870static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
1871 uint32_t uInteger32)
1872{
1873 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
1874}
1875
1876
1877static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
1878 uint64_t uInteger64)
1879{
1880 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
1881}
1882
1883
1884static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
1885 float f)
1886{
1887 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
1888}
1889
1890
1891static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
1892 double d)
1893{
1894 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
1895}
1896
1897
1898static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
1899{
1900 return pMe->err;
1901}
1902
1903
1904static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
1905{
1906 return pMe->UB.len - pMe->data_len;
1907}
1908
1909
1910static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
1911{
1912 return uLen <= UsefulOutBuf_RoomLeft(pMe);
1913}
1914
1915
1916static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
1917{
1918 return pMe->UB.ptr == NULL;
1919}
1920
1921
1922
1923static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
1924{
1925 pMe->cursor = 0;
1926 pMe->err = 0;
1927 pMe->magic = UIB_MAGIC;
1928 pMe->UB = UB;
1929}
1930
1931static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
1932{
1933 return pMe->cursor;
1934}
1935
1936
Laurence Lundblade0750fc42020-06-20 21:02:34 -07001937static inline size_t UsefulInputBuf_GetLength(UsefulInputBuf *pMe)
1938{
1939 return pMe->UB.len;
1940}
1941
1942
Michael Eckel5c531332020-03-02 01:35:30 +01001943static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
1944{
1945 if(uPos > pMe->UB.len) {
1946 pMe->err = 1;
1947 } else {
1948 pMe->cursor = uPos;
1949 }
1950}
1951
1952
1953static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
1954{
1955 // Code Reviewers: THIS FUNCTION DOES POINTER MATH
1956
1957 // Magic number is messed up. Either the structure got overwritten
1958 // or was never initialized.
1959 if(pMe->magic != UIB_MAGIC) {
1960 return 0;
1961 }
1962
1963 // The cursor is off the end of the input buffer given.
1964 // Presuming there are no bugs in this code, this should never happen.
1965 // If it so, the struct was corrupted. The check is retained as
1966 // as a defense in case there is a bug in this code or the struct is
1967 // corrupted.
1968 if(pMe->cursor > pMe->UB.len) {
1969 return 0;
1970 }
1971
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001972 // subtraction can't go negative because of check above
Michael Eckel5c531332020-03-02 01:35:30 +01001973 return pMe->UB.len - pMe->cursor;
1974}
1975
1976
1977static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
1978{
1979 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
1980}
1981
1982
1983static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
1984{
1985 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
1986 if(!pResult) {
1987 return NULLUsefulBufC;
1988 } else {
1989 return (UsefulBufC){pResult, uNum};
1990 }
1991}
1992
1993
1994static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
1995{
1996 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
1997
1998 // The ternery operator is subject to integer promotion, because the
1999 // operands are smaller than int, so cast back to uint8_t is needed
2000 // to be completely explicit about types (for static analyzers)
2001 return (uint8_t)(pResult ? *(uint8_t *)pResult : 0);
2002}
2003
2004static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2005{
2006 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2007
2008 if(!pResult) {
2009 return 0;
2010 }
2011
2012 // See UsefulInputBuf_GetUint64() for comments on this code
2013#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2014 uint16_t uTmp;
2015 memcpy(&uTmp, pResult, sizeof(uint16_t));
2016
2017#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2018 return uTmp;
2019
2020#elif defined(USEFULBUF_CONFIG_HTON)
2021 return ntohs(uTmp);
2022
2023#else
2024 return __builtin_bswap16(uTmp);
2025
2026#endif
2027
2028#else
2029
2030 // The operations here are subject to integer promotion because the
2031 // operands are smaller than int. They will be promoted to unsigned
2032 // int for the shift and addition. The cast back to uint16_t is is needed
2033 // to be completely explicit about types (for static analyzers)
2034 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2035
2036#endif
2037}
2038
2039
2040static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2041{
2042 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2043
2044 if(!pResult) {
2045 return 0;
2046 }
2047
2048 // See UsefulInputBuf_GetUint64() for comments on this code
2049#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2050 uint32_t uTmp;
2051 memcpy(&uTmp, pResult, sizeof(uint32_t));
2052
2053#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2054 return uTmp;
2055
2056#elif defined(USEFULBUF_CONFIG_HTON)
2057 return ntohl(uTmp);
2058
2059#else
2060 return __builtin_bswap32(uTmp);
2061
2062#endif
2063
2064#else
2065 return ((uint32_t)pResult[0]<<24) +
2066 ((uint32_t)pResult[1]<<16) +
2067 ((uint32_t)pResult[2]<<8) +
2068 (uint32_t)pResult[3];
2069#endif
2070}
2071
2072
2073static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2074{
2075 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2076
2077 if(!pResult) {
2078 return 0;
2079 }
2080
2081#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2082 // pResult will probably not be aligned. This memcpy() moves the
2083 // bytes into a temp variable safely for CPUs that can or can't do
2084 // unaligned memory access. Many compilers will optimize the
2085 // memcpy() into a simple move instruction.
2086 uint64_t uTmp;
2087 memcpy(&uTmp, pResult, sizeof(uint64_t));
2088
2089#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2090 // We have been told expliclity this is a big-endian CPU. Since
2091 // network byte order is big-endian, there is nothing to do.
2092
2093 return uTmp;
2094
2095#elif defined(USEFULBUF_CONFIG_HTON)
2096 // We have been told to use ntoh(), the system function to handle
2097 // big- and little-endian. This works on both big- and
2098 // little-endian machines, but ntoh() is not always available or in
2099 // a standard place so it is not used by default. On some CPUs the
2100 // code for this is very compact through use of a special swap
2101 // instruction.
2102
2103 return ntohll(uTmp);
2104
2105#else
2106 // Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2107 // USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2108 // __builtin_bswap64() and friends are not conditional on CPU
2109 // endianness so this must only be used on little-endian machines.
2110
2111 return __builtin_bswap64(uTmp);
2112
2113
2114#endif
2115
2116#else
2117 // This is the default code that works on every CPU and every
2118 // endianness with no dependency on ntoh(). This works on CPUs
2119 // that either allow or do not allow unaligned access. It will
2120 // always work, but usually is a little less efficient than ntoh().
2121
2122 return ((uint64_t)pResult[0]<<56) +
2123 ((uint64_t)pResult[1]<<48) +
2124 ((uint64_t)pResult[2]<<40) +
2125 ((uint64_t)pResult[3]<<32) +
2126 ((uint64_t)pResult[4]<<24) +
2127 ((uint64_t)pResult[5]<<16) +
2128 ((uint64_t)pResult[6]<<8) +
2129 (uint64_t)pResult[7];
2130#endif
2131}
2132
2133
2134static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2135{
2136 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2137
2138 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2139}
2140
2141
2142static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2143{
2144 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2145
2146 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2147}
2148
2149
2150static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2151{
2152 return pMe->err;
2153}
2154
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002155
2156static inline void UsefulInputBuf_SetBufferLen(UsefulInputBuf *pMe, size_t uNewLen)
2157{
2158 pMe->UB.len = uNewLen;
2159}
2160
2161
Michael Eckel5c531332020-03-02 01:35:30 +01002162#ifdef __cplusplus
2163}
2164#endif
2165
2166#endif // _UsefulBuf_h
2167
2168