blob: 1a4a3bf45983f2cb4396c4beaa59edaa7901e238 [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07003 * Copyright (c) 2018-2024, Laurence Lundblade.
Laurence Lundblade3eead482023-12-16 20:53:22 -07004 * Copyright (c) 2021, Arm Limited. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Michael Eckel5c531332020-03-02 01:35:30 +010033
34/*============================================================================
35 FILE: UsefulBuf.h
36
37 DESCRIPTION: General purpose input and output buffers
38
39 EDIT HISTORY FOR FILE:
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44 when who what, where, why
45 -------- ---- --------------------------------------------------
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -070046 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070047 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
48 19/11/2023 llundblade Add UsefulOutBuf_Swap().
49 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070050 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060051 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070052 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070053 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070054 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080055 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070056 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010057 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
58 5/21/2019 llundblade #define configs for efficient endianness handling.
59 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
60 3/23/2019 llundblade Big documentation & style update. No interface
61 change.
62 3/6/2019 llundblade Add UsefulBuf_IsValue()
63 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
64 12/13/2018 llundblade Documentation improvements
65 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
66 UsefulBufC.
67 02/02/18 llundbla Full support for integers in and out; fix pointer
68 alignment bug. Incompatible change: integers
69 in/out are now in network byte order.
70 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
71 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
72 comparison for < or > for unequal length buffers.
73 Added UsefulBuf_Set() function.
74 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
75 11/13/16 llundbla Initial Version.
76
77 =============================================================================*/
78
79#ifndef _UsefulBuf_h
80#define _UsefulBuf_h
81
82
83/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070084 * Endianness Configuration
85 *
86 * This code is written so it will work correctly on big- and
87 * little-endian CPUs without configuration or any auto-detection of
88 * endianness. All code here will run correctly regardless of the
89 * endianness of the CPU it is running on.
90 *
91 * There are four C preprocessor macros that can be set with #define
92 * to explicitly configure endianness handling. Setting them can
93 * reduce code size a little and improve efficiency a little.
94 *
95 * Note that most of QCBOR is unaffected by this configuration. Its
96 * endianness handling is integrated with the code that handles
97 * alignment and preferred serialization. This configuration does
98 * affect QCBOR's (planned) implementation of integer arrays (tagged
99 * arrays) and use of the functions here to serialize or deserialize
100 * integers and floating-point values.
101 *
102 * Following is the recipe for configuring the endianness-related
103 * #defines.
104 *
105 * The first option is to not define anything. This will work fine
106 * with all CPUs, OS's and compilers. The code for encoding integers
107 * may be a little larger and slower.
108 *
109 * If your CPU is big-endian then define
110 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
111 * for big-endian CPUs. It will be small and efficient because there
112 * will be no byte swapping.
113 *
114 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
115 * OS's and compilers, but not all. On big-endian CPUs this should
116 * give the most efficient code, the same as
117 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
118 * call the system-defined byte swapping method which is presumably
119 * implemented efficiently. In some cases, this will be a dedicated
120 * byte swap instruction like Intel's bswap.
121 *
122 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
123 * little-endian, it is also good to define
124 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
125 *
126 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
127 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
128 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
129 * system-defined byte swap method. However, note
130 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
131 * this is fixed now. Often hton() and ntoh() will call the built-in
132 * __builtin_bswapXX()() function, so this size issue could affect
133 * USEFULBUF_CONFIG_HTON.
134 *
135 * Last, run the tests. They must all pass.
136 *
137 * These #define config options affect the inline implementation of
138 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
139 * also affect the 16-, 32-bit, float and double versions of these
140 * functions. Since they are inline, the size effect is not in the
141 * UsefulBuf object code, but in the calling code.
142 *
143 * Summary:
144 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
145 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
146 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
147 * handle big and little-endian with system option.
148 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
149 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200150 *
151 * It is possible to run this code in environments where using floating point is
152 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
153 * that is related to handling floating point types, along with related
154 * interfaces. This makes it possible to compile the code with the compile
155 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100156 */
157
158#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
159#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
160#endif
161
162
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700163#include <stdint.h> /* for uint8_t, uint16_t.... */
164#include <string.h> /* for strlen, memcpy, memmove, memset */
165#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100166
167
168#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700169#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100170#endif
171
172#ifdef __cplusplus
173extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700174#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700175} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700176#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100177#endif
178
179/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700180 * @file UsefulBuf.h
181 *
182 * The goal of this code is to make buffer and pointer manipulation
183 * easier and safer when working with binary data.
184 *
185 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
186 * structures are used to represent buffers rather than ad hoc
187 * pointers and lengths.
188 *
189 * With these it is possible to write code that does little or no
190 * direct pointer manipulation for copying and formatting data. For
191 * example, the QCBOR encoder was written using these and has less
192 * pointer manipulation.
193 *
194 * While it is true that object code using these functions will be a
195 * little larger and slower than a white-knuckle clever use of
196 * pointers might be, but not by that much or enough to have an effect
197 * for most use cases. For security-oriented code this is highly
198 * worthwhile. Clarity, simplicity, reviewability and are more
199 * important.
200 *
201 * There are some extra sanity and double checks in this code to help
202 * catch coding errors and simple memory corruption. They are helpful,
203 * but not a substitute for proper code review, input validation and
204 * such.
205 *
206 * This code consists of a lot of inline functions and a few that are
207 * not. It should not generate very much object code, especially with
208 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100209 */
210
211
212/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700213 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
214 * hold a pointer and length for binary data. In C99 this data
215 * structure can be passed on the stack making a lot of code cleaner
216 * than carrying around a pointer and length as two parameters.
217 *
218 * This is also conducive to secure coding practice as the length is
219 * always carried with the pointer and the convention for handling a
220 * pointer and a length is clear.
221 *
222 * While it might be possible to write buffer and pointer code more
223 * efficiently in some use cases, the thought is that unless there is
224 * an extreme need for performance (e.g., you are building a
225 * gigabit-per-second IP router), it is probably better to have
226 * cleaner code you can be most certain about the security of.
227 *
228 * The non-const @ref UsefulBuf is usually used to refer an empty
229 * buffer to be filled in. The length is the size of the buffer.
230 *
231 * The const @ref UsefulBufC is usually used to refer to some data
232 * that has been filled in. The length is amount of valid data pointed
233 * to.
234 *
235 * A common use mode is to pass a @ref UsefulBuf to a function, the
236 * function puts some data in it, then the function returns a @ref
237 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
238 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
239 * so the constness stays correct. There is no single "in,out"
240 * parameter (if there was, it would have to be non-const). Note that
241 * the pointer returned in the @ref UsefulBufC usually ends up being
242 * the same pointer passed in as a @ref UsefulBuf, though this is not
243 * striclty required.
244 *
245 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
246 * @c NULL.
247 *
248 * There are functions and macros for the following:
249 * - Initializing
250 * - Create initialized const @ref UsefulBufC from compiler literals
251 * - Create initialized const @ref UsefulBufC from NULL-terminated string
252 * - Make an empty @ref UsefulBuf on the stack
253 * - Checking whether a @ref UsefulBuf is null, empty or both
254 * - Copying, copying with offset, copying head or tail
255 * - Comparing and finding substrings
256 *
257 * See also @ref UsefulOutBuf. It is a richer structure that has both
258 * the size of the valid data and the size of the buffer.
259 *
260 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
261 * it can go on the stack and be a function parameter or return value.
262 *
263 * Another way to look at it is this. C has the NULL-terminated string
264 * as a means for handling text strings, but no means or convention
265 * for binary strings. Other languages do have such means, Rust, an
266 * efficient compiled language, for example.
267 *
268 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
269 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
270 * out like anything".
271 */
Michael Eckel5c531332020-03-02 01:35:30 +0100272typedef struct q_useful_buf_c {
273 const void *ptr;
274 size_t len;
275} UsefulBufC;
276
277
278/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700279 * This non-const @ref UsefulBuf is typically used for some allocated
280 * memory that is to be filled in. The @c len is the amount of memory,
281 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100282 */
283typedef struct q_useful_buf {
284 void *ptr;
285 size_t len;
286} UsefulBuf;
287
288
289/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700290 * A null @ref UsefulBufC is one that has no value in the same way a
291 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
292 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
293 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100294 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700295/*
296 * NULLUsefulBufC and few other macros have to be
297 * definied differently in C than C++ because there
298 * is no common construct for a literal structure.
299 *
300 * In C compound literals are used.
301 *
302 * In C++ list initalization is used. This only works
303 * in C++11 and later.
304 *
305 * Note that some popular C++ compilers can handle compound
306 * literals with on-by-default extensions, however
307 * this code aims for full correctness with strict
308 * compilers so they are not used.
309 */
310#ifdef __cplusplus
311#define NULLUsefulBufC {NULL, 0}
312#else
313#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
314#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100315
316/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700317 * A null @ref UsefulBuf is one that has no memory associated the same
318 * way @c NULL points to nothing. It does not matter what @c len is.
319 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700320#ifdef __cplusplus
321#define NULLUsefulBuf {NULL, 0}
322#else
323#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
324#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100325
326
327/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700328 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
329 *
330 * @param[in] UB The UsefulBuf to check.
331 *
332 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100333 */
334static inline int UsefulBuf_IsNULL(UsefulBuf UB);
335
336
337/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700338 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
339 *
340 * @param[in] UB The @ref UsefulBufC to check.
341 *
342 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100343 */
344static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
345
346
347/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700348 * @brief Check if a @ref UsefulBuf is empty or not.
349 *
350 * @param[in] UB The @ref UsefulBuf to check.
351 *
352 * @return 1 if it is empty, 0 if not.
353 *
354 * An "empty" @ref UsefulBuf is one that has a value and can be
355 * considered to be set, but that value is of zero length. It is
356 * empty when @c len is zero. It doesn't matter what the @c ptr is.
357 *
358 * Many uses will not need to clearly distinguish a @c NULL @ref
359 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
360 * @c len 0. However if a use of @ref UsefulBuf needs to make a
361 * distinction then @c ptr should not be @c NULL when the @ref
362 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100363 */
364static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
365
366
367/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700368 * @brief Check if a @ref UsefulBufC is empty or not.
369 *
370 * @param[in] UB The @ref UsefulBufC to check.
371 *
372 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100373 */
374static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
375
376
377/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700378 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
379 *
380 * @param[in] UB The @ref UsefulBuf to check.
381 *
382 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100383 */
384static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
385
386
387/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700388 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
389 *
390 * @param[in] UB The @ref UsefulBufC to check.
391 *
392 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100393 */
394static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
395
396
397/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700398 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
399 *
400 * @param[in] UB The @ref UsefulBuf to convert.
401 *
402 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100403 */
404static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
405
406
407/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700408 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
409 *
410 * @param[in] UBC The @ref UsefulBuf to convert.
411 *
412 * @return A non-const @ref UsefulBuf struct.
413 *
414 * Use of this is not necessary for the intended use mode of @ref
415 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
416 * created to describe a buffer that has not had any data put in
417 * it. Then the data is put in it. Then a @ref UsefulBufC is create
418 * to describe the part with the data in it. This goes from non-const
419 * to const, so this function is not needed.
420 *
421 * If the -Wcast-qual warning is enabled, this function can be used to
422 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100423 */
424static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
425
426
427/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700428 * Convert a literal string to a @ref UsefulBufC.
429 *
430 * @c szString must be a literal string that @c sizeof() works on.
431 * This is better for literal strings than UsefulBuf_FromSZ() because
432 * it generates less code. It will not work on non-literal strings.
433 *
434 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100435 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700436#ifdef __cplusplus
437#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
438#else
Michael Eckel5c531332020-03-02 01:35:30 +0100439#define UsefulBuf_FROM_SZ_LITERAL(szString) \
440 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700441#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100442
443
444/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700445 * Convert a literal byte array to a @ref UsefulBufC.
446 *
447 * @c pBytes must be a literal string that @c sizeof() works on. It
448 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100449 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700450#ifdef __cplusplus
451#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
452#else
Michael Eckel5c531332020-03-02 01:35:30 +0100453#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700454 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
455#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100456
457/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700458 * Make an automatic variable named @c name of type @ref UsefulBuf and
459 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100460 */
461#define UsefulBuf_MAKE_STACK_UB(name, size) \
462 uint8_t __pBuf##name[(size)];\
463 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
464
465
466/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700467 * Make a byte array in to a @ref UsefulBuf. This is usually used on
468 * stack variables or static variables. Also see @ref
469 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100470 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700471#ifdef __cplusplus
472#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
473#else
Michael Eckel5c531332020-03-02 01:35:30 +0100474#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700475 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
476#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100477
478
479/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700480 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
481 *
482 * @param[in] szString The string to convert.
483 *
484 * @return A @ref UsefulBufC struct.
485 *
486 * @c UsefulBufC.ptr points to the string so its lifetime must be
487 * maintained.
488 *
489 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100490 */
491static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
492
493
494/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700495 * @brief Copy one @ref UsefulBuf into another at an offset.
496 *
497 * @param[in] Dest Destination buffer to copy into.
498 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
499 * @param[in] Src The bytes to copy.
500 *
501 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
502 *
503 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
504 * size of @c Dest.
505 *
506 * This fails and returns @ref NULLUsefulBufC if the @c Src length
507 * plus @c uOffset is greater than the length of @c Dest.
508 *
509 * The results are undefined if @c Dest and @c Src overlap.
510 *
511 * This assumes that there is valid data in @c Dest up to @c
512 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
513 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100514 */
515UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
516
517
518/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700519 * @brief Copy one @ref UsefulBuf into another.
520 *
521 * @param[in] Dest The destination buffer to copy into.
522 * @param[out] Src The source to copy from.
523 *
524 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
525 * on failure.
526 *
527 * This fails if @c Src.len is greater than @c Dest.len.
528 *
529 * Note that like @c memcpy(), the pointers are not checked and this
530 * will crash rather than return @ref NULLUsefulBufC if they are @c
531 * NULL or invalid.
532 *
533 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100534 */
535static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
536
537
538/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700539 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
540 *
541 * @param[in] pDest The destination buffer to copy into.
542 * @param[in] value The value to set the bytes to.
543 *
544 * Note that like @c memset(), the pointer in @c pDest is not checked
545 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100546 */
547static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
548
549
550/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700551 * @brief Copy a pointer into a @ref UsefulBuf.
552 *
553 * @param[in,out] Dest The destination buffer to copy into.
554 * @param[in] ptr The source to copy from.
555 * @param[in] uLen Length of the source; amount to copy.
556 *
557 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
558 * on failure.
559 *
560 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
561 * than @c pDest->len.
562 *
563 * Note that like @c memcpy(), the pointers are not checked and this
564 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100565 */
566static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
567 const void *ptr,
568 size_t uLen);
569
570
571/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700572 * @brief Returns a truncation of a @ref UsefulBufC.
573 *
574 * @param[in] UB The buffer to get the head of.
575 * @param[in] uAmount The number of bytes in the head.
576 *
577 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100578 */
579static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
580
581
582/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700583 * @brief Returns bytes from the end of a @ref UsefulBufC.
584 *
585 * @param[in] UB The buffer to get the tail of.
586 * @param[in] uAmount The offset from the start where the tail is to begin.
587 *
588 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
589 * if @c uAmount is greater than the length of the @ref UsefulBufC.
590 *
591 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
592 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
593 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100594 */
595static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
596
597
598/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700599 * @brief Compare one @ref UsefulBufC to another.
600 *
601 * @param[in] UB1 The first buffer to compare.
602 * @param[in] UB2 The second buffer to compare.
603 *
604 * @return 0, positive or negative value.
605 *
606 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
607 * less than @c UB2 if it is shorter or the first byte that is not the
608 * same is less.
609 *
610 * Returns 0 if the inputs are the same.
611 *
612 * Returns a positive value if @c UB2 is less than @c UB1.
613 *
614 * All that is of significance is that the result is positive, negative
615 * or 0. (This doesn't return the difference between the first
616 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100617 */
618int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
619
620
621/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700622 * @brief Find first byte that is not a particular byte value.
623 *
624 * @param[in] UB The destination buffer for byte comparison.
625 * @param[in] uValue The byte value to compare to.
626 *
627 * @return Offset of first byte that isn't @c uValue or
628 * @c SIZE_MAX if all bytes are @c uValue.
629 *
630 * Note that unlike most comparison functions, 0
631 * does not indicate a successful comparison, so the
632 * test for match is:
633 *
634 * UsefulBuf_IsValue(...) == SIZE_MAX
635 *
636 * If @c UB is null or empty, there is no match
637 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100638 */
639size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
640
641
642/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700643 * @brief Find one @ref UsefulBufC in another.
644 *
645 * @param[in] BytesToSearch Buffer to search through.
646 * @param[in] BytesToFind Buffer with bytes to be found.
647 *
648 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100649 */
650size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
651
652
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700653/**
654 @brief Convert a pointer to an offset with bounds checking.
655
656 @param[in] UB Pointer to the UsefulInputBuf.
657 @param[in] p Pointer to convert to offset.
658
659 @return SIZE_MAX if @c p is out of range, the byte offset if not.
660*/
661static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
662
663
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800664#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100665/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700666#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100667
668/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
669#define MakeUsefulBufOnStack(name, size) \
670 uint8_t __pBuf##name[(size)];\
671 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
672
673/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
674#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700675 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100676
677/** Deprecated function; use UsefulBuf_Unconst() instead */
678static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
679{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700680 UsefulBuf UB;
681
Laurence Lundblade3eead482023-12-16 20:53:22 -0700682 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300683 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700684
685 UB.len = UBC.len;
686
687 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100688}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800689#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100690
691
692
693
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200694#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100695/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700696 * @brief Copy a @c float to a @c uint32_t.
697 *
698 * @param[in] f Float value to copy.
699 *
700 * @return A @c uint32_t with the float bits.
701 *
702 * Convenience function to avoid type punning, compiler warnings and
703 * such. The optimizer usually reduces this to a simple assignment. This
704 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100705 */
706static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
707
708
709/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700710 * @brief Copy a @c double to a @c uint64_t.
711 *
712 * @param[in] d Double value to copy.
713 *
714 * @return A @c uint64_t with the double bits.
715 *
716 * Convenience function to avoid type punning, compiler warnings and
717 * such. The optimizer usually reduces this to a simple assignment. This
718 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100719 */
720static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
721
722
723/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700724 * @brief Copy a @c uint32_t to a @c float.
725 *
726 * @param[in] u32 Integer value to copy.
727 *
728 * @return The value as a @c float.
729 *
730 * Convenience function to avoid type punning, compiler warnings and
731 * such. The optimizer usually reduces this to a simple assignment. This
732 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100733 */
734static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
735
736
737/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700738 * @brief Copy a @c uint64_t to a @c double.
739 *
740 * @param[in] u64 Integer value to copy.
741 *
742 * @return The value as a @c double.
743 *
744 * Convenience function to avoid type punning, compiler warnings and
745 * such. The optimizer usually reduces this to a simple assignment. This
746 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100747 */
748static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200749#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100750
751
752
753
754/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700755 * UsefulOutBuf is a structure and functions (an object) for
756 * serializing data into a buffer to encode for a network protocol or
757 * write data to a file.
758 *
759 * The main idea is that all the pointer manipulation is performed by
760 * @ref UsefulOutBuf functions so the caller doesn't have to do any
761 * pointer manipulation. The pointer manipulation is centralized.
762 * This code has been reviewed and written carefully so it
763 * spares the caller of much of this work and results in safer code
764 * with less effort.
765 *
766 * The @ref UsefulOutBuf methods that add data to the output buffer
767 * always check the length and will never write off the end of the
768 * output buffer. If an attempt to add data that will not fit is made,
769 * an internal error flag will be set and further attempts to add data
770 * will not do anything.
771 *
772 * There is no way to ever write off the end of that buffer when
773 * calling the @c UsefulOutBuf_AddXxx() and
774 * @c UsefulOutBuf_InsertXxx() functions.
775 *
776 * The functions to add data do not report success of failure. The
777 * caller only needs to check for an error in the final call, either
778 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
779 * result. This makes the calling code cleaner.
780 *
781 * There is a utility function to get the error status anytime along
782 * the way for a special circumstance. There are functions to see how
783 * much room is left and see if some data will fit too, but their use
784 * is generally unnecessary.
785 *
786 * The general call flow is:
787 *
788 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
789 * buffer given to it can be from the heap, stack or
790 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
791 * macro that makes a buffer on the stack and initializes it.
792 *
793 * - Call methods like UsefulOutBuf_InsertString(),
794 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
795 * to output data. The append calls add data to the end of the
796 * valid data. The insert calls take a position argument.
797 *
798 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
799 * there were no errors and to get the serialized output bytes.
800 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700801 * @ref UsefulOutBuf can be used in a mode to calculate the size of
802 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700803 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700804 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700805 *
806 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700807 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700808 *
809 * The possible errors are:
810 *
811 * - The @ref UsefulOutBuf was not initialized or was corrupted.
812 *
813 * - An attempt was made to add data that will not fit.
814 *
815 * - An attempt was made to insert data at a position beyond the end of
816 * the buffer.
817 *
818 * - An attempt was made to insert data at a position beyond the valid
819 * data in the buffer.
820 *
821 * Some inexpensive simple sanity checks are performed before every
822 * data addition to guard against use of an uninitialized or corrupted
823 * UsefulOutBuf.
824 *
825 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
826 * encoder has almost no pointer manipulation in it, is easier to
827 * read, and easier to review.
828 *
829 * A @ref UsefulOutBuf is small and can go on the stack:
830 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
831 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100832 */
833typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700834 /* PRIVATE DATA STRUCTURE */
835 UsefulBuf UB; /* Memory that is being output to */
836 size_t data_len; /* length of the valid data, the insertion point */
837 uint16_t magic; /* Used to detect corruption and lack
838 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100839 uint8_t err;
840} UsefulOutBuf;
841
842
843/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700844 * This is a @ref UsefulBuf value that can be passed to
845 * UsefulOutBuf_Init() to have it calculate the size of the output
846 * buffer needed. Pass this for @c Storage, call all the append and
847 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
848 * returned @ref UsefulBufC has the size.
849 *
850 * As one can see, this is just a NULL pointer and very large size.
851 * The NULL pointer tells UsefulOutputBuf to not copy any data.
852 */
853#ifdef __cplusplus
854#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
855#else
856#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
857#endif
858
859
860/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700861 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700862 *
863 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
864 * @param[in] Storage Buffer to output into.
865 *
866 * This initializes the @ref UsefulOutBuf with storage, sets the
867 * current position to the beginning of the buffer and clears the
868 * error state.
869 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700870 * See @ref SizeCalculateUsefulBuf for instructions on how to
871 * initialize a @ref UsefulOutBuf to calculate the size that would be
872 * output without actually outputting.
873 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700874 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100875 */
876void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
877
878
879/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700880 * Convenience macro to make a @ref UsefulOutBuf on the stack and
881 * initialize it with a stack buffer of the given size. The variable
882 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100883 */
884#define UsefulOutBuf_MakeOnStack(name, size) \
885 uint8_t __pBuf##name[(size)];\
886 UsefulOutBuf name;\
887 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
888
889
890/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700891 * @brief Reset a @ref UsefulOutBuf for re use.
892 *
893 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
894 *
895 * This sets the amount of data in the output buffer to none and
896 * clears the error state.
897 *
898 * The output buffer is still the same one and size as from the
899 * UsefulOutBuf_Init() call.
900 *
901 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100902 */
903static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
904
905
906/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700907 * @brief Returns position of end of data in the @ref UsefulOutBuf.
908 *
909 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
910 *
911 * @return position of end of data.
912 *
913 * On a freshly initialized @ref UsefulOutBuf with no data added, this
914 * will return 0. After 10 bytes have been added, it will return 10
915 * and so on.
916 *
917 * Generally, there is no need to call this for most uses of @ref
918 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100919 */
920static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
921
922
923/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700924 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
925 *
926 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
927 *
928 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100929 */
930static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
931
932
933/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700934 * @brief Inserts bytes into the @ref UsefulOutBuf.
935 *
936 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
937 * @param[in] NewData The bytes to insert.
938 * @param[in] uPos Index in output buffer at which to insert.
939 *
940 * @c NewData is the pointer and length for the bytes to be added to
941 * the output buffer. There must be room in the output buffer for all
942 * of @c NewData or an error will occur.
943 *
944 * The insertion point must be between 0 and the current valid
945 * data. If not, an error will occur. Appending data to the output
946 * buffer is achieved by inserting at the end of the valid data. This
947 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
948 *
949 * When insertion is performed, the bytes between the insertion point
950 * and the end of data previously added to the output buffer are slid
951 * to the right to make room for the new data.
952 *
953 * Overlapping buffers are OK. @c NewData can point to data in the
954 * output buffer.
955 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700956 * NewData.len may be 0 in which case nothing will be inserted.
957 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700958 * If an error occurs, an error state is set in the @ref
959 * UsefulOutBuf. No error is returned. All subsequent attempts to add
960 * data will do nothing.
961 *
962 * The intended use is that all additions are made without checking
963 * for an error. The error will be taken into account when
964 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
965 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100966 */
967void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
968 UsefulBufC NewData,
969 size_t uPos);
970
971
972/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700973 * @brief Insert a data buffer into the @ref UsefulOutBuf.
974 *
975 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
976 * @param[in] pBytes Pointer to the bytes to insert
977 * @param[in] uLen Length of the bytes to insert
978 * @param[in] uPos Index in output buffer at which to insert
979 *
980 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
981 * the difference being a pointer and length is passed in rather than an
982 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100983 */
984static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
985 const void *pBytes,
986 size_t uLen,
987 size_t uPos);
988
989
990/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700991 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
992 *
993 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
994 * @param[in] szString NULL-terminated string to insert.
995 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100996 */
997static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
998 const char *szString,
999 size_t uPos);
1000
1001
1002/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001003 * @brief Insert a byte into the @ref UsefulOutBuf.
1004 *
1005 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1006 * @param[in] byte Bytes to insert.
1007 * @param[in] uPos Index in output buffer at which to insert.
1008 *
1009 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1010 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001011 */
1012static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1013 uint8_t byte,
1014 size_t uPos);
1015
1016
1017/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001018 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1019 *
1020 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1021 * @param[in] uInteger16 Integer to insert.
1022 * @param[in] uPos Index in output buffer at which to insert.
1023 *
1024 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1025 * with the difference being a two-byte integer is to be inserted.
1026 *
1027 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001028 */
1029static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1030 uint16_t uInteger16,
1031 size_t uPos);
1032
1033
1034/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001035 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1036 *
1037 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1038 * @param[in] uInteger32 Integer to insert.
1039 * @param[in] uPos Index in output buffer at which to insert.
1040 *
1041 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1042 * with the difference being a four-byte integer is to be inserted.
1043 *
1044 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001045 */
1046static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1047 uint32_t uInteger32,
1048 size_t uPos);
1049
1050
1051/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001052 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1053 *
1054 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1055 * @param[in] uInteger64 Integer to insert.
1056 * @param[in] uPos Index in output buffer at which to insert.
1057 *
1058 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1059 * with the difference being an eight-byte integer is to be inserted.
1060 *
1061 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001062 */
1063static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1064 uint64_t uInteger64,
1065 size_t uPos);
1066
1067
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001068#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001069/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001070 * @brief Insert a @c float into the @ref UsefulOutBuf.
1071 *
1072 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1073 * @param[in] f @c float to insert.
1074 * @param[in] uPos Index in output buffer at which to insert.
1075 *
1076 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1077 * with the difference being a @c float is to be inserted.
1078 *
1079 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001080 */
1081static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1082 float f,
1083 size_t uPos);
1084
1085
1086/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001087 * @brief Insert a @c double into the @ref UsefulOutBuf.
1088 *
1089 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1090 * @param[in] d @c double to insert.
1091 * @param[in] uPos Index in output buffer at which to insert.
1092 *
1093 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1094 * with the difference being a @c double is to be inserted.
1095 *
1096 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001097 */
1098static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1099 double d,
1100 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001101#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001102
1103
1104/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001105 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1106 *
1107 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1108 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1109 *
1110 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1111 * with the insertion point at the end of the valid data.
1112 */
Michael Eckel5c531332020-03-02 01:35:30 +01001113static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1114 UsefulBufC NewData);
1115
1116
1117/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001118 * @brief Append bytes to the @ref UsefulOutBuf.
1119 *
1120 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1121 * @param[in] pBytes Pointer to bytes to append.
1122 * @param[in] uLen Length of @c pBytes to append.
1123 *
1124 * See UsefulOutBuf_InsertData() for details. This does the same with
1125 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001126 */
1127static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1128 const void *pBytes,
1129 size_t uLen);
1130
1131
1132/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001133 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1134 *
1135 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1136 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001137 */
1138static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1139 const char *szString);
1140
1141
1142/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001143 * @brief Append a byte to the @ref UsefulOutBuf
1144 *
1145 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1146 * @param[in] byte Bytes to append.
1147 *
1148 * See UsefulOutBuf_InsertByte() for details. This does the same
1149 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001150 */
1151static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1152 uint8_t byte);
1153
1154
1155/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001156 * @brief Append an integer to the @ref UsefulOutBuf
1157 *
1158 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1159 * @param[in] uInteger16 Integer to append.
1160 *
1161 * See UsefulOutBuf_InsertUint16() for details. This does the same
1162 * with the insertion point at the end of the valid data.
1163 *
1164 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001165 */
1166static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1167 uint16_t uInteger16);
1168
1169
1170/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001171 * @brief Append an integer to the @ref UsefulOutBuf
1172 *
1173 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1174 * @param[in] uInteger32 Integer to append.
1175 *
1176 * See UsefulOutBuf_InsertUint32() for details. This does the same
1177 * with the insertion point at the end of the valid data.
1178 *
1179 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001180 */
1181static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1182 uint32_t uInteger32);
1183
1184
1185/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001186 * @brief Append an integer to the @ref UsefulOutBuf
1187 *
1188 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1189 * @param[in] uInteger64 Integer to append.
1190 *
1191 * See UsefulOutBuf_InsertUint64() for details. This does the same
1192 * with the insertion point at the end of the valid data.
1193 *
1194 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001195 */
1196static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1197 uint64_t uInteger64);
1198
1199
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001200#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001201/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001202 * @brief Append a @c float to the @ref UsefulOutBuf
1203 *
1204 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1205 * @param[in] f @c float to append.
1206 *
1207 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1208 * the insertion point at the end of the valid data.
1209 *
1210 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001211 */
1212static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1213 float f);
1214
1215
1216/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001217 * @brief Append a @c double to the @ref UsefulOutBuf
1218 *
1219 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1220 * @param[in] d @c double to append.
1221 *
1222 * See UsefulOutBuf_InsertDouble() for details. This does the same
1223 * with the insertion point at the end of the valid data.
1224 *
1225 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001226 */
1227static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1228 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001229#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001230
1231
1232/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001233 * @brief Returns the current error status.
1234 *
1235 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1236 *
1237 * @return 0 if all OK, 1 on error.
1238 *
1239 * This returns the error status since a call to either
1240 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1241 * goes into the error state, it will stay until one of those
1242 * functions is called.
1243 *
1244 * Possible error conditions are:
1245 * - bytes to be inserted will not fit
1246 * - insertion point is out of buffer or past valid data
1247 * - current position is off end of buffer (probably corrupted or uninitialized)
1248 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001249 */
1250static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1251
1252
1253/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001254 * @brief Returns number of bytes unused used in the output buffer.
1255 *
1256 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1257 *
1258 * @return Number of unused bytes or zero.
1259 *
1260 * Because of the error handling strategy and checks in
1261 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1262 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001263 */
1264static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1265
1266
1267/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001268 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1269 *
1270 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1271 * @param[in] uLen Number of bytes for which to check
1272 *
1273 * @return 1 if @c uLen bytes will fit, 0 if not.
1274 *
1275 * Because of the error handling strategy and checks in
1276 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1277 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001278 */
1279static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1280
1281
1282 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001283 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1284 *
1285 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1286 *
1287 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1288 *
1289 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1290 * just calculating the length of the encoded data.
1291 */
Michael Eckel5c531332020-03-02 01:35:30 +01001292static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1293
1294
1295/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001296 * @brief Returns pointer and length of the output buffer not yet used.
1297 *
1298 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1299 *
1300 * @return pointer and length of output buffer not used.
1301 *
1302 * This is an escape that allows the caller to write directly
1303 * to the output buffer without any checks. This doesn't
1304 * change the output buffer or state. It just returns a pointer
1305 * and length of the bytes remaining.
1306 *
1307 * This is useful to avoid having the bytes to be added all
1308 * in a contiguous buffer. Its use can save memory. A good
1309 * example is in the COSE encrypt implementation where
1310 * the output of the symmetric cipher can go directly
1311 * into the output buffer, rather than having to go into
1312 * an intermediate buffer.
1313 *
1314 * See UsefulOutBuf_Advance() which is used to tell
1315 * UsefulOutBuf how much was written.
1316 *
1317 * Warning: this bypasses the buffer safety provided by
1318 * UsefulOutBuf!
1319 */
1320static inline UsefulBuf
1321UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1322
1323
1324/**
1325 * @brief Advance the amount output assuming it was written by the caller.
1326 *
1327 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1328 * @param[in] uAmount The amount to advance.
1329 *
1330 * This advances the position in the output buffer
1331 * by \c uAmount. This assumes that the
1332 * caller has written \c uAmount to the pointer obtained
1333 * with UsefulOutBuf_GetOutPlace().
1334 *
1335 * Warning: this bypasses the buffer safety provided by
1336 * UsefulOutBuf!
1337 */
1338void
1339UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1340
1341
1342/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001343 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001344 *
1345 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1346 *
1347 * @return The valid data in @ref UsefulOutBuf or
1348 * @ref NULLUsefulBufC if there was an error adding data.
1349 *
1350 * The storage for the returned data is the @c Storage parameter
1351 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1352 *
1353 * This can be called anytime and many times to get intermediate
1354 * results. It doesn't change the data or reset the current position,
1355 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001356 */
1357UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1358
1359
1360/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001361 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001362 *
1363 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1364 * @param[out] Dest The destination buffer to copy into.
1365 *
1366 * @return Pointer and length of copied data or @c NULLUsefulBufC
1367 * if it will not fit in the @c Dest buffer or the error
1368 * state was entered.
1369 *
1370 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001371 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001372 */
Michael Eckel5c531332020-03-02 01:35:30 +01001373UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1374
1375
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001376/**
1377 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1378 *
1379 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1380 * @param[in] uOffset Offset to bytes to return.
1381 *
1382 * @return NULLUsefulBufC or the bytes at the offset.
1383 *
1384 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1385 * maybe specified. It returns the bytes starting at @c uOffset to the
1386 * end of what was encoded so far. Calling this with @c uOffset 0 is
1387 * equivalent to UsefulOutBuf_OutUBuf().
1388 *
1389 * If there's nothing at @c uOffset or it is past the in the output
1390 * buffer, a \ref NULLUsefulBufC is returned.
1391 *
1392 * This is typically not needed in typical use. It is used by QCBOR
1393 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1394 * sorting CBOR maps.
1395 */
1396UsefulBufC
1397UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1398
1399
1400/**
1401 * @brief Compare bytes at offsets.
1402 *
1403 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1404 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001405 * @param[in] uLen1 Length of first bytes to compare.
1406 * @param[in] uStart2 Offset of second bytes to compare.
1407 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001408 *
1409 * @return 0 for equality, positive if uStart1 is lexographically larger,
1410 * negative if uStart2 is lexographically larger.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001411 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001412 * This looks into bytes that have been output at the offsets @c start1
1413 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001414 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1415 * length of the string given is off the end of the output data, the
1416 * string will be effectively concated to the data in the output
1417 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001418 *
1419 * This returns positive when @c uStart1 lexographically sorts ahead
1420 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001421 * compare equally.
1422 *
1423 * If lengths are unequal and the first bytes are an exact subset of
1424 * the second string, then a positve value will be returned and vice
1425 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001426 *
1427 * If either start is past the end of data in the output buffer, 0
1428 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001429 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001430 * being made. No data will ever be read off the end of the buffer so
1431 * this safe no matter what offsets are passed.
1432 *
1433 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001434 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1435 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001436 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001437int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1438 size_t uStart1, size_t uLen1,
1439 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001440
1441/**
1442 * @brief Swap two regions of output bytes.
1443 *
1444 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1445 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1446 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1447 * @param[in] uEndOffset Offset to end of region to be swappe.
1448 *
1449 * This reaches into bytes that have been output and swaps two
1450 * adjacent regions.
1451 *
1452 * If any of the offsets are outside the range of valid data, no
1453 * swapping will be performed. If the start is not the smallest and
1454 * the pivot is not in the middle no swapping will be performed.
1455 *
1456 * The byte at @c uStartOffset will participate in the swapping. The
1457 * byte at @c uEndOffset will not participate in the swapping, only
1458 * the byte before it.
1459 *
1460 * This is a relatively odd function in that it works on data in the
1461 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1462 * maps.
1463 */
1464void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1465 size_t uStartOffset,
1466 size_t uPivotOffset,
1467 size_t uEndOffset);
1468
1469
Michael Eckel5c531332020-03-02 01:35:30 +01001470
1471
1472/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001473 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1474 * for parsing data received. Initialize it with the data from the
1475 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1476 * get data chunks of various types. A position cursor is maintained
1477 * internally.
1478 *
1479 * As long as the functions here are used, there will never be any
1480 * reference off the end of the given buffer (except
1481 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1482 * called incorrectly, an attempt is made to seek off the end of the
1483 * buffer or such. This makes it easier to write safe and correct
1484 * code. For example, the QCBOR decoder implementation is safer and
1485 * easier to review through its use of @ref UsefulInputBuf.
1486 *
1487 * @ref UsefulInputBuf maintains an internal error state. The
1488 * intended use is fetching data chunks without any error checks until
1489 * the end. If there was any error, such as an attempt to fetch data
1490 * off the end, the error state is entered and no further data will be
1491 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1492 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1493 * null is not dereferenced, the error check can be put off until the
1494 * end, simplifying the calling code.
1495 *
1496 * The integer and float parsing expects network byte order (big
1497 * endian). Network byte order is what is used by TCP/IP, CBOR and
1498 * most internet protocols.
1499 *
1500 * Lots of inline functions are used to keep code size down. The
1501 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1502 * code size a lot. The only non-inline code is
1503 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1504 * @ref UsefulInputBuf doesn't add much code for all the messy
1505 * hard-to-get right issues with parsing binary protocols in C that it
1506 * solves.
1507 *
1508 * The parse context size is:
1509 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1510 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001511 */
1512typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001513 /* PRIVATE DATA STRUCTURE */
1514 UsefulBufC UB; /* Data being parsed */
1515 size_t cursor; /* Current offset in data being parse */
1516 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1517 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001518} UsefulInputBuf;
1519
1520#define UIB_MAGIC (0xB00F)
1521
1522
1523/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001524 * @brief Initialize the @ref UsefulInputBuf structure before use.
1525 *
1526 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1527 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001528 */
1529static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1530
1531
1532/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001533 * @brief Returns current position in input buffer.
1534 *
1535 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1536 *
1537 * @return Integer position of the cursor.
1538 *
1539 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001540 */
1541static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1542
1543
1544/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001545 * @brief Sets the current position in input buffer.
1546 *
1547 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1548 * @param[in] uPos Position to set to.
1549 *
1550 * If the position is off the end of the input buffer, the error state
1551 * is entered.
1552 *
1553 * Seeking to a valid position in the buffer will not reset the error
1554 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001555 */
1556static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1557
1558
1559/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001560 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1561 * the unconsumed bytes.
1562 *
1563 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1564 *
1565 * @return Number of bytes unconsumed or 0 on error.
1566 *
1567 * Returns 0 if the cursor is invalid or corruption of the
1568 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001569 */
1570static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1571
1572
1573/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001574 * @brief Check if there are unconsumed bytes.
1575 *
1576 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1577 * @param[in] uLen Number of bytes to check availability for.
1578 *
1579 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001580 */
1581static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1582
1583
1584/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001585 * @brief Convert a pointer to an offset with bounds checking.
1586 *
1587 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1588 * @param[in] p Pointer to convert to offset.
1589 *
1590 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1591 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001592static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1593
1594
1595/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001596 * @brief Get pointer to bytes out of the input buffer.
1597 *
1598 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1599 * @param[in] uNum Number of bytes to get.
1600 *
1601 * @return Pointer to bytes.
1602 *
1603 * This consumes @c uNum bytes from the input buffer. This returns a
1604 * pointer to the start of the @c uNum bytes.
1605 *
1606 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1607 * returned and the error state is entered.
1608 *
1609 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001610 */
1611const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1612
1613
1614/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001615 * @brief Get @ref UsefulBuf out of the input buffer.
1616 *
1617 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1618 * @param[in] uNum Number of bytes to get.
1619 *
1620 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1621 *
1622 * This consumes @c uNum bytes from the input buffer and returns the
1623 * pointer and length for them as a @ref UsefulBufC. The length
1624 * returned will always be @c uNum. The position cursor is advanced by
1625 * @c uNum bytes.
1626 *
1627 * If there are not @c uNum bytes in the input buffer, @ref
1628 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001629 */
1630static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1631
1632
1633/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001634 * @brief Get a byte out of the input buffer.
1635 *
1636 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1637 *
1638 * @return The byte.
1639 *
1640 * This consumes 1 byte from the input buffer, returns it and advances
1641 * the position cursor by 1.
1642 *
1643 * If there is not 1 byte in the buffer, 0 will be returned for the
1644 * byte and the error state is entered. To know if the 0 returned was
1645 * in error or the real value, the error state must be checked. If
1646 * possible, put this off until all values are retrieved to have
1647 * smaller and simpler code, but if not possible
1648 * UsefulInputBuf_GetError() can be called. Also, in the error state
1649 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1650 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001651 */
1652static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1653
1654
1655/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001656 * @brief Get a @c uint16_t out of the input buffer.
1657 *
1658 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1659 *
1660 * @return The @c uint16_t.
1661 *
1662 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1663 * a @c uint16_t and two bytes are consumed.
1664 *
1665 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001666 */
1667static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1668
1669
1670/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001671 * @brief Get a @c uint32_t out of the input buffer.
1672 *
1673 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1674 *
1675 * @return The @c uint32_t.
1676 *
1677 * See UsefulInputBuf_GetByte(). This works the same, except it
1678 * returns a @c uint32_t and four bytes are consumed.
1679 *
1680 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001681 */
1682static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1683
1684
1685/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001686 * @brief Get a @c uint64_t out of the input buffer.
1687 *
1688 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1689 *
1690 * @return The uint64_t.
1691 *
1692 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1693 * a @c uint64_t and eight bytes are consumed.
1694 *
1695 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001696 */
1697static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1698
1699
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001700#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001701/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001702 * @brief Get a float out of the input buffer.
1703 *
1704 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1705 *
1706 * @return The float.
1707 *
1708 * See UsefulInputBuf_GetByte(). This works the same, except it
1709 * returns a float and four bytes are consumed.
1710 *
1711 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001712 */
1713static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1714
1715
1716/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001717 * @brief Get a double out of the input buffer.
1718 *
1719 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1720 *
1721 * @return The double.
1722 *
1723 * See UsefulInputBuf_GetByte(). This works the same, except it
1724 * returns a double and eight bytes are consumed.
1725 *
1726 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001727 */
1728static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001729#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001730
1731
1732/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001733 * @brief Get the error status.
1734 *
1735 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1736 *
1737 * @return 0 if not in the error state, 1 if in the error state.
1738 *
1739 * This returns whether the @ref UsefulInputBuf is in the
1740 * error state or not.
1741 *
1742 * The error state is entered for one of these reasons:
1743 * - Attempt to fetch data past the end of the buffer
1744 * - Attempt to seek to a position past the end of the buffer
1745 * - Attempt to get data from an uninitialized or corrupt instance
1746 * of @ref UsefulInputBuf
1747 *
1748 * Once in the error state, it can only be cleared by calling
1749 * UsefulInputBuf_Init().
1750 *
1751 * For many use cases, it is possible to only call this once after all
1752 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1753 * possible if no reference to the data returned are needed before the
1754 * error state is checked.
1755 *
1756 * In some cases UsefulInputBuf_GetUsefulBuf() or
1757 * UsefulInputBuf_GetBytes() can stand in for this because they return
1758 * @c NULL if the error state has been entered. (The others can't stand
1759 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001760 */
1761static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1762
1763
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001764/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001765 * @brief Gets the input buffer length.
1766 *
1767 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1768 *
1769 * @return The length of the input buffer.
1770 *
1771 * This returns the length of the input buffer set by
1772 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001773 */
1774static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1775
1776
1777/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001778 * @brief Alters the input buffer length (use with caution).
1779 *
1780 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1781 * @param[in] uNewLen The new length of the input buffer.
1782 *
1783 * This alters the internal remembered length of the input buffer set
1784 * when UsefulInputBuf_Init() was called.
1785 *
1786 * The new length given here should always be equal to or less than
1787 * the length given when UsefulInputBuf_Init() was called. Making it
1788 * larger allows @ref UsefulInputBuf to run off the input buffer.
1789 *
1790 * The typical use is to set a length shorter than that when
1791 * initialized to constrain parsing. If
1792 * UsefulInputBuf_GetBufferLength() was called before this, then the
1793 * original length can be restored with another call to this.
1794 *
1795 * This should be used with caution. It is the only
1796 * @ref UsefulInputBuf method that can violate the safety of input
1797 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001798 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001799static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001800
1801
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001802
1803
Michael Eckel5c531332020-03-02 01:35:30 +01001804/*----------------------------------------------------------
1805 Inline implementations.
1806 */
1807static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1808{
1809 return !UB.ptr;
1810}
1811
1812
1813static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1814{
1815 return !UB.ptr;
1816}
1817
1818
1819static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1820{
1821 return !UB.len;
1822}
1823
1824
1825static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1826{
1827 return !UB.len;
1828}
1829
1830
1831static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1832{
1833 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1834}
1835
1836
1837static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1838{
1839 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1840}
1841
1842
1843static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1844{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001845 UsefulBufC UBC;
1846 UBC.ptr = UB.ptr;
1847 UBC.len = UB.len;
1848
1849 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001850}
1851
Michael Eckel5c531332020-03-02 01:35:30 +01001852static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1853{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001854 UsefulBuf UB;
1855
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001856 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001857 * the one place in UsefulBuf where it needs to be quieted.
1858 */
1859 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001860
1861 UB.len = UBC.len;
1862
1863 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001864}
1865
1866
1867static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1868{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001869 UsefulBufC UBC;
1870 UBC.ptr = szString;
1871 UBC.len = strlen(szString);
1872 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001873}
1874
1875
1876static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1877{
1878 return UsefulBuf_CopyOffset(Dest, 0, Src);
1879}
1880
1881
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001882static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001883{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001884 memset(Dest.ptr, value, Dest.len);
1885
1886 UsefulBufC UBC;
1887 UBC.ptr = Dest.ptr;
1888 UBC.len = Dest.len;
1889
1890 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001891}
1892
1893
1894static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1895{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001896 UsefulBufC UBC;
1897 UBC.ptr = ptr;
1898 UBC.len = len;
1899 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001900}
1901
1902
1903static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1904{
1905 if(uAmount > UB.len) {
1906 return NULLUsefulBufC;
1907 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001908 UsefulBufC UBC;
1909
1910 UBC.ptr = UB.ptr;
1911 UBC.len = uAmount;
1912
1913 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001914}
1915
1916
1917static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1918{
1919 UsefulBufC ReturnValue;
1920
1921 if(uAmount > UB.len) {
1922 ReturnValue = NULLUsefulBufC;
1923 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001924 ReturnValue.ptr = NULL;
1925 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001926 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001927 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1928 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001929 }
1930
1931 return ReturnValue;
1932}
1933
1934
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001935static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1936{
1937 if(UB.ptr == NULL) {
1938 return SIZE_MAX;
1939 }
1940
1941 if(p < UB.ptr) {
1942 /* given pointer is before start of buffer */
1943 return SIZE_MAX;
1944 }
1945
Laurence Lundblade3eead482023-12-16 20:53:22 -07001946 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001947 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001948
1949 if(uOffset >= UB.len) {
1950 /* given pointer is off the end of the buffer */
1951 return SIZE_MAX;
1952 }
1953
1954 return uOffset;
1955}
1956
Michael Eckel5c531332020-03-02 01:35:30 +01001957
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001958#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001959static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1960{
1961 uint32_t u32;
1962 memcpy(&u32, &f, sizeof(uint32_t));
1963 return u32;
1964}
1965
1966static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1967{
1968 uint64_t u64;
1969 memcpy(&u64, &d, sizeof(uint64_t));
1970 return u64;
1971}
1972
1973static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1974{
1975 double d;
1976 memcpy(&d, &u64, sizeof(uint64_t));
1977 return d;
1978}
1979
1980static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1981{
1982 float f;
1983 memcpy(&f, &u32, sizeof(uint32_t));
1984 return f;
1985}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001986#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001987
1988
1989
1990
1991static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1992{
1993 pMe->data_len = 0;
1994 pMe->err = 0;
1995}
1996
1997
1998static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1999{
2000 return pMe->data_len;
2001}
2002
2003
2004static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2005{
2006 return 0 == pMe->data_len;
2007}
2008
2009
2010static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2011 const void *pBytes,
2012 size_t uLen,
2013 size_t uPos)
2014{
2015 UsefulBufC Data = {pBytes, uLen};
2016 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2017}
2018
2019
2020static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2021 const char *szString,
2022 size_t uPos)
2023{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002024 UsefulBufC UBC;
2025 UBC.ptr = szString;
2026 UBC.len = strlen(szString);
2027
2028 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002029}
2030
2031
2032static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2033 uint8_t byte,
2034 size_t uPos)
2035{
2036 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2037}
2038
2039
2040static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2041 uint16_t uInteger16,
2042 size_t uPos)
2043{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002044 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002045
2046 const void *pBytes;
2047
2048#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2049 pBytes = &uInteger16;
2050
2051#elif defined(USEFULBUF_CONFIG_HTON)
2052 uint16_t uTmp = htons(uInteger16);
2053 pBytes = &uTmp;
2054
2055#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2056 uint16_t uTmp = __builtin_bswap16(uInteger16);
2057 pBytes = &uTmp;
2058
2059#else
2060 uint8_t aTmp[2];
2061
2062 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2063 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2064
2065 pBytes = aTmp;
2066#endif
2067
2068 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2069}
2070
2071
2072static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2073 uint32_t uInteger32,
2074 size_t uPos)
2075{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002076 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002077
2078 const void *pBytes;
2079
2080#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2081 pBytes = &uInteger32;
2082
2083#elif defined(USEFULBUF_CONFIG_HTON)
2084 uint32_t uTmp = htonl(uInteger32);
2085 pBytes = &uTmp;
2086
2087#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2088 uint32_t uTmp = __builtin_bswap32(uInteger32);
2089
2090 pBytes = &uTmp;
2091
2092#else
2093 uint8_t aTmp[4];
2094
2095 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2096 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2097 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2098 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2099
2100 pBytes = aTmp;
2101#endif
2102
2103 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2104}
2105
2106static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002107 uint64_t uInteger64,
2108 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002109{
2110 const void *pBytes;
2111
2112#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002113 /* We have been told explicitly we are running on a big-endian
2114 * machine. Network byte order is big endian, so just copy. There
2115 * is no issue with alignment here because uInteger64 is always
2116 * aligned (and it doesn't matter if pBytes is aligned).
2117 */
Michael Eckel5c531332020-03-02 01:35:30 +01002118 pBytes = &uInteger64;
2119
2120#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002121 /* Use system function to handle big- and little-endian. This works
2122 * on both big- and little-endian machines, but hton() is not
2123 * always available or in a standard place so it is not used by
2124 * default. With some compilers and CPUs the code for this is very
2125 * compact through use of a special swap instruction and on
2126 * big-endian machines hton() will reduce to nothing.
2127 */
Michael Eckel5c531332020-03-02 01:35:30 +01002128 uint64_t uTmp = htonll(uInteger64);
2129
2130 pBytes = &uTmp;
2131
2132#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002133 /* Use built-in function for byte swapping. This usually compiles
2134 * to an efficient special byte swap instruction. Unlike hton() it
2135 * does not do this conditionally on the CPU endianness, so this
2136 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2137 */
Michael Eckel5c531332020-03-02 01:35:30 +01002138 uint64_t uTmp = __builtin_bswap64(uInteger64);
2139
2140 pBytes = &uTmp;
2141
2142#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002143 /* Default which works on every CPU with no dependency on anything
2144 * from the CPU, compiler, libraries or OS. This always works, but
2145 * it is usually a little larger and slower than hton().
2146 */
Michael Eckel5c531332020-03-02 01:35:30 +01002147 uint8_t aTmp[8];
2148
2149 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2150 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2151 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2152 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2153 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2154 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2155 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2156 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2157
2158 pBytes = aTmp;
2159#endif
2160
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002161 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002162 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2163}
2164
2165
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002166#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002167static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2168 float f,
2169 size_t uPos)
2170{
2171 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2172}
2173
2174
2175static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2176 double d,
2177 size_t uPos)
2178{
2179 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2180}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002181#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002182
2183
2184static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2185 UsefulBufC NewData)
2186{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002187 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002188 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2189}
2190
2191
2192static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2193 const void *pBytes,
2194 size_t uLen)
2195{
2196 UsefulBufC Data = {pBytes, uLen};
2197 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2198}
2199
2200
2201static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2202 const char *szString)
2203{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002204 UsefulBufC UBC;
2205 UBC.ptr = szString;
2206 UBC.len = strlen(szString);
2207
2208 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002209}
2210
2211
2212static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2213 uint8_t byte)
2214{
2215 UsefulOutBuf_AppendData(pMe, &byte, 1);
2216}
2217
2218
2219static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2220 uint16_t uInteger16)
2221{
2222 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2223}
2224
2225static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2226 uint32_t uInteger32)
2227{
2228 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2229}
2230
2231
2232static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2233 uint64_t uInteger64)
2234{
2235 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2236}
2237
2238
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002239#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002240static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2241 float f)
2242{
2243 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2244}
2245
2246
2247static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2248 double d)
2249{
2250 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2251}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002252#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002253
2254
2255static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2256{
2257 return pMe->err;
2258}
2259
2260
2261static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2262{
2263 return pMe->UB.len - pMe->data_len;
2264}
2265
2266
2267static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2268{
2269 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2270}
2271
2272
2273static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2274{
2275 return pMe->UB.ptr == NULL;
2276}
2277
2278
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002279static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2280{
2281 UsefulBuf R;
2282
2283 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002284 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002285 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2286 } else {
2287 R.ptr = NULL;
2288 }
2289
2290 return R;
2291}
2292
2293
2294
Michael Eckel5c531332020-03-02 01:35:30 +01002295
2296static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2297{
2298 pMe->cursor = 0;
2299 pMe->err = 0;
2300 pMe->magic = UIB_MAGIC;
2301 pMe->UB = UB;
2302}
2303
2304static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2305{
2306 return pMe->cursor;
2307}
2308
2309
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002310static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002311{
2312 return pMe->UB.len;
2313}
2314
2315
Michael Eckel5c531332020-03-02 01:35:30 +01002316static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2317{
2318 if(uPos > pMe->UB.len) {
2319 pMe->err = 1;
2320 } else {
2321 pMe->cursor = uPos;
2322 }
2323}
2324
2325
2326static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2327{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002328 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002329
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002330 /* Magic number is messed up. Either the structure got overwritten
2331 * or was never initialized.
2332 */
Michael Eckel5c531332020-03-02 01:35:30 +01002333 if(pMe->magic != UIB_MAGIC) {
2334 return 0;
2335 }
2336
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002337 /* The cursor is off the end of the input buffer given.
2338 * Presuming there are no bugs in this code, this should never happen.
2339 * If it so, the struct was corrupted. The check is retained as
2340 * as a defense in case there is a bug in this code or the struct is
2341 * corrupted.
2342 */
Michael Eckel5c531332020-03-02 01:35:30 +01002343 if(pMe->cursor > pMe->UB.len) {
2344 return 0;
2345 }
2346
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002347 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002348 return pMe->UB.len - pMe->cursor;
2349}
2350
2351
2352static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2353{
2354 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2355}
2356
2357
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002358static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2359{
2360 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2361}
2362
2363
Michael Eckel5c531332020-03-02 01:35:30 +01002364static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2365{
2366 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2367 if(!pResult) {
2368 return NULLUsefulBufC;
2369 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002370 UsefulBufC UBC;
2371 UBC.ptr = pResult;
2372 UBC.len = uNum;
2373 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002374 }
2375}
2376
2377
2378static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2379{
2380 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2381
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002382 /* The ternary operator is subject to integer promotion, because
2383 * the operands are smaller than int, so cast back to uint8_t is
2384 * needed to be completely explicit about types (for static
2385 * analyzers).
2386 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002387 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002388}
2389
2390static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2391{
2392 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2393
2394 if(!pResult) {
2395 return 0;
2396 }
2397
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002398 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002399#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2400 uint16_t uTmp;
2401 memcpy(&uTmp, pResult, sizeof(uint16_t));
2402
2403#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2404 return uTmp;
2405
2406#elif defined(USEFULBUF_CONFIG_HTON)
2407 return ntohs(uTmp);
2408
2409#else
2410 return __builtin_bswap16(uTmp);
2411
2412#endif
2413
2414#else
2415
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002416 /* The operations here are subject to integer promotion because the
2417 * operands are smaller than int. They will be promoted to unsigned
2418 * int for the shift and addition. The cast back to uint16_t is is
2419 * needed to be completely explicit about types (for static
2420 * analyzers).
2421 */
Michael Eckel5c531332020-03-02 01:35:30 +01002422 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2423
2424#endif
2425}
2426
2427
2428static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2429{
2430 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2431
2432 if(!pResult) {
2433 return 0;
2434 }
2435
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002436 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002437#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2438 uint32_t uTmp;
2439 memcpy(&uTmp, pResult, sizeof(uint32_t));
2440
2441#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2442 return uTmp;
2443
2444#elif defined(USEFULBUF_CONFIG_HTON)
2445 return ntohl(uTmp);
2446
2447#else
2448 return __builtin_bswap32(uTmp);
2449
2450#endif
2451
2452#else
2453 return ((uint32_t)pResult[0]<<24) +
2454 ((uint32_t)pResult[1]<<16) +
2455 ((uint32_t)pResult[2]<<8) +
2456 (uint32_t)pResult[3];
2457#endif
2458}
2459
2460
2461static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2462{
2463 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2464
2465 if(!pResult) {
2466 return 0;
2467 }
2468
2469#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002470 /* pResult will probably not be aligned. This memcpy() moves the
2471 * bytes into a temp variable safely for CPUs that can or can't do
2472 * unaligned memory access. Many compilers will optimize the
2473 * memcpy() into a simple move instruction.
2474 */
Michael Eckel5c531332020-03-02 01:35:30 +01002475 uint64_t uTmp;
2476 memcpy(&uTmp, pResult, sizeof(uint64_t));
2477
2478#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002479 /* We have been told expliclity this is a big-endian CPU. Since
2480 * network byte order is big-endian, there is nothing to do.
2481 */
Michael Eckel5c531332020-03-02 01:35:30 +01002482
2483 return uTmp;
2484
2485#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002486 /* We have been told to use ntoh(), the system function to handle
2487 * big- and little-endian. This works on both big- and
2488 * little-endian machines, but ntoh() is not always available or in
2489 * a standard place so it is not used by default. On some CPUs the
2490 * code for this is very compact through use of a special swap
2491 * instruction.
2492 */
Michael Eckel5c531332020-03-02 01:35:30 +01002493
2494 return ntohll(uTmp);
2495
2496#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002497 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2498 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2499 * __builtin_bswap64() and friends are not conditional on CPU
2500 * endianness so this must only be used on little-endian machines.
2501 */
Michael Eckel5c531332020-03-02 01:35:30 +01002502
2503 return __builtin_bswap64(uTmp);
2504
2505
2506#endif
2507
2508#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002509 /* This is the default code that works on every CPU and every
2510 * endianness with no dependency on ntoh(). This works on CPUs
2511 * that either allow or do not allow unaligned access. It will
2512 * always work, but usually is a little less efficient than ntoh().
2513 */
Michael Eckel5c531332020-03-02 01:35:30 +01002514
2515 return ((uint64_t)pResult[0]<<56) +
2516 ((uint64_t)pResult[1]<<48) +
2517 ((uint64_t)pResult[2]<<40) +
2518 ((uint64_t)pResult[3]<<32) +
2519 ((uint64_t)pResult[4]<<24) +
2520 ((uint64_t)pResult[5]<<16) +
2521 ((uint64_t)pResult[6]<<8) +
2522 (uint64_t)pResult[7];
2523#endif
2524}
2525
2526
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002527#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002528static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2529{
2530 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2531
2532 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2533}
2534
2535
2536static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2537{
2538 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2539
2540 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2541}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002542#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002543
2544
2545static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2546{
2547 return pMe->err;
2548}
2549
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002550
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002551static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002552{
2553 pMe->UB.len = uNewLen;
2554}
2555
2556
Michael Eckel5c531332020-03-02 01:35:30 +01002557#ifdef __cplusplus
2558}
2559#endif
2560
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002561#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002562
2563