blob: 3b7afd749b58a05d3f396bed4c8537ece55a2659 [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 Lundbladea29f45a2024-05-14 15:55:19 -070046 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070047 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060048 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070049 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070050 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070051 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080052 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070053 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010054 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
55 5/21/2019 llundblade #define configs for efficient endianness handling.
56 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
57 3/23/2019 llundblade Big documentation & style update. No interface
58 change.
59 3/6/2019 llundblade Add UsefulBuf_IsValue()
60 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
61 12/13/2018 llundblade Documentation improvements
62 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
63 UsefulBufC.
64 02/02/18 llundbla Full support for integers in and out; fix pointer
65 alignment bug. Incompatible change: integers
66 in/out are now in network byte order.
67 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
68 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
69 comparison for < or > for unequal length buffers.
70 Added UsefulBuf_Set() function.
71 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
72 11/13/16 llundbla Initial Version.
73
74 =============================================================================*/
75
76#ifndef _UsefulBuf_h
77#define _UsefulBuf_h
78
79
80/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070081 * Endianness Configuration
82 *
83 * This code is written so it will work correctly on big- and
84 * little-endian CPUs without configuration or any auto-detection of
85 * endianness. All code here will run correctly regardless of the
86 * endianness of the CPU it is running on.
87 *
88 * There are four C preprocessor macros that can be set with #define
89 * to explicitly configure endianness handling. Setting them can
90 * reduce code size a little and improve efficiency a little.
91 *
92 * Note that most of QCBOR is unaffected by this configuration. Its
93 * endianness handling is integrated with the code that handles
94 * alignment and preferred serialization. This configuration does
95 * affect QCBOR's (planned) implementation of integer arrays (tagged
96 * arrays) and use of the functions here to serialize or deserialize
97 * integers and floating-point values.
98 *
99 * Following is the recipe for configuring the endianness-related
100 * #defines.
101 *
102 * The first option is to not define anything. This will work fine
103 * with all CPUs, OS's and compilers. The code for encoding integers
104 * may be a little larger and slower.
105 *
106 * If your CPU is big-endian then define
107 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
108 * for big-endian CPUs. It will be small and efficient because there
109 * will be no byte swapping.
110 *
111 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
112 * OS's and compilers, but not all. On big-endian CPUs this should
113 * give the most efficient code, the same as
114 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
115 * call the system-defined byte swapping method which is presumably
116 * implemented efficiently. In some cases, this will be a dedicated
117 * byte swap instruction like Intel's bswap.
118 *
119 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
120 * little-endian, it is also good to define
121 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
122 *
123 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
124 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
125 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
126 * system-defined byte swap method. However, note
127 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
128 * this is fixed now. Often hton() and ntoh() will call the built-in
129 * __builtin_bswapXX()() function, so this size issue could affect
130 * USEFULBUF_CONFIG_HTON.
131 *
132 * Last, run the tests. They must all pass.
133 *
134 * These #define config options affect the inline implementation of
135 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
136 * also affect the 16-, 32-bit, float and double versions of these
137 * functions. Since they are inline, the size effect is not in the
138 * UsefulBuf object code, but in the calling code.
139 *
140 * Summary:
141 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
142 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
143 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
144 * handle big and little-endian with system option.
145 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
146 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200147 *
148 * It is possible to run this code in environments where using floating point is
149 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
150 * that is related to handling floating point types, along with related
151 * interfaces. This makes it possible to compile the code with the compile
152 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100153 */
154
155#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
156#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
157#endif
158
159
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700160#include <stdint.h> /* for uint8_t, uint16_t.... */
161#include <string.h> /* for strlen, memcpy, memmove, memset */
162#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100163
164
165#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700166#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100167#endif
168
169#ifdef __cplusplus
170extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700171#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700172} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700173#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100174#endif
175
176/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700177 * @file UsefulBuf.h
178 *
179 * The goal of this code is to make buffer and pointer manipulation
180 * easier and safer when working with binary data.
181 *
182 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
183 * structures are used to represent buffers rather than ad hoc
184 * pointers and lengths.
185 *
186 * With these it is possible to write code that does little or no
187 * direct pointer manipulation for copying and formatting data. For
188 * example, the QCBOR encoder was written using these and has less
189 * pointer manipulation.
190 *
191 * While it is true that object code using these functions will be a
192 * little larger and slower than a white-knuckle clever use of
193 * pointers might be, but not by that much or enough to have an effect
194 * for most use cases. For security-oriented code this is highly
195 * worthwhile. Clarity, simplicity, reviewability and are more
196 * important.
197 *
198 * There are some extra sanity and double checks in this code to help
199 * catch coding errors and simple memory corruption. They are helpful,
200 * but not a substitute for proper code review, input validation and
201 * such.
202 *
203 * This code consists of a lot of inline functions and a few that are
204 * not. It should not generate very much object code, especially with
205 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100206 */
207
208
209/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700210 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
211 * hold a pointer and length for binary data. In C99 this data
212 * structure can be passed on the stack making a lot of code cleaner
213 * than carrying around a pointer and length as two parameters.
214 *
215 * This is also conducive to secure coding practice as the length is
216 * always carried with the pointer and the convention for handling a
217 * pointer and a length is clear.
218 *
219 * While it might be possible to write buffer and pointer code more
220 * efficiently in some use cases, the thought is that unless there is
221 * an extreme need for performance (e.g., you are building a
222 * gigabit-per-second IP router), it is probably better to have
223 * cleaner code you can be most certain about the security of.
224 *
225 * The non-const @ref UsefulBuf is usually used to refer an empty
226 * buffer to be filled in. The length is the size of the buffer.
227 *
228 * The const @ref UsefulBufC is usually used to refer to some data
229 * that has been filled in. The length is amount of valid data pointed
230 * to.
231 *
232 * A common use mode is to pass a @ref UsefulBuf to a function, the
233 * function puts some data in it, then the function returns a @ref
234 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
235 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
236 * so the constness stays correct. There is no single "in,out"
237 * parameter (if there was, it would have to be non-const). Note that
238 * the pointer returned in the @ref UsefulBufC usually ends up being
239 * the same pointer passed in as a @ref UsefulBuf, though this is not
240 * striclty required.
241 *
242 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
243 * @c NULL.
244 *
245 * There are functions and macros for the following:
246 * - Initializing
247 * - Create initialized const @ref UsefulBufC from compiler literals
248 * - Create initialized const @ref UsefulBufC from NULL-terminated string
249 * - Make an empty @ref UsefulBuf on the stack
250 * - Checking whether a @ref UsefulBuf is null, empty or both
251 * - Copying, copying with offset, copying head or tail
252 * - Comparing and finding substrings
253 *
254 * See also @ref UsefulOutBuf. It is a richer structure that has both
255 * the size of the valid data and the size of the buffer.
256 *
257 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
258 * it can go on the stack and be a function parameter or return value.
259 *
260 * Another way to look at it is this. C has the NULL-terminated string
261 * as a means for handling text strings, but no means or convention
262 * for binary strings. Other languages do have such means, Rust, an
263 * efficient compiled language, for example.
264 *
265 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
266 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
267 * out like anything".
268 */
Michael Eckel5c531332020-03-02 01:35:30 +0100269typedef struct q_useful_buf_c {
270 const void *ptr;
271 size_t len;
272} UsefulBufC;
273
274
275/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700276 * This non-const @ref UsefulBuf is typically used for some allocated
277 * memory that is to be filled in. The @c len is the amount of memory,
278 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100279 */
280typedef struct q_useful_buf {
281 void *ptr;
282 size_t len;
283} UsefulBuf;
284
285
286/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700287 * A null @ref UsefulBufC is one that has no value in the same way a
288 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
289 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
290 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100291 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700292/*
293 * NULLUsefulBufC and few other macros have to be
294 * definied differently in C than C++ because there
295 * is no common construct for a literal structure.
296 *
297 * In C compound literals are used.
298 *
299 * In C++ list initalization is used. This only works
300 * in C++11 and later.
301 *
302 * Note that some popular C++ compilers can handle compound
303 * literals with on-by-default extensions, however
304 * this code aims for full correctness with strict
305 * compilers so they are not used.
306 */
307#ifdef __cplusplus
308#define NULLUsefulBufC {NULL, 0}
309#else
310#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
311#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100312
313/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700314 * A null @ref UsefulBuf is one that has no memory associated the same
315 * way @c NULL points to nothing. It does not matter what @c len is.
316 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700317#ifdef __cplusplus
318#define NULLUsefulBuf {NULL, 0}
319#else
320#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
321#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100322
323
324/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700325 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
326 *
327 * @param[in] UB The UsefulBuf to check.
328 *
329 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100330 */
331static inline int UsefulBuf_IsNULL(UsefulBuf UB);
332
333
334/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700335 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
336 *
337 * @param[in] UB The @ref UsefulBufC to check.
338 *
339 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100340 */
341static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
342
343
344/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700345 * @brief Check if a @ref UsefulBuf is empty or not.
346 *
347 * @param[in] UB The @ref UsefulBuf to check.
348 *
349 * @return 1 if it is empty, 0 if not.
350 *
351 * An "empty" @ref UsefulBuf is one that has a value and can be
352 * considered to be set, but that value is of zero length. It is
353 * empty when @c len is zero. It doesn't matter what the @c ptr is.
354 *
355 * Many uses will not need to clearly distinguish a @c NULL @ref
356 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
357 * @c len 0. However if a use of @ref UsefulBuf needs to make a
358 * distinction then @c ptr should not be @c NULL when the @ref
359 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100360 */
361static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
362
363
364/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700365 * @brief Check if a @ref UsefulBufC is empty or not.
366 *
367 * @param[in] UB The @ref UsefulBufC to check.
368 *
369 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100370 */
371static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
372
373
374/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700375 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
376 *
377 * @param[in] UB The @ref UsefulBuf to check.
378 *
379 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100380 */
381static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
382
383
384/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700385 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
386 *
387 * @param[in] UB The @ref UsefulBufC to check.
388 *
389 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100390 */
391static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
392
393
394/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700395 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
396 *
397 * @param[in] UB The @ref UsefulBuf to convert.
398 *
399 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100400 */
401static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
402
403
404/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700405 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
406 *
407 * @param[in] UBC The @ref UsefulBuf to convert.
408 *
409 * @return A non-const @ref UsefulBuf struct.
410 *
411 * Use of this is not necessary for the intended use mode of @ref
412 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
413 * created to describe a buffer that has not had any data put in
414 * it. Then the data is put in it. Then a @ref UsefulBufC is create
415 * to describe the part with the data in it. This goes from non-const
416 * to const, so this function is not needed.
417 *
418 * If the -Wcast-qual warning is enabled, this function can be used to
419 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100420 */
421static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
422
423
424/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700425 * Convert a literal string to a @ref UsefulBufC.
426 *
427 * @c szString must be a literal string that @c sizeof() works on.
428 * This is better for literal strings than UsefulBuf_FromSZ() because
429 * it generates less code. It will not work on non-literal strings.
430 *
431 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100432 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700433#ifdef __cplusplus
434#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
435#else
Michael Eckel5c531332020-03-02 01:35:30 +0100436#define UsefulBuf_FROM_SZ_LITERAL(szString) \
437 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700438#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100439
440
441/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700442 * Convert a literal byte array to a @ref UsefulBufC.
443 *
444 * @c pBytes must be a literal string that @c sizeof() works on. It
445 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100446 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700447#ifdef __cplusplus
448#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
449#else
Michael Eckel5c531332020-03-02 01:35:30 +0100450#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700451 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
452#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100453
454/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700455 * Make an automatic variable named @c name of type @ref UsefulBuf and
456 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100457 */
458#define UsefulBuf_MAKE_STACK_UB(name, size) \
459 uint8_t __pBuf##name[(size)];\
460 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
461
462
463/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700464 * Make a byte array in to a @ref UsefulBuf. This is usually used on
465 * stack variables or static variables. Also see @ref
466 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100467 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700468#ifdef __cplusplus
469#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
470#else
Michael Eckel5c531332020-03-02 01:35:30 +0100471#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700472 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
473#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100474
475
476/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700477 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
478 *
479 * @param[in] szString The string to convert.
480 *
481 * @return A @ref UsefulBufC struct.
482 *
483 * @c UsefulBufC.ptr points to the string so its lifetime must be
484 * maintained.
485 *
486 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100487 */
488static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
489
490
491/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700492 * @brief Copy one @ref UsefulBuf into another at an offset.
493 *
494 * @param[in] Dest Destination buffer to copy into.
495 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
496 * @param[in] Src The bytes to copy.
497 *
498 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
499 *
500 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
501 * size of @c Dest.
502 *
503 * This fails and returns @ref NULLUsefulBufC if the @c Src length
504 * plus @c uOffset is greater than the length of @c Dest.
505 *
506 * The results are undefined if @c Dest and @c Src overlap.
507 *
508 * This assumes that there is valid data in @c Dest up to @c
509 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
510 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100511 */
512UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
513
514
515/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700516 * @brief Copy one @ref UsefulBuf into another.
517 *
518 * @param[in] Dest The destination buffer to copy into.
519 * @param[out] Src The source to copy from.
520 *
521 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
522 * on failure.
523 *
524 * This fails if @c Src.len is greater than @c Dest.len.
525 *
526 * Note that like @c memcpy(), the pointers are not checked and this
527 * will crash rather than return @ref NULLUsefulBufC if they are @c
528 * NULL or invalid.
529 *
530 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100531 */
532static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
533
534
535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700536 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
537 *
538 * @param[in] pDest The destination buffer to copy into.
539 * @param[in] value The value to set the bytes to.
540 *
541 * Note that like @c memset(), the pointer in @c pDest is not checked
542 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100543 */
544static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
545
546
547/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700548 * @brief Copy a pointer into a @ref UsefulBuf.
549 *
550 * @param[in,out] Dest The destination buffer to copy into.
551 * @param[in] ptr The source to copy from.
552 * @param[in] uLen Length of the source; amount to copy.
553 *
554 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
555 * on failure.
556 *
557 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
558 * than @c pDest->len.
559 *
560 * Note that like @c memcpy(), the pointers are not checked and this
561 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100562 */
563static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
564 const void *ptr,
565 size_t uLen);
566
567
568/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700569 * @brief Returns a truncation of a @ref UsefulBufC.
570 *
571 * @param[in] UB The buffer to get the head of.
572 * @param[in] uAmount The number of bytes in the head.
573 *
574 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100575 */
576static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
577
578
579/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700580 * @brief Returns bytes from the end of a @ref UsefulBufC.
581 *
582 * @param[in] UB The buffer to get the tail of.
583 * @param[in] uAmount The offset from the start where the tail is to begin.
584 *
585 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
586 * if @c uAmount is greater than the length of the @ref UsefulBufC.
587 *
588 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
589 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
590 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100591 */
592static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
593
594
595/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700596 * @brief Compare one @ref UsefulBufC to another.
597 *
598 * @param[in] UB1 The first buffer to compare.
599 * @param[in] UB2 The second buffer to compare.
600 *
601 * @return 0, positive or negative value.
602 *
603 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
604 * less than @c UB2 if it is shorter or the first byte that is not the
605 * same is less.
606 *
607 * Returns 0 if the inputs are the same.
608 *
609 * Returns a positive value if @c UB2 is less than @c UB1.
610 *
611 * All that is of significance is that the result is positive, negative
612 * or 0. (This doesn't return the difference between the first
613 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100614 */
615int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
616
617
618/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700619 * @brief Find first byte that is not a particular byte value.
620 *
621 * @param[in] UB The destination buffer for byte comparison.
622 * @param[in] uValue The byte value to compare to.
623 *
624 * @return Offset of first byte that isn't @c uValue or
625 * @c SIZE_MAX if all bytes are @c uValue.
626 *
627 * Note that unlike most comparison functions, 0
628 * does not indicate a successful comparison, so the
629 * test for match is:
630 *
631 * UsefulBuf_IsValue(...) == SIZE_MAX
632 *
633 * If @c UB is null or empty, there is no match
634 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100635 */
636size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
637
638
639/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700640 * @brief Find one @ref UsefulBufC in another.
641 *
642 * @param[in] BytesToSearch Buffer to search through.
643 * @param[in] BytesToFind Buffer with bytes to be found.
644 *
645 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100646 */
647size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
648
649
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700650/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700651 * @brief Convert a pointer to an offset with bounds checking.
652 *
653 * @param[in] UB A UsefulBuf.
654 * @param[in] p Pointer to convert to offset.
655 *
656 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700657*/
658static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
659
660
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700661/**
662 * @brief Convert an offset to a pointer with bounds checking.
663 *
664 * @param[in] UB A UsefulBuf.
665 * @param[in] uOffset Offset in @c pUInBuf.
666 *
667 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
668 */
669static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
670
671
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800672#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100673/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700674#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100675
676/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
677#define MakeUsefulBufOnStack(name, size) \
678 uint8_t __pBuf##name[(size)];\
679 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
680
681/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
682#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700683 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100684
685/** Deprecated function; use UsefulBuf_Unconst() instead */
686static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
687{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700688 UsefulBuf UB;
689
Laurence Lundblade3eead482023-12-16 20:53:22 -0700690 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300691 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700692
693 UB.len = UBC.len;
694
695 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100696}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800697#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100698
699
700
701
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200702#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100703/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700704 * @brief Copy a @c float to a @c uint32_t.
705 *
706 * @param[in] f Float value to copy.
707 *
708 * @return A @c uint32_t with the float bits.
709 *
710 * Convenience function to avoid type punning, compiler warnings and
711 * such. The optimizer usually reduces this to a simple assignment. This
712 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100713 */
714static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
715
716
717/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700718 * @brief Copy a @c double to a @c uint64_t.
719 *
720 * @param[in] d Double value to copy.
721 *
722 * @return A @c uint64_t with the double bits.
723 *
724 * Convenience function to avoid type punning, compiler warnings and
725 * such. The optimizer usually reduces this to a simple assignment. This
726 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100727 */
728static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
729
730
731/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700732 * @brief Copy a @c uint32_t to a @c float.
733 *
734 * @param[in] u32 Integer value to copy.
735 *
736 * @return The value as a @c float.
737 *
738 * Convenience function to avoid type punning, compiler warnings and
739 * such. The optimizer usually reduces this to a simple assignment. This
740 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100741 */
742static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
743
744
745/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700746 * @brief Copy a @c uint64_t to a @c double.
747 *
748 * @param[in] u64 Integer value to copy.
749 *
750 * @return The value as a @c double.
751 *
752 * Convenience function to avoid type punning, compiler warnings and
753 * such. The optimizer usually reduces this to a simple assignment. This
754 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100755 */
756static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200757#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100758
759
760
761
762/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700763 * UsefulOutBuf is a structure and functions (an object) for
764 * serializing data into a buffer to encode for a network protocol or
765 * write data to a file.
766 *
767 * The main idea is that all the pointer manipulation is performed by
768 * @ref UsefulOutBuf functions so the caller doesn't have to do any
769 * pointer manipulation. The pointer manipulation is centralized.
770 * This code has been reviewed and written carefully so it
771 * spares the caller of much of this work and results in safer code
772 * with less effort.
773 *
774 * The @ref UsefulOutBuf methods that add data to the output buffer
775 * always check the length and will never write off the end of the
776 * output buffer. If an attempt to add data that will not fit is made,
777 * an internal error flag will be set and further attempts to add data
778 * will not do anything.
779 *
780 * There is no way to ever write off the end of that buffer when
781 * calling the @c UsefulOutBuf_AddXxx() and
782 * @c UsefulOutBuf_InsertXxx() functions.
783 *
784 * The functions to add data do not report success of failure. The
785 * caller only needs to check for an error in the final call, either
786 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
787 * result. This makes the calling code cleaner.
788 *
789 * There is a utility function to get the error status anytime along
790 * the way for a special circumstance. There are functions to see how
791 * much room is left and see if some data will fit too, but their use
792 * is generally unnecessary.
793 *
794 * The general call flow is:
795 *
796 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
797 * buffer given to it can be from the heap, stack or
798 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
799 * macro that makes a buffer on the stack and initializes it.
800 *
801 * - Call methods like UsefulOutBuf_InsertString(),
802 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
803 * to output data. The append calls add data to the end of the
804 * valid data. The insert calls take a position argument.
805 *
806 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
807 * there were no errors and to get the serialized output bytes.
808 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700809 * @ref UsefulOutBuf can be used in a mode to calculate the size of
810 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700811 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700812 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700813 *
814 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700815 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700816 *
817 * The possible errors are:
818 *
819 * - The @ref UsefulOutBuf was not initialized or was corrupted.
820 *
821 * - An attempt was made to add data that will not fit.
822 *
823 * - An attempt was made to insert data at a position beyond the end of
824 * the buffer.
825 *
826 * - An attempt was made to insert data at a position beyond the valid
827 * data in the buffer.
828 *
829 * Some inexpensive simple sanity checks are performed before every
830 * data addition to guard against use of an uninitialized or corrupted
831 * UsefulOutBuf.
832 *
833 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
834 * encoder has almost no pointer manipulation in it, is easier to
835 * read, and easier to review.
836 *
837 * A @ref UsefulOutBuf is small and can go on the stack:
838 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
839 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100840 */
841typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700842 /* PRIVATE DATA STRUCTURE */
843 UsefulBuf UB; /* Memory that is being output to */
844 size_t data_len; /* length of the valid data, the insertion point */
845 uint16_t magic; /* Used to detect corruption and lack
846 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100847 uint8_t err;
848} UsefulOutBuf;
849
850
851/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700852 * This is a @ref UsefulBuf value that can be passed to
853 * UsefulOutBuf_Init() to have it calculate the size of the output
854 * buffer needed. Pass this for @c Storage, call all the append and
855 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
856 * returned @ref UsefulBufC has the size.
857 *
858 * As one can see, this is just a NULL pointer and very large size.
859 * The NULL pointer tells UsefulOutputBuf to not copy any data.
860 */
861#ifdef __cplusplus
862#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
863#else
864#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
865#endif
866
867
868/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700869 * @brief Initialize and supply the actual output buffer.
870 *
871 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
872 * @param[in] Storage Buffer to output into.
873 *
874 * This initializes the @ref UsefulOutBuf with storage, sets the
875 * current position to the beginning of the buffer and clears the
876 * error state.
877 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700878 * See @ref SizeCalculateUsefulBuf for instructions on how to
879 * initialize a @ref UsefulOutBuf to calculate the size that would be
880 * output without actually outputting.
881 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700882 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100883 */
884void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
885
886
887/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700888 * Convenience macro to make a @ref UsefulOutBuf on the stack and
889 * initialize it with a stack buffer of the given size. The variable
890 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100891 */
892#define UsefulOutBuf_MakeOnStack(name, size) \
893 uint8_t __pBuf##name[(size)];\
894 UsefulOutBuf name;\
895 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
896
897
898/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700899 * @brief Reset a @ref UsefulOutBuf for re use.
900 *
901 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
902 *
903 * This sets the amount of data in the output buffer to none and
904 * clears the error state.
905 *
906 * The output buffer is still the same one and size as from the
907 * UsefulOutBuf_Init() call.
908 *
909 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100910 */
911static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
912
913
914/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700915 * @brief Returns position of end of data in the @ref UsefulOutBuf.
916 *
917 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
918 *
919 * @return position of end of data.
920 *
921 * On a freshly initialized @ref UsefulOutBuf with no data added, this
922 * will return 0. After 10 bytes have been added, it will return 10
923 * and so on.
924 *
925 * Generally, there is no need to call this for most uses of @ref
926 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100927 */
928static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
929
930
931/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700932 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
933 *
934 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
935 *
936 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100937 */
938static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
939
940
941/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700942 * @brief Inserts bytes into the @ref UsefulOutBuf.
943 *
944 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
945 * @param[in] NewData The bytes to insert.
946 * @param[in] uPos Index in output buffer at which to insert.
947 *
948 * @c NewData is the pointer and length for the bytes to be added to
949 * the output buffer. There must be room in the output buffer for all
950 * of @c NewData or an error will occur.
951 *
952 * The insertion point must be between 0 and the current valid
953 * data. If not, an error will occur. Appending data to the output
954 * buffer is achieved by inserting at the end of the valid data. This
955 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
956 *
957 * When insertion is performed, the bytes between the insertion point
958 * and the end of data previously added to the output buffer are slid
959 * to the right to make room for the new data.
960 *
961 * Overlapping buffers are OK. @c NewData can point to data in the
962 * output buffer.
963 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700964 * NewData.len may be 0 in which case nothing will be inserted.
965 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700966 * If an error occurs, an error state is set in the @ref
967 * UsefulOutBuf. No error is returned. All subsequent attempts to add
968 * data will do nothing.
969 *
970 * The intended use is that all additions are made without checking
971 * for an error. The error will be taken into account when
972 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
973 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100974 */
975void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
976 UsefulBufC NewData,
977 size_t uPos);
978
979
980/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700981 * @brief Insert a data buffer into the @ref UsefulOutBuf.
982 *
983 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
984 * @param[in] pBytes Pointer to the bytes to insert
985 * @param[in] uLen Length of the bytes to insert
986 * @param[in] uPos Index in output buffer at which to insert
987 *
988 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
989 * the difference being a pointer and length is passed in rather than an
990 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100991 */
992static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
993 const void *pBytes,
994 size_t uLen,
995 size_t uPos);
996
997
998/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700999 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1000 *
1001 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1002 * @param[in] szString NULL-terminated string to insert.
1003 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001004 */
1005static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1006 const char *szString,
1007 size_t uPos);
1008
1009
1010/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001011 * @brief Insert a byte into the @ref UsefulOutBuf.
1012 *
1013 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1014 * @param[in] byte Bytes to insert.
1015 * @param[in] uPos Index in output buffer at which to insert.
1016 *
1017 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1018 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001019 */
1020static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1021 uint8_t byte,
1022 size_t uPos);
1023
1024
1025/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001026 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1027 *
1028 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1029 * @param[in] uInteger16 Integer to insert.
1030 * @param[in] uPos Index in output buffer at which to insert.
1031 *
1032 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1033 * with the difference being a two-byte integer is to be inserted.
1034 *
1035 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001036 */
1037static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1038 uint16_t uInteger16,
1039 size_t uPos);
1040
1041
1042/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001043 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1044 *
1045 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1046 * @param[in] uInteger32 Integer to insert.
1047 * @param[in] uPos Index in output buffer at which to insert.
1048 *
1049 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1050 * with the difference being a four-byte integer is to be inserted.
1051 *
1052 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001053 */
1054static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1055 uint32_t uInteger32,
1056 size_t uPos);
1057
1058
1059/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001060 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1061 *
1062 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1063 * @param[in] uInteger64 Integer to insert.
1064 * @param[in] uPos Index in output buffer at which to insert.
1065 *
1066 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1067 * with the difference being an eight-byte integer is to be inserted.
1068 *
1069 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001070 */
1071static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1072 uint64_t uInteger64,
1073 size_t uPos);
1074
1075
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001076#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001077/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001078 * @brief Insert a @c float into the @ref UsefulOutBuf.
1079 *
1080 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1081 * @param[in] f @c float to insert.
1082 * @param[in] uPos Index in output buffer at which to insert.
1083 *
1084 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1085 * with the difference being a @c float is to be inserted.
1086 *
1087 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001088 */
1089static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1090 float f,
1091 size_t uPos);
1092
1093
1094/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001095 * @brief Insert a @c double into the @ref UsefulOutBuf.
1096 *
1097 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1098 * @param[in] d @c double to insert.
1099 * @param[in] uPos Index in output buffer at which to insert.
1100 *
1101 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1102 * with the difference being a @c double is to be inserted.
1103 *
1104 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001105 */
1106static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1107 double d,
1108 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001109#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001110
1111
1112/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001113 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1114 *
1115 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1116 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1117 *
1118 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1119 * with the insertion point at the end of the valid data.
1120 */
Michael Eckel5c531332020-03-02 01:35:30 +01001121static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1122 UsefulBufC NewData);
1123
1124
1125/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001126 * @brief Append bytes to the @ref UsefulOutBuf.
1127 *
1128 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1129 * @param[in] pBytes Pointer to bytes to append.
1130 * @param[in] uLen Length of @c pBytes to append.
1131 *
1132 * See UsefulOutBuf_InsertData() for details. This does the same with
1133 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001134 */
1135static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1136 const void *pBytes,
1137 size_t uLen);
1138
1139
1140/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001141 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1142 *
1143 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1144 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001145 */
1146static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1147 const char *szString);
1148
1149
1150/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001151 * @brief Append a byte to the @ref UsefulOutBuf
1152 *
1153 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1154 * @param[in] byte Bytes to append.
1155 *
1156 * See UsefulOutBuf_InsertByte() for details. This does the same
1157 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001158 */
1159static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1160 uint8_t byte);
1161
1162
1163/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001164 * @brief Append an integer to the @ref UsefulOutBuf
1165 *
1166 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1167 * @param[in] uInteger16 Integer to append.
1168 *
1169 * See UsefulOutBuf_InsertUint16() for details. This does the same
1170 * with the insertion point at the end of the valid data.
1171 *
1172 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001173 */
1174static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1175 uint16_t uInteger16);
1176
1177
1178/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001179 * @brief Append an integer to the @ref UsefulOutBuf
1180 *
1181 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1182 * @param[in] uInteger32 Integer to append.
1183 *
1184 * See UsefulOutBuf_InsertUint32() for details. This does the same
1185 * with the insertion point at the end of the valid data.
1186 *
1187 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001188 */
1189static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1190 uint32_t uInteger32);
1191
1192
1193/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001194 * @brief Append an integer to the @ref UsefulOutBuf
1195 *
1196 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1197 * @param[in] uInteger64 Integer to append.
1198 *
1199 * See UsefulOutBuf_InsertUint64() for details. This does the same
1200 * with the insertion point at the end of the valid data.
1201 *
1202 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001203 */
1204static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1205 uint64_t uInteger64);
1206
1207
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001208#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001209/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001210 * @brief Append a @c float to the @ref UsefulOutBuf
1211 *
1212 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1213 * @param[in] f @c float to append.
1214 *
1215 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1216 * the insertion point at the end of the valid data.
1217 *
1218 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001219 */
1220static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1221 float f);
1222
1223
1224/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001225 * @brief Append a @c double to the @ref UsefulOutBuf
1226 *
1227 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1228 * @param[in] d @c double to append.
1229 *
1230 * See UsefulOutBuf_InsertDouble() for details. This does the same
1231 * with the insertion point at the end of the valid data.
1232 *
1233 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001234 */
1235static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1236 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001237#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001238
1239
1240/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001241 * @brief Returns the current error status.
1242 *
1243 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1244 *
1245 * @return 0 if all OK, 1 on error.
1246 *
1247 * This returns the error status since a call to either
1248 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1249 * goes into the error state, it will stay until one of those
1250 * functions is called.
1251 *
1252 * Possible error conditions are:
1253 * - bytes to be inserted will not fit
1254 * - insertion point is out of buffer or past valid data
1255 * - current position is off end of buffer (probably corrupted or uninitialized)
1256 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001257 */
1258static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1259
1260
1261/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001262 * @brief Returns number of bytes unused used in the output buffer.
1263 *
1264 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1265 *
1266 * @return Number of unused bytes or zero.
1267 *
1268 * Because of the error handling strategy and checks in
1269 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1270 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001271 */
1272static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1273
1274
1275/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001276 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1277 *
1278 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1279 * @param[in] uLen Number of bytes for which to check
1280 *
1281 * @return 1 if @c uLen bytes will fit, 0 if not.
1282 *
1283 * Because of the error handling strategy and checks in
1284 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1285 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001286 */
1287static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1288
1289
1290 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001291 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1292 *
1293 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1294 *
1295 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1296 *
1297 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1298 * just calculating the length of the encoded data.
1299 */
Michael Eckel5c531332020-03-02 01:35:30 +01001300static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1301
1302
1303/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001304 * @brief Returns pointer and length of the output buffer not yet used.
1305 *
1306 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1307 *
1308 * @return pointer and length of output buffer not used.
1309 *
1310 * This is an escape that allows the caller to write directly
1311 * to the output buffer without any checks. This doesn't
1312 * change the output buffer or state. It just returns a pointer
1313 * and length of the bytes remaining.
1314 *
1315 * This is useful to avoid having the bytes to be added all
1316 * in a contiguous buffer. Its use can save memory. A good
1317 * example is in the COSE encrypt implementation where
1318 * the output of the symmetric cipher can go directly
1319 * into the output buffer, rather than having to go into
1320 * an intermediate buffer.
1321 *
1322 * See UsefulOutBuf_Advance() which is used to tell
1323 * UsefulOutBuf how much was written.
1324 *
1325 * Warning: this bypasses the buffer safety provided by
1326 * UsefulOutBuf!
1327 */
1328static inline UsefulBuf
1329UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1330
1331
1332/**
1333 * @brief Advance the amount output assuming it was written by the caller.
1334 *
1335 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1336 * @param[in] uAmount The amount to advance.
1337 *
1338 * This advances the position in the output buffer
1339 * by \c uAmount. This assumes that the
1340 * caller has written \c uAmount to the pointer obtained
1341 * with UsefulOutBuf_GetOutPlace().
1342 *
1343 * Warning: this bypasses the buffer safety provided by
1344 * UsefulOutBuf!
1345 */
1346void
1347UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1348
1349
1350/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001351 * @brief Returns the resulting valid data in a UsefulOutBuf
1352 *
1353 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1354 *
1355 * @return The valid data in @ref UsefulOutBuf or
1356 * @ref NULLUsefulBufC if there was an error adding data.
1357 *
1358 * The storage for the returned data is the @c Storage parameter
1359 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1360 *
1361 * This can be called anytime and many times to get intermediate
1362 * results. It doesn't change the data or reset the current position,
1363 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001364 */
1365UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1366
1367
1368/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001369 * @brief Copies the valid data into a supplied buffer
1370 *
1371 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1372 * @param[out] Dest The destination buffer to copy into.
1373 *
1374 * @return Pointer and length of copied data or @c NULLUsefulBufC
1375 * if it will not fit in the @c Dest buffer or the error
1376 * state was entered.
1377 *
1378 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1379 * data to @c Dest.
1380 */
Michael Eckel5c531332020-03-02 01:35:30 +01001381UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1382
1383
1384
1385
1386/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001387 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1388 * for parsing data received. Initialize it with the data from the
1389 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1390 * get data chunks of various types. A position cursor is maintained
1391 * internally.
1392 *
1393 * As long as the functions here are used, there will never be any
1394 * reference off the end of the given buffer (except
1395 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1396 * called incorrectly, an attempt is made to seek off the end of the
1397 * buffer or such. This makes it easier to write safe and correct
1398 * code. For example, the QCBOR decoder implementation is safer and
1399 * easier to review through its use of @ref UsefulInputBuf.
1400 *
1401 * @ref UsefulInputBuf maintains an internal error state. The
1402 * intended use is fetching data chunks without any error checks until
1403 * the end. If there was any error, such as an attempt to fetch data
1404 * off the end, the error state is entered and no further data will be
1405 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1406 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1407 * null is not dereferenced, the error check can be put off until the
1408 * end, simplifying the calling code.
1409 *
1410 * The integer and float parsing expects network byte order (big
1411 * endian). Network byte order is what is used by TCP/IP, CBOR and
1412 * most internet protocols.
1413 *
1414 * Lots of inline functions are used to keep code size down. The
1415 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1416 * code size a lot. The only non-inline code is
1417 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1418 * @ref UsefulInputBuf doesn't add much code for all the messy
1419 * hard-to-get right issues with parsing binary protocols in C that it
1420 * solves.
1421 *
1422 * The parse context size is:
1423 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1424 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001425 */
1426typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001427 /* PRIVATE DATA STRUCTURE */
1428 UsefulBufC UB; /* Data being parsed */
1429 size_t cursor; /* Current offset in data being parse */
1430 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1431 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001432} UsefulInputBuf;
1433
1434#define UIB_MAGIC (0xB00F)
1435
1436
1437/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001438 * @brief Initialize the @ref UsefulInputBuf structure before use.
1439 *
1440 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1441 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001442 */
1443static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1444
1445
1446/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001447 * @brief Returns current position in input buffer.
1448 *
1449 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1450 *
1451 * @return Integer position of the cursor.
1452 *
1453 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001454 */
1455static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1456
1457
1458/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001459 * @brief Sets the current position in input buffer.
1460 *
1461 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1462 * @param[in] uPos Position to set to.
1463 *
1464 * If the position is off the end of the input buffer, the error state
1465 * is entered.
1466 *
1467 * Seeking to a valid position in the buffer will not reset the error
1468 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001469 */
1470static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1471
1472
1473/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001474 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1475 * the unconsumed bytes.
1476 *
1477 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1478 *
1479 * @return Number of bytes unconsumed or 0 on error.
1480 *
1481 * Returns 0 if the cursor is invalid or corruption of the
1482 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001483 */
1484static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1485
1486
1487/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001488 * @brief Check if there are unconsumed bytes.
1489 *
1490 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1491 * @param[in] uLen Number of bytes to check availability for.
1492 *
1493 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001494 */
1495static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1496
1497
1498/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001499 * @brief Convert a pointer to an offset with bounds checking.
1500 *
1501 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1502 * @param[in] p Pointer to convert to offset.
1503 *
1504 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1505 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001506static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1507
1508
1509/**
1510 * @brief Convert an offset to a pointer with bounds checking.
1511 *
1512 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1513 * @param[in] uOffset Offset in @c pUInBuf.
1514 *
1515 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1516 */
1517static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001518
1519
1520/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001521 * @brief Get pointer to bytes out of the input buffer.
1522 *
1523 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1524 * @param[in] uNum Number of bytes to get.
1525 *
1526 * @return Pointer to bytes.
1527 *
1528 * This consumes @c uNum bytes from the input buffer. This returns a
1529 * pointer to the start of the @c uNum bytes.
1530 *
1531 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1532 * returned and the error state is entered.
1533 *
1534 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001535 */
1536const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1537
1538
1539/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001540 * @brief Get @ref UsefulBuf out of the input buffer.
1541 *
1542 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1543 * @param[in] uNum Number of bytes to get.
1544 *
1545 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1546 *
1547 * This consumes @c uNum bytes from the input buffer and returns the
1548 * pointer and length for them as a @ref UsefulBufC. The length
1549 * returned will always be @c uNum. The position cursor is advanced by
1550 * @c uNum bytes.
1551 *
1552 * If there are not @c uNum bytes in the input buffer, @ref
1553 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001554 */
1555static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1556
1557
1558/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001559 * @brief Get a byte out of the input buffer.
1560 *
1561 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1562 *
1563 * @return The byte.
1564 *
1565 * This consumes 1 byte from the input buffer, returns it and advances
1566 * the position cursor by 1.
1567 *
1568 * If there is not 1 byte in the buffer, 0 will be returned for the
1569 * byte and the error state is entered. To know if the 0 returned was
1570 * in error or the real value, the error state must be checked. If
1571 * possible, put this off until all values are retrieved to have
1572 * smaller and simpler code, but if not possible
1573 * UsefulInputBuf_GetError() can be called. Also, in the error state
1574 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1575 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001576 */
1577static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1578
1579
1580/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001581 * @brief Get a @c uint16_t out of the input buffer.
1582 *
1583 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1584 *
1585 * @return The @c uint16_t.
1586 *
1587 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1588 * a @c uint16_t and two bytes are consumed.
1589 *
1590 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001591 */
1592static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1593
1594
1595/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001596 * @brief Get a @c uint32_t out of the input buffer.
1597 *
1598 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1599 *
1600 * @return The @c uint32_t.
1601 *
1602 * See UsefulInputBuf_GetByte(). This works the same, except it
1603 * returns a @c uint32_t and four bytes are consumed.
1604 *
1605 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001606 */
1607static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1608
1609
1610/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001611 * @brief Get a @c uint64_t out of the input buffer.
1612 *
1613 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1614 *
1615 * @return The uint64_t.
1616 *
1617 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1618 * a @c uint64_t and eight bytes are consumed.
1619 *
1620 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001621 */
1622static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1623
1624
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001625#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001626/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001627 * @brief Get a float out of the input buffer.
1628 *
1629 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1630 *
1631 * @return The float.
1632 *
1633 * See UsefulInputBuf_GetByte(). This works the same, except it
1634 * returns a float and four bytes are consumed.
1635 *
1636 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001637 */
1638static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1639
1640
1641/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001642 * @brief Get a double out of the input buffer.
1643 *
1644 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1645 *
1646 * @return The double.
1647 *
1648 * See UsefulInputBuf_GetByte(). This works the same, except it
1649 * returns a double and eight bytes are consumed.
1650 *
1651 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001652 */
1653static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001654#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001655
1656
1657/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001658 * @brief Get the error status.
1659 *
1660 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1661 *
1662 * @return 0 if not in the error state, 1 if in the error state.
1663 *
1664 * This returns whether the @ref UsefulInputBuf is in the
1665 * error state or not.
1666 *
1667 * The error state is entered for one of these reasons:
1668 * - Attempt to fetch data past the end of the buffer
1669 * - Attempt to seek to a position past the end of the buffer
1670 * - Attempt to get data from an uninitialized or corrupt instance
1671 * of @ref UsefulInputBuf
1672 *
1673 * Once in the error state, it can only be cleared by calling
1674 * UsefulInputBuf_Init().
1675 *
1676 * For many use cases, it is possible to only call this once after all
1677 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1678 * possible if no reference to the data returned are needed before the
1679 * error state is checked.
1680 *
1681 * In some cases UsefulInputBuf_GetUsefulBuf() or
1682 * UsefulInputBuf_GetBytes() can stand in for this because they return
1683 * @c NULL if the error state has been entered. (The others can't stand
1684 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001685 */
1686static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1687
1688
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001689/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001690 * @brief Gets the input buffer length.
1691 *
1692 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1693 *
1694 * @return The length of the input buffer.
1695 *
1696 * This returns the length of the input buffer set by
1697 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001698 */
1699static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1700
1701
1702/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001703 * @brief Alters the input buffer length (use with caution).
1704 *
1705 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1706 * @param[in] uNewLen The new length of the input buffer.
1707 *
1708 * This alters the internal remembered length of the input buffer set
1709 * when UsefulInputBuf_Init() was called.
1710 *
1711 * The new length given here should always be equal to or less than
1712 * the length given when UsefulInputBuf_Init() was called. Making it
1713 * larger allows @ref UsefulInputBuf to run off the input buffer.
1714 *
1715 * The typical use is to set a length shorter than that when
1716 * initialized to constrain parsing. If
1717 * UsefulInputBuf_GetBufferLength() was called before this, then the
1718 * original length can be restored with another call to this.
1719 *
1720 * This should be used with caution. It is the only
1721 * @ref UsefulInputBuf method that can violate the safety of input
1722 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001723 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001724static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001725
1726
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001727
1728
Michael Eckel5c531332020-03-02 01:35:30 +01001729/*----------------------------------------------------------
1730 Inline implementations.
1731 */
1732static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1733{
1734 return !UB.ptr;
1735}
1736
1737
1738static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1739{
1740 return !UB.ptr;
1741}
1742
1743
1744static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1745{
1746 return !UB.len;
1747}
1748
1749
1750static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1751{
1752 return !UB.len;
1753}
1754
1755
1756static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1757{
1758 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1759}
1760
1761
1762static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1763{
1764 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1765}
1766
1767
1768static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1769{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001770 UsefulBufC UBC;
1771 UBC.ptr = UB.ptr;
1772 UBC.len = UB.len;
1773
1774 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001775}
1776
Michael Eckel5c531332020-03-02 01:35:30 +01001777static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1778{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001779 UsefulBuf UB;
1780
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001781 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001782 * the one place in UsefulBuf where it needs to be quieted.
1783 */
1784 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001785
1786 UB.len = UBC.len;
1787
1788 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001789}
1790
1791
1792static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1793{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001794 UsefulBufC UBC;
1795 UBC.ptr = szString;
1796 UBC.len = strlen(szString);
1797 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001798}
1799
1800
1801static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1802{
1803 return UsefulBuf_CopyOffset(Dest, 0, Src);
1804}
1805
1806
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001807static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001808{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001809 memset(Dest.ptr, value, Dest.len);
1810
1811 UsefulBufC UBC;
1812 UBC.ptr = Dest.ptr;
1813 UBC.len = Dest.len;
1814
1815 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001816}
1817
1818
1819static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1820{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001821 UsefulBufC UBC;
1822 UBC.ptr = ptr;
1823 UBC.len = len;
1824 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001825}
1826
1827
1828static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1829{
1830 if(uAmount > UB.len) {
1831 return NULLUsefulBufC;
1832 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001833 UsefulBufC UBC;
1834
1835 UBC.ptr = UB.ptr;
1836 UBC.len = uAmount;
1837
1838 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001839}
1840
1841
1842static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1843{
1844 UsefulBufC ReturnValue;
1845
1846 if(uAmount > UB.len) {
1847 ReturnValue = NULLUsefulBufC;
1848 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001849 ReturnValue.ptr = NULL;
1850 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001851 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001852 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1853 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001854 }
1855
1856 return ReturnValue;
1857}
1858
1859
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001860static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1861{
1862 if(UB.ptr == NULL) {
1863 return SIZE_MAX;
1864 }
1865
1866 if(p < UB.ptr) {
1867 /* given pointer is before start of buffer */
1868 return SIZE_MAX;
1869 }
1870
Laurence Lundblade3eead482023-12-16 20:53:22 -07001871 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001872 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001873
1874 if(uOffset >= UB.len) {
1875 /* given pointer is off the end of the buffer */
1876 return SIZE_MAX;
1877 }
1878
1879 return uOffset;
1880}
1881
Michael Eckel5c531332020-03-02 01:35:30 +01001882
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001883static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
1884{
1885 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
1886 return NULL;
1887 }
1888
1889 return (const uint8_t *)UB.ptr + uOffset;
1890}
1891
1892
1893
1894
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001895#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001896static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1897{
1898 uint32_t u32;
1899 memcpy(&u32, &f, sizeof(uint32_t));
1900 return u32;
1901}
1902
1903static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1904{
1905 uint64_t u64;
1906 memcpy(&u64, &d, sizeof(uint64_t));
1907 return u64;
1908}
1909
1910static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1911{
1912 double d;
1913 memcpy(&d, &u64, sizeof(uint64_t));
1914 return d;
1915}
1916
1917static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1918{
1919 float f;
1920 memcpy(&f, &u32, sizeof(uint32_t));
1921 return f;
1922}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001923#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001924
1925
1926
1927
1928static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1929{
1930 pMe->data_len = 0;
1931 pMe->err = 0;
1932}
1933
1934
1935static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1936{
1937 return pMe->data_len;
1938}
1939
1940
1941static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1942{
1943 return 0 == pMe->data_len;
1944}
1945
1946
1947static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1948 const void *pBytes,
1949 size_t uLen,
1950 size_t uPos)
1951{
1952 UsefulBufC Data = {pBytes, uLen};
1953 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1954}
1955
1956
1957static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1958 const char *szString,
1959 size_t uPos)
1960{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001961 UsefulBufC UBC;
1962 UBC.ptr = szString;
1963 UBC.len = strlen(szString);
1964
1965 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001966}
1967
1968
1969static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1970 uint8_t byte,
1971 size_t uPos)
1972{
1973 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1974}
1975
1976
1977static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1978 uint16_t uInteger16,
1979 size_t uPos)
1980{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001981 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001982
1983 const void *pBytes;
1984
1985#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1986 pBytes = &uInteger16;
1987
1988#elif defined(USEFULBUF_CONFIG_HTON)
1989 uint16_t uTmp = htons(uInteger16);
1990 pBytes = &uTmp;
1991
1992#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1993 uint16_t uTmp = __builtin_bswap16(uInteger16);
1994 pBytes = &uTmp;
1995
1996#else
1997 uint8_t aTmp[2];
1998
1999 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2000 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2001
2002 pBytes = aTmp;
2003#endif
2004
2005 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2006}
2007
2008
2009static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2010 uint32_t uInteger32,
2011 size_t uPos)
2012{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002013 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002014
2015 const void *pBytes;
2016
2017#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2018 pBytes = &uInteger32;
2019
2020#elif defined(USEFULBUF_CONFIG_HTON)
2021 uint32_t uTmp = htonl(uInteger32);
2022 pBytes = &uTmp;
2023
2024#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2025 uint32_t uTmp = __builtin_bswap32(uInteger32);
2026
2027 pBytes = &uTmp;
2028
2029#else
2030 uint8_t aTmp[4];
2031
2032 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2033 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2034 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2035 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2036
2037 pBytes = aTmp;
2038#endif
2039
2040 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2041}
2042
2043static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002044 uint64_t uInteger64,
2045 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002046{
2047 const void *pBytes;
2048
2049#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002050 /* We have been told explicitly we are running on a big-endian
2051 * machine. Network byte order is big endian, so just copy. There
2052 * is no issue with alignment here because uInteger64 is always
2053 * aligned (and it doesn't matter if pBytes is aligned).
2054 */
Michael Eckel5c531332020-03-02 01:35:30 +01002055 pBytes = &uInteger64;
2056
2057#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002058 /* Use system function to handle big- and little-endian. This works
2059 * on both big- and little-endian machines, but hton() is not
2060 * always available or in a standard place so it is not used by
2061 * default. With some compilers and CPUs the code for this is very
2062 * compact through use of a special swap instruction and on
2063 * big-endian machines hton() will reduce to nothing.
2064 */
Michael Eckel5c531332020-03-02 01:35:30 +01002065 uint64_t uTmp = htonll(uInteger64);
2066
2067 pBytes = &uTmp;
2068
2069#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002070 /* Use built-in function for byte swapping. This usually compiles
2071 * to an efficient special byte swap instruction. Unlike hton() it
2072 * does not do this conditionally on the CPU endianness, so this
2073 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2074 */
Michael Eckel5c531332020-03-02 01:35:30 +01002075 uint64_t uTmp = __builtin_bswap64(uInteger64);
2076
2077 pBytes = &uTmp;
2078
2079#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002080 /* Default which works on every CPU with no dependency on anything
2081 * from the CPU, compiler, libraries or OS. This always works, but
2082 * it is usually a little larger and slower than hton().
2083 */
Michael Eckel5c531332020-03-02 01:35:30 +01002084 uint8_t aTmp[8];
2085
2086 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2087 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2088 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2089 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2090 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2091 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2092 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2093 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2094
2095 pBytes = aTmp;
2096#endif
2097
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002098 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002099 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2100}
2101
2102
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002103#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002104static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2105 float f,
2106 size_t uPos)
2107{
2108 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2109}
2110
2111
2112static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2113 double d,
2114 size_t uPos)
2115{
2116 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2117}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002118#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002119
2120
2121static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2122 UsefulBufC NewData)
2123{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002124 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002125 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2126}
2127
2128
2129static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2130 const void *pBytes,
2131 size_t uLen)
2132{
2133 UsefulBufC Data = {pBytes, uLen};
2134 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2135}
2136
2137
2138static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2139 const char *szString)
2140{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002141 UsefulBufC UBC;
2142 UBC.ptr = szString;
2143 UBC.len = strlen(szString);
2144
2145 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002146}
2147
2148
2149static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2150 uint8_t byte)
2151{
2152 UsefulOutBuf_AppendData(pMe, &byte, 1);
2153}
2154
2155
2156static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2157 uint16_t uInteger16)
2158{
2159 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2160}
2161
2162static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2163 uint32_t uInteger32)
2164{
2165 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2166}
2167
2168
2169static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2170 uint64_t uInteger64)
2171{
2172 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2173}
2174
2175
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002176#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002177static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2178 float f)
2179{
2180 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2181}
2182
2183
2184static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2185 double d)
2186{
2187 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2188}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002189#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002190
2191
2192static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2193{
2194 return pMe->err;
2195}
2196
2197
2198static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2199{
2200 return pMe->UB.len - pMe->data_len;
2201}
2202
2203
2204static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2205{
2206 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2207}
2208
2209
2210static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2211{
2212 return pMe->UB.ptr == NULL;
2213}
2214
2215
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002216static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2217{
2218 UsefulBuf R;
2219
2220 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002221 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002222 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2223 } else {
2224 R.ptr = NULL;
2225 }
2226
2227 return R;
2228}
2229
2230
2231
Michael Eckel5c531332020-03-02 01:35:30 +01002232
2233static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2234{
2235 pMe->cursor = 0;
2236 pMe->err = 0;
2237 pMe->magic = UIB_MAGIC;
2238 pMe->UB = UB;
2239}
2240
2241static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2242{
2243 return pMe->cursor;
2244}
2245
2246
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002247static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002248{
2249 return pMe->UB.len;
2250}
2251
2252
Michael Eckel5c531332020-03-02 01:35:30 +01002253static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2254{
2255 if(uPos > pMe->UB.len) {
2256 pMe->err = 1;
2257 } else {
2258 pMe->cursor = uPos;
2259 }
2260}
2261
2262
2263static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2264{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002265 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002266
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002267 /* Magic number is messed up. Either the structure got overwritten
2268 * or was never initialized.
2269 */
Michael Eckel5c531332020-03-02 01:35:30 +01002270 if(pMe->magic != UIB_MAGIC) {
2271 return 0;
2272 }
2273
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002274 /* The cursor is off the end of the input buffer given.
2275 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002276 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002277 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002278 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002279 */
Michael Eckel5c531332020-03-02 01:35:30 +01002280 if(pMe->cursor > pMe->UB.len) {
2281 return 0;
2282 }
2283
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002284 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002285 return pMe->UB.len - pMe->cursor;
2286}
2287
2288
2289static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2290{
2291 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2292}
2293
2294
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002295static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2296{
2297 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2298}
2299
2300
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002301static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2302 {
2303 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2304 }
2305
2306
Michael Eckel5c531332020-03-02 01:35:30 +01002307static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2308{
2309 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2310 if(!pResult) {
2311 return NULLUsefulBufC;
2312 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002313 UsefulBufC UBC;
2314 UBC.ptr = pResult;
2315 UBC.len = uNum;
2316 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002317 }
2318}
2319
2320
2321static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2322{
2323 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2324
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002325 /* The ternary operator is subject to integer promotion, because
2326 * the operands are smaller than int, so cast back to uint8_t is
2327 * needed to be completely explicit about types (for static
2328 * analyzers).
2329 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002330 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002331}
2332
2333static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2334{
2335 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2336
2337 if(!pResult) {
2338 return 0;
2339 }
2340
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002341 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002342#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2343 uint16_t uTmp;
2344 memcpy(&uTmp, pResult, sizeof(uint16_t));
2345
2346#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2347 return uTmp;
2348
2349#elif defined(USEFULBUF_CONFIG_HTON)
2350 return ntohs(uTmp);
2351
2352#else
2353 return __builtin_bswap16(uTmp);
2354
2355#endif
2356
2357#else
2358
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002359 /* The operations here are subject to integer promotion because the
2360 * operands are smaller than int. They will be promoted to unsigned
2361 * int for the shift and addition. The cast back to uint16_t is is
2362 * needed to be completely explicit about types (for static
2363 * analyzers).
2364 */
Michael Eckel5c531332020-03-02 01:35:30 +01002365 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2366
2367#endif
2368}
2369
2370
2371static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2372{
2373 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2374
2375 if(!pResult) {
2376 return 0;
2377 }
2378
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002379 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002380#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2381 uint32_t uTmp;
2382 memcpy(&uTmp, pResult, sizeof(uint32_t));
2383
2384#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2385 return uTmp;
2386
2387#elif defined(USEFULBUF_CONFIG_HTON)
2388 return ntohl(uTmp);
2389
2390#else
2391 return __builtin_bswap32(uTmp);
2392
2393#endif
2394
2395#else
2396 return ((uint32_t)pResult[0]<<24) +
2397 ((uint32_t)pResult[1]<<16) +
2398 ((uint32_t)pResult[2]<<8) +
2399 (uint32_t)pResult[3];
2400#endif
2401}
2402
2403
2404static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2405{
2406 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2407
2408 if(!pResult) {
2409 return 0;
2410 }
2411
2412#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002413 /* pResult will probably not be aligned. This memcpy() moves the
2414 * bytes into a temp variable safely for CPUs that can or can't do
2415 * unaligned memory access. Many compilers will optimize the
2416 * memcpy() into a simple move instruction.
2417 */
Michael Eckel5c531332020-03-02 01:35:30 +01002418 uint64_t uTmp;
2419 memcpy(&uTmp, pResult, sizeof(uint64_t));
2420
2421#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002422 /* We have been told expliclity this is a big-endian CPU. Since
2423 * network byte order is big-endian, there is nothing to do.
2424 */
Michael Eckel5c531332020-03-02 01:35:30 +01002425
2426 return uTmp;
2427
2428#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002429 /* We have been told to use ntoh(), the system function to handle
2430 * big- and little-endian. This works on both big- and
2431 * little-endian machines, but ntoh() is not always available or in
2432 * a standard place so it is not used by default. On some CPUs the
2433 * code for this is very compact through use of a special swap
2434 * instruction.
2435 */
Michael Eckel5c531332020-03-02 01:35:30 +01002436
2437 return ntohll(uTmp);
2438
2439#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002440 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2441 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2442 * __builtin_bswap64() and friends are not conditional on CPU
2443 * endianness so this must only be used on little-endian machines.
2444 */
Michael Eckel5c531332020-03-02 01:35:30 +01002445
2446 return __builtin_bswap64(uTmp);
2447
2448
2449#endif
2450
2451#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002452 /* This is the default code that works on every CPU and every
2453 * endianness with no dependency on ntoh(). This works on CPUs
2454 * that either allow or do not allow unaligned access. It will
2455 * always work, but usually is a little less efficient than ntoh().
2456 */
Michael Eckel5c531332020-03-02 01:35:30 +01002457
2458 return ((uint64_t)pResult[0]<<56) +
2459 ((uint64_t)pResult[1]<<48) +
2460 ((uint64_t)pResult[2]<<40) +
2461 ((uint64_t)pResult[3]<<32) +
2462 ((uint64_t)pResult[4]<<24) +
2463 ((uint64_t)pResult[5]<<16) +
2464 ((uint64_t)pResult[6]<<8) +
2465 (uint64_t)pResult[7];
2466#endif
2467}
2468
2469
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002470#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002471static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2472{
2473 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2474
2475 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2476}
2477
2478
2479static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2480{
2481 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2482
2483 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2484}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002485#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002486
2487
2488static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2489{
2490 return pMe->err;
2491}
2492
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002493
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002494static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002495{
2496 pMe->UB.len = uNewLen;
2497}
2498
2499
Michael Eckel5c531332020-03-02 01:35:30 +01002500#ifdef __cplusplus
2501}
2502#endif
2503
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002504#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002505
2506