blob: 38bdb8dfbb0d777dd904181531c56839a119315b [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladea29f45a2024-05-14 15:55:19 -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 Lundbladee2226742024-08-16 10:50:23 -070046 08/14/2024 llundblade Add UsefulOutBuf_RetrieveOutputStorage().
47 08/13/2024 llundblade Add UsefulInputBuf_RetrieveUndecodedInput().
48 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070049 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070050 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060051 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070052 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070053 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070054 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080055 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070056 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010057 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
58 5/21/2019 llundblade #define configs for efficient endianness handling.
59 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
60 3/23/2019 llundblade Big documentation & style update. No interface
61 change.
62 3/6/2019 llundblade Add UsefulBuf_IsValue()
63 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
64 12/13/2018 llundblade Documentation improvements
65 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
66 UsefulBufC.
67 02/02/18 llundbla Full support for integers in and out; fix pointer
68 alignment bug. Incompatible change: integers
69 in/out are now in network byte order.
70 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
71 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
72 comparison for < or > for unequal length buffers.
73 Added UsefulBuf_Set() function.
74 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
75 11/13/16 llundbla Initial Version.
76
77 =============================================================================*/
78
79#ifndef _UsefulBuf_h
80#define _UsefulBuf_h
81
82
83/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070084 * Endianness Configuration
85 *
86 * This code is written so it will work correctly on big- and
87 * little-endian CPUs without configuration or any auto-detection of
88 * endianness. All code here will run correctly regardless of the
89 * endianness of the CPU it is running on.
90 *
91 * There are four C preprocessor macros that can be set with #define
92 * to explicitly configure endianness handling. Setting them can
93 * reduce code size a little and improve efficiency a little.
94 *
95 * Note that most of QCBOR is unaffected by this configuration. Its
96 * endianness handling is integrated with the code that handles
97 * alignment and preferred serialization. This configuration does
98 * affect QCBOR's (planned) implementation of integer arrays (tagged
99 * arrays) and use of the functions here to serialize or deserialize
100 * integers and floating-point values.
101 *
102 * Following is the recipe for configuring the endianness-related
103 * #defines.
104 *
105 * The first option is to not define anything. This will work fine
106 * with all CPUs, OS's and compilers. The code for encoding integers
107 * may be a little larger and slower.
108 *
109 * If your CPU is big-endian then define
110 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
111 * for big-endian CPUs. It will be small and efficient because there
112 * will be no byte swapping.
113 *
114 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
115 * OS's and compilers, but not all. On big-endian CPUs this should
116 * give the most efficient code, the same as
117 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
118 * call the system-defined byte swapping method which is presumably
119 * implemented efficiently. In some cases, this will be a dedicated
120 * byte swap instruction like Intel's bswap.
121 *
122 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
123 * little-endian, it is also good to define
124 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
125 *
126 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
127 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
128 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
129 * system-defined byte swap method. However, note
130 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
131 * this is fixed now. Often hton() and ntoh() will call the built-in
132 * __builtin_bswapXX()() function, so this size issue could affect
133 * USEFULBUF_CONFIG_HTON.
134 *
135 * Last, run the tests. They must all pass.
136 *
137 * These #define config options affect the inline implementation of
138 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
139 * also affect the 16-, 32-bit, float and double versions of these
140 * functions. Since they are inline, the size effect is not in the
141 * UsefulBuf object code, but in the calling code.
142 *
143 * Summary:
144 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
145 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
146 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
147 * handle big and little-endian with system option.
148 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
149 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200150 *
151 * It is possible to run this code in environments where using floating point is
152 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
153 * that is related to handling floating point types, along with related
154 * interfaces. This makes it possible to compile the code with the compile
155 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100156 */
157
158#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
159#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
160#endif
161
162
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700163#include <stdint.h> /* for uint8_t, uint16_t.... */
164#include <string.h> /* for strlen, memcpy, memmove, memset */
165#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100166
167
168#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700169#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100170#endif
171
172#ifdef __cplusplus
173extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700174#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700175} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700176#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100177#endif
178
179/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700180 * @file UsefulBuf.h
181 *
182 * The goal of this code is to make buffer and pointer manipulation
183 * easier and safer when working with binary data.
184 *
185 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
186 * structures are used to represent buffers rather than ad hoc
187 * pointers and lengths.
188 *
189 * With these it is possible to write code that does little or no
190 * direct pointer manipulation for copying and formatting data. For
191 * example, the QCBOR encoder was written using these and has less
192 * pointer manipulation.
193 *
194 * While it is true that object code using these functions will be a
195 * little larger and slower than a white-knuckle clever use of
196 * pointers might be, but not by that much or enough to have an effect
197 * for most use cases. For security-oriented code this is highly
198 * worthwhile. Clarity, simplicity, reviewability and are more
199 * important.
200 *
201 * There are some extra sanity and double checks in this code to help
202 * catch coding errors and simple memory corruption. They are helpful,
203 * but not a substitute for proper code review, input validation and
204 * such.
205 *
206 * This code consists of a lot of inline functions and a few that are
207 * not. It should not generate very much object code, especially with
208 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100209 */
210
211
212/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700213 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
214 * hold a pointer and length for binary data. In C99 this data
215 * structure can be passed on the stack making a lot of code cleaner
216 * than carrying around a pointer and length as two parameters.
217 *
218 * This is also conducive to secure coding practice as the length is
219 * always carried with the pointer and the convention for handling a
220 * pointer and a length is clear.
221 *
222 * While it might be possible to write buffer and pointer code more
223 * efficiently in some use cases, the thought is that unless there is
224 * an extreme need for performance (e.g., you are building a
225 * gigabit-per-second IP router), it is probably better to have
226 * cleaner code you can be most certain about the security of.
227 *
228 * The non-const @ref UsefulBuf is usually used to refer an empty
229 * buffer to be filled in. The length is the size of the buffer.
230 *
231 * The const @ref UsefulBufC is usually used to refer to some data
232 * that has been filled in. The length is amount of valid data pointed
233 * to.
234 *
235 * A common use mode is to pass a @ref UsefulBuf to a function, the
236 * function puts some data in it, then the function returns a @ref
237 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
238 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
239 * so the constness stays correct. There is no single "in,out"
240 * parameter (if there was, it would have to be non-const). Note that
241 * the pointer returned in the @ref UsefulBufC usually ends up being
242 * the same pointer passed in as a @ref UsefulBuf, though this is not
243 * striclty required.
244 *
245 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
246 * @c NULL.
247 *
248 * There are functions and macros for the following:
249 * - Initializing
250 * - Create initialized const @ref UsefulBufC from compiler literals
251 * - Create initialized const @ref UsefulBufC from NULL-terminated string
252 * - Make an empty @ref UsefulBuf on the stack
253 * - Checking whether a @ref UsefulBuf is null, empty or both
254 * - Copying, copying with offset, copying head or tail
255 * - Comparing and finding substrings
256 *
257 * See also @ref UsefulOutBuf. It is a richer structure that has both
258 * the size of the valid data and the size of the buffer.
259 *
260 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
261 * it can go on the stack and be a function parameter or return value.
262 *
263 * Another way to look at it is this. C has the NULL-terminated string
264 * as a means for handling text strings, but no means or convention
265 * for binary strings. Other languages do have such means, Rust, an
266 * efficient compiled language, for example.
267 *
268 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
269 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
270 * out like anything".
271 */
Michael Eckel5c531332020-03-02 01:35:30 +0100272typedef struct q_useful_buf_c {
273 const void *ptr;
274 size_t len;
275} UsefulBufC;
276
277
278/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700279 * This non-const @ref UsefulBuf is typically used for some allocated
280 * memory that is to be filled in. The @c len is the amount of memory,
281 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100282 */
283typedef struct q_useful_buf {
284 void *ptr;
285 size_t len;
286} UsefulBuf;
287
288
289/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700290 * A null @ref UsefulBufC is one that has no value in the same way a
291 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
292 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
293 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100294 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700295/*
296 * NULLUsefulBufC and few other macros have to be
297 * definied differently in C than C++ because there
298 * is no common construct for a literal structure.
299 *
300 * In C compound literals are used.
301 *
302 * In C++ list initalization is used. This only works
303 * in C++11 and later.
304 *
305 * Note that some popular C++ compilers can handle compound
306 * literals with on-by-default extensions, however
307 * this code aims for full correctness with strict
308 * compilers so they are not used.
309 */
310#ifdef __cplusplus
311#define NULLUsefulBufC {NULL, 0}
312#else
313#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
314#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100315
316/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700317 * A null @ref UsefulBuf is one that has no memory associated the same
318 * way @c NULL points to nothing. It does not matter what @c len is.
319 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700320#ifdef __cplusplus
321#define NULLUsefulBuf {NULL, 0}
322#else
323#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
324#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100325
326
327/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700328 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
329 *
330 * @param[in] UB The UsefulBuf to check.
331 *
332 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100333 */
334static inline int UsefulBuf_IsNULL(UsefulBuf UB);
335
336
337/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700338 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
339 *
340 * @param[in] UB The @ref UsefulBufC to check.
341 *
342 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100343 */
344static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
345
346
347/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700348 * @brief Check if a @ref UsefulBuf is empty or not.
349 *
350 * @param[in] UB The @ref UsefulBuf to check.
351 *
352 * @return 1 if it is empty, 0 if not.
353 *
354 * An "empty" @ref UsefulBuf is one that has a value and can be
355 * considered to be set, but that value is of zero length. It is
356 * empty when @c len is zero. It doesn't matter what the @c ptr is.
357 *
358 * Many uses will not need to clearly distinguish a @c NULL @ref
359 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
360 * @c len 0. However if a use of @ref UsefulBuf needs to make a
361 * distinction then @c ptr should not be @c NULL when the @ref
362 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100363 */
364static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
365
366
367/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700368 * @brief Check if a @ref UsefulBufC is empty or not.
369 *
370 * @param[in] UB The @ref UsefulBufC to check.
371 *
372 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100373 */
374static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
375
376
377/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700378 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
379 *
380 * @param[in] UB The @ref UsefulBuf to check.
381 *
382 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100383 */
384static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
385
386
387/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700388 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
389 *
390 * @param[in] UB The @ref UsefulBufC to check.
391 *
392 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100393 */
394static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
395
396
397/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700398 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
399 *
400 * @param[in] UB The @ref UsefulBuf to convert.
401 *
402 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100403 */
404static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
405
406
407/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700408 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
409 *
410 * @param[in] UBC The @ref UsefulBuf to convert.
411 *
412 * @return A non-const @ref UsefulBuf struct.
413 *
414 * Use of this is not necessary for the intended use mode of @ref
415 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
416 * created to describe a buffer that has not had any data put in
417 * it. Then the data is put in it. Then a @ref UsefulBufC is create
418 * to describe the part with the data in it. This goes from non-const
419 * to const, so this function is not needed.
420 *
421 * If the -Wcast-qual warning is enabled, this function can be used to
422 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100423 */
424static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
425
426
427/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700428 * Convert a literal string to a @ref UsefulBufC.
429 *
430 * @c szString must be a literal string that @c sizeof() works on.
431 * This is better for literal strings than UsefulBuf_FromSZ() because
432 * it generates less code. It will not work on non-literal strings.
433 *
434 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100435 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700436#ifdef __cplusplus
437#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
438#else
Michael Eckel5c531332020-03-02 01:35:30 +0100439#define UsefulBuf_FROM_SZ_LITERAL(szString) \
440 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700441#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100442
443
444/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700445 * Convert a literal byte array to a @ref UsefulBufC.
446 *
447 * @c pBytes must be a literal string that @c sizeof() works on. It
448 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100449 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700450#ifdef __cplusplus
451#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
452#else
Michael Eckel5c531332020-03-02 01:35:30 +0100453#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700454 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
455#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100456
457/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700458 * Make an automatic variable named @c name of type @ref UsefulBuf and
459 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100460 */
461#define UsefulBuf_MAKE_STACK_UB(name, size) \
462 uint8_t __pBuf##name[(size)];\
463 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
464
465
466/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700467 * Make a byte array in to a @ref UsefulBuf. This is usually used on
468 * stack variables or static variables. Also see @ref
469 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100470 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700471#ifdef __cplusplus
472#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
473#else
Michael Eckel5c531332020-03-02 01:35:30 +0100474#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700475 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
476#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100477
478
479/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700480 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
481 *
482 * @param[in] szString The string to convert.
483 *
484 * @return A @ref UsefulBufC struct.
485 *
486 * @c UsefulBufC.ptr points to the string so its lifetime must be
487 * maintained.
488 *
489 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100490 */
491static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
492
493
494/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700495 * @brief Copy one @ref UsefulBuf into another at an offset.
496 *
497 * @param[in] Dest Destination buffer to copy into.
498 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
499 * @param[in] Src The bytes to copy.
500 *
501 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
502 *
503 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
504 * size of @c Dest.
505 *
506 * This fails and returns @ref NULLUsefulBufC if the @c Src length
507 * plus @c uOffset is greater than the length of @c Dest.
508 *
509 * The results are undefined if @c Dest and @c Src overlap.
510 *
511 * This assumes that there is valid data in @c Dest up to @c
512 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
513 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100514 */
515UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
516
517
518/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700519 * @brief Copy one @ref UsefulBuf into another.
520 *
521 * @param[in] Dest The destination buffer to copy into.
522 * @param[out] Src The source to copy from.
523 *
524 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
525 * on failure.
526 *
527 * This fails if @c Src.len is greater than @c Dest.len.
528 *
529 * Note that like @c memcpy(), the pointers are not checked and this
530 * will crash rather than return @ref NULLUsefulBufC if they are @c
531 * NULL or invalid.
532 *
533 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100534 */
535static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
536
537
538/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700539 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
540 *
541 * @param[in] pDest The destination buffer to copy into.
542 * @param[in] value The value to set the bytes to.
543 *
544 * Note that like @c memset(), the pointer in @c pDest is not checked
545 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100546 */
547static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
548
549
550/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700551 * @brief Copy a pointer into a @ref UsefulBuf.
552 *
553 * @param[in,out] Dest The destination buffer to copy into.
554 * @param[in] ptr The source to copy from.
555 * @param[in] uLen Length of the source; amount to copy.
556 *
557 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
558 * on failure.
559 *
560 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
561 * than @c pDest->len.
562 *
563 * Note that like @c memcpy(), the pointers are not checked and this
564 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100565 */
566static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
567 const void *ptr,
568 size_t uLen);
569
570
571/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700572 * @brief Returns a truncation of a @ref UsefulBufC.
573 *
574 * @param[in] UB The buffer to get the head of.
575 * @param[in] uAmount The number of bytes in the head.
576 *
577 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100578 */
579static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
580
581
582/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700583 * @brief Returns bytes from the end of a @ref UsefulBufC.
584 *
585 * @param[in] UB The buffer to get the tail of.
586 * @param[in] uAmount The offset from the start where the tail is to begin.
587 *
588 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
589 * if @c uAmount is greater than the length of the @ref UsefulBufC.
590 *
591 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
592 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
593 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100594 */
595static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
596
597
598/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700599 * @brief Compare one @ref UsefulBufC to another.
600 *
601 * @param[in] UB1 The first buffer to compare.
602 * @param[in] UB2 The second buffer to compare.
603 *
604 * @return 0, positive or negative value.
605 *
606 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
607 * less than @c UB2 if it is shorter or the first byte that is not the
608 * same is less.
609 *
610 * Returns 0 if the inputs are the same.
611 *
612 * Returns a positive value if @c UB2 is less than @c UB1.
613 *
614 * All that is of significance is that the result is positive, negative
615 * or 0. (This doesn't return the difference between the first
616 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100617 */
618int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
619
620
621/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700622 * @brief Find first byte that is not a particular byte value.
623 *
624 * @param[in] UB The destination buffer for byte comparison.
625 * @param[in] uValue The byte value to compare to.
626 *
627 * @return Offset of first byte that isn't @c uValue or
628 * @c SIZE_MAX if all bytes are @c uValue.
629 *
630 * Note that unlike most comparison functions, 0
631 * does not indicate a successful comparison, so the
632 * test for match is:
633 *
634 * UsefulBuf_IsValue(...) == SIZE_MAX
635 *
636 * If @c UB is null or empty, there is no match
637 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100638 */
639size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
640
641
642/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700643 * @brief Find one @ref UsefulBufC in another.
644 *
645 * @param[in] BytesToSearch Buffer to search through.
646 * @param[in] BytesToFind Buffer with bytes to be found.
647 *
648 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100649 */
650size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
651
652
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700653/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700654 * @brief Convert a pointer to an offset with bounds checking.
655 *
656 * @param[in] UB A UsefulBuf.
657 * @param[in] p Pointer to convert to offset.
658 *
659 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700660*/
661static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
662
663
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700664/**
665 * @brief Convert an offset to a pointer with bounds checking.
666 *
667 * @param[in] UB A UsefulBuf.
668 * @param[in] uOffset Offset in @c pUInBuf.
669 *
670 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
671 */
672static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
673
674
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800675#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100676/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700677#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100678
679/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
680#define MakeUsefulBufOnStack(name, size) \
681 uint8_t __pBuf##name[(size)];\
682 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
683
684/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
685#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700686 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100687
688/** Deprecated function; use UsefulBuf_Unconst() instead */
689static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
690{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700691 UsefulBuf UB;
692
Laurence Lundblade3eead482023-12-16 20:53:22 -0700693 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300694 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700695
696 UB.len = UBC.len;
697
698 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100699}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800700#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100701
702
703
704
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200705#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100706/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700707 * @brief Copy a @c float to a @c uint32_t.
708 *
709 * @param[in] f Float value to copy.
710 *
711 * @return A @c uint32_t with the float bits.
712 *
713 * Convenience function to avoid type punning, compiler warnings and
714 * such. The optimizer usually reduces this to a simple assignment. This
715 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100716 */
717static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
718
719
720/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700721 * @brief Copy a @c double to a @c uint64_t.
722 *
723 * @param[in] d Double value to copy.
724 *
725 * @return A @c uint64_t with the double bits.
726 *
727 * Convenience function to avoid type punning, compiler warnings and
728 * such. The optimizer usually reduces this to a simple assignment. This
729 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100730 */
731static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
732
733
734/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700735 * @brief Copy a @c uint32_t to a @c float.
736 *
737 * @param[in] u32 Integer value to copy.
738 *
739 * @return The value as a @c float.
740 *
741 * Convenience function to avoid type punning, compiler warnings and
742 * such. The optimizer usually reduces this to a simple assignment. This
743 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100744 */
745static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
746
747
748/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700749 * @brief Copy a @c uint64_t to a @c double.
750 *
751 * @param[in] u64 Integer value to copy.
752 *
753 * @return The value as a @c double.
754 *
755 * Convenience function to avoid type punning, compiler warnings and
756 * such. The optimizer usually reduces this to a simple assignment. This
757 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100758 */
759static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200760#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100761
762
763
764
765/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700766 * UsefulOutBuf is a structure and functions (an object) for
767 * serializing data into a buffer to encode for a network protocol or
768 * write data to a file.
769 *
770 * The main idea is that all the pointer manipulation is performed by
771 * @ref UsefulOutBuf functions so the caller doesn't have to do any
772 * pointer manipulation. The pointer manipulation is centralized.
773 * This code has been reviewed and written carefully so it
774 * spares the caller of much of this work and results in safer code
775 * with less effort.
776 *
777 * The @ref UsefulOutBuf methods that add data to the output buffer
778 * always check the length and will never write off the end of the
779 * output buffer. If an attempt to add data that will not fit is made,
780 * an internal error flag will be set and further attempts to add data
781 * will not do anything.
782 *
783 * There is no way to ever write off the end of that buffer when
784 * calling the @c UsefulOutBuf_AddXxx() and
785 * @c UsefulOutBuf_InsertXxx() functions.
786 *
787 * The functions to add data do not report success of failure. The
788 * caller only needs to check for an error in the final call, either
789 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
790 * result. This makes the calling code cleaner.
791 *
792 * There is a utility function to get the error status anytime along
793 * the way for a special circumstance. There are functions to see how
794 * much room is left and see if some data will fit too, but their use
795 * is generally unnecessary.
796 *
797 * The general call flow is:
798 *
799 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
800 * buffer given to it can be from the heap, stack or
801 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
802 * macro that makes a buffer on the stack and initializes it.
803 *
804 * - Call methods like UsefulOutBuf_InsertString(),
805 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
806 * to output data. The append calls add data to the end of the
807 * valid data. The insert calls take a position argument.
808 *
809 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
810 * there were no errors and to get the serialized output bytes.
811 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700812 * @ref UsefulOutBuf can be used in a mode to calculate the size of
813 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700814 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700815 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700816 *
817 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700818 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700819 *
820 * The possible errors are:
821 *
822 * - The @ref UsefulOutBuf was not initialized or was corrupted.
823 *
824 * - An attempt was made to add data that will not fit.
825 *
826 * - An attempt was made to insert data at a position beyond the end of
827 * the buffer.
828 *
829 * - An attempt was made to insert data at a position beyond the valid
830 * data in the buffer.
831 *
832 * Some inexpensive simple sanity checks are performed before every
833 * data addition to guard against use of an uninitialized or corrupted
834 * UsefulOutBuf.
835 *
836 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
837 * encoder has almost no pointer manipulation in it, is easier to
838 * read, and easier to review.
839 *
840 * A @ref UsefulOutBuf is small and can go on the stack:
841 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
842 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100843 */
844typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700845 /* PRIVATE DATA STRUCTURE */
846 UsefulBuf UB; /* Memory that is being output to */
847 size_t data_len; /* length of the valid data, the insertion point */
848 uint16_t magic; /* Used to detect corruption and lack
849 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100850 uint8_t err;
851} UsefulOutBuf;
852
853
854/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700855 * This is a @ref UsefulBuf value that can be passed to
856 * UsefulOutBuf_Init() to have it calculate the size of the output
857 * buffer needed. Pass this for @c Storage, call all the append and
858 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
859 * returned @ref UsefulBufC has the size.
860 *
861 * As one can see, this is just a NULL pointer and very large size.
862 * The NULL pointer tells UsefulOutputBuf to not copy any data.
863 */
864#ifdef __cplusplus
865#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
866#else
867#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
868#endif
869
870
871/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700872 * @brief Initialize and supply the actual output buffer.
873 *
874 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
875 * @param[in] Storage Buffer to output into.
876 *
877 * This initializes the @ref UsefulOutBuf with storage, sets the
878 * current position to the beginning of the buffer and clears the
879 * error state.
880 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700881 * See @ref SizeCalculateUsefulBuf for instructions on how to
882 * initialize a @ref UsefulOutBuf to calculate the size that would be
883 * output without actually outputting.
884 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700885 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100886 */
887void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
888
889
890/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700891 * Convenience macro to make a @ref UsefulOutBuf on the stack and
892 * initialize it with a stack buffer of the given size. The variable
893 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100894 */
895#define UsefulOutBuf_MakeOnStack(name, size) \
896 uint8_t __pBuf##name[(size)];\
897 UsefulOutBuf name;\
898 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
899
900
901/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700902 * @brief Reset a @ref UsefulOutBuf for re use.
903 *
904 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
905 *
906 * This sets the amount of data in the output buffer to none and
907 * clears the error state.
908 *
909 * The output buffer is still the same one and size as from the
910 * UsefulOutBuf_Init() call.
911 *
912 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100913 */
914static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
915
916
917/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700918 * @brief Returns position of end of data in the @ref UsefulOutBuf.
919 *
920 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
921 *
922 * @return position of end of data.
923 *
924 * On a freshly initialized @ref UsefulOutBuf with no data added, this
925 * will return 0. After 10 bytes have been added, it will return 10
926 * and so on.
927 *
928 * Generally, there is no need to call this for most uses of @ref
929 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100930 */
931static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
932
933
934/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700935 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
936 *
937 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
938 *
939 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100940 */
941static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
942
943
944/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700945 * @brief Inserts bytes into the @ref UsefulOutBuf.
946 *
947 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
948 * @param[in] NewData The bytes to insert.
949 * @param[in] uPos Index in output buffer at which to insert.
950 *
951 * @c NewData is the pointer and length for the bytes to be added to
952 * the output buffer. There must be room in the output buffer for all
953 * of @c NewData or an error will occur.
954 *
955 * The insertion point must be between 0 and the current valid
956 * data. If not, an error will occur. Appending data to the output
957 * buffer is achieved by inserting at the end of the valid data. This
958 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
959 *
960 * When insertion is performed, the bytes between the insertion point
961 * and the end of data previously added to the output buffer are slid
962 * to the right to make room for the new data.
963 *
964 * Overlapping buffers are OK. @c NewData can point to data in the
965 * output buffer.
966 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700967 * NewData.len may be 0 in which case nothing will be inserted.
968 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700969 * If an error occurs, an error state is set in the @ref
970 * UsefulOutBuf. No error is returned. All subsequent attempts to add
971 * data will do nothing.
972 *
973 * The intended use is that all additions are made without checking
974 * for an error. The error will be taken into account when
975 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
976 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100977 */
978void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
979 UsefulBufC NewData,
980 size_t uPos);
981
982
983/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700984 * @brief Insert a data buffer into the @ref UsefulOutBuf.
985 *
986 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
987 * @param[in] pBytes Pointer to the bytes to insert
988 * @param[in] uLen Length of the bytes to insert
989 * @param[in] uPos Index in output buffer at which to insert
990 *
991 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
992 * the difference being a pointer and length is passed in rather than an
993 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100994 */
995static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
996 const void *pBytes,
997 size_t uLen,
998 size_t uPos);
999
1000
1001/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001002 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1003 *
1004 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1005 * @param[in] szString NULL-terminated string to insert.
1006 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001007 */
1008static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1009 const char *szString,
1010 size_t uPos);
1011
1012
1013/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001014 * @brief Insert a byte into the @ref UsefulOutBuf.
1015 *
1016 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1017 * @param[in] byte Bytes to insert.
1018 * @param[in] uPos Index in output buffer at which to insert.
1019 *
1020 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1021 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001022 */
1023static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1024 uint8_t byte,
1025 size_t uPos);
1026
1027
1028/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001029 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1030 *
1031 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1032 * @param[in] uInteger16 Integer to insert.
1033 * @param[in] uPos Index in output buffer at which to insert.
1034 *
1035 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1036 * with the difference being a two-byte integer is to be inserted.
1037 *
1038 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001039 */
1040static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1041 uint16_t uInteger16,
1042 size_t uPos);
1043
1044
1045/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001046 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1047 *
1048 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1049 * @param[in] uInteger32 Integer to insert.
1050 * @param[in] uPos Index in output buffer at which to insert.
1051 *
1052 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1053 * with the difference being a four-byte integer is to be inserted.
1054 *
1055 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001056 */
1057static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1058 uint32_t uInteger32,
1059 size_t uPos);
1060
1061
1062/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001063 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1064 *
1065 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1066 * @param[in] uInteger64 Integer to insert.
1067 * @param[in] uPos Index in output buffer at which to insert.
1068 *
1069 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1070 * with the difference being an eight-byte integer is to be inserted.
1071 *
1072 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001073 */
1074static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1075 uint64_t uInteger64,
1076 size_t uPos);
1077
1078
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001079#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001080/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001081 * @brief Insert a @c float into the @ref UsefulOutBuf.
1082 *
1083 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1084 * @param[in] f @c float to insert.
1085 * @param[in] uPos Index in output buffer at which to insert.
1086 *
1087 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1088 * with the difference being a @c float is to be inserted.
1089 *
1090 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001091 */
1092static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1093 float f,
1094 size_t uPos);
1095
1096
1097/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001098 * @brief Insert a @c double into the @ref UsefulOutBuf.
1099 *
1100 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1101 * @param[in] d @c double to insert.
1102 * @param[in] uPos Index in output buffer at which to insert.
1103 *
1104 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1105 * with the difference being a @c double is to be inserted.
1106 *
1107 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001108 */
1109static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1110 double d,
1111 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001112#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001113
1114
1115/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001116 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1117 *
1118 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1119 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1120 *
1121 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1122 * with the insertion point at the end of the valid data.
1123 */
Michael Eckel5c531332020-03-02 01:35:30 +01001124static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1125 UsefulBufC NewData);
1126
1127
1128/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001129 * @brief Append bytes to the @ref UsefulOutBuf.
1130 *
1131 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1132 * @param[in] pBytes Pointer to bytes to append.
1133 * @param[in] uLen Length of @c pBytes to append.
1134 *
1135 * See UsefulOutBuf_InsertData() for details. This does the same with
1136 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001137 */
1138static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1139 const void *pBytes,
1140 size_t uLen);
1141
1142
1143/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001144 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1145 *
1146 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1147 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001148 */
1149static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1150 const char *szString);
1151
1152
1153/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001154 * @brief Append a byte to the @ref UsefulOutBuf
1155 *
1156 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1157 * @param[in] byte Bytes to append.
1158 *
1159 * See UsefulOutBuf_InsertByte() for details. This does the same
1160 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001161 */
1162static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1163 uint8_t byte);
1164
1165
1166/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001167 * @brief Append an integer to the @ref UsefulOutBuf
1168 *
1169 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1170 * @param[in] uInteger16 Integer to append.
1171 *
1172 * See UsefulOutBuf_InsertUint16() for details. This does the same
1173 * with the insertion point at the end of the valid data.
1174 *
1175 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001176 */
1177static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1178 uint16_t uInteger16);
1179
1180
1181/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001182 * @brief Append an integer to the @ref UsefulOutBuf
1183 *
1184 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1185 * @param[in] uInteger32 Integer to append.
1186 *
1187 * See UsefulOutBuf_InsertUint32() for details. This does the same
1188 * with the insertion point at the end of the valid data.
1189 *
1190 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001191 */
1192static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1193 uint32_t uInteger32);
1194
1195
1196/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001197 * @brief Append an integer to the @ref UsefulOutBuf
1198 *
1199 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1200 * @param[in] uInteger64 Integer to append.
1201 *
1202 * See UsefulOutBuf_InsertUint64() for details. This does the same
1203 * with the insertion point at the end of the valid data.
1204 *
1205 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001206 */
1207static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1208 uint64_t uInteger64);
1209
1210
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001211#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001212/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001213 * @brief Append a @c float to the @ref UsefulOutBuf
1214 *
1215 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1216 * @param[in] f @c float to append.
1217 *
1218 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1219 * the insertion point at the end of the valid data.
1220 *
1221 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001222 */
1223static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1224 float f);
1225
1226
1227/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001228 * @brief Append a @c double to the @ref UsefulOutBuf
1229 *
1230 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1231 * @param[in] d @c double to append.
1232 *
1233 * See UsefulOutBuf_InsertDouble() for details. This does the same
1234 * with the insertion point at the end of the valid data.
1235 *
1236 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001237 */
1238static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1239 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001240#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001241
1242
1243/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001244 * @brief Returns the current error status.
1245 *
1246 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1247 *
1248 * @return 0 if all OK, 1 on error.
1249 *
1250 * This returns the error status since a call to either
1251 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1252 * goes into the error state, it will stay until one of those
1253 * functions is called.
1254 *
1255 * Possible error conditions are:
1256 * - bytes to be inserted will not fit
1257 * - insertion point is out of buffer or past valid data
1258 * - current position is off end of buffer (probably corrupted or uninitialized)
1259 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001260 */
1261static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1262
1263
1264/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001265 * @brief Returns number of bytes unused used in the output buffer.
1266 *
1267 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1268 *
1269 * @return Number of unused bytes or zero.
1270 *
1271 * Because of the error handling strategy and checks in
1272 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1273 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001274 */
1275static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1276
1277
1278/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001279 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1280 *
1281 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1282 * @param[in] uLen Number of bytes for which to check
1283 *
1284 * @return 1 if @c uLen bytes will fit, 0 if not.
1285 *
1286 * Because of the error handling strategy and checks in
1287 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1288 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001289 */
1290static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1291
1292
1293 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001294 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1295 *
1296 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1297 *
1298 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1299 *
1300 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1301 * just calculating the length of the encoded data.
1302 */
Michael Eckel5c531332020-03-02 01:35:30 +01001303static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1304
1305
1306/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001307 * @brief Returns pointer and length of the output buffer not yet used.
1308 *
1309 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1310 *
1311 * @return pointer and length of output buffer not used.
1312 *
1313 * This is an escape that allows the caller to write directly
1314 * to the output buffer without any checks. This doesn't
1315 * change the output buffer or state. It just returns a pointer
1316 * and length of the bytes remaining.
1317 *
1318 * This is useful to avoid having the bytes to be added all
1319 * in a contiguous buffer. Its use can save memory. A good
1320 * example is in the COSE encrypt implementation where
1321 * the output of the symmetric cipher can go directly
1322 * into the output buffer, rather than having to go into
1323 * an intermediate buffer.
1324 *
1325 * See UsefulOutBuf_Advance() which is used to tell
1326 * UsefulOutBuf how much was written.
1327 *
1328 * Warning: this bypasses the buffer safety provided by
1329 * UsefulOutBuf!
1330 */
1331static inline UsefulBuf
1332UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1333
1334
1335/**
1336 * @brief Advance the amount output assuming it was written by the caller.
1337 *
1338 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1339 * @param[in] uAmount The amount to advance.
1340 *
1341 * This advances the position in the output buffer
1342 * by \c uAmount. This assumes that the
1343 * caller has written \c uAmount to the pointer obtained
1344 * with UsefulOutBuf_GetOutPlace().
1345 *
1346 * Warning: this bypasses the buffer safety provided by
1347 * UsefulOutBuf!
1348 */
1349void
1350UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1351
1352
1353/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001354 * @brief Returns the resulting valid data in a UsefulOutBuf
1355 *
1356 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1357 *
1358 * @return The valid data in @ref UsefulOutBuf or
1359 * @ref NULLUsefulBufC if there was an error adding data.
1360 *
1361 * The storage for the returned data is the @c Storage parameter
1362 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1363 *
1364 * This can be called anytime and many times to get intermediate
1365 * results. It doesn't change the data or reset the current position,
1366 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001367 */
1368UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1369
1370
1371/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001372 * @brief Copies the valid data into a supplied buffer
1373 *
1374 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1375 * @param[out] Dest The destination buffer to copy into.
1376 *
1377 * @return Pointer and length of copied data or @c NULLUsefulBufC
1378 * if it will not fit in the @c Dest buffer or the error
1379 * state was entered.
1380 *
1381 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1382 * data to @c Dest.
1383 */
Michael Eckel5c531332020-03-02 01:35:30 +01001384UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1385
1386
Laurence Lundbladee2226742024-08-16 10:50:23 -07001387/**
1388 * @beief Return a substring of the output data.
1389 *
1390 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1391 * @param[in] uStart Offset of start of substring.
1392 * @param[in] uLen Length of substring.
1393 *
1394 * This is the same as UsefulOutBuf_OutUBuf(), but returns a
1395 * substring. @c NULLUsefulBufC is returned if the requested substring
1396 * is off the end of the output bytes or if in error state.
1397 */
1398UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pUOutBuf,
1399 const size_t uStart,
1400 const size_t uLen);
1401
1402
1403/**
1404 * @brief Retrieve the storage buffer passed in to UsefulOutBuf_Init().
1405 *
1406 * @param[in] pUOutBuf The encoding context.
1407 *
1408 * @return The output storage buffer passed to UsefulOutBuf_Init().
1409 *
1410 * This doesn't give any information about how much has been encoded
1411 * or the error state. It just returns the exact @ref UsefulOutBuf given
1412 * to UsefulOutBuf_Init().
1413 */
1414static UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pUOutBuf);
1415
Michael Eckel5c531332020-03-02 01:35:30 +01001416
1417
1418/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001419 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1420 * for parsing data received. Initialize it with the data from the
1421 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1422 * get data chunks of various types. A position cursor is maintained
1423 * internally.
1424 *
1425 * As long as the functions here are used, there will never be any
1426 * reference off the end of the given buffer (except
1427 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1428 * called incorrectly, an attempt is made to seek off the end of the
1429 * buffer or such. This makes it easier to write safe and correct
1430 * code. For example, the QCBOR decoder implementation is safer and
1431 * easier to review through its use of @ref UsefulInputBuf.
1432 *
1433 * @ref UsefulInputBuf maintains an internal error state. The
1434 * intended use is fetching data chunks without any error checks until
1435 * the end. If there was any error, such as an attempt to fetch data
1436 * off the end, the error state is entered and no further data will be
1437 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1438 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1439 * null is not dereferenced, the error check can be put off until the
1440 * end, simplifying the calling code.
1441 *
1442 * The integer and float parsing expects network byte order (big
1443 * endian). Network byte order is what is used by TCP/IP, CBOR and
1444 * most internet protocols.
1445 *
1446 * Lots of inline functions are used to keep code size down. The
1447 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1448 * code size a lot. The only non-inline code is
1449 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1450 * @ref UsefulInputBuf doesn't add much code for all the messy
1451 * hard-to-get right issues with parsing binary protocols in C that it
1452 * solves.
1453 *
1454 * The parse context size is:
1455 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1456 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001457 */
1458typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001459 /* PRIVATE DATA STRUCTURE */
1460 UsefulBufC UB; /* Data being parsed */
1461 size_t cursor; /* Current offset in data being parse */
1462 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1463 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001464} UsefulInputBuf;
1465
1466#define UIB_MAGIC (0xB00F)
1467
1468
1469/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001470 * @brief Initialize the @ref UsefulInputBuf structure before use.
1471 *
1472 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1473 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001474 */
1475static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1476
1477
1478/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001479 * @brief Returns current position in input buffer.
1480 *
1481 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1482 *
1483 * @return Integer position of the cursor.
1484 *
1485 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001486 */
1487static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1488
1489
1490/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001491 * @brief Sets the current position in input buffer.
1492 *
1493 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1494 * @param[in] uPos Position to set to.
1495 *
1496 * If the position is off the end of the input buffer, the error state
1497 * is entered.
1498 *
1499 * Seeking to a valid position in the buffer will not reset the error
1500 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001501 */
1502static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1503
1504
1505/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001506 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1507 * the unconsumed bytes.
1508 *
1509 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1510 *
1511 * @return Number of bytes unconsumed or 0 on error.
1512 *
1513 * Returns 0 if the cursor is invalid or corruption of the
1514 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001515 */
1516static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1517
1518
1519/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001520 * @brief Check if there are unconsumed bytes.
1521 *
1522 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1523 * @param[in] uLen Number of bytes to check availability for.
1524 *
1525 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001526 */
1527static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1528
1529
1530/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001531 * @brief Convert a pointer to an offset with bounds checking.
1532 *
1533 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1534 * @param[in] p Pointer to convert to offset.
1535 *
1536 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1537 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001538static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1539
1540
1541/**
1542 * @brief Convert an offset to a pointer with bounds checking.
1543 *
1544 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1545 * @param[in] uOffset Offset in @c pUInBuf.
1546 *
1547 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1548 */
1549static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001550
1551
1552/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001553 * @brief Get pointer to bytes out of the input buffer.
1554 *
1555 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1556 * @param[in] uNum Number of bytes to get.
1557 *
1558 * @return Pointer to bytes.
1559 *
1560 * This consumes @c uNum bytes from the input buffer. This returns a
1561 * pointer to the start of the @c uNum bytes.
1562 *
1563 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1564 * returned and the error state is entered.
1565 *
1566 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001567 */
1568const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1569
1570
1571/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001572 * @brief Get @ref UsefulBuf out of the input buffer.
1573 *
1574 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1575 * @param[in] uNum Number of bytes to get.
1576 *
1577 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1578 *
1579 * This consumes @c uNum bytes from the input buffer and returns the
1580 * pointer and length for them as a @ref UsefulBufC. The length
1581 * returned will always be @c uNum. The position cursor is advanced by
1582 * @c uNum bytes.
1583 *
1584 * If there are not @c uNum bytes in the input buffer, @ref
1585 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001586 */
1587static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1588
1589
1590/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001591 * @brief Get a byte out of the input buffer.
1592 *
1593 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1594 *
1595 * @return The byte.
1596 *
1597 * This consumes 1 byte from the input buffer, returns it and advances
1598 * the position cursor by 1.
1599 *
1600 * If there is not 1 byte in the buffer, 0 will be returned for the
1601 * byte and the error state is entered. To know if the 0 returned was
1602 * in error or the real value, the error state must be checked. If
1603 * possible, put this off until all values are retrieved to have
1604 * smaller and simpler code, but if not possible
1605 * UsefulInputBuf_GetError() can be called. Also, in the error state
1606 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1607 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001608 */
1609static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1610
1611
1612/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001613 * @brief Get a @c uint16_t out of the input buffer.
1614 *
1615 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1616 *
1617 * @return The @c uint16_t.
1618 *
1619 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1620 * a @c uint16_t and two bytes are consumed.
1621 *
1622 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001623 */
1624static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1625
1626
1627/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001628 * @brief Get a @c uint32_t out of the input buffer.
1629 *
1630 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1631 *
1632 * @return The @c uint32_t.
1633 *
1634 * See UsefulInputBuf_GetByte(). This works the same, except it
1635 * returns a @c uint32_t and four bytes are consumed.
1636 *
1637 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001638 */
1639static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1640
1641
1642/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001643 * @brief Get a @c uint64_t out of the input buffer.
1644 *
1645 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1646 *
1647 * @return The uint64_t.
1648 *
1649 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1650 * a @c uint64_t and eight bytes are consumed.
1651 *
1652 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001653 */
1654static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1655
1656
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001657#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001658/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001659 * @brief Get a float out of the input buffer.
1660 *
1661 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1662 *
1663 * @return The float.
1664 *
1665 * See UsefulInputBuf_GetByte(). This works the same, except it
1666 * returns a float and four bytes are consumed.
1667 *
1668 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001669 */
1670static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1671
1672
1673/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001674 * @brief Get a double out of the input buffer.
1675 *
1676 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1677 *
1678 * @return The double.
1679 *
1680 * See UsefulInputBuf_GetByte(). This works the same, except it
1681 * returns a double and eight bytes are consumed.
1682 *
1683 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001684 */
1685static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001686#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001687
1688
1689/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001690 * @brief Get the error status.
1691 *
1692 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1693 *
1694 * @return 0 if not in the error state, 1 if in the error state.
1695 *
1696 * This returns whether the @ref UsefulInputBuf is in the
1697 * error state or not.
1698 *
1699 * The error state is entered for one of these reasons:
1700 * - Attempt to fetch data past the end of the buffer
1701 * - Attempt to seek to a position past the end of the buffer
1702 * - Attempt to get data from an uninitialized or corrupt instance
1703 * of @ref UsefulInputBuf
1704 *
1705 * Once in the error state, it can only be cleared by calling
1706 * UsefulInputBuf_Init().
1707 *
1708 * For many use cases, it is possible to only call this once after all
1709 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1710 * possible if no reference to the data returned are needed before the
1711 * error state is checked.
1712 *
1713 * In some cases UsefulInputBuf_GetUsefulBuf() or
1714 * UsefulInputBuf_GetBytes() can stand in for this because they return
1715 * @c NULL if the error state has been entered. (The others can't stand
1716 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001717 */
1718static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1719
1720
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001721/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001722 * @brief Gets the input buffer length.
1723 *
1724 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1725 *
1726 * @return The length of the input buffer.
1727 *
1728 * This returns the length of the input buffer set by
1729 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001730 */
1731static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1732
1733
1734/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001735 * @brief Alters the input buffer length (use with caution).
1736 *
1737 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1738 * @param[in] uNewLen The new length of the input buffer.
1739 *
1740 * This alters the internal remembered length of the input buffer set
1741 * when UsefulInputBuf_Init() was called.
1742 *
1743 * The new length given here should always be equal to or less than
1744 * the length given when UsefulInputBuf_Init() was called. Making it
1745 * larger allows @ref UsefulInputBuf to run off the input buffer.
1746 *
1747 * The typical use is to set a length shorter than that when
1748 * initialized to constrain parsing. If
1749 * UsefulInputBuf_GetBufferLength() was called before this, then the
1750 * original length can be restored with another call to this.
1751 *
1752 * This should be used with caution. It is the only
1753 * @ref UsefulInputBuf method that can violate the safety of input
1754 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001755 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001756static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001757
1758
Laurence Lundbladee2226742024-08-16 10:50:23 -07001759/**
1760 * @brief Retrieve the undecoded input buffer.
1761 *
1762 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1763 *
1764 * @return The input that was given to UsefulInputBuf_Init().
1765 *
1766 * A simple convenience method, should it be useful to get the original input back.
1767 */
1768static UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pUInBuf);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001769
1770
Michael Eckel5c531332020-03-02 01:35:30 +01001771/*----------------------------------------------------------
1772 Inline implementations.
1773 */
1774static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1775{
1776 return !UB.ptr;
1777}
1778
1779
1780static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1781{
1782 return !UB.ptr;
1783}
1784
1785
1786static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1787{
1788 return !UB.len;
1789}
1790
1791
1792static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1793{
1794 return !UB.len;
1795}
1796
1797
1798static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1799{
1800 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1801}
1802
1803
1804static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1805{
1806 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1807}
1808
1809
1810static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1811{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001812 UsefulBufC UBC;
1813 UBC.ptr = UB.ptr;
1814 UBC.len = UB.len;
1815
1816 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001817}
1818
Michael Eckel5c531332020-03-02 01:35:30 +01001819static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1820{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001821 UsefulBuf UB;
1822
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001823 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001824 * the one place in UsefulBuf where it needs to be quieted.
1825 */
1826 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001827
1828 UB.len = UBC.len;
1829
1830 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001831}
1832
1833
1834static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1835{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001836 UsefulBufC UBC;
1837 UBC.ptr = szString;
1838 UBC.len = strlen(szString);
1839 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001840}
1841
1842
1843static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1844{
1845 return UsefulBuf_CopyOffset(Dest, 0, Src);
1846}
1847
1848
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001849static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001850{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001851 memset(Dest.ptr, value, Dest.len);
1852
1853 UsefulBufC UBC;
1854 UBC.ptr = Dest.ptr;
1855 UBC.len = Dest.len;
1856
1857 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001858}
1859
1860
1861static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1862{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001863 UsefulBufC UBC;
1864 UBC.ptr = ptr;
1865 UBC.len = len;
1866 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001867}
1868
1869
1870static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1871{
1872 if(uAmount > UB.len) {
1873 return NULLUsefulBufC;
1874 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001875 UsefulBufC UBC;
1876
1877 UBC.ptr = UB.ptr;
1878 UBC.len = uAmount;
1879
1880 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001881}
1882
1883
1884static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1885{
1886 UsefulBufC ReturnValue;
1887
1888 if(uAmount > UB.len) {
1889 ReturnValue = NULLUsefulBufC;
1890 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001891 ReturnValue.ptr = NULL;
1892 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001893 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001894 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1895 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001896 }
1897
1898 return ReturnValue;
1899}
1900
1901
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001902static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1903{
1904 if(UB.ptr == NULL) {
1905 return SIZE_MAX;
1906 }
1907
1908 if(p < UB.ptr) {
1909 /* given pointer is before start of buffer */
1910 return SIZE_MAX;
1911 }
1912
Laurence Lundblade3eead482023-12-16 20:53:22 -07001913 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001914 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001915
1916 if(uOffset >= UB.len) {
1917 /* given pointer is off the end of the buffer */
1918 return SIZE_MAX;
1919 }
1920
1921 return uOffset;
1922}
1923
Michael Eckel5c531332020-03-02 01:35:30 +01001924
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001925static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
1926{
1927 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
1928 return NULL;
1929 }
1930
1931 return (const uint8_t *)UB.ptr + uOffset;
1932}
1933
1934
1935
1936
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001937#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001938static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1939{
1940 uint32_t u32;
1941 memcpy(&u32, &f, sizeof(uint32_t));
1942 return u32;
1943}
1944
1945static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1946{
1947 uint64_t u64;
1948 memcpy(&u64, &d, sizeof(uint64_t));
1949 return u64;
1950}
1951
1952static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1953{
1954 double d;
1955 memcpy(&d, &u64, sizeof(uint64_t));
1956 return d;
1957}
1958
1959static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1960{
1961 float f;
1962 memcpy(&f, &u32, sizeof(uint32_t));
1963 return f;
1964}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001965#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001966
1967
1968
1969
1970static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1971{
1972 pMe->data_len = 0;
1973 pMe->err = 0;
1974}
1975
1976
1977static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1978{
1979 return pMe->data_len;
1980}
1981
1982
1983static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1984{
1985 return 0 == pMe->data_len;
1986}
1987
1988
1989static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1990 const void *pBytes,
1991 size_t uLen,
1992 size_t uPos)
1993{
1994 UsefulBufC Data = {pBytes, uLen};
1995 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1996}
1997
1998
1999static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2000 const char *szString,
2001 size_t uPos)
2002{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002003 UsefulBufC UBC;
2004 UBC.ptr = szString;
2005 UBC.len = strlen(szString);
2006
2007 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002008}
2009
2010
2011static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2012 uint8_t byte,
2013 size_t uPos)
2014{
2015 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2016}
2017
2018
2019static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2020 uint16_t uInteger16,
2021 size_t uPos)
2022{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002023 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002024
2025 const void *pBytes;
2026
2027#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2028 pBytes = &uInteger16;
2029
2030#elif defined(USEFULBUF_CONFIG_HTON)
2031 uint16_t uTmp = htons(uInteger16);
2032 pBytes = &uTmp;
2033
2034#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2035 uint16_t uTmp = __builtin_bswap16(uInteger16);
2036 pBytes = &uTmp;
2037
2038#else
2039 uint8_t aTmp[2];
2040
2041 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2042 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2043
2044 pBytes = aTmp;
2045#endif
2046
2047 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2048}
2049
2050
2051static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2052 uint32_t uInteger32,
2053 size_t uPos)
2054{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002055 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002056
2057 const void *pBytes;
2058
2059#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2060 pBytes = &uInteger32;
2061
2062#elif defined(USEFULBUF_CONFIG_HTON)
2063 uint32_t uTmp = htonl(uInteger32);
2064 pBytes = &uTmp;
2065
2066#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2067 uint32_t uTmp = __builtin_bswap32(uInteger32);
2068
2069 pBytes = &uTmp;
2070
2071#else
2072 uint8_t aTmp[4];
2073
2074 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2075 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2076 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2077 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2078
2079 pBytes = aTmp;
2080#endif
2081
2082 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2083}
2084
2085static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002086 uint64_t uInteger64,
2087 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002088{
2089 const void *pBytes;
2090
2091#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002092 /* We have been told explicitly we are running on a big-endian
2093 * machine. Network byte order is big endian, so just copy. There
2094 * is no issue with alignment here because uInteger64 is always
2095 * aligned (and it doesn't matter if pBytes is aligned).
2096 */
Michael Eckel5c531332020-03-02 01:35:30 +01002097 pBytes = &uInteger64;
2098
2099#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002100 /* Use system function to handle big- and little-endian. This works
2101 * on both big- and little-endian machines, but hton() is not
2102 * always available or in a standard place so it is not used by
2103 * default. With some compilers and CPUs the code for this is very
2104 * compact through use of a special swap instruction and on
2105 * big-endian machines hton() will reduce to nothing.
2106 */
Michael Eckel5c531332020-03-02 01:35:30 +01002107 uint64_t uTmp = htonll(uInteger64);
2108
2109 pBytes = &uTmp;
2110
2111#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002112 /* Use built-in function for byte swapping. This usually compiles
2113 * to an efficient special byte swap instruction. Unlike hton() it
2114 * does not do this conditionally on the CPU endianness, so this
2115 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2116 */
Michael Eckel5c531332020-03-02 01:35:30 +01002117 uint64_t uTmp = __builtin_bswap64(uInteger64);
2118
2119 pBytes = &uTmp;
2120
2121#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002122 /* Default which works on every CPU with no dependency on anything
2123 * from the CPU, compiler, libraries or OS. This always works, but
2124 * it is usually a little larger and slower than hton().
2125 */
Michael Eckel5c531332020-03-02 01:35:30 +01002126 uint8_t aTmp[8];
2127
2128 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2129 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2130 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2131 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2132 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2133 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2134 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2135 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2136
2137 pBytes = aTmp;
2138#endif
2139
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002140 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002141 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2142}
2143
2144
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002145#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002146static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2147 float f,
2148 size_t uPos)
2149{
2150 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2151}
2152
2153
2154static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2155 double d,
2156 size_t uPos)
2157{
2158 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2159}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002160#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002161
2162
2163static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2164 UsefulBufC NewData)
2165{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002166 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002167 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2168}
2169
2170
2171static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2172 const void *pBytes,
2173 size_t uLen)
2174{
2175 UsefulBufC Data = {pBytes, uLen};
2176 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2177}
2178
2179
2180static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2181 const char *szString)
2182{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002183 UsefulBufC UBC;
2184 UBC.ptr = szString;
2185 UBC.len = strlen(szString);
2186
2187 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002188}
2189
2190
2191static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2192 uint8_t byte)
2193{
2194 UsefulOutBuf_AppendData(pMe, &byte, 1);
2195}
2196
2197
2198static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2199 uint16_t uInteger16)
2200{
2201 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2202}
2203
2204static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2205 uint32_t uInteger32)
2206{
2207 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2208}
2209
2210
2211static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2212 uint64_t uInteger64)
2213{
2214 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2215}
2216
2217
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002218#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002219static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2220 float f)
2221{
2222 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2223}
2224
2225
2226static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2227 double d)
2228{
2229 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2230}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002231#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002232
2233
2234static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2235{
2236 return pMe->err;
2237}
2238
2239
2240static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2241{
2242 return pMe->UB.len - pMe->data_len;
2243}
2244
2245
2246static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2247{
2248 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2249}
2250
2251
2252static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2253{
2254 return pMe->UB.ptr == NULL;
2255}
2256
2257
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002258static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2259{
2260 UsefulBuf R;
2261
2262 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002263 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002264 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2265 } else {
2266 R.ptr = NULL;
2267 }
2268
2269 return R;
2270}
2271
2272
Laurence Lundbladee2226742024-08-16 10:50:23 -07002273static inline UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pMe)
2274{
2275 return pMe->UB;
2276}
2277
2278
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002279
Michael Eckel5c531332020-03-02 01:35:30 +01002280
2281static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2282{
2283 pMe->cursor = 0;
2284 pMe->err = 0;
2285 pMe->magic = UIB_MAGIC;
2286 pMe->UB = UB;
2287}
2288
2289static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2290{
2291 return pMe->cursor;
2292}
2293
2294
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002295static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002296{
2297 return pMe->UB.len;
2298}
2299
2300
Michael Eckel5c531332020-03-02 01:35:30 +01002301static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2302{
2303 if(uPos > pMe->UB.len) {
2304 pMe->err = 1;
2305 } else {
2306 pMe->cursor = uPos;
2307 }
2308}
2309
2310
2311static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2312{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002313 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002314
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002315 /* Magic number is messed up. Either the structure got overwritten
2316 * or was never initialized.
2317 */
Michael Eckel5c531332020-03-02 01:35:30 +01002318 if(pMe->magic != UIB_MAGIC) {
2319 return 0;
2320 }
2321
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002322 /* The cursor is off the end of the input buffer given.
2323 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002324 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002325 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002326 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002327 */
Michael Eckel5c531332020-03-02 01:35:30 +01002328 if(pMe->cursor > pMe->UB.len) {
2329 return 0;
2330 }
2331
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002332 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002333 return pMe->UB.len - pMe->cursor;
2334}
2335
2336
2337static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2338{
2339 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2340}
2341
2342
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002343static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2344{
2345 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2346}
2347
2348
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002349static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2350 {
2351 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2352 }
2353
2354
Michael Eckel5c531332020-03-02 01:35:30 +01002355static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2356{
2357 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2358 if(!pResult) {
2359 return NULLUsefulBufC;
2360 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002361 UsefulBufC UBC;
2362 UBC.ptr = pResult;
2363 UBC.len = uNum;
2364 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002365 }
2366}
2367
2368
2369static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2370{
2371 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2372
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002373 /* The ternary operator is subject to integer promotion, because
2374 * the operands are smaller than int, so cast back to uint8_t is
2375 * needed to be completely explicit about types (for static
2376 * analyzers).
2377 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002378 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002379}
2380
2381static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2382{
2383 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2384
2385 if(!pResult) {
2386 return 0;
2387 }
2388
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002389 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002390#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2391 uint16_t uTmp;
2392 memcpy(&uTmp, pResult, sizeof(uint16_t));
2393
2394#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2395 return uTmp;
2396
2397#elif defined(USEFULBUF_CONFIG_HTON)
2398 return ntohs(uTmp);
2399
2400#else
2401 return __builtin_bswap16(uTmp);
2402
2403#endif
2404
2405#else
2406
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002407 /* The operations here are subject to integer promotion because the
2408 * operands are smaller than int. They will be promoted to unsigned
2409 * int for the shift and addition. The cast back to uint16_t is is
2410 * needed to be completely explicit about types (for static
2411 * analyzers).
2412 */
Michael Eckel5c531332020-03-02 01:35:30 +01002413 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2414
2415#endif
2416}
2417
2418
2419static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2420{
2421 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2422
2423 if(!pResult) {
2424 return 0;
2425 }
2426
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002427 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002428#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2429 uint32_t uTmp;
2430 memcpy(&uTmp, pResult, sizeof(uint32_t));
2431
2432#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2433 return uTmp;
2434
2435#elif defined(USEFULBUF_CONFIG_HTON)
2436 return ntohl(uTmp);
2437
2438#else
2439 return __builtin_bswap32(uTmp);
2440
2441#endif
2442
2443#else
2444 return ((uint32_t)pResult[0]<<24) +
2445 ((uint32_t)pResult[1]<<16) +
2446 ((uint32_t)pResult[2]<<8) +
2447 (uint32_t)pResult[3];
2448#endif
2449}
2450
2451
2452static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2453{
2454 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2455
2456 if(!pResult) {
2457 return 0;
2458 }
2459
2460#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002461 /* pResult will probably not be aligned. This memcpy() moves the
2462 * bytes into a temp variable safely for CPUs that can or can't do
2463 * unaligned memory access. Many compilers will optimize the
2464 * memcpy() into a simple move instruction.
2465 */
Michael Eckel5c531332020-03-02 01:35:30 +01002466 uint64_t uTmp;
2467 memcpy(&uTmp, pResult, sizeof(uint64_t));
2468
2469#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002470 /* We have been told expliclity this is a big-endian CPU. Since
2471 * network byte order is big-endian, there is nothing to do.
2472 */
Michael Eckel5c531332020-03-02 01:35:30 +01002473
2474 return uTmp;
2475
2476#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002477 /* We have been told to use ntoh(), the system function to handle
2478 * big- and little-endian. This works on both big- and
2479 * little-endian machines, but ntoh() is not always available or in
2480 * a standard place so it is not used by default. On some CPUs the
2481 * code for this is very compact through use of a special swap
2482 * instruction.
2483 */
Michael Eckel5c531332020-03-02 01:35:30 +01002484
2485 return ntohll(uTmp);
2486
2487#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002488 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2489 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2490 * __builtin_bswap64() and friends are not conditional on CPU
2491 * endianness so this must only be used on little-endian machines.
2492 */
Michael Eckel5c531332020-03-02 01:35:30 +01002493
2494 return __builtin_bswap64(uTmp);
2495
2496
2497#endif
2498
2499#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002500 /* This is the default code that works on every CPU and every
2501 * endianness with no dependency on ntoh(). This works on CPUs
2502 * that either allow or do not allow unaligned access. It will
2503 * always work, but usually is a little less efficient than ntoh().
2504 */
Michael Eckel5c531332020-03-02 01:35:30 +01002505
2506 return ((uint64_t)pResult[0]<<56) +
2507 ((uint64_t)pResult[1]<<48) +
2508 ((uint64_t)pResult[2]<<40) +
2509 ((uint64_t)pResult[3]<<32) +
2510 ((uint64_t)pResult[4]<<24) +
2511 ((uint64_t)pResult[5]<<16) +
2512 ((uint64_t)pResult[6]<<8) +
2513 (uint64_t)pResult[7];
2514#endif
2515}
2516
2517
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002518#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002519static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2520{
2521 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2522
2523 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2524}
2525
2526
2527static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2528{
2529 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2530
2531 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2532}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002533#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002534
2535
2536static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2537{
2538 return pMe->err;
2539}
2540
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002541
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002542static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002543{
2544 pMe->UB.len = uNewLen;
2545}
2546
Laurence Lundbladee2226742024-08-16 10:50:23 -07002547static inline UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pMe)
2548{
2549 return pMe->UB;
2550}
2551
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002552
Michael Eckel5c531332020-03-02 01:35:30 +01002553#ifdef __cplusplus
2554}
2555#endif
2556
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002557#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002558
2559