blob: 218d2694b4b85d4dbb75324b5e49122e9f0f9a9f [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 Lundbladea29f45a2024-05-14 15:55:19 -070046 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070047 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070048 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
49 19/11/2023 llundblade Add UsefulOutBuf_Swap().
50 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070051 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060052 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070053 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070054 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070055 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080056 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070057 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010058 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
59 5/21/2019 llundblade #define configs for efficient endianness handling.
60 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
61 3/23/2019 llundblade Big documentation & style update. No interface
62 change.
63 3/6/2019 llundblade Add UsefulBuf_IsValue()
64 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
65 12/13/2018 llundblade Documentation improvements
66 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
67 UsefulBufC.
68 02/02/18 llundbla Full support for integers in and out; fix pointer
69 alignment bug. Incompatible change: integers
70 in/out are now in network byte order.
71 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
72 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
73 comparison for < or > for unequal length buffers.
74 Added UsefulBuf_Set() function.
75 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
76 11/13/16 llundbla Initial Version.
77
78 =============================================================================*/
79
80#ifndef _UsefulBuf_h
81#define _UsefulBuf_h
82
83
84/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070085 * Endianness Configuration
86 *
87 * This code is written so it will work correctly on big- and
88 * little-endian CPUs without configuration or any auto-detection of
89 * endianness. All code here will run correctly regardless of the
90 * endianness of the CPU it is running on.
91 *
92 * There are four C preprocessor macros that can be set with #define
93 * to explicitly configure endianness handling. Setting them can
94 * reduce code size a little and improve efficiency a little.
95 *
96 * Note that most of QCBOR is unaffected by this configuration. Its
97 * endianness handling is integrated with the code that handles
98 * alignment and preferred serialization. This configuration does
99 * affect QCBOR's (planned) implementation of integer arrays (tagged
100 * arrays) and use of the functions here to serialize or deserialize
101 * integers and floating-point values.
102 *
103 * Following is the recipe for configuring the endianness-related
104 * #defines.
105 *
106 * The first option is to not define anything. This will work fine
107 * with all CPUs, OS's and compilers. The code for encoding integers
108 * may be a little larger and slower.
109 *
110 * If your CPU is big-endian then define
111 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
112 * for big-endian CPUs. It will be small and efficient because there
113 * will be no byte swapping.
114 *
115 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
116 * OS's and compilers, but not all. On big-endian CPUs this should
117 * give the most efficient code, the same as
118 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
119 * call the system-defined byte swapping method which is presumably
120 * implemented efficiently. In some cases, this will be a dedicated
121 * byte swap instruction like Intel's bswap.
122 *
123 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
124 * little-endian, it is also good to define
125 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
126 *
127 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
128 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
129 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
130 * system-defined byte swap method. However, note
131 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
132 * this is fixed now. Often hton() and ntoh() will call the built-in
133 * __builtin_bswapXX()() function, so this size issue could affect
134 * USEFULBUF_CONFIG_HTON.
135 *
136 * Last, run the tests. They must all pass.
137 *
138 * These #define config options affect the inline implementation of
139 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
140 * also affect the 16-, 32-bit, float and double versions of these
141 * functions. Since they are inline, the size effect is not in the
142 * UsefulBuf object code, but in the calling code.
143 *
144 * Summary:
145 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
146 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
147 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
148 * handle big and little-endian with system option.
149 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
150 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200151 *
152 * It is possible to run this code in environments where using floating point is
153 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
154 * that is related to handling floating point types, along with related
155 * interfaces. This makes it possible to compile the code with the compile
156 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100157 */
158
159#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
160#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
161#endif
162
163
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700164#include <stdint.h> /* for uint8_t, uint16_t.... */
165#include <string.h> /* for strlen, memcpy, memmove, memset */
166#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100167
168
169#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700170#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100171#endif
172
173#ifdef __cplusplus
174extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700175#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700176} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700177#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100178#endif
179
180/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700181 * @file UsefulBuf.h
182 *
183 * The goal of this code is to make buffer and pointer manipulation
184 * easier and safer when working with binary data.
185 *
186 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
187 * structures are used to represent buffers rather than ad hoc
188 * pointers and lengths.
189 *
190 * With these it is possible to write code that does little or no
191 * direct pointer manipulation for copying and formatting data. For
192 * example, the QCBOR encoder was written using these and has less
193 * pointer manipulation.
194 *
195 * While it is true that object code using these functions will be a
196 * little larger and slower than a white-knuckle clever use of
197 * pointers might be, but not by that much or enough to have an effect
198 * for most use cases. For security-oriented code this is highly
199 * worthwhile. Clarity, simplicity, reviewability and are more
200 * important.
201 *
202 * There are some extra sanity and double checks in this code to help
203 * catch coding errors and simple memory corruption. They are helpful,
204 * but not a substitute for proper code review, input validation and
205 * such.
206 *
207 * This code consists of a lot of inline functions and a few that are
208 * not. It should not generate very much object code, especially with
209 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100210 */
211
212
213/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700214 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
215 * hold a pointer and length for binary data. In C99 this data
216 * structure can be passed on the stack making a lot of code cleaner
217 * than carrying around a pointer and length as two parameters.
218 *
219 * This is also conducive to secure coding practice as the length is
220 * always carried with the pointer and the convention for handling a
221 * pointer and a length is clear.
222 *
223 * While it might be possible to write buffer and pointer code more
224 * efficiently in some use cases, the thought is that unless there is
225 * an extreme need for performance (e.g., you are building a
226 * gigabit-per-second IP router), it is probably better to have
227 * cleaner code you can be most certain about the security of.
228 *
229 * The non-const @ref UsefulBuf is usually used to refer an empty
230 * buffer to be filled in. The length is the size of the buffer.
231 *
232 * The const @ref UsefulBufC is usually used to refer to some data
233 * that has been filled in. The length is amount of valid data pointed
234 * to.
235 *
236 * A common use mode is to pass a @ref UsefulBuf to a function, the
237 * function puts some data in it, then the function returns a @ref
238 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
239 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
240 * so the constness stays correct. There is no single "in,out"
241 * parameter (if there was, it would have to be non-const). Note that
242 * the pointer returned in the @ref UsefulBufC usually ends up being
243 * the same pointer passed in as a @ref UsefulBuf, though this is not
244 * striclty required.
245 *
246 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
247 * @c NULL.
248 *
249 * There are functions and macros for the following:
250 * - Initializing
251 * - Create initialized const @ref UsefulBufC from compiler literals
252 * - Create initialized const @ref UsefulBufC from NULL-terminated string
253 * - Make an empty @ref UsefulBuf on the stack
254 * - Checking whether a @ref UsefulBuf is null, empty or both
255 * - Copying, copying with offset, copying head or tail
256 * - Comparing and finding substrings
257 *
258 * See also @ref UsefulOutBuf. It is a richer structure that has both
259 * the size of the valid data and the size of the buffer.
260 *
261 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
262 * it can go on the stack and be a function parameter or return value.
263 *
264 * Another way to look at it is this. C has the NULL-terminated string
265 * as a means for handling text strings, but no means or convention
266 * for binary strings. Other languages do have such means, Rust, an
267 * efficient compiled language, for example.
268 *
269 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
270 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
271 * out like anything".
272 */
Michael Eckel5c531332020-03-02 01:35:30 +0100273typedef struct q_useful_buf_c {
274 const void *ptr;
275 size_t len;
276} UsefulBufC;
277
278
279/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700280 * This non-const @ref UsefulBuf is typically used for some allocated
281 * memory that is to be filled in. The @c len is the amount of memory,
282 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100283 */
284typedef struct q_useful_buf {
285 void *ptr;
286 size_t len;
287} UsefulBuf;
288
289
290/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700291 * A null @ref UsefulBufC is one that has no value in the same way a
292 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
293 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
294 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100295 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700296/*
297 * NULLUsefulBufC and few other macros have to be
298 * definied differently in C than C++ because there
299 * is no common construct for a literal structure.
300 *
301 * In C compound literals are used.
302 *
303 * In C++ list initalization is used. This only works
304 * in C++11 and later.
305 *
306 * Note that some popular C++ compilers can handle compound
307 * literals with on-by-default extensions, however
308 * this code aims for full correctness with strict
309 * compilers so they are not used.
310 */
311#ifdef __cplusplus
312#define NULLUsefulBufC {NULL, 0}
313#else
314#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
315#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100316
317/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700318 * A null @ref UsefulBuf is one that has no memory associated the same
319 * way @c NULL points to nothing. It does not matter what @c len is.
320 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700321#ifdef __cplusplus
322#define NULLUsefulBuf {NULL, 0}
323#else
324#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
325#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100326
327
328/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700329 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
330 *
331 * @param[in] UB The UsefulBuf to check.
332 *
333 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100334 */
335static inline int UsefulBuf_IsNULL(UsefulBuf UB);
336
337
338/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700339 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
340 *
341 * @param[in] UB The @ref UsefulBufC to check.
342 *
343 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100344 */
345static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
346
347
348/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700349 * @brief Check if a @ref UsefulBuf is empty or not.
350 *
351 * @param[in] UB The @ref UsefulBuf to check.
352 *
353 * @return 1 if it is empty, 0 if not.
354 *
355 * An "empty" @ref UsefulBuf is one that has a value and can be
356 * considered to be set, but that value is of zero length. It is
357 * empty when @c len is zero. It doesn't matter what the @c ptr is.
358 *
359 * Many uses will not need to clearly distinguish a @c NULL @ref
360 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
361 * @c len 0. However if a use of @ref UsefulBuf needs to make a
362 * distinction then @c ptr should not be @c NULL when the @ref
363 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100364 */
365static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
366
367
368/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700369 * @brief Check if a @ref UsefulBufC is empty or not.
370 *
371 * @param[in] UB The @ref UsefulBufC to check.
372 *
373 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100374 */
375static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
376
377
378/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700379 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
380 *
381 * @param[in] UB The @ref UsefulBuf to check.
382 *
383 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100384 */
385static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
386
387
388/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700389 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
390 *
391 * @param[in] UB The @ref UsefulBufC to check.
392 *
393 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100394 */
395static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
396
397
398/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700399 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
400 *
401 * @param[in] UB The @ref UsefulBuf to convert.
402 *
403 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100404 */
405static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
406
407
408/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700409 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
410 *
411 * @param[in] UBC The @ref UsefulBuf to convert.
412 *
413 * @return A non-const @ref UsefulBuf struct.
414 *
415 * Use of this is not necessary for the intended use mode of @ref
416 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
417 * created to describe a buffer that has not had any data put in
418 * it. Then the data is put in it. Then a @ref UsefulBufC is create
419 * to describe the part with the data in it. This goes from non-const
420 * to const, so this function is not needed.
421 *
422 * If the -Wcast-qual warning is enabled, this function can be used to
423 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100424 */
425static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
426
427
428/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700429 * Convert a literal string to a @ref UsefulBufC.
430 *
431 * @c szString must be a literal string that @c sizeof() works on.
432 * This is better for literal strings than UsefulBuf_FromSZ() because
433 * it generates less code. It will not work on non-literal strings.
434 *
435 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100436 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700437#ifdef __cplusplus
438#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
439#else
Michael Eckel5c531332020-03-02 01:35:30 +0100440#define UsefulBuf_FROM_SZ_LITERAL(szString) \
441 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700442#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100443
444
445/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700446 * Convert a literal byte array to a @ref UsefulBufC.
447 *
448 * @c pBytes must be a literal string that @c sizeof() works on. It
449 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100450 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700451#ifdef __cplusplus
452#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
453#else
Michael Eckel5c531332020-03-02 01:35:30 +0100454#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700455 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
456#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100457
458/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700459 * Make an automatic variable named @c name of type @ref UsefulBuf and
460 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100461 */
462#define UsefulBuf_MAKE_STACK_UB(name, size) \
463 uint8_t __pBuf##name[(size)];\
464 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
465
466
467/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700468 * Make a byte array in to a @ref UsefulBuf. This is usually used on
469 * stack variables or static variables. Also see @ref
470 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100471 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700472#ifdef __cplusplus
473#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
474#else
Michael Eckel5c531332020-03-02 01:35:30 +0100475#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700476 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
477#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100478
479
480/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700481 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
482 *
483 * @param[in] szString The string to convert.
484 *
485 * @return A @ref UsefulBufC struct.
486 *
487 * @c UsefulBufC.ptr points to the string so its lifetime must be
488 * maintained.
489 *
490 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100491 */
492static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
493
494
495/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700496 * @brief Copy one @ref UsefulBuf into another at an offset.
497 *
498 * @param[in] Dest Destination buffer to copy into.
499 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
500 * @param[in] Src The bytes to copy.
501 *
502 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
503 *
504 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
505 * size of @c Dest.
506 *
507 * This fails and returns @ref NULLUsefulBufC if the @c Src length
508 * plus @c uOffset is greater than the length of @c Dest.
509 *
510 * The results are undefined if @c Dest and @c Src overlap.
511 *
512 * This assumes that there is valid data in @c Dest up to @c
513 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
514 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100515 */
516UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
517
518
519/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700520 * @brief Copy one @ref UsefulBuf into another.
521 *
522 * @param[in] Dest The destination buffer to copy into.
523 * @param[out] Src The source to copy from.
524 *
525 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
526 * on failure.
527 *
528 * This fails if @c Src.len is greater than @c Dest.len.
529 *
530 * Note that like @c memcpy(), the pointers are not checked and this
531 * will crash rather than return @ref NULLUsefulBufC if they are @c
532 * NULL or invalid.
533 *
534 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100535 */
536static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
537
538
539/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700540 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
541 *
542 * @param[in] pDest The destination buffer to copy into.
543 * @param[in] value The value to set the bytes to.
544 *
545 * Note that like @c memset(), the pointer in @c pDest is not checked
546 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100547 */
548static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
549
550
551/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700552 * @brief Copy a pointer into a @ref UsefulBuf.
553 *
554 * @param[in,out] Dest The destination buffer to copy into.
555 * @param[in] ptr The source to copy from.
556 * @param[in] uLen Length of the source; amount to copy.
557 *
558 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
559 * on failure.
560 *
561 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
562 * than @c pDest->len.
563 *
564 * Note that like @c memcpy(), the pointers are not checked and this
565 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100566 */
567static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
568 const void *ptr,
569 size_t uLen);
570
571
572/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700573 * @brief Returns a truncation of a @ref UsefulBufC.
574 *
575 * @param[in] UB The buffer to get the head of.
576 * @param[in] uAmount The number of bytes in the head.
577 *
578 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100579 */
580static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
581
582
583/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700584 * @brief Returns bytes from the end of a @ref UsefulBufC.
585 *
586 * @param[in] UB The buffer to get the tail of.
587 * @param[in] uAmount The offset from the start where the tail is to begin.
588 *
589 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
590 * if @c uAmount is greater than the length of the @ref UsefulBufC.
591 *
592 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
593 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
594 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100595 */
596static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
597
598
599/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700600 * @brief Compare one @ref UsefulBufC to another.
601 *
602 * @param[in] UB1 The first buffer to compare.
603 * @param[in] UB2 The second buffer to compare.
604 *
605 * @return 0, positive or negative value.
606 *
607 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
608 * less than @c UB2 if it is shorter or the first byte that is not the
609 * same is less.
610 *
611 * Returns 0 if the inputs are the same.
612 *
613 * Returns a positive value if @c UB2 is less than @c UB1.
614 *
615 * All that is of significance is that the result is positive, negative
616 * or 0. (This doesn't return the difference between the first
617 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100618 */
619int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
620
621
622/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700623 * @brief Find first byte that is not a particular byte value.
624 *
625 * @param[in] UB The destination buffer for byte comparison.
626 * @param[in] uValue The byte value to compare to.
627 *
628 * @return Offset of first byte that isn't @c uValue or
629 * @c SIZE_MAX if all bytes are @c uValue.
630 *
631 * Note that unlike most comparison functions, 0
632 * does not indicate a successful comparison, so the
633 * test for match is:
634 *
635 * UsefulBuf_IsValue(...) == SIZE_MAX
636 *
637 * If @c UB is null or empty, there is no match
638 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100639 */
640size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
641
642
643/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700644 * @brief Find one @ref UsefulBufC in another.
645 *
646 * @param[in] BytesToSearch Buffer to search through.
647 * @param[in] BytesToFind Buffer with bytes to be found.
648 *
649 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100650 */
651size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
652
653
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700654/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700655 * @brief Convert a pointer to an offset with bounds checking.
656 *
657 * @param[in] UB A UsefulBuf.
658 * @param[in] p Pointer to convert to offset.
659 *
660 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700661*/
662static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
663
664
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700665/**
666 * @brief Convert an offset to a pointer with bounds checking.
667 *
668 * @param[in] UB A UsefulBuf.
669 * @param[in] uOffset Offset in @c pUInBuf.
670 *
671 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
672 */
673static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
674
675
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800676#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100677/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700678#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100679
680/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
681#define MakeUsefulBufOnStack(name, size) \
682 uint8_t __pBuf##name[(size)];\
683 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
684
685/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
686#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700687 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100688
689/** Deprecated function; use UsefulBuf_Unconst() instead */
690static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
691{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700692 UsefulBuf UB;
693
Laurence Lundblade3eead482023-12-16 20:53:22 -0700694 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300695 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700696
697 UB.len = UBC.len;
698
699 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100700}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800701#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100702
703
704
705
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200706#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100707/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700708 * @brief Copy a @c float to a @c uint32_t.
709 *
710 * @param[in] f Float value to copy.
711 *
712 * @return A @c uint32_t with the float bits.
713 *
714 * Convenience function to avoid type punning, compiler warnings and
715 * such. The optimizer usually reduces this to a simple assignment. This
716 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100717 */
718static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
719
720
721/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700722 * @brief Copy a @c double to a @c uint64_t.
723 *
724 * @param[in] d Double value to copy.
725 *
726 * @return A @c uint64_t with the double bits.
727 *
728 * Convenience function to avoid type punning, compiler warnings and
729 * such. The optimizer usually reduces this to a simple assignment. This
730 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100731 */
732static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
733
734
735/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700736 * @brief Copy a @c uint32_t to a @c float.
737 *
738 * @param[in] u32 Integer value to copy.
739 *
740 * @return The value as a @c float.
741 *
742 * Convenience function to avoid type punning, compiler warnings and
743 * such. The optimizer usually reduces this to a simple assignment. This
744 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100745 */
746static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
747
748
749/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700750 * @brief Copy a @c uint64_t to a @c double.
751 *
752 * @param[in] u64 Integer value to copy.
753 *
754 * @return The value as a @c double.
755 *
756 * Convenience function to avoid type punning, compiler warnings and
757 * such. The optimizer usually reduces this to a simple assignment. This
758 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100759 */
760static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200761#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100762
763
764
765
766/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700767 * UsefulOutBuf is a structure and functions (an object) for
768 * serializing data into a buffer to encode for a network protocol or
769 * write data to a file.
770 *
771 * The main idea is that all the pointer manipulation is performed by
772 * @ref UsefulOutBuf functions so the caller doesn't have to do any
773 * pointer manipulation. The pointer manipulation is centralized.
774 * This code has been reviewed and written carefully so it
775 * spares the caller of much of this work and results in safer code
776 * with less effort.
777 *
778 * The @ref UsefulOutBuf methods that add data to the output buffer
779 * always check the length and will never write off the end of the
780 * output buffer. If an attempt to add data that will not fit is made,
781 * an internal error flag will be set and further attempts to add data
782 * will not do anything.
783 *
784 * There is no way to ever write off the end of that buffer when
785 * calling the @c UsefulOutBuf_AddXxx() and
786 * @c UsefulOutBuf_InsertXxx() functions.
787 *
788 * The functions to add data do not report success of failure. The
789 * caller only needs to check for an error in the final call, either
790 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
791 * result. This makes the calling code cleaner.
792 *
793 * There is a utility function to get the error status anytime along
794 * the way for a special circumstance. There are functions to see how
795 * much room is left and see if some data will fit too, but their use
796 * is generally unnecessary.
797 *
798 * The general call flow is:
799 *
800 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
801 * buffer given to it can be from the heap, stack or
802 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
803 * macro that makes a buffer on the stack and initializes it.
804 *
805 * - Call methods like UsefulOutBuf_InsertString(),
806 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
807 * to output data. The append calls add data to the end of the
808 * valid data. The insert calls take a position argument.
809 *
810 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
811 * there were no errors and to get the serialized output bytes.
812 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700813 * @ref UsefulOutBuf can be used in a mode to calculate the size of
814 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700815 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700816 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700817 *
818 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700819 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700820 *
821 * The possible errors are:
822 *
823 * - The @ref UsefulOutBuf was not initialized or was corrupted.
824 *
825 * - An attempt was made to add data that will not fit.
826 *
827 * - An attempt was made to insert data at a position beyond the end of
828 * the buffer.
829 *
830 * - An attempt was made to insert data at a position beyond the valid
831 * data in the buffer.
832 *
833 * Some inexpensive simple sanity checks are performed before every
834 * data addition to guard against use of an uninitialized or corrupted
835 * UsefulOutBuf.
836 *
837 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
838 * encoder has almost no pointer manipulation in it, is easier to
839 * read, and easier to review.
840 *
841 * A @ref UsefulOutBuf is small and can go on the stack:
842 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
843 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100844 */
845typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700846 /* PRIVATE DATA STRUCTURE */
847 UsefulBuf UB; /* Memory that is being output to */
848 size_t data_len; /* length of the valid data, the insertion point */
849 uint16_t magic; /* Used to detect corruption and lack
850 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100851 uint8_t err;
852} UsefulOutBuf;
853
854
855/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700856 * This is a @ref UsefulBuf value that can be passed to
857 * UsefulOutBuf_Init() to have it calculate the size of the output
858 * buffer needed. Pass this for @c Storage, call all the append and
859 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
860 * returned @ref UsefulBufC has the size.
861 *
862 * As one can see, this is just a NULL pointer and very large size.
863 * The NULL pointer tells UsefulOutputBuf to not copy any data.
864 */
865#ifdef __cplusplus
866#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
867#else
868#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
869#endif
870
871
872/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700873 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700874 *
875 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
876 * @param[in] Storage Buffer to output into.
877 *
878 * This initializes the @ref UsefulOutBuf with storage, sets the
879 * current position to the beginning of the buffer and clears the
880 * error state.
881 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700882 * See @ref SizeCalculateUsefulBuf for instructions on how to
883 * initialize a @ref UsefulOutBuf to calculate the size that would be
884 * output without actually outputting.
885 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700886 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100887 */
888void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
889
890
891/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700892 * Convenience macro to make a @ref UsefulOutBuf on the stack and
893 * initialize it with a stack buffer of the given size. The variable
894 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100895 */
896#define UsefulOutBuf_MakeOnStack(name, size) \
897 uint8_t __pBuf##name[(size)];\
898 UsefulOutBuf name;\
899 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
900
901
902/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700903 * @brief Reset a @ref UsefulOutBuf for re use.
904 *
905 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
906 *
907 * This sets the amount of data in the output buffer to none and
908 * clears the error state.
909 *
910 * The output buffer is still the same one and size as from the
911 * UsefulOutBuf_Init() call.
912 *
913 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100914 */
915static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
916
917
918/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700919 * @brief Returns position of end of data in the @ref UsefulOutBuf.
920 *
921 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
922 *
923 * @return position of end of data.
924 *
925 * On a freshly initialized @ref UsefulOutBuf with no data added, this
926 * will return 0. After 10 bytes have been added, it will return 10
927 * and so on.
928 *
929 * Generally, there is no need to call this for most uses of @ref
930 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100931 */
932static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
933
934
935/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700936 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
937 *
938 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
939 *
940 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100941 */
942static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
943
944
945/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700946 * @brief Inserts bytes into the @ref UsefulOutBuf.
947 *
948 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
949 * @param[in] NewData The bytes to insert.
950 * @param[in] uPos Index in output buffer at which to insert.
951 *
952 * @c NewData is the pointer and length for the bytes to be added to
953 * the output buffer. There must be room in the output buffer for all
954 * of @c NewData or an error will occur.
955 *
956 * The insertion point must be between 0 and the current valid
957 * data. If not, an error will occur. Appending data to the output
958 * buffer is achieved by inserting at the end of the valid data. This
959 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
960 *
961 * When insertion is performed, the bytes between the insertion point
962 * and the end of data previously added to the output buffer are slid
963 * to the right to make room for the new data.
964 *
965 * Overlapping buffers are OK. @c NewData can point to data in the
966 * output buffer.
967 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700968 * NewData.len may be 0 in which case nothing will be inserted.
969 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700970 * If an error occurs, an error state is set in the @ref
971 * UsefulOutBuf. No error is returned. All subsequent attempts to add
972 * data will do nothing.
973 *
974 * The intended use is that all additions are made without checking
975 * for an error. The error will be taken into account when
976 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
977 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100978 */
979void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
980 UsefulBufC NewData,
981 size_t uPos);
982
983
984/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700985 * @brief Insert a data buffer into the @ref UsefulOutBuf.
986 *
987 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
988 * @param[in] pBytes Pointer to the bytes to insert
989 * @param[in] uLen Length of the bytes to insert
990 * @param[in] uPos Index in output buffer at which to insert
991 *
992 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
993 * the difference being a pointer and length is passed in rather than an
994 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100995 */
996static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
997 const void *pBytes,
998 size_t uLen,
999 size_t uPos);
1000
1001
1002/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001003 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1004 *
1005 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1006 * @param[in] szString NULL-terminated string to insert.
1007 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001008 */
1009static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1010 const char *szString,
1011 size_t uPos);
1012
1013
1014/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001015 * @brief Insert a byte into the @ref UsefulOutBuf.
1016 *
1017 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1018 * @param[in] byte Bytes to insert.
1019 * @param[in] uPos Index in output buffer at which to insert.
1020 *
1021 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1022 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001023 */
1024static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1025 uint8_t byte,
1026 size_t uPos);
1027
1028
1029/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001030 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1031 *
1032 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1033 * @param[in] uInteger16 Integer to insert.
1034 * @param[in] uPos Index in output buffer at which to insert.
1035 *
1036 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1037 * with the difference being a two-byte integer is to be inserted.
1038 *
1039 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001040 */
1041static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1042 uint16_t uInteger16,
1043 size_t uPos);
1044
1045
1046/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001047 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1048 *
1049 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1050 * @param[in] uInteger32 Integer to insert.
1051 * @param[in] uPos Index in output buffer at which to insert.
1052 *
1053 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1054 * with the difference being a four-byte integer is to be inserted.
1055 *
1056 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001057 */
1058static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1059 uint32_t uInteger32,
1060 size_t uPos);
1061
1062
1063/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001064 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1065 *
1066 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1067 * @param[in] uInteger64 Integer to insert.
1068 * @param[in] uPos Index in output buffer at which to insert.
1069 *
1070 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1071 * with the difference being an eight-byte integer is to be inserted.
1072 *
1073 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001074 */
1075static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1076 uint64_t uInteger64,
1077 size_t uPos);
1078
1079
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001080#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001081/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001082 * @brief Insert a @c float into the @ref UsefulOutBuf.
1083 *
1084 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1085 * @param[in] f @c float to insert.
1086 * @param[in] uPos Index in output buffer at which to insert.
1087 *
1088 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1089 * with the difference being a @c float is to be inserted.
1090 *
1091 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001092 */
1093static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1094 float f,
1095 size_t uPos);
1096
1097
1098/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001099 * @brief Insert a @c double into the @ref UsefulOutBuf.
1100 *
1101 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1102 * @param[in] d @c double to insert.
1103 * @param[in] uPos Index in output buffer at which to insert.
1104 *
1105 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1106 * with the difference being a @c double is to be inserted.
1107 *
1108 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001109 */
1110static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1111 double d,
1112 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001113#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001114
1115
1116/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001117 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1118 *
1119 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1120 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1121 *
1122 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1123 * with the insertion point at the end of the valid data.
1124 */
Michael Eckel5c531332020-03-02 01:35:30 +01001125static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1126 UsefulBufC NewData);
1127
1128
1129/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001130 * @brief Append bytes to the @ref UsefulOutBuf.
1131 *
1132 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1133 * @param[in] pBytes Pointer to bytes to append.
1134 * @param[in] uLen Length of @c pBytes to append.
1135 *
1136 * See UsefulOutBuf_InsertData() for details. This does the same with
1137 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001138 */
1139static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1140 const void *pBytes,
1141 size_t uLen);
1142
1143
1144/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001145 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1146 *
1147 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1148 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001149 */
1150static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1151 const char *szString);
1152
1153
1154/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001155 * @brief Append a byte to the @ref UsefulOutBuf
1156 *
1157 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1158 * @param[in] byte Bytes to append.
1159 *
1160 * See UsefulOutBuf_InsertByte() for details. This does the same
1161 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001162 */
1163static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1164 uint8_t byte);
1165
1166
1167/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001168 * @brief Append an integer to the @ref UsefulOutBuf
1169 *
1170 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1171 * @param[in] uInteger16 Integer to append.
1172 *
1173 * See UsefulOutBuf_InsertUint16() for details. This does the same
1174 * with the insertion point at the end of the valid data.
1175 *
1176 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001177 */
1178static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1179 uint16_t uInteger16);
1180
1181
1182/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001183 * @brief Append an integer to the @ref UsefulOutBuf
1184 *
1185 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1186 * @param[in] uInteger32 Integer to append.
1187 *
1188 * See UsefulOutBuf_InsertUint32() for details. This does the same
1189 * with the insertion point at the end of the valid data.
1190 *
1191 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001192 */
1193static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1194 uint32_t uInteger32);
1195
1196
1197/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001198 * @brief Append an integer to the @ref UsefulOutBuf
1199 *
1200 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1201 * @param[in] uInteger64 Integer to append.
1202 *
1203 * See UsefulOutBuf_InsertUint64() for details. This does the same
1204 * with the insertion point at the end of the valid data.
1205 *
1206 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001207 */
1208static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1209 uint64_t uInteger64);
1210
1211
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001212#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001213/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001214 * @brief Append a @c float to the @ref UsefulOutBuf
1215 *
1216 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1217 * @param[in] f @c float to append.
1218 *
1219 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1220 * the insertion point at the end of the valid data.
1221 *
1222 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001223 */
1224static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1225 float f);
1226
1227
1228/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001229 * @brief Append a @c double to the @ref UsefulOutBuf
1230 *
1231 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1232 * @param[in] d @c double to append.
1233 *
1234 * See UsefulOutBuf_InsertDouble() for details. This does the same
1235 * with the insertion point at the end of the valid data.
1236 *
1237 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001238 */
1239static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1240 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001241#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001242
1243
1244/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001245 * @brief Returns the current error status.
1246 *
1247 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1248 *
1249 * @return 0 if all OK, 1 on error.
1250 *
1251 * This returns the error status since a call to either
1252 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1253 * goes into the error state, it will stay until one of those
1254 * functions is called.
1255 *
1256 * Possible error conditions are:
1257 * - bytes to be inserted will not fit
1258 * - insertion point is out of buffer or past valid data
1259 * - current position is off end of buffer (probably corrupted or uninitialized)
1260 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001261 */
1262static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1263
1264
1265/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001266 * @brief Returns number of bytes unused used in the output buffer.
1267 *
1268 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1269 *
1270 * @return Number of unused bytes or zero.
1271 *
1272 * Because of the error handling strategy and checks in
1273 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1274 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001275 */
1276static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1277
1278
1279/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001280 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1281 *
1282 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1283 * @param[in] uLen Number of bytes for which to check
1284 *
1285 * @return 1 if @c uLen bytes will fit, 0 if not.
1286 *
1287 * Because of the error handling strategy and checks in
1288 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1289 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001290 */
1291static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1292
1293
1294 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001295 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1296 *
1297 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1298 *
1299 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1300 *
1301 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1302 * just calculating the length of the encoded data.
1303 */
Michael Eckel5c531332020-03-02 01:35:30 +01001304static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1305
1306
1307/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001308 * @brief Returns pointer and length of the output buffer not yet used.
1309 *
1310 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1311 *
1312 * @return pointer and length of output buffer not used.
1313 *
1314 * This is an escape that allows the caller to write directly
1315 * to the output buffer without any checks. This doesn't
1316 * change the output buffer or state. It just returns a pointer
1317 * and length of the bytes remaining.
1318 *
1319 * This is useful to avoid having the bytes to be added all
1320 * in a contiguous buffer. Its use can save memory. A good
1321 * example is in the COSE encrypt implementation where
1322 * the output of the symmetric cipher can go directly
1323 * into the output buffer, rather than having to go into
1324 * an intermediate buffer.
1325 *
1326 * See UsefulOutBuf_Advance() which is used to tell
1327 * UsefulOutBuf how much was written.
1328 *
1329 * Warning: this bypasses the buffer safety provided by
1330 * UsefulOutBuf!
1331 */
1332static inline UsefulBuf
1333UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1334
1335
1336/**
1337 * @brief Advance the amount output assuming it was written by the caller.
1338 *
1339 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1340 * @param[in] uAmount The amount to advance.
1341 *
1342 * This advances the position in the output buffer
1343 * by \c uAmount. This assumes that the
1344 * caller has written \c uAmount to the pointer obtained
1345 * with UsefulOutBuf_GetOutPlace().
1346 *
1347 * Warning: this bypasses the buffer safety provided by
1348 * UsefulOutBuf!
1349 */
1350void
1351UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1352
1353
1354/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001355 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001356 *
1357 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1358 *
1359 * @return The valid data in @ref UsefulOutBuf or
1360 * @ref NULLUsefulBufC if there was an error adding data.
1361 *
1362 * The storage for the returned data is the @c Storage parameter
1363 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1364 *
1365 * This can be called anytime and many times to get intermediate
1366 * results. It doesn't change the data or reset the current position,
1367 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001368 */
1369UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1370
1371
1372/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001373 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001374 *
1375 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1376 * @param[out] Dest The destination buffer to copy into.
1377 *
1378 * @return Pointer and length of copied data or @c NULLUsefulBufC
1379 * if it will not fit in the @c Dest buffer or the error
1380 * state was entered.
1381 *
1382 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001383 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001384 */
Michael Eckel5c531332020-03-02 01:35:30 +01001385UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1386
1387
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001388/**
1389 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1390 *
1391 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1392 * @param[in] uOffset Offset to bytes to return.
1393 *
1394 * @return NULLUsefulBufC or the bytes at the offset.
1395 *
1396 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1397 * maybe specified. It returns the bytes starting at @c uOffset to the
1398 * end of what was encoded so far. Calling this with @c uOffset 0 is
1399 * equivalent to UsefulOutBuf_OutUBuf().
1400 *
1401 * If there's nothing at @c uOffset or it is past the in the output
1402 * buffer, a \ref NULLUsefulBufC is returned.
1403 *
1404 * This is typically not needed in typical use. It is used by QCBOR
1405 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1406 * sorting CBOR maps.
1407 */
1408UsefulBufC
1409UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1410
1411
1412/**
1413 * @brief Compare bytes at offsets.
1414 *
1415 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1416 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001417 * @param[in] uLen1 Length of first bytes to compare.
1418 * @param[in] uStart2 Offset of second bytes to compare.
1419 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001420 *
1421 * @return 0 for equality, positive if uStart1 is lexographically larger,
1422 * negative if uStart2 is lexographically larger.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001423 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001424 * This looks into bytes that have been output at the offsets @c start1
1425 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001426 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1427 * length of the string given is off the end of the output data, the
1428 * string will be effectively concated to the data in the output
1429 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001430 *
1431 * This returns positive when @c uStart1 lexographically sorts ahead
1432 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001433 * compare equally.
1434 *
1435 * If lengths are unequal and the first bytes are an exact subset of
1436 * the second string, then a positve value will be returned and vice
1437 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001438 *
1439 * If either start is past the end of data in the output buffer, 0
1440 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001441 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001442 * being made. No data will ever be read off the end of the buffer so
1443 * this safe no matter what offsets are passed.
1444 *
1445 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001446 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1447 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001448 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001449int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1450 size_t uStart1, size_t uLen1,
1451 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001452
1453/**
1454 * @brief Swap two regions of output bytes.
1455 *
1456 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1457 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1458 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1459 * @param[in] uEndOffset Offset to end of region to be swappe.
1460 *
1461 * This reaches into bytes that have been output and swaps two
1462 * adjacent regions.
1463 *
1464 * If any of the offsets are outside the range of valid data, no
1465 * swapping will be performed. If the start is not the smallest and
1466 * the pivot is not in the middle no swapping will be performed.
1467 *
1468 * The byte at @c uStartOffset will participate in the swapping. The
1469 * byte at @c uEndOffset will not participate in the swapping, only
1470 * the byte before it.
1471 *
1472 * This is a relatively odd function in that it works on data in the
1473 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1474 * maps.
1475 */
1476void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1477 size_t uStartOffset,
1478 size_t uPivotOffset,
1479 size_t uEndOffset);
1480
1481
Michael Eckel5c531332020-03-02 01:35:30 +01001482
1483
1484/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001485 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1486 * for parsing data received. Initialize it with the data from the
1487 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1488 * get data chunks of various types. A position cursor is maintained
1489 * internally.
1490 *
1491 * As long as the functions here are used, there will never be any
1492 * reference off the end of the given buffer (except
1493 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1494 * called incorrectly, an attempt is made to seek off the end of the
1495 * buffer or such. This makes it easier to write safe and correct
1496 * code. For example, the QCBOR decoder implementation is safer and
1497 * easier to review through its use of @ref UsefulInputBuf.
1498 *
1499 * @ref UsefulInputBuf maintains an internal error state. The
1500 * intended use is fetching data chunks without any error checks until
1501 * the end. If there was any error, such as an attempt to fetch data
1502 * off the end, the error state is entered and no further data will be
1503 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1504 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1505 * null is not dereferenced, the error check can be put off until the
1506 * end, simplifying the calling code.
1507 *
1508 * The integer and float parsing expects network byte order (big
1509 * endian). Network byte order is what is used by TCP/IP, CBOR and
1510 * most internet protocols.
1511 *
1512 * Lots of inline functions are used to keep code size down. The
1513 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1514 * code size a lot. The only non-inline code is
1515 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1516 * @ref UsefulInputBuf doesn't add much code for all the messy
1517 * hard-to-get right issues with parsing binary protocols in C that it
1518 * solves.
1519 *
1520 * The parse context size is:
1521 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1522 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001523 */
1524typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001525 /* PRIVATE DATA STRUCTURE */
1526 UsefulBufC UB; /* Data being parsed */
1527 size_t cursor; /* Current offset in data being parse */
1528 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1529 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001530} UsefulInputBuf;
1531
1532#define UIB_MAGIC (0xB00F)
1533
1534
1535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001536 * @brief Initialize the @ref UsefulInputBuf structure before use.
1537 *
1538 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1539 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001540 */
1541static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1542
1543
1544/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001545 * @brief Returns current position in input buffer.
1546 *
1547 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1548 *
1549 * @return Integer position of the cursor.
1550 *
1551 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001552 */
1553static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1554
1555
1556/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001557 * @brief Sets the current position in input buffer.
1558 *
1559 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1560 * @param[in] uPos Position to set to.
1561 *
1562 * If the position is off the end of the input buffer, the error state
1563 * is entered.
1564 *
1565 * Seeking to a valid position in the buffer will not reset the error
1566 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001567 */
1568static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1569
1570
1571/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001572 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1573 * the unconsumed bytes.
1574 *
1575 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1576 *
1577 * @return Number of bytes unconsumed or 0 on error.
1578 *
1579 * Returns 0 if the cursor is invalid or corruption of the
1580 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001581 */
1582static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1583
1584
1585/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001586 * @brief Check if there are unconsumed bytes.
1587 *
1588 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1589 * @param[in] uLen Number of bytes to check availability for.
1590 *
1591 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001592 */
1593static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1594
1595
1596/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001597 * @brief Convert a pointer to an offset with bounds checking.
1598 *
1599 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1600 * @param[in] p Pointer to convert to offset.
1601 *
1602 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1603 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001604static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1605
1606
1607/**
1608 * @brief Convert an offset to a pointer with bounds checking.
1609 *
1610 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1611 * @param[in] uOffset Offset in @c pUInBuf.
1612 *
1613 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1614 */
1615static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001616
1617
1618/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001619 * @brief Get pointer to bytes out of the input buffer.
1620 *
1621 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1622 * @param[in] uNum Number of bytes to get.
1623 *
1624 * @return Pointer to bytes.
1625 *
1626 * This consumes @c uNum bytes from the input buffer. This returns a
1627 * pointer to the start of the @c uNum bytes.
1628 *
1629 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1630 * returned and the error state is entered.
1631 *
1632 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001633 */
1634const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1635
1636
1637/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001638 * @brief Get @ref UsefulBuf out of the input buffer.
1639 *
1640 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1641 * @param[in] uNum Number of bytes to get.
1642 *
1643 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1644 *
1645 * This consumes @c uNum bytes from the input buffer and returns the
1646 * pointer and length for them as a @ref UsefulBufC. The length
1647 * returned will always be @c uNum. The position cursor is advanced by
1648 * @c uNum bytes.
1649 *
1650 * If there are not @c uNum bytes in the input buffer, @ref
1651 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001652 */
1653static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1654
1655
1656/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001657 * @brief Get a byte out of the input buffer.
1658 *
1659 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1660 *
1661 * @return The byte.
1662 *
1663 * This consumes 1 byte from the input buffer, returns it and advances
1664 * the position cursor by 1.
1665 *
1666 * If there is not 1 byte in the buffer, 0 will be returned for the
1667 * byte and the error state is entered. To know if the 0 returned was
1668 * in error or the real value, the error state must be checked. If
1669 * possible, put this off until all values are retrieved to have
1670 * smaller and simpler code, but if not possible
1671 * UsefulInputBuf_GetError() can be called. Also, in the error state
1672 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1673 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001674 */
1675static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1676
1677
1678/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001679 * @brief Get a @c uint16_t out of the input buffer.
1680 *
1681 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1682 *
1683 * @return The @c uint16_t.
1684 *
1685 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1686 * a @c uint16_t and two bytes are consumed.
1687 *
1688 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001689 */
1690static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1691
1692
1693/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001694 * @brief Get a @c uint32_t out of the input buffer.
1695 *
1696 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1697 *
1698 * @return The @c uint32_t.
1699 *
1700 * See UsefulInputBuf_GetByte(). This works the same, except it
1701 * returns a @c uint32_t and four bytes are consumed.
1702 *
1703 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001704 */
1705static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1706
1707
1708/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001709 * @brief Get a @c uint64_t out of the input buffer.
1710 *
1711 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1712 *
1713 * @return The uint64_t.
1714 *
1715 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1716 * a @c uint64_t and eight bytes are consumed.
1717 *
1718 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001719 */
1720static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1721
1722
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001723#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001724/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001725 * @brief Get a float out of the input buffer.
1726 *
1727 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1728 *
1729 * @return The float.
1730 *
1731 * See UsefulInputBuf_GetByte(). This works the same, except it
1732 * returns a float and four bytes are consumed.
1733 *
1734 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001735 */
1736static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1737
1738
1739/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001740 * @brief Get a double out of the input buffer.
1741 *
1742 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1743 *
1744 * @return The double.
1745 *
1746 * See UsefulInputBuf_GetByte(). This works the same, except it
1747 * returns a double and eight bytes are consumed.
1748 *
1749 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001750 */
1751static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001752#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001753
1754
1755/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001756 * @brief Get the error status.
1757 *
1758 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1759 *
1760 * @return 0 if not in the error state, 1 if in the error state.
1761 *
1762 * This returns whether the @ref UsefulInputBuf is in the
1763 * error state or not.
1764 *
1765 * The error state is entered for one of these reasons:
1766 * - Attempt to fetch data past the end of the buffer
1767 * - Attempt to seek to a position past the end of the buffer
1768 * - Attempt to get data from an uninitialized or corrupt instance
1769 * of @ref UsefulInputBuf
1770 *
1771 * Once in the error state, it can only be cleared by calling
1772 * UsefulInputBuf_Init().
1773 *
1774 * For many use cases, it is possible to only call this once after all
1775 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1776 * possible if no reference to the data returned are needed before the
1777 * error state is checked.
1778 *
1779 * In some cases UsefulInputBuf_GetUsefulBuf() or
1780 * UsefulInputBuf_GetBytes() can stand in for this because they return
1781 * @c NULL if the error state has been entered. (The others can't stand
1782 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001783 */
1784static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1785
1786
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001787/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001788 * @brief Gets the input buffer length.
1789 *
1790 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1791 *
1792 * @return The length of the input buffer.
1793 *
1794 * This returns the length of the input buffer set by
1795 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001796 */
1797static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1798
1799
1800/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001801 * @brief Alters the input buffer length (use with caution).
1802 *
1803 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1804 * @param[in] uNewLen The new length of the input buffer.
1805 *
1806 * This alters the internal remembered length of the input buffer set
1807 * when UsefulInputBuf_Init() was called.
1808 *
1809 * The new length given here should always be equal to or less than
1810 * the length given when UsefulInputBuf_Init() was called. Making it
1811 * larger allows @ref UsefulInputBuf to run off the input buffer.
1812 *
1813 * The typical use is to set a length shorter than that when
1814 * initialized to constrain parsing. If
1815 * UsefulInputBuf_GetBufferLength() was called before this, then the
1816 * original length can be restored with another call to this.
1817 *
1818 * This should be used with caution. It is the only
1819 * @ref UsefulInputBuf method that can violate the safety of input
1820 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001821 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001822static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001823
1824
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001825
1826
Michael Eckel5c531332020-03-02 01:35:30 +01001827/*----------------------------------------------------------
1828 Inline implementations.
1829 */
1830static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1831{
1832 return !UB.ptr;
1833}
1834
1835
1836static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1837{
1838 return !UB.ptr;
1839}
1840
1841
1842static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1843{
1844 return !UB.len;
1845}
1846
1847
1848static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1849{
1850 return !UB.len;
1851}
1852
1853
1854static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1855{
1856 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1857}
1858
1859
1860static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1861{
1862 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1863}
1864
1865
1866static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1867{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001868 UsefulBufC UBC;
1869 UBC.ptr = UB.ptr;
1870 UBC.len = UB.len;
1871
1872 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001873}
1874
Michael Eckel5c531332020-03-02 01:35:30 +01001875static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1876{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001877 UsefulBuf UB;
1878
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001879 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001880 * the one place in UsefulBuf where it needs to be quieted.
1881 */
1882 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001883
1884 UB.len = UBC.len;
1885
1886 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001887}
1888
1889
1890static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1891{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001892 UsefulBufC UBC;
1893 UBC.ptr = szString;
1894 UBC.len = strlen(szString);
1895 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001896}
1897
1898
1899static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1900{
1901 return UsefulBuf_CopyOffset(Dest, 0, Src);
1902}
1903
1904
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001905static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001906{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001907 memset(Dest.ptr, value, Dest.len);
1908
1909 UsefulBufC UBC;
1910 UBC.ptr = Dest.ptr;
1911 UBC.len = Dest.len;
1912
1913 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001914}
1915
1916
1917static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1918{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001919 UsefulBufC UBC;
1920 UBC.ptr = ptr;
1921 UBC.len = len;
1922 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001923}
1924
1925
1926static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1927{
1928 if(uAmount > UB.len) {
1929 return NULLUsefulBufC;
1930 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001931 UsefulBufC UBC;
1932
1933 UBC.ptr = UB.ptr;
1934 UBC.len = uAmount;
1935
1936 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001937}
1938
1939
1940static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1941{
1942 UsefulBufC ReturnValue;
1943
1944 if(uAmount > UB.len) {
1945 ReturnValue = NULLUsefulBufC;
1946 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001947 ReturnValue.ptr = NULL;
1948 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001949 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001950 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1951 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001952 }
1953
1954 return ReturnValue;
1955}
1956
1957
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001958static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1959{
1960 if(UB.ptr == NULL) {
1961 return SIZE_MAX;
1962 }
1963
1964 if(p < UB.ptr) {
1965 /* given pointer is before start of buffer */
1966 return SIZE_MAX;
1967 }
1968
Laurence Lundblade3eead482023-12-16 20:53:22 -07001969 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001970 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001971
1972 if(uOffset >= UB.len) {
1973 /* given pointer is off the end of the buffer */
1974 return SIZE_MAX;
1975 }
1976
1977 return uOffset;
1978}
1979
Michael Eckel5c531332020-03-02 01:35:30 +01001980
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001981static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
1982{
1983 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
1984 return NULL;
1985 }
1986
1987 return (const uint8_t *)UB.ptr + uOffset;
1988}
1989
1990
1991
1992
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001993#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001994static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1995{
1996 uint32_t u32;
1997 memcpy(&u32, &f, sizeof(uint32_t));
1998 return u32;
1999}
2000
2001static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2002{
2003 uint64_t u64;
2004 memcpy(&u64, &d, sizeof(uint64_t));
2005 return u64;
2006}
2007
2008static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2009{
2010 double d;
2011 memcpy(&d, &u64, sizeof(uint64_t));
2012 return d;
2013}
2014
2015static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2016{
2017 float f;
2018 memcpy(&f, &u32, sizeof(uint32_t));
2019 return f;
2020}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002021#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002022
2023
2024
2025
2026static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2027{
2028 pMe->data_len = 0;
2029 pMe->err = 0;
2030}
2031
2032
2033static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2034{
2035 return pMe->data_len;
2036}
2037
2038
2039static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2040{
2041 return 0 == pMe->data_len;
2042}
2043
2044
2045static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2046 const void *pBytes,
2047 size_t uLen,
2048 size_t uPos)
2049{
2050 UsefulBufC Data = {pBytes, uLen};
2051 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2052}
2053
2054
2055static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2056 const char *szString,
2057 size_t uPos)
2058{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002059 UsefulBufC UBC;
2060 UBC.ptr = szString;
2061 UBC.len = strlen(szString);
2062
2063 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002064}
2065
2066
2067static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2068 uint8_t byte,
2069 size_t uPos)
2070{
2071 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2072}
2073
2074
2075static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2076 uint16_t uInteger16,
2077 size_t uPos)
2078{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002079 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002080
2081 const void *pBytes;
2082
2083#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2084 pBytes = &uInteger16;
2085
2086#elif defined(USEFULBUF_CONFIG_HTON)
2087 uint16_t uTmp = htons(uInteger16);
2088 pBytes = &uTmp;
2089
2090#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2091 uint16_t uTmp = __builtin_bswap16(uInteger16);
2092 pBytes = &uTmp;
2093
2094#else
2095 uint8_t aTmp[2];
2096
2097 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2098 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2099
2100 pBytes = aTmp;
2101#endif
2102
2103 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2104}
2105
2106
2107static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2108 uint32_t uInteger32,
2109 size_t uPos)
2110{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002111 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002112
2113 const void *pBytes;
2114
2115#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2116 pBytes = &uInteger32;
2117
2118#elif defined(USEFULBUF_CONFIG_HTON)
2119 uint32_t uTmp = htonl(uInteger32);
2120 pBytes = &uTmp;
2121
2122#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2123 uint32_t uTmp = __builtin_bswap32(uInteger32);
2124
2125 pBytes = &uTmp;
2126
2127#else
2128 uint8_t aTmp[4];
2129
2130 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2131 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2132 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2133 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2134
2135 pBytes = aTmp;
2136#endif
2137
2138 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2139}
2140
2141static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002142 uint64_t uInteger64,
2143 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002144{
2145 const void *pBytes;
2146
2147#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002148 /* We have been told explicitly we are running on a big-endian
2149 * machine. Network byte order is big endian, so just copy. There
2150 * is no issue with alignment here because uInteger64 is always
2151 * aligned (and it doesn't matter if pBytes is aligned).
2152 */
Michael Eckel5c531332020-03-02 01:35:30 +01002153 pBytes = &uInteger64;
2154
2155#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002156 /* Use system function to handle big- and little-endian. This works
2157 * on both big- and little-endian machines, but hton() is not
2158 * always available or in a standard place so it is not used by
2159 * default. With some compilers and CPUs the code for this is very
2160 * compact through use of a special swap instruction and on
2161 * big-endian machines hton() will reduce to nothing.
2162 */
Michael Eckel5c531332020-03-02 01:35:30 +01002163 uint64_t uTmp = htonll(uInteger64);
2164
2165 pBytes = &uTmp;
2166
2167#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002168 /* Use built-in function for byte swapping. This usually compiles
2169 * to an efficient special byte swap instruction. Unlike hton() it
2170 * does not do this conditionally on the CPU endianness, so this
2171 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2172 */
Michael Eckel5c531332020-03-02 01:35:30 +01002173 uint64_t uTmp = __builtin_bswap64(uInteger64);
2174
2175 pBytes = &uTmp;
2176
2177#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002178 /* Default which works on every CPU with no dependency on anything
2179 * from the CPU, compiler, libraries or OS. This always works, but
2180 * it is usually a little larger and slower than hton().
2181 */
Michael Eckel5c531332020-03-02 01:35:30 +01002182 uint8_t aTmp[8];
2183
2184 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2185 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2186 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2187 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2188 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2189 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2190 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2191 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2192
2193 pBytes = aTmp;
2194#endif
2195
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002196 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002197 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2198}
2199
2200
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002201#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002202static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2203 float f,
2204 size_t uPos)
2205{
2206 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2207}
2208
2209
2210static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2211 double d,
2212 size_t uPos)
2213{
2214 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2215}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002216#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002217
2218
2219static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2220 UsefulBufC NewData)
2221{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002222 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002223 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2224}
2225
2226
2227static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2228 const void *pBytes,
2229 size_t uLen)
2230{
2231 UsefulBufC Data = {pBytes, uLen};
2232 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2233}
2234
2235
2236static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2237 const char *szString)
2238{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002239 UsefulBufC UBC;
2240 UBC.ptr = szString;
2241 UBC.len = strlen(szString);
2242
2243 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002244}
2245
2246
2247static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2248 uint8_t byte)
2249{
2250 UsefulOutBuf_AppendData(pMe, &byte, 1);
2251}
2252
2253
2254static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2255 uint16_t uInteger16)
2256{
2257 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2258}
2259
2260static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2261 uint32_t uInteger32)
2262{
2263 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2264}
2265
2266
2267static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2268 uint64_t uInteger64)
2269{
2270 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2271}
2272
2273
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002274#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002275static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2276 float f)
2277{
2278 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2279}
2280
2281
2282static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2283 double d)
2284{
2285 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2286}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002287#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002288
2289
2290static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2291{
2292 return pMe->err;
2293}
2294
2295
2296static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2297{
2298 return pMe->UB.len - pMe->data_len;
2299}
2300
2301
2302static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2303{
2304 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2305}
2306
2307
2308static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2309{
2310 return pMe->UB.ptr == NULL;
2311}
2312
2313
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002314static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2315{
2316 UsefulBuf R;
2317
2318 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002319 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002320 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2321 } else {
2322 R.ptr = NULL;
2323 }
2324
2325 return R;
2326}
2327
2328
2329
Michael Eckel5c531332020-03-02 01:35:30 +01002330
2331static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2332{
2333 pMe->cursor = 0;
2334 pMe->err = 0;
2335 pMe->magic = UIB_MAGIC;
2336 pMe->UB = UB;
2337}
2338
2339static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2340{
2341 return pMe->cursor;
2342}
2343
2344
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002345static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002346{
2347 return pMe->UB.len;
2348}
2349
2350
Michael Eckel5c531332020-03-02 01:35:30 +01002351static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2352{
2353 if(uPos > pMe->UB.len) {
2354 pMe->err = 1;
2355 } else {
2356 pMe->cursor = uPos;
2357 }
2358}
2359
2360
2361static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2362{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002363 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002364
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002365 /* Magic number is messed up. Either the structure got overwritten
2366 * or was never initialized.
2367 */
Michael Eckel5c531332020-03-02 01:35:30 +01002368 if(pMe->magic != UIB_MAGIC) {
2369 return 0;
2370 }
2371
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002372 /* The cursor is off the end of the input buffer given.
2373 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002374 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002375 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002376 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002377 */
Michael Eckel5c531332020-03-02 01:35:30 +01002378 if(pMe->cursor > pMe->UB.len) {
2379 return 0;
2380 }
2381
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002382 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002383 return pMe->UB.len - pMe->cursor;
2384}
2385
2386
2387static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2388{
2389 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2390}
2391
2392
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002393static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2394{
2395 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2396}
2397
2398
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002399static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2400 {
2401 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2402 }
2403
2404
Michael Eckel5c531332020-03-02 01:35:30 +01002405static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2406{
2407 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2408 if(!pResult) {
2409 return NULLUsefulBufC;
2410 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002411 UsefulBufC UBC;
2412 UBC.ptr = pResult;
2413 UBC.len = uNum;
2414 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002415 }
2416}
2417
2418
2419static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2420{
2421 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2422
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002423 /* The ternary operator is subject to integer promotion, because
2424 * the operands are smaller than int, so cast back to uint8_t is
2425 * needed to be completely explicit about types (for static
2426 * analyzers).
2427 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002428 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002429}
2430
2431static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2432{
2433 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2434
2435 if(!pResult) {
2436 return 0;
2437 }
2438
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002439 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002440#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2441 uint16_t uTmp;
2442 memcpy(&uTmp, pResult, sizeof(uint16_t));
2443
2444#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2445 return uTmp;
2446
2447#elif defined(USEFULBUF_CONFIG_HTON)
2448 return ntohs(uTmp);
2449
2450#else
2451 return __builtin_bswap16(uTmp);
2452
2453#endif
2454
2455#else
2456
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002457 /* The operations here are subject to integer promotion because the
2458 * operands are smaller than int. They will be promoted to unsigned
2459 * int for the shift and addition. The cast back to uint16_t is is
2460 * needed to be completely explicit about types (for static
2461 * analyzers).
2462 */
Michael Eckel5c531332020-03-02 01:35:30 +01002463 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2464
2465#endif
2466}
2467
2468
2469static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2470{
2471 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2472
2473 if(!pResult) {
2474 return 0;
2475 }
2476
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002477 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002478#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2479 uint32_t uTmp;
2480 memcpy(&uTmp, pResult, sizeof(uint32_t));
2481
2482#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2483 return uTmp;
2484
2485#elif defined(USEFULBUF_CONFIG_HTON)
2486 return ntohl(uTmp);
2487
2488#else
2489 return __builtin_bswap32(uTmp);
2490
2491#endif
2492
2493#else
2494 return ((uint32_t)pResult[0]<<24) +
2495 ((uint32_t)pResult[1]<<16) +
2496 ((uint32_t)pResult[2]<<8) +
2497 (uint32_t)pResult[3];
2498#endif
2499}
2500
2501
2502static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2503{
2504 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2505
2506 if(!pResult) {
2507 return 0;
2508 }
2509
2510#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002511 /* pResult will probably not be aligned. This memcpy() moves the
2512 * bytes into a temp variable safely for CPUs that can or can't do
2513 * unaligned memory access. Many compilers will optimize the
2514 * memcpy() into a simple move instruction.
2515 */
Michael Eckel5c531332020-03-02 01:35:30 +01002516 uint64_t uTmp;
2517 memcpy(&uTmp, pResult, sizeof(uint64_t));
2518
2519#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002520 /* We have been told expliclity this is a big-endian CPU. Since
2521 * network byte order is big-endian, there is nothing to do.
2522 */
Michael Eckel5c531332020-03-02 01:35:30 +01002523
2524 return uTmp;
2525
2526#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002527 /* We have been told to use ntoh(), the system function to handle
2528 * big- and little-endian. This works on both big- and
2529 * little-endian machines, but ntoh() is not always available or in
2530 * a standard place so it is not used by default. On some CPUs the
2531 * code for this is very compact through use of a special swap
2532 * instruction.
2533 */
Michael Eckel5c531332020-03-02 01:35:30 +01002534
2535 return ntohll(uTmp);
2536
2537#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002538 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2539 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2540 * __builtin_bswap64() and friends are not conditional on CPU
2541 * endianness so this must only be used on little-endian machines.
2542 */
Michael Eckel5c531332020-03-02 01:35:30 +01002543
2544 return __builtin_bswap64(uTmp);
2545
2546
2547#endif
2548
2549#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002550 /* This is the default code that works on every CPU and every
2551 * endianness with no dependency on ntoh(). This works on CPUs
2552 * that either allow or do not allow unaligned access. It will
2553 * always work, but usually is a little less efficient than ntoh().
2554 */
Michael Eckel5c531332020-03-02 01:35:30 +01002555
2556 return ((uint64_t)pResult[0]<<56) +
2557 ((uint64_t)pResult[1]<<48) +
2558 ((uint64_t)pResult[2]<<40) +
2559 ((uint64_t)pResult[3]<<32) +
2560 ((uint64_t)pResult[4]<<24) +
2561 ((uint64_t)pResult[5]<<16) +
2562 ((uint64_t)pResult[6]<<8) +
2563 (uint64_t)pResult[7];
2564#endif
2565}
2566
2567
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002568#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002569static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2570{
2571 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2572
2573 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2574}
2575
2576
2577static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2578{
2579 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2580
2581 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2582}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002583#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002584
2585
2586static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2587{
2588 return pMe->err;
2589}
2590
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002591
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002592static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002593{
2594 pMe->UB.len = uNewLen;
2595}
2596
2597
Michael Eckel5c531332020-03-02 01:35:30 +01002598#ifdef __cplusplus
2599}
2600#endif
2601
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002602#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002603
2604