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