blob: 748ea24e4a90985bd1f7216af7609a3f42ce0782 [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 {
751 // 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 of initialization
755 uint8_t err;
756} UsefulOutBuf;
757
758
759/**
760 @brief Initialize and supply the actual output buffer.
761
762 @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
763 @param[in] Storage Buffer to output into.
764
765 Initializes the @ref UsefulOutBuf with storage. Sets the current
766 position to the beginning of the buffer clears the error.
767
768 This must be called before the @ref UsefulOutBuf is used.
769 */
770void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
771
772
773/**
774 Convenience macro to make a @ref UsefulOutBuf on the stack and
775 initialize it with a stack buffer of the given size. The variable
776 will be named @c name.
777 */
778#define UsefulOutBuf_MakeOnStack(name, size) \
779 uint8_t __pBuf##name[(size)];\
780 UsefulOutBuf name;\
781 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
782
783
784/**
785 @brief Reset a @ref UsefulOutBuf for re use
786
787 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
788
789 This sets the amount of data in the output buffer to none and clears
790 the error state.
791
792 The output buffer is still the same one and size as from the
793 UsefulOutBuf_Init() call.
794
795 This doesn't zero the data, just resets to 0 bytes of valid data.
796 */
797static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
798
799
800/**
801 @brief Returns position of end of data in the @ref UsefulOutBuf.
802
803 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
804
805 @return position of end of data.
806
807 On a freshly initialized @ref UsefulOutBuf with no data added, this
808 will return 0. After 10 bytes have been added, it will return 10 and
809 so on.
810
811 Generally callers will not need this function for most uses of @ref
812 UsefulOutBuf.
813 */
814static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
815
816
817/**
818 @brief Returns whether any data has been added to the @ref UsefulOutBuf.
819
820 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
821
822 @return 1 if output position is at start.
823 */
824static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
825
826
827/**
828 @brief Inserts bytes into the @ref UsefulOutBuf.
829
830 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
831 @param[in] NewData The bytes to insert.
832 @param[in] uPos Index in output buffer at which to insert.
833
834 @c NewData is the pointer and length for the bytes to be added to the
835 output buffer. There must be room in the output buffer for all of @c
836 NewData or an error will occur.
837
838 The insertion point must be between 0 and the current valid data. If
839 not, an error will occur. Appending data to the output buffer is
840 achieved by inserting at the end of the valid data. This can be
841 retrieved by calling UsefulOutBuf_GetEndPosition().
842
843 When insertion is performed, the bytes between the insertion point
844 and the end of data previously added to the output buffer are slid to
845 the right to make room for the new data.
846
847 Overlapping buffers are OK. @c NewData can point to data in the
848 output buffer.
849
850 If an error occurs an error state is set in the @ref UsefulOutBuf. No
851 error is returned. All subsequent attempts to add data will do
852 nothing.
853
854 The intended use is that all additions are made without checking for
855 an error. The error will be taken into account when
856 UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
857 UsefulOutBuf_GetError() can also be called to check for an error.
858 */
859void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
860 UsefulBufC NewData,
861 size_t uPos);
862
863
864/**
865 @brief Insert a data buffer into the @ref UsefulOutBuf.
866
867 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
868 @param[in] pBytes Pointer to the bytes to insert
869 @param[in] uLen Length of the bytes to insert
870 @param[in] uPos Index in output buffer at which to insert
871
872 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
873 the difference being a pointer and length is passed in rather than an
874 @ref UsefulBufC.
875 */
876static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
877 const void *pBytes,
878 size_t uLen,
879 size_t uPos);
880
881
882/**
883 @brief Insert a NULL-terminated string into the UsefulOutBuf.
884
885 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
886 @param[in] szString NULL-terminated string to insert.
887 @param[in] uPos Index in output buffer at which to insert.
888 */
889static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
890 const char *szString,
891 size_t uPos);
892
893
894/**
895 @brief Insert a byte into the @ref UsefulOutBuf.
896
897 @param[in] pUOutBuf Pointer to the UsefulOutBuf.
898 @param[in] byte Bytes to insert.
899 @param[in] uPos Index in output buffer at which to insert.
900
901 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
902 the difference being a single byte is to be inserted.
903 */
904static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
905 uint8_t byte,
906 size_t uPos);
907
908
909/**
910 @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
911
912 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
913 @param[in] uInteger16 Integer to insert.
914 @param[in] uPos Index in output buffer at which to insert.
915
916 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
917 the difference being a two-byte integer is to be inserted.
918
919 The integer will be inserted in network byte order (big endian).
920 */
921static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
922 uint16_t uInteger16,
923 size_t uPos);
924
925
926/**
927 @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
928
929 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
930 @param[in] uInteger32 Integer to insert.
931 @param[in] uPos Index in output buffer at which to insert.
932
933 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
934 the difference being a four-byte integer is to be inserted.
935
936 The integer will be inserted in network byte order (big endian).
937 */
938static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
939 uint32_t uInteger32,
940 size_t uPos);
941
942
943/**
944 @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
945
946 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
947 @param[in] uInteger64 Integer to insert.
948 @param[in] uPos Index in output buffer at which to insert.
949
950 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
951 the difference being an eight-byte integer is to be inserted.
952
953 The integer will be inserted in network byte order (big endian).
954 */
955static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
956 uint64_t uInteger64,
957 size_t uPos);
958
959
960/**
961 @brief Insert a @c float into the @ref UsefulOutBuf.
962
963 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
964 @param[in] f @c float to insert.
965 @param[in] uPos Index in output buffer at which to insert.
966
967 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
968 the difference being a @c float is to be inserted.
969
970 The @c float will be inserted in network byte order (big endian).
971 */
972static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
973 float f,
974 size_t uPos);
975
976
977/**
978 @brief Insert a @c double into the @ref UsefulOutBuf.
979
980 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
981 @param[in] d @c double to insert.
982 @param[in] uPos Index in output buffer at which to insert.
983
984 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
985 the difference being a @c double is to be inserted.
986
987 The @c double will be inserted in network byte order (big endian).
988 */
989static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
990 double d,
991 size_t uPos);
992
993
994/**
995 @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
996
997 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
998 @param[in] NewData The @ref UsefulBuf with the bytes to append.
999
1000 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1001 with the insertion point at the end of the valid data.
1002*/
1003static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1004 UsefulBufC NewData);
1005
1006
1007/**
1008 @brief Append bytes to the @ref UsefulOutBuf.
1009
1010 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1011 @param[in] pBytes Pointer to bytes to append.
1012 @param[in] uLen Length of @c pBytes to append.
1013
1014 See UsefulOutBuf_InsertData() for details. This does the same
1015 with the insertion point at the end of the valid data.
1016 */
1017static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1018 const void *pBytes,
1019 size_t uLen);
1020
1021
1022/**
1023 @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1024
1025 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1026 @param[in] szString NULL-terminated string to append.
1027 */
1028static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1029 const char *szString);
1030
1031
1032/**
1033 @brief Append a byte to the @ref UsefulOutBuf
1034
1035 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1036 @param[in] byte Bytes to append.
1037
1038 See UsefulOutBuf_InsertByte() for details. This does the same
1039 with the insertion point at the end of the valid data.
1040 */
1041static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1042 uint8_t byte);
1043
1044
1045/**
1046 @brief Append an integer to the @ref UsefulOutBuf
1047
1048 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1049 @param[in] uInteger16 Integer to append.
1050
1051 See UsefulOutBuf_InsertUint16() for details. This does the same
1052 with the insertion point at the end of the valid data.
1053
1054 The integer will be appended in network byte order (big endian).
1055 */
1056static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1057 uint16_t uInteger16);
1058
1059
1060/**
1061 @brief Append an integer to the @ref UsefulOutBuf
1062
1063 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1064 @param[in] uInteger32 Integer to append.
1065
1066 See UsefulOutBuf_InsertUint32() for details. This does the same
1067 with the insertion point at the end of the valid data.
1068
1069 The integer will be appended in network byte order (big endian).
1070 */
1071static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1072 uint32_t uInteger32);
1073
1074
1075/**
1076 @brief Append an integer to the @ref UsefulOutBuf
1077
1078 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1079 @param[in] uInteger64 Integer to append.
1080
1081 See UsefulOutBuf_InsertUint64() for details. This does the same
1082 with the insertion point at the end of the valid data.
1083
1084 The integer will be appended in network byte order (big endian).
1085 */
1086static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1087 uint64_t uInteger64);
1088
1089
1090/**
1091 @brief Append a @c float to the @ref UsefulOutBuf
1092
1093 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1094 @param[in] f @c float to append.
1095
1096 See UsefulOutBuf_InsertFloat() for details. This does the same
1097 with the insertion point at the end of the valid data.
1098
1099 The float will be appended in network byte order (big endian).
1100 */
1101static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1102 float f);
1103
1104
1105/**
1106 @brief Append a @c double to the @ref UsefulOutBuf
1107
1108 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1109 @param[in] d @c double to append.
1110
1111 See UsefulOutBuf_InsertDouble() for details. This does the same
1112 with the insertion point at the end of the valid data.
1113
1114 The double will be appended in network byte order (big endian).
1115 */
1116static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1117 double d);
1118
1119
1120/**
1121 @brief Returns the current error status.
1122
1123 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1124
1125 @return 0 if all OK, 1 on error.
1126
1127 This is the error status since the call to either
1128 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1129 state it will stay until one of those functions is called.
1130
1131 Possible error conditions are:
1132 - bytes to be inserted will not fit
1133 - insertion point is out of buffer or past valid data
1134 - current position is off end of buffer (probably corrupted or uninitialized)
1135 - detect corruption / uninitialized by bad magic number
1136 */
1137static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1138
1139
1140/**
1141 @brief Returns number of bytes unused used in the output buffer.
1142
1143 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1144
1145 @return Number of unused bytes or zero.
1146
1147 Because of the error handling strategy and checks in
1148 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1149 this.
1150 */
1151static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1152
1153
1154/**
1155 @brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1156
1157 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1158 @param[in] uLen Number of bytes for which to check
1159
1160 @return 1 if @c uLen bytes will fit, 0 if not.
1161
1162 Because of the error handling strategy and checks in
1163 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1164 this.
1165 */
1166static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1167
1168
1169 /**
1170 @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1171
1172 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1173
1174 @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1175
1176 Giving a @c NULL output buffer to UsefulOutBuf_Init() is used
1177 when just calculating the length of the encoded data.
1178 */
1179static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1180
1181
1182/**
1183 @brief Returns the resulting valid data in a UsefulOutBuf
1184
1185 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1186
1187 @return The valid data in @ref UsefulOutBuf or
1188 @ref NULLUsefulBufC if there was an error adding data.
1189
1190 The storage for the returned data is the @c Storage parameter passed
1191 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1192
1193 This can be called anytime and many times to get intermediate
1194 results. It doesn't change the data or reset the current position
1195 so you can keep adding data.
1196 */
1197UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1198
1199
1200/**
1201 @brief Copies the valid data into a supplied buffer
1202
1203 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1204 @param[out] Dest The destination buffer to copy into.
1205
1206 @return Pointer and length of copied data or @c NULLUsefulBufC
1207 if it will not fit in the @c Dest buffer.
1208
1209 This is the same as UsefulOutBuf_OutUBuf() except it copies the data
1210 to @c Dest.
1211*/
1212UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1213
1214
1215
1216
1217/**
1218 @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf and is
1219 for parsing data read or received. Initialize it with the data from
1220 the network. Then use the functions here to get data chunks of
1221 various types. A position cursor is maintained internally.
1222
1223 As long as the functions here are used, there will never be a
1224 reference off the end of the given buffer. This is true even if they
1225 care called incorrectly, an attempt is made to seek of the end of the
1226 buffer, etc. This makes it easier to write safe and correct code.
1227 For example, the QCBOR decoder implementation is safer and easier to
1228 review through its use of @ref UsefulInputBuf.
1229
1230 @ref UsefulInputBuf maintains an internal error state. The
1231 intended use is that data chunks can be fetched without error
1232 checking until the end. Once data has been requested off the end of
1233 the buffer, the error state is entered. In the error state the
1234 @c UsefulInputBuf_GetXxxx() functions return 0, or @c NULL or
1235 @ref NULLUsefulBufC. As long as null are not dereferenced, the
1236 error check can be put off until the end, simplifying the calling
1237 code.
1238
1239 The integer and float parsing expects network byte order (big
1240 endian). Network byte order is what is used by TCP/IP, CBOR and most
1241 internet protocols.
1242
1243 Lots of inline functions are used to keep code size down. The code
1244 optimizer, particularly with the @c -Os or @c -O3, also reduces code
1245 size a lot. The only non-inline code is UsefulInputBuf_GetBytes()
1246 which is less than 100 bytes so use of @ref UsefulInputBuf doesn't
1247 add much code for all the messy hard-to-get right issues with parsing
1248 in C that is solves.
1249
1250 The parse context size is:
1251 - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1252 - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1253 */
1254typedef struct useful_input_buf {
1255 // PRIVATE DATA STRUCTURE
1256 UsefulBufC UB; // Data being parsed
1257 size_t cursor; // Current offset in data being parse
1258 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1259 uint8_t err; // Set request goes off end or magic number is bad
1260} UsefulInputBuf;
1261
1262#define UIB_MAGIC (0xB00F)
1263
1264
1265/**
1266 @brief Initialize the UsefulInputBuf structure before use.
1267
1268 @param[in] pUInBuf Pointer to the UsefulInputBuf instance.
1269 @param[in] UB The data to parse.
1270 */
1271static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1272
1273
1274/**
1275 @brief Returns current position in input buffer.
1276
1277 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1278
1279 @return Integer position of the cursor.
1280
1281 The position that the next bytes will be returned from.
1282 */
1283static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1284
1285
1286/**
1287 @brief Sets the current position in input buffer.
1288
1289 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1290 @param[in] uPos Position to set to.
1291
1292 If the position is off the end of the input buffer, the error state
1293 is entered, and all functions will do nothing.
1294
1295 Seeking to a valid position in the buffer will not reset the error
1296 state. Only re initialization will do that.
1297 */
1298static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1299
1300
1301/**
1302 @brief Returns the number of bytes from the cursor to the end of the buffer,
1303 the unconsumed bytes.
1304
1305 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1306
1307 @return Number of bytes unconsumed or 0 on error.
1308
1309 This is a critical function for input length validation.
1310
1311 Returns 0 if the cursor it invalid or corruption of the structure is
1312 detected.
1313 */
1314static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1315
1316
1317/**
1318 @brief Check if there are any unconsumed bytes.
1319
1320 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1321 @param[in] uLen Number of bytes to check availability for.
1322
1323 @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
1324 */
1325static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1326
1327
1328/**
1329 @brief Get pointer to bytes out of the input buffer.
1330
1331 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1332 @param[in] uNum Number of bytes to get.
1333
1334 @return Pointer to bytes.
1335
1336 This consumes @c uNum bytes from the input buffer. It returns a
1337 pointer to the start of the @c uNum bytes.
1338
1339 If there are not @c uNum bytes in the input buffer, @c NULL will be
1340 returned and an error will be set.
1341
1342 It advances the current position by @c uNum bytes.
1343 */
1344const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1345
1346
1347/**
1348 @brief Get @ref UsefulBuf out of the input buffer.
1349
1350 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1351 @param[in] uNum Number of bytes to get.
1352
1353 @return A @ref UsefulBufC with ptr and length of bytes consumed.
1354
1355 This consumes @c uNum bytes from the input buffer and returns the
1356 pointer and length for them as a @ref UsefulBufC. The length returned
1357 will always be @c uNum.
1358
1359 If there are not @c uNum bytes in the input buffer, @ref NULLUsefulBufC
1360 will be returned and the error state is set.
1361
1362 It advances the current position by @c uNum bytes.
1363 */
1364static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1365
1366
1367/**
1368 @brief Get a byte out of the input buffer.
1369
1370 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1371
1372 @return The byte.
1373
1374 This consumes 1 byte from the input buffer. It returns the byte.
1375
1376 If there is not 1 byte in the buffer, 0 will be returned for the byte
1377 and an error set internally. You must check the error at some point
1378 to know whether the 0 was the real value or just returned in error,
1379 but you may not have to do that right away. Check the error state
1380 with UsefulInputBuf_GetError(). You can also know you are in the
1381 error state if UsefulInputBuf_GetBytes() returns @c NULL or the @c
1382 ptr from UsefulInputBuf_GetUsefulBuf() is @c NULL.
1383
1384 It advances the current position by 1 byte.
1385 */
1386static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1387
1388
1389/**
1390 @brief Get a @c uint16_t out of the input buffer.
1391
1392 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1393
1394 @return The @c uint16_t.
1395
1396 See UsefulInputBuf_GetByte(). This works the same, except it returns
1397 a @c uint16_t and two bytes are consumed.
1398
1399 The input bytes must be in network order (big endian).
1400 */
1401static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1402
1403
1404/**
1405 @brief Get a uint32_t out of the input buffer.
1406
1407 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1408
1409 @return The @c uint32_t.
1410
1411 See UsefulInputBuf_GetByte(). This works the same, except it returns
1412 a @c uint32_t and four bytes are consumed.
1413
1414 The input bytes must be in network order (big endian).
1415 */
1416static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1417
1418
1419/**
1420 @brief Get a uint64_t out of the input buffer.
1421
1422 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1423
1424 @return The uint64_t.
1425
1426 See UsefulInputBuf_GetByte(). This works the same, except it returns
1427 a @c uint64_t and eight bytes are consumed.
1428
1429 The input bytes must be in network order (big endian).
1430 */
1431static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1432
1433
1434/**
1435 @brief Get a float out of the input buffer.
1436
1437 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1438
1439 @return The float.
1440
1441 See UsefulInputBuf_GetByte(). This works the same, except it returns
1442 a float and four bytes are consumed.
1443
1444 The input bytes must be in network order (big endian).
1445 */
1446static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1447
1448
1449/**
1450 @brief Get a double out of the input buffer.
1451
1452 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1453
1454 @return The double.
1455
1456 See UsefulInputBuf_GetByte(). This works the same, except it returns
1457 a double and eight bytes are consumed.
1458
1459 The input bytes must be in network order (big endian).
1460 */
1461static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1462
1463
1464/**
1465 @brief Get the error status.
1466
1467 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1468
1469 @return 0 if there is no error, 1 if there is.
1470
1471 The error state is entered for one of these reasons:
1472 - Attempt to fetch data past the end of the buffer
1473 - Attempt to seek to a position past the end of the buffer
1474 - Attempt to get data from an uninitialized or corrupt instance
1475 of @ref UsefulInputBuf
1476
1477 Once in the error state, it can only be cleared by calling
1478 UsefulInputBuf_Init().
1479
1480 You may be able to only check the error state at the end after all
1481 the UsefulInputBuf_GetXxxx() calls have been made, but if what you
1482 get later depends on what you get sooner you cannot. For example,
1483 if you get a length or count of following items you will have to
1484 check the error.
1485 */
1486static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1487
1488
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001489/**
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001490 @brief Gets the input buffer length.
1491
1492 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1493
1494 @return The length of the input buffer.
1495
1496 This returns the length of th input buffer from UsefulInputBuf_Init()
1497 of from UsefulInputBuf_SetBufferLength().
1498 */
1499static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1500
1501
1502/**
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001503 @brief Sets the input buffer length (use with caution)
1504
1505 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1506
1507 This changes the internal remembered length of the input buffer
1508 set when UsefulInputBuf_Init() was called. It is used by QCBOR
1509 to handle CBOR that is wrapped and embedded in CBOR.
1510
1511 Since this allows setting the length beyond the length of the
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001512 original input buffer it allows the overall safety of UsefulInputBug to
1513 be undermined. Use it carefully.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001514
1515 The new length given here should always be equal to or less than
1516 the length given when UsefulInputBuf_Init() was called.
1517
1518 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001519static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001520
1521
1522/*----------------------------------------------------------
1523 Inline implementations.
1524 */
1525static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1526{
1527 return !UB.ptr;
1528}
1529
1530
1531static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1532{
1533 return !UB.ptr;
1534}
1535
1536
1537static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1538{
1539 return !UB.len;
1540}
1541
1542
1543static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1544{
1545 return !UB.len;
1546}
1547
1548
1549static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1550{
1551 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1552}
1553
1554
1555static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1556{
1557 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1558}
1559
1560
1561static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1562{
1563 return (UsefulBufC){UB.ptr, UB.len};
1564}
1565
1566
1567static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1568{
1569 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
1570}
1571
1572
1573static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1574{
1575 return ((UsefulBufC) {szString, strlen(szString)});
1576}
1577
1578
1579static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1580{
1581 return UsefulBuf_CopyOffset(Dest, 0, Src);
1582}
1583
1584
1585static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
1586{
1587 memset(pDest.ptr, value, pDest.len);
1588 return (UsefulBufC){pDest.ptr, pDest.len};
1589}
1590
1591
1592static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1593{
1594 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
1595}
1596
1597
1598static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1599{
1600 if(uAmount > UB.len) {
1601 return NULLUsefulBufC;
1602 }
1603 return (UsefulBufC){UB.ptr, uAmount};
1604}
1605
1606
1607static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1608{
1609 UsefulBufC ReturnValue;
1610
1611 if(uAmount > UB.len) {
1612 ReturnValue = NULLUsefulBufC;
1613 } else if(UB.ptr == NULL) {
1614 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
1615 } else {
1616 ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
1617 }
1618
1619 return ReturnValue;
1620}
1621
1622
1623
1624static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1625{
1626 uint32_t u32;
1627 memcpy(&u32, &f, sizeof(uint32_t));
1628 return u32;
1629}
1630
1631static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1632{
1633 uint64_t u64;
1634 memcpy(&u64, &d, sizeof(uint64_t));
1635 return u64;
1636}
1637
1638static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1639{
1640 double d;
1641 memcpy(&d, &u64, sizeof(uint64_t));
1642 return d;
1643}
1644
1645static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1646{
1647 float f;
1648 memcpy(&f, &u32, sizeof(uint32_t));
1649 return f;
1650}
1651
1652
1653
1654
1655static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1656{
1657 pMe->data_len = 0;
1658 pMe->err = 0;
1659}
1660
1661
1662static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1663{
1664 return pMe->data_len;
1665}
1666
1667
1668static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1669{
1670 return 0 == pMe->data_len;
1671}
1672
1673
1674static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1675 const void *pBytes,
1676 size_t uLen,
1677 size_t uPos)
1678{
1679 UsefulBufC Data = {pBytes, uLen};
1680 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1681}
1682
1683
1684static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1685 const char *szString,
1686 size_t uPos)
1687{
1688 UsefulOutBuf_InsertUsefulBuf(pMe,
1689 (UsefulBufC){szString, strlen(szString)},
1690 uPos);
1691}
1692
1693
1694static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1695 uint8_t byte,
1696 size_t uPos)
1697{
1698 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1699}
1700
1701
1702static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1703 uint16_t uInteger16,
1704 size_t uPos)
1705{
1706 // See UsefulOutBuf_InsertUint64() for comments on this code
1707
1708 const void *pBytes;
1709
1710#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1711 pBytes = &uInteger16;
1712
1713#elif defined(USEFULBUF_CONFIG_HTON)
1714 uint16_t uTmp = htons(uInteger16);
1715 pBytes = &uTmp;
1716
1717#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1718 uint16_t uTmp = __builtin_bswap16(uInteger16);
1719 pBytes = &uTmp;
1720
1721#else
1722 uint8_t aTmp[2];
1723
1724 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1725 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1726
1727 pBytes = aTmp;
1728#endif
1729
1730 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1731}
1732
1733
1734static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1735 uint32_t uInteger32,
1736 size_t uPos)
1737{
1738 // See UsefulOutBuf_InsertUint64() for comments on this code
1739
1740 const void *pBytes;
1741
1742#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1743 pBytes = &uInteger32;
1744
1745#elif defined(USEFULBUF_CONFIG_HTON)
1746 uint32_t uTmp = htonl(uInteger32);
1747 pBytes = &uTmp;
1748
1749#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1750 uint32_t uTmp = __builtin_bswap32(uInteger32);
1751
1752 pBytes = &uTmp;
1753
1754#else
1755 uint8_t aTmp[4];
1756
1757 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1758 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1759 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1760 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1761
1762 pBytes = aTmp;
1763#endif
1764
1765 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1766}
1767
1768static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
1769 uint64_t uInteger64,
1770 size_t uPos)
1771{
1772 const void *pBytes;
1773
1774#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1775 // We have been told explicitly we are running on a big-endian
1776 // machine. Network byte order is big endian, so just copy. There
1777 // is no issue with alignment here because uInter64 is always
1778 // aligned (and it doesn't matter if pBytes is aligned).
1779 pBytes = &uInteger64;
1780
1781#elif defined(USEFULBUF_CONFIG_HTON)
1782 // Use system function to handle big- and little-endian. This works
1783 // on both big- and little-endian machines, but hton() is not
1784 // always available or in a standard place so it is not used by
1785 // default. With some compilers and CPUs the code for this is very
1786 // compact through use of a special swap instruction and on
1787 // big-endian machines hton() will reduce to nothing.
1788 uint64_t uTmp = htonll(uInteger64);
1789
1790 pBytes = &uTmp;
1791
1792#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1793 // Use built-in function for byte swapping. This usually compiles
1794 // to an efficient special byte swap instruction. Unlike hton() it
1795 // does not do this conditionally on the CPU endianness, so this
1796 // code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1797 uint64_t uTmp = __builtin_bswap64(uInteger64);
1798
1799 pBytes = &uTmp;
1800
1801#else
1802 // Default which works on every CPU with no dependency on anything
1803 // from the CPU, compiler, libraries or OS. This always works, but
1804 // it is usually a little larger and slower than hton().
1805 uint8_t aTmp[8];
1806
1807 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1808 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1809 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1810 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1811 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1812 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1813 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1814 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
1815
1816 pBytes = aTmp;
1817#endif
1818
1819 // Do the insert
1820 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
1821}
1822
1823
1824static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1825 float f,
1826 size_t uPos)
1827{
1828 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
1829}
1830
1831
1832static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1833 double d,
1834 size_t uPos)
1835{
1836 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
1837}
1838
1839
1840static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
1841 UsefulBufC NewData)
1842{
1843 // An append is just a insert at the end
1844 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
1845}
1846
1847
1848static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
1849 const void *pBytes,
1850 size_t uLen)
1851{
1852 UsefulBufC Data = {pBytes, uLen};
1853 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
1854}
1855
1856
1857static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
1858 const char *szString)
1859{
1860 UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
1861}
1862
1863
1864static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
1865 uint8_t byte)
1866{
1867 UsefulOutBuf_AppendData(pMe, &byte, 1);
1868}
1869
1870
1871static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
1872 uint16_t uInteger16)
1873{
1874 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
1875}
1876
1877static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
1878 uint32_t uInteger32)
1879{
1880 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
1881}
1882
1883
1884static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
1885 uint64_t uInteger64)
1886{
1887 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
1888}
1889
1890
1891static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
1892 float f)
1893{
1894 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
1895}
1896
1897
1898static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
1899 double d)
1900{
1901 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
1902}
1903
1904
1905static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
1906{
1907 return pMe->err;
1908}
1909
1910
1911static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
1912{
1913 return pMe->UB.len - pMe->data_len;
1914}
1915
1916
1917static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
1918{
1919 return uLen <= UsefulOutBuf_RoomLeft(pMe);
1920}
1921
1922
1923static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
1924{
1925 return pMe->UB.ptr == NULL;
1926}
1927
1928
1929
1930static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
1931{
1932 pMe->cursor = 0;
1933 pMe->err = 0;
1934 pMe->magic = UIB_MAGIC;
1935 pMe->UB = UB;
1936}
1937
1938static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
1939{
1940 return pMe->cursor;
1941}
1942
1943
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001944static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07001945{
1946 return pMe->UB.len;
1947}
1948
1949
Michael Eckel5c531332020-03-02 01:35:30 +01001950static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
1951{
1952 if(uPos > pMe->UB.len) {
1953 pMe->err = 1;
1954 } else {
1955 pMe->cursor = uPos;
1956 }
1957}
1958
1959
1960static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
1961{
1962 // Code Reviewers: THIS FUNCTION DOES POINTER MATH
1963
1964 // Magic number is messed up. Either the structure got overwritten
1965 // or was never initialized.
1966 if(pMe->magic != UIB_MAGIC) {
1967 return 0;
1968 }
1969
1970 // The cursor is off the end of the input buffer given.
1971 // Presuming there are no bugs in this code, this should never happen.
1972 // If it so, the struct was corrupted. The check is retained as
1973 // as a defense in case there is a bug in this code or the struct is
1974 // corrupted.
1975 if(pMe->cursor > pMe->UB.len) {
1976 return 0;
1977 }
1978
Laurence Lundbladebfbf4942020-09-16 23:31:00 -07001979 // subtraction can't go negative because of check above
Michael Eckel5c531332020-03-02 01:35:30 +01001980 return pMe->UB.len - pMe->cursor;
1981}
1982
1983
1984static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
1985{
1986 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
1987}
1988
1989
1990static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
1991{
1992 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
1993 if(!pResult) {
1994 return NULLUsefulBufC;
1995 } else {
1996 return (UsefulBufC){pResult, uNum};
1997 }
1998}
1999
2000
2001static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2002{
2003 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2004
2005 // The ternery operator is subject to integer promotion, because the
2006 // operands are smaller than int, so cast back to uint8_t is needed
2007 // to be completely explicit about types (for static analyzers)
2008 return (uint8_t)(pResult ? *(uint8_t *)pResult : 0);
2009}
2010
2011static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2012{
2013 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2014
2015 if(!pResult) {
2016 return 0;
2017 }
2018
2019 // See UsefulInputBuf_GetUint64() for comments on this code
2020#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2021 uint16_t uTmp;
2022 memcpy(&uTmp, pResult, sizeof(uint16_t));
2023
2024#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2025 return uTmp;
2026
2027#elif defined(USEFULBUF_CONFIG_HTON)
2028 return ntohs(uTmp);
2029
2030#else
2031 return __builtin_bswap16(uTmp);
2032
2033#endif
2034
2035#else
2036
2037 // The operations here are subject to integer promotion because the
2038 // operands are smaller than int. They will be promoted to unsigned
2039 // int for the shift and addition. The cast back to uint16_t is is needed
2040 // to be completely explicit about types (for static analyzers)
2041 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2042
2043#endif
2044}
2045
2046
2047static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2048{
2049 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2050
2051 if(!pResult) {
2052 return 0;
2053 }
2054
2055 // See UsefulInputBuf_GetUint64() for comments on this code
2056#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2057 uint32_t uTmp;
2058 memcpy(&uTmp, pResult, sizeof(uint32_t));
2059
2060#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2061 return uTmp;
2062
2063#elif defined(USEFULBUF_CONFIG_HTON)
2064 return ntohl(uTmp);
2065
2066#else
2067 return __builtin_bswap32(uTmp);
2068
2069#endif
2070
2071#else
2072 return ((uint32_t)pResult[0]<<24) +
2073 ((uint32_t)pResult[1]<<16) +
2074 ((uint32_t)pResult[2]<<8) +
2075 (uint32_t)pResult[3];
2076#endif
2077}
2078
2079
2080static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2081{
2082 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2083
2084 if(!pResult) {
2085 return 0;
2086 }
2087
2088#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2089 // pResult will probably not be aligned. This memcpy() moves the
2090 // bytes into a temp variable safely for CPUs that can or can't do
2091 // unaligned memory access. Many compilers will optimize the
2092 // memcpy() into a simple move instruction.
2093 uint64_t uTmp;
2094 memcpy(&uTmp, pResult, sizeof(uint64_t));
2095
2096#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2097 // We have been told expliclity this is a big-endian CPU. Since
2098 // network byte order is big-endian, there is nothing to do.
2099
2100 return uTmp;
2101
2102#elif defined(USEFULBUF_CONFIG_HTON)
2103 // We have been told to use ntoh(), the system function to handle
2104 // big- and little-endian. This works on both big- and
2105 // little-endian machines, but ntoh() is not always available or in
2106 // a standard place so it is not used by default. On some CPUs the
2107 // code for this is very compact through use of a special swap
2108 // instruction.
2109
2110 return ntohll(uTmp);
2111
2112#else
2113 // Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2114 // USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2115 // __builtin_bswap64() and friends are not conditional on CPU
2116 // endianness so this must only be used on little-endian machines.
2117
2118 return __builtin_bswap64(uTmp);
2119
2120
2121#endif
2122
2123#else
2124 // This is the default code that works on every CPU and every
2125 // endianness with no dependency on ntoh(). This works on CPUs
2126 // that either allow or do not allow unaligned access. It will
2127 // always work, but usually is a little less efficient than ntoh().
2128
2129 return ((uint64_t)pResult[0]<<56) +
2130 ((uint64_t)pResult[1]<<48) +
2131 ((uint64_t)pResult[2]<<40) +
2132 ((uint64_t)pResult[3]<<32) +
2133 ((uint64_t)pResult[4]<<24) +
2134 ((uint64_t)pResult[5]<<16) +
2135 ((uint64_t)pResult[6]<<8) +
2136 (uint64_t)pResult[7];
2137#endif
2138}
2139
2140
2141static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2142{
2143 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2144
2145 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2146}
2147
2148
2149static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2150{
2151 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2152
2153 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2154}
2155
2156
2157static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2158{
2159 return pMe->err;
2160}
2161
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002162
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002163static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002164{
2165 pMe->UB.len = uNewLen;
2166}
2167
2168
Michael Eckel5c531332020-03-02 01:35:30 +01002169#ifdef __cplusplus
2170}
2171#endif
2172
2173#endif // _UsefulBuf_h
2174
2175