blob: f3b86daa72faf26f34f6e920aa5f731e936b3197 [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07003 * Copyright (c) 2018-2024, Laurence Lundblade.
Laurence Lundblade3eead482023-12-16 20:53:22 -07004 * Copyright (c) 2021, Arm Limited. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Michael Eckel5c531332020-03-02 01:35:30 +010033
34/*============================================================================
35 FILE: UsefulBuf.h
36
37 DESCRIPTION: General purpose input and output buffers
38
39 EDIT HISTORY FOR FILE:
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44 when who what, where, why
45 -------- ---- --------------------------------------------------
Laurence Lundblade9b244a32025-01-01 12:12:17 -070046 12/31/2024 llundblade Minor documentation tweaks for Doxygen.
Laurence Lundblade68769332024-11-03 13:09:20 -080047 08/31/2024 llundblade Add UsefulBufC_NTH_BYTE().
Laurence Lundbladee2226742024-08-16 10:50:23 -070048 08/14/2024 llundblade Add UsefulOutBuf_RetrieveOutputStorage().
49 08/13/2024 llundblade Add UsefulInputBuf_RetrieveUndecodedInput().
Laurence Lundblade68769332024-11-03 13:09:20 -080050 8/10/2024 llundblade Add UsefulBuf_SkipLeading().
Laurence Lundbladee2226742024-08-16 10:50:23 -070051 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070052 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070053 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladede2e1502024-08-26 11:37:05 -070054 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070055 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
56 19/11/2023 llundblade Add UsefulOutBuf_Swap().
57 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070058 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060059 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070060 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070061 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070062 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080063 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070064 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010065 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
66 5/21/2019 llundblade #define configs for efficient endianness handling.
67 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
68 3/23/2019 llundblade Big documentation & style update. No interface
69 change.
70 3/6/2019 llundblade Add UsefulBuf_IsValue()
71 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
72 12/13/2018 llundblade Documentation improvements
73 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
74 UsefulBufC.
75 02/02/18 llundbla Full support for integers in and out; fix pointer
76 alignment bug. Incompatible change: integers
77 in/out are now in network byte order.
78 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
79 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
80 comparison for < or > for unequal length buffers.
81 Added UsefulBuf_Set() function.
82 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
83 11/13/16 llundbla Initial Version.
84
85 =============================================================================*/
86
87#ifndef _UsefulBuf_h
88#define _UsefulBuf_h
89
90
91/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070092 * Endianness Configuration
93 *
94 * This code is written so it will work correctly on big- and
95 * little-endian CPUs without configuration or any auto-detection of
96 * endianness. All code here will run correctly regardless of the
97 * endianness of the CPU it is running on.
98 *
99 * There are four C preprocessor macros that can be set with #define
100 * to explicitly configure endianness handling. Setting them can
101 * reduce code size a little and improve efficiency a little.
102 *
103 * Note that most of QCBOR is unaffected by this configuration. Its
104 * endianness handling is integrated with the code that handles
105 * alignment and preferred serialization. This configuration does
106 * affect QCBOR's (planned) implementation of integer arrays (tagged
107 * arrays) and use of the functions here to serialize or deserialize
108 * integers and floating-point values.
109 *
110 * Following is the recipe for configuring the endianness-related
111 * #defines.
112 *
113 * The first option is to not define anything. This will work fine
114 * with all CPUs, OS's and compilers. The code for encoding integers
115 * may be a little larger and slower.
116 *
117 * If your CPU is big-endian then define
118 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
119 * for big-endian CPUs. It will be small and efficient because there
120 * will be no byte swapping.
121 *
122 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
123 * OS's and compilers, but not all. On big-endian CPUs this should
124 * give the most efficient code, the same as
125 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
126 * call the system-defined byte swapping method which is presumably
127 * implemented efficiently. In some cases, this will be a dedicated
128 * byte swap instruction like Intel's bswap.
129 *
130 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
131 * little-endian, it is also good to define
132 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
133 *
134 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
135 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
136 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
137 * system-defined byte swap method. However, note
138 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
139 * this is fixed now. Often hton() and ntoh() will call the built-in
140 * __builtin_bswapXX()() function, so this size issue could affect
141 * USEFULBUF_CONFIG_HTON.
142 *
143 * Last, run the tests. They must all pass.
144 *
145 * These #define config options affect the inline implementation of
146 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
147 * also affect the 16-, 32-bit, float and double versions of these
148 * functions. Since they are inline, the size effect is not in the
149 * UsefulBuf object code, but in the calling code.
150 *
151 * Summary:
152 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
153 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
154 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
155 * handle big and little-endian with system option.
156 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
157 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200158 *
159 * It is possible to run this code in environments where using floating point is
160 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
161 * that is related to handling floating point types, along with related
162 * interfaces. This makes it possible to compile the code with the compile
163 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100164 */
165
166#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
167#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
168#endif
169
170
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700171#include <stdint.h> /* for uint8_t, uint16_t.... */
172#include <string.h> /* for strlen, memcpy, memmove, memset */
173#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100174
175
176#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700177#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100178#endif
179
180#ifdef __cplusplus
181extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700182#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700183} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700184#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100185#endif
186
187/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700188 * @file UsefulBuf.h
189 *
190 * The goal of this code is to make buffer and pointer manipulation
191 * easier and safer when working with binary data.
192 *
193 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
194 * structures are used to represent buffers rather than ad hoc
195 * pointers and lengths.
196 *
197 * With these it is possible to write code that does little or no
198 * direct pointer manipulation for copying and formatting data. For
199 * example, the QCBOR encoder was written using these and has less
200 * pointer manipulation.
201 *
202 * While it is true that object code using these functions will be a
203 * little larger and slower than a white-knuckle clever use of
204 * pointers might be, but not by that much or enough to have an effect
205 * for most use cases. For security-oriented code this is highly
206 * worthwhile. Clarity, simplicity, reviewability and are more
207 * important.
208 *
209 * There are some extra sanity and double checks in this code to help
210 * catch coding errors and simple memory corruption. They are helpful,
211 * but not a substitute for proper code review, input validation and
212 * such.
213 *
214 * This code consists of a lot of inline functions and a few that are
215 * not. It should not generate very much object code, especially with
216 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100217 */
218
219
220/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700221 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
222 * hold a pointer and length for binary data. In C99 this data
223 * structure can be passed on the stack making a lot of code cleaner
224 * than carrying around a pointer and length as two parameters.
225 *
226 * This is also conducive to secure coding practice as the length is
227 * always carried with the pointer and the convention for handling a
228 * pointer and a length is clear.
229 *
230 * While it might be possible to write buffer and pointer code more
231 * efficiently in some use cases, the thought is that unless there is
232 * an extreme need for performance (e.g., you are building a
233 * gigabit-per-second IP router), it is probably better to have
234 * cleaner code you can be most certain about the security of.
235 *
236 * The non-const @ref UsefulBuf is usually used to refer an empty
237 * buffer to be filled in. The length is the size of the buffer.
238 *
239 * The const @ref UsefulBufC is usually used to refer to some data
240 * that has been filled in. The length is amount of valid data pointed
241 * to.
242 *
243 * A common use mode is to pass a @ref UsefulBuf to a function, the
244 * function puts some data in it, then the function returns a @ref
245 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
246 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
247 * so the constness stays correct. There is no single "in,out"
248 * parameter (if there was, it would have to be non-const). Note that
249 * the pointer returned in the @ref UsefulBufC usually ends up being
250 * the same pointer passed in as a @ref UsefulBuf, though this is not
251 * striclty required.
252 *
253 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
254 * @c NULL.
255 *
256 * There are functions and macros for the following:
257 * - Initializing
258 * - Create initialized const @ref UsefulBufC from compiler literals
259 * - Create initialized const @ref UsefulBufC from NULL-terminated string
260 * - Make an empty @ref UsefulBuf on the stack
261 * - Checking whether a @ref UsefulBuf is null, empty or both
262 * - Copying, copying with offset, copying head or tail
263 * - Comparing and finding substrings
264 *
265 * See also @ref UsefulOutBuf. It is a richer structure that has both
266 * the size of the valid data and the size of the buffer.
267 *
268 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
269 * it can go on the stack and be a function parameter or return value.
270 *
271 * Another way to look at it is this. C has the NULL-terminated string
272 * as a means for handling text strings, but no means or convention
273 * for binary strings. Other languages do have such means, Rust, an
274 * efficient compiled language, for example.
275 *
276 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
277 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
278 * out like anything".
279 */
Michael Eckel5c531332020-03-02 01:35:30 +0100280typedef struct q_useful_buf_c {
281 const void *ptr;
282 size_t len;
283} UsefulBufC;
284
285
286/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700287 * This non-const @ref UsefulBuf is typically used for some allocated
288 * memory that is to be filled in. The @c len is the amount of memory,
289 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100290 */
291typedef struct q_useful_buf {
292 void *ptr;
293 size_t len;
294} UsefulBuf;
295
296
297/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700298 * A null @ref UsefulBufC is one that has no value in the same way a
299 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
300 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
301 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100302 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700303/*
304 * NULLUsefulBufC and few other macros have to be
305 * definied differently in C than C++ because there
306 * is no common construct for a literal structure.
307 *
308 * In C compound literals are used.
309 *
310 * In C++ list initalization is used. This only works
311 * in C++11 and later.
312 *
313 * Note that some popular C++ compilers can handle compound
314 * literals with on-by-default extensions, however
315 * this code aims for full correctness with strict
316 * compilers so they are not used.
317 */
318#ifdef __cplusplus
319#define NULLUsefulBufC {NULL, 0}
320#else
321#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
322#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100323
324/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700325 * A null @ref UsefulBuf is one that has no memory associated the same
326 * way @c NULL points to nothing. It does not matter what @c len is.
327 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700328#ifdef __cplusplus
329#define NULLUsefulBuf {NULL, 0}
330#else
331#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
332#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100333
334
335/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700336 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
337 *
338 * @param[in] UB The UsefulBuf to check.
339 *
340 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100341 */
342static inline int UsefulBuf_IsNULL(UsefulBuf UB);
343
344
345/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700346 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
347 *
348 * @param[in] UB The @ref UsefulBufC to check.
349 *
350 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100351 */
352static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
353
354
355/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700356 * @brief Check if a @ref UsefulBuf is empty or not.
357 *
358 * @param[in] UB The @ref UsefulBuf to check.
359 *
360 * @return 1 if it is empty, 0 if not.
361 *
362 * An "empty" @ref UsefulBuf is one that has a value and can be
363 * considered to be set, but that value is of zero length. It is
364 * empty when @c len is zero. It doesn't matter what the @c ptr is.
365 *
366 * Many uses will not need to clearly distinguish a @c NULL @ref
367 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
368 * @c len 0. However if a use of @ref UsefulBuf needs to make a
369 * distinction then @c ptr should not be @c NULL when the @ref
370 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100371 */
372static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
373
374
375/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700376 * @brief Check if a @ref UsefulBufC is empty or not.
377 *
378 * @param[in] UB The @ref UsefulBufC to check.
379 *
380 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100381 */
382static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
383
384
385/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700386 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
387 *
388 * @param[in] UB The @ref UsefulBuf to check.
389 *
390 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100391 */
392static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
393
394
395/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700396 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
397 *
398 * @param[in] UB The @ref UsefulBufC to check.
399 *
400 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100401 */
402static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
403
404
405/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700406 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
407 *
408 * @param[in] UB The @ref UsefulBuf to convert.
409 *
410 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100411 */
412static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
413
414
415/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700416 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
417 *
418 * @param[in] UBC The @ref UsefulBuf to convert.
419 *
420 * @return A non-const @ref UsefulBuf struct.
421 *
422 * Use of this is not necessary for the intended use mode of @ref
423 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
424 * created to describe a buffer that has not had any data put in
425 * it. Then the data is put in it. Then a @ref UsefulBufC is create
426 * to describe the part with the data in it. This goes from non-const
427 * to const, so this function is not needed.
428 *
429 * If the -Wcast-qual warning is enabled, this function can be used to
430 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100431 */
432static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
433
434
435/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700436 * Convert a literal string to a @ref UsefulBufC.
437 *
438 * @c szString must be a literal string that @c sizeof() works on.
439 * This is better for literal strings than UsefulBuf_FromSZ() because
440 * it generates less code. It will not work on non-literal strings.
441 *
442 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100443 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700444#ifdef __cplusplus
445#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
446#else
Michael Eckel5c531332020-03-02 01:35:30 +0100447#define UsefulBuf_FROM_SZ_LITERAL(szString) \
448 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700449#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100450
451
452/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700453 * Convert a literal byte array to a @ref UsefulBufC.
454 *
455 * @c pBytes must be a literal string that @c sizeof() works on. It
456 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100457 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700458#ifdef __cplusplus
459#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
460#else
Michael Eckel5c531332020-03-02 01:35:30 +0100461#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700462 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
463#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100464
465/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700466 * Make an automatic variable named @c name of type @ref UsefulBuf and
467 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100468 */
469#define UsefulBuf_MAKE_STACK_UB(name, size) \
470 uint8_t __pBuf##name[(size)];\
471 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
472
473
474/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700475 * Make a byte array in to a @ref UsefulBuf. This is usually used on
476 * stack variables or static variables. Also see @ref
477 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100478 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700479#ifdef __cplusplus
480#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
481#else
Michael Eckel5c531332020-03-02 01:35:30 +0100482#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700483 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
484#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100485
486
487/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700488 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
489 *
490 * @param[in] szString The string to convert.
491 *
492 * @return A @ref UsefulBufC struct.
493 *
494 * @c UsefulBufC.ptr points to the string so its lifetime must be
495 * maintained.
496 *
497 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100498 */
499static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
500
501
Laurence Lundblade9b244a32025-01-01 12:12:17 -0700502/**
503 * @brief Get the nth byte from a UsefulBufC.
504 *
505 * @param[in] UBC UsefulBufC from which to get byte
506 * @param[in] n Index of byte to get
507 *
508 * WARNING: this doesn't check that @c is within the UsefulBufC. This point
509 * of this is to have the ugly cast in just one place.
510 */
Laurence Lundblade68769332024-11-03 13:09:20 -0800511#define UsefulBufC_NTH_BYTE(UBC, n) (((const uint8_t *)(UBC.ptr))[n])
512
513
Michael Eckel5c531332020-03-02 01:35:30 +0100514/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700515 * @brief Copy one @ref UsefulBuf into another at an offset.
516 *
517 * @param[in] Dest Destination buffer to copy into.
518 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
519 * @param[in] Src The bytes to copy.
520 *
521 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
522 *
523 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
524 * size of @c Dest.
525 *
526 * This fails and returns @ref NULLUsefulBufC if the @c Src length
527 * plus @c uOffset is greater than the length of @c Dest.
528 *
529 * The results are undefined if @c Dest and @c Src overlap.
530 *
531 * This assumes that there is valid data in @c Dest up to @c
532 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
533 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100534 */
535UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
536
537
538/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700539 * @brief Copy one @ref UsefulBuf into another.
540 *
541 * @param[in] Dest The destination buffer to copy into.
542 * @param[out] Src The source to copy from.
543 *
544 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
545 * on failure.
546 *
547 * This fails if @c Src.len is greater than @c Dest.len.
548 *
549 * Note that like @c memcpy(), the pointers are not checked and this
550 * will crash rather than return @ref NULLUsefulBufC if they are @c
551 * NULL or invalid.
552 *
553 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100554 */
555static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
556
557
558/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700559 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
560 *
561 * @param[in] pDest The destination buffer to copy into.
562 * @param[in] value The value to set the bytes to.
563 *
564 * Note that like @c memset(), the pointer in @c pDest is not checked
565 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100566 */
567static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
568
569
570/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700571 * @brief Copy a pointer into a @ref UsefulBuf.
572 *
573 * @param[in,out] Dest The destination buffer to copy into.
574 * @param[in] ptr The source to copy from.
575 * @param[in] uLen Length of the source; amount to copy.
576 *
577 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
578 * on failure.
579 *
580 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
581 * than @c pDest->len.
582 *
583 * Note that like @c memcpy(), the pointers are not checked and this
584 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100585 */
586static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
587 const void *ptr,
588 size_t uLen);
589
590
591/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700592 * @brief Returns a truncation of a @ref UsefulBufC.
593 *
594 * @param[in] UB The buffer to get the head of.
595 * @param[in] uAmount The number of bytes in the head.
596 *
597 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100598 */
599static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
600
601
602/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700603 * @brief Returns bytes from the end of a @ref UsefulBufC.
604 *
605 * @param[in] UB The buffer to get the tail of.
606 * @param[in] uAmount The offset from the start where the tail is to begin.
607 *
608 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
609 * if @c uAmount is greater than the length of the @ref UsefulBufC.
610 *
611 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
612 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
613 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100614 */
615static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
616
617
618/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700619 * @brief Compare one @ref UsefulBufC to another.
620 *
621 * @param[in] UB1 The first buffer to compare.
622 * @param[in] UB2 The second buffer to compare.
623 *
624 * @return 0, positive or negative value.
625 *
626 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
627 * less than @c UB2 if it is shorter or the first byte that is not the
628 * same is less.
629 *
630 * Returns 0 if the inputs are the same.
631 *
632 * Returns a positive value if @c UB2 is less than @c UB1.
633 *
634 * All that is of significance is that the result is positive, negative
635 * or 0. (This doesn't return the difference between the first
636 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100637 */
638int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
639
640
641/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700642 * @brief Find first byte that is not a particular byte value.
643 *
644 * @param[in] UB The destination buffer for byte comparison.
645 * @param[in] uValue The byte value to compare to.
646 *
647 * @return Offset of first byte that isn't @c uValue or
648 * @c SIZE_MAX if all bytes are @c uValue.
649 *
650 * Note that unlike most comparison functions, 0
651 * does not indicate a successful comparison, so the
652 * test for match is:
653 *
654 * UsefulBuf_IsValue(...) == SIZE_MAX
655 *
656 * If @c UB is null or empty, there is no match
657 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100658 */
659size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
660
661
662/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700663 * @brief Find one @ref UsefulBufC in another.
664 *
665 * @param[in] BytesToSearch Buffer to search through.
666 * @param[in] BytesToFind Buffer with bytes to be found.
667 *
668 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100669 */
670size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
671
672
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700673/**
Laurence Lundblade68769332024-11-03 13:09:20 -0800674 * @brief Skip leading bytes of a particular value in a string.
675 *
676 * @param[in] String The input string. String.ptr must not be @c NULL.
677 * @param[in] uByte The byte value.
678 *
679 * @return Substring with leading bytes with value @c uByte removed.
680 */
681UsefulBufC UsefulBuf_SkipLeading(UsefulBufC String, uint8_t uByte);
682
683
684/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700685 * @brief Convert a pointer to an offset with bounds checking.
686 *
687 * @param[in] UB A UsefulBuf.
688 * @param[in] p Pointer to convert to offset.
689 *
690 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700691*/
692static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
693
694
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700695/**
696 * @brief Convert an offset to a pointer with bounds checking.
697 *
698 * @param[in] UB A UsefulBuf.
699 * @param[in] uOffset Offset in @c pUInBuf.
700 *
701 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
702 */
703static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
704
705
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800706#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100707/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700708#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100709
710/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
711#define MakeUsefulBufOnStack(name, size) \
712 uint8_t __pBuf##name[(size)];\
713 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
714
715/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
716#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700717 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100718
719/** Deprecated function; use UsefulBuf_Unconst() instead */
720static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
721{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700722 UsefulBuf UB;
723
Laurence Lundblade3eead482023-12-16 20:53:22 -0700724 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300725 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700726
727 UB.len = UBC.len;
728
729 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100730}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800731#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100732
733
734
735
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200736#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100737/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700738 * @brief Copy a @c float to a @c uint32_t.
739 *
740 * @param[in] f Float value to copy.
741 *
742 * @return A @c uint32_t with the float bits.
743 *
744 * Convenience function to avoid type punning, compiler warnings and
745 * such. The optimizer usually reduces this to a simple assignment. This
746 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100747 */
748static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
749
750
751/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700752 * @brief Copy a @c double to a @c uint64_t.
753 *
754 * @param[in] d Double value to copy.
755 *
756 * @return A @c uint64_t with the double bits.
757 *
758 * Convenience function to avoid type punning, compiler warnings and
759 * such. The optimizer usually reduces this to a simple assignment. This
760 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100761 */
762static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
763
764
765/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700766 * @brief Copy a @c uint32_t to a @c float.
767 *
768 * @param[in] u32 Integer value to copy.
769 *
770 * @return The value as a @c float.
771 *
772 * Convenience function to avoid type punning, compiler warnings and
773 * such. The optimizer usually reduces this to a simple assignment. This
774 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100775 */
776static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
777
778
779/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700780 * @brief Copy a @c uint64_t to a @c double.
781 *
782 * @param[in] u64 Integer value to copy.
783 *
784 * @return The value as a @c double.
785 *
786 * Convenience function to avoid type punning, compiler warnings and
787 * such. The optimizer usually reduces this to a simple assignment. This
788 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100789 */
790static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200791#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100792
793
794
795
796/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700797 * UsefulOutBuf is a structure and functions (an object) for
798 * serializing data into a buffer to encode for a network protocol or
799 * write data to a file.
800 *
801 * The main idea is that all the pointer manipulation is performed by
802 * @ref UsefulOutBuf functions so the caller doesn't have to do any
803 * pointer manipulation. The pointer manipulation is centralized.
804 * This code has been reviewed and written carefully so it
805 * spares the caller of much of this work and results in safer code
806 * with less effort.
807 *
808 * The @ref UsefulOutBuf methods that add data to the output buffer
809 * always check the length and will never write off the end of the
810 * output buffer. If an attempt to add data that will not fit is made,
811 * an internal error flag will be set and further attempts to add data
812 * will not do anything.
813 *
814 * There is no way to ever write off the end of that buffer when
815 * calling the @c UsefulOutBuf_AddXxx() and
816 * @c UsefulOutBuf_InsertXxx() functions.
817 *
818 * The functions to add data do not report success of failure. The
819 * caller only needs to check for an error in the final call, either
820 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
821 * result. This makes the calling code cleaner.
822 *
823 * There is a utility function to get the error status anytime along
824 * the way for a special circumstance. There are functions to see how
825 * much room is left and see if some data will fit too, but their use
826 * is generally unnecessary.
827 *
828 * The general call flow is:
829 *
830 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
831 * buffer given to it can be from the heap, stack or
832 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
833 * macro that makes a buffer on the stack and initializes it.
834 *
835 * - Call methods like UsefulOutBuf_InsertString(),
836 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
837 * to output data. The append calls add data to the end of the
838 * valid data. The insert calls take a position argument.
839 *
840 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
841 * there were no errors and to get the serialized output bytes.
842 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700843 * @ref UsefulOutBuf can be used in a mode to calculate the size of
844 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700845 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700846 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700847 *
848 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700849 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700850 *
851 * The possible errors are:
852 *
853 * - The @ref UsefulOutBuf was not initialized or was corrupted.
854 *
855 * - An attempt was made to add data that will not fit.
856 *
857 * - An attempt was made to insert data at a position beyond the end of
858 * the buffer.
859 *
860 * - An attempt was made to insert data at a position beyond the valid
861 * data in the buffer.
862 *
863 * Some inexpensive simple sanity checks are performed before every
864 * data addition to guard against use of an uninitialized or corrupted
865 * UsefulOutBuf.
866 *
867 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
868 * encoder has almost no pointer manipulation in it, is easier to
869 * read, and easier to review.
870 *
871 * A @ref UsefulOutBuf is small and can go on the stack:
872 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
873 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100874 */
875typedef struct useful_out_buf {
Laurence Lundblade9b244a32025-01-01 12:12:17 -0700876 /** @private Memory that is being output to */
877 UsefulBuf UB;
878 /** @private length of the valid data, the insertion point */
879 size_t data_len;
880 /** @private Magic number to detect lack of initalization/corruption */
881 uint16_t magic;
882 /** @private Used to detect corruption and lack of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100883 uint8_t err;
884} UsefulOutBuf;
885
886
887/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700888 * This is a @ref UsefulBuf value that can be passed to
889 * UsefulOutBuf_Init() to have it calculate the size of the output
890 * buffer needed. Pass this for @c Storage, call all the append and
891 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
892 * returned @ref UsefulBufC has the size.
893 *
894 * As one can see, this is just a NULL pointer and very large size.
Laurence Lundblade9b244a32025-01-01 12:12:17 -0700895 * The NULL pointer tells @ref UsefulOutBuf to not copy any data.
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700896 */
897#ifdef __cplusplus
898#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
899#else
900#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
901#endif
902
903
904/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700905 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700906 *
907 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
908 * @param[in] Storage Buffer to output into.
909 *
910 * This initializes the @ref UsefulOutBuf with storage, sets the
911 * current position to the beginning of the buffer and clears the
912 * error state.
913 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700914 * See @ref SizeCalculateUsefulBuf for instructions on how to
915 * initialize a @ref UsefulOutBuf to calculate the size that would be
916 * output without actually outputting.
917 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700918 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100919 */
920void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
921
922
923/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700924 * Convenience macro to make a @ref UsefulOutBuf on the stack and
925 * initialize it with a stack buffer of the given size. The variable
926 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100927 */
928#define UsefulOutBuf_MakeOnStack(name, size) \
929 uint8_t __pBuf##name[(size)];\
930 UsefulOutBuf name;\
931 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
932
933
934/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700935 * @brief Reset a @ref UsefulOutBuf for re use.
936 *
937 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
938 *
939 * This sets the amount of data in the output buffer to none and
940 * clears the error state.
941 *
942 * The output buffer is still the same one and size as from the
943 * UsefulOutBuf_Init() call.
944 *
945 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100946 */
947static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
948
949
950/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700951 * @brief Returns position of end of data in the @ref UsefulOutBuf.
952 *
953 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
954 *
955 * @return position of end of data.
956 *
957 * On a freshly initialized @ref UsefulOutBuf with no data added, this
958 * will return 0. After 10 bytes have been added, it will return 10
959 * and so on.
960 *
961 * Generally, there is no need to call this for most uses of @ref
962 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100963 */
964static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
965
966
967/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700968 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
969 *
970 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
971 *
972 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100973 */
974static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
975
976
977/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700978 * @brief Inserts bytes into the @ref UsefulOutBuf.
979 *
980 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
981 * @param[in] NewData The bytes to insert.
982 * @param[in] uPos Index in output buffer at which to insert.
983 *
984 * @c NewData is the pointer and length for the bytes to be added to
985 * the output buffer. There must be room in the output buffer for all
986 * of @c NewData or an error will occur.
987 *
988 * The insertion point must be between 0 and the current valid
989 * data. If not, an error will occur. Appending data to the output
990 * buffer is achieved by inserting at the end of the valid data. This
991 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
992 *
993 * When insertion is performed, the bytes between the insertion point
994 * and the end of data previously added to the output buffer are slid
995 * to the right to make room for the new data.
996 *
997 * Overlapping buffers are OK. @c NewData can point to data in the
998 * output buffer.
999 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -07001000 * NewData.len may be 0 in which case nothing will be inserted.
1001 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001002 * If an error occurs, an error state is set in the @ref
1003 * UsefulOutBuf. No error is returned. All subsequent attempts to add
1004 * data will do nothing.
1005 *
1006 * The intended use is that all additions are made without checking
1007 * for an error. The error will be taken into account when
1008 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
1009 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +01001010 */
1011void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
1012 UsefulBufC NewData,
1013 size_t uPos);
1014
1015
1016/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001017 * @brief Insert a data buffer into the @ref UsefulOutBuf.
1018 *
1019 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1020 * @param[in] pBytes Pointer to the bytes to insert
1021 * @param[in] uLen Length of the bytes to insert
1022 * @param[in] uPos Index in output buffer at which to insert
1023 *
1024 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
1025 * the difference being a pointer and length is passed in rather than an
1026 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +01001027 */
1028static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
1029 const void *pBytes,
1030 size_t uLen,
1031 size_t uPos);
1032
1033
1034/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001035 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1036 *
1037 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1038 * @param[in] szString NULL-terminated string to insert.
1039 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001040 */
1041static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1042 const char *szString,
1043 size_t uPos);
1044
1045
1046/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001047 * @brief Insert a byte into the @ref UsefulOutBuf.
1048 *
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001049 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001050 * @param[in] byte Bytes to insert.
1051 * @param[in] uPos Index in output buffer at which to insert.
1052 *
1053 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1054 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001055 */
1056static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1057 uint8_t byte,
1058 size_t uPos);
1059
1060
1061/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001062 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1063 *
1064 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1065 * @param[in] uInteger16 Integer to insert.
1066 * @param[in] uPos Index in output buffer at which to insert.
1067 *
1068 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1069 * with the difference being a two-byte integer is to be inserted.
1070 *
1071 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001072 */
1073static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1074 uint16_t uInteger16,
1075 size_t uPos);
1076
1077
1078/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001079 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1080 *
1081 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1082 * @param[in] uInteger32 Integer to insert.
1083 * @param[in] uPos Index in output buffer at which to insert.
1084 *
1085 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1086 * with the difference being a four-byte integer is to be inserted.
1087 *
1088 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001089 */
1090static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1091 uint32_t uInteger32,
1092 size_t uPos);
1093
1094
1095/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001096 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1097 *
1098 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1099 * @param[in] uInteger64 Integer to insert.
1100 * @param[in] uPos Index in output buffer at which to insert.
1101 *
1102 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1103 * with the difference being an eight-byte integer is to be inserted.
1104 *
1105 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001106 */
1107static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1108 uint64_t uInteger64,
1109 size_t uPos);
1110
1111
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001112#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001113/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001114 * @brief Insert a @c float into the @ref UsefulOutBuf.
1115 *
1116 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1117 * @param[in] f @c float to insert.
1118 * @param[in] uPos Index in output buffer at which to insert.
1119 *
1120 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1121 * with the difference being a @c float is to be inserted.
1122 *
1123 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001124 */
1125static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1126 float f,
1127 size_t uPos);
1128
1129
1130/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001131 * @brief Insert a @c double into the @ref UsefulOutBuf.
1132 *
1133 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1134 * @param[in] d @c double to insert.
1135 * @param[in] uPos Index in output buffer at which to insert.
1136 *
1137 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1138 * with the difference being a @c double is to be inserted.
1139 *
1140 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001141 */
1142static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1143 double d,
1144 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001145#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001146
1147
1148/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001149 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1150 *
1151 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1152 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1153 *
1154 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1155 * with the insertion point at the end of the valid data.
1156 */
Michael Eckel5c531332020-03-02 01:35:30 +01001157static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1158 UsefulBufC NewData);
1159
1160
1161/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001162 * @brief Append bytes to the @ref UsefulOutBuf.
1163 *
1164 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1165 * @param[in] pBytes Pointer to bytes to append.
1166 * @param[in] uLen Length of @c pBytes to append.
1167 *
1168 * See UsefulOutBuf_InsertData() for details. This does the same with
1169 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001170 */
1171static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1172 const void *pBytes,
1173 size_t uLen);
1174
1175
1176/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001177 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1178 *
1179 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1180 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001181 */
1182static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1183 const char *szString);
1184
1185
1186/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001187 * @brief Append a byte to the @ref UsefulOutBuf
1188 *
1189 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1190 * @param[in] byte Bytes to append.
1191 *
1192 * See UsefulOutBuf_InsertByte() for details. This does the same
1193 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001194 */
1195static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1196 uint8_t byte);
1197
1198
1199/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001200 * @brief Append an integer to the @ref UsefulOutBuf
1201 *
1202 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1203 * @param[in] uInteger16 Integer to append.
1204 *
1205 * See UsefulOutBuf_InsertUint16() for details. This does the same
1206 * with the insertion point at the end of the valid data.
1207 *
1208 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001209 */
1210static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1211 uint16_t uInteger16);
1212
1213
1214/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001215 * @brief Append an integer to the @ref UsefulOutBuf
1216 *
1217 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1218 * @param[in] uInteger32 Integer to append.
1219 *
1220 * See UsefulOutBuf_InsertUint32() for details. This does the same
1221 * with the insertion point at the end of the valid data.
1222 *
1223 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001224 */
1225static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1226 uint32_t uInteger32);
1227
1228
1229/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001230 * @brief Append an integer to the @ref UsefulOutBuf
1231 *
1232 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1233 * @param[in] uInteger64 Integer to append.
1234 *
1235 * See UsefulOutBuf_InsertUint64() for details. This does the same
1236 * with the insertion point at the end of the valid data.
1237 *
1238 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001239 */
1240static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1241 uint64_t uInteger64);
1242
1243
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001244#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001245/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001246 * @brief Append a @c float to the @ref UsefulOutBuf
1247 *
1248 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1249 * @param[in] f @c float to append.
1250 *
1251 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1252 * the insertion point at the end of the valid data.
1253 *
1254 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001255 */
1256static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1257 float f);
1258
1259
1260/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001261 * @brief Append a @c double to the @ref UsefulOutBuf
1262 *
1263 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1264 * @param[in] d @c double to append.
1265 *
1266 * See UsefulOutBuf_InsertDouble() for details. This does the same
1267 * with the insertion point at the end of the valid data.
1268 *
1269 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001270 */
1271static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1272 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001273#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001274
1275
1276/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001277 * @brief Returns the current error status.
1278 *
1279 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1280 *
1281 * @return 0 if all OK, 1 on error.
1282 *
1283 * This returns the error status since a call to either
1284 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1285 * goes into the error state, it will stay until one of those
1286 * functions is called.
1287 *
1288 * Possible error conditions are:
1289 * - bytes to be inserted will not fit
1290 * - insertion point is out of buffer or past valid data
1291 * - current position is off end of buffer (probably corrupted or uninitialized)
1292 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001293 */
1294static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1295
1296
1297/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001298 * @brief Returns number of bytes unused used in the output buffer.
1299 *
1300 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1301 *
1302 * @return Number of unused bytes or zero.
1303 *
1304 * Because of the error handling strategy and checks in
1305 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1306 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001307 */
1308static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1309
1310
1311/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001312 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1313 *
1314 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1315 * @param[in] uLen Number of bytes for which to check
1316 *
1317 * @return 1 if @c uLen bytes will fit, 0 if not.
1318 *
1319 * Because of the error handling strategy and checks in
1320 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1321 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001322 */
1323static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1324
1325
1326 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001327 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1328 *
1329 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1330 *
1331 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1332 *
1333 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1334 * just calculating the length of the encoded data.
1335 */
Michael Eckel5c531332020-03-02 01:35:30 +01001336static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1337
1338
1339/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001340 * @brief Returns pointer and length of the output buffer not yet used.
1341 *
1342 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1343 *
1344 * @return pointer and length of output buffer not used.
1345 *
1346 * This is an escape that allows the caller to write directly
1347 * to the output buffer without any checks. This doesn't
1348 * change the output buffer or state. It just returns a pointer
1349 * and length of the bytes remaining.
1350 *
1351 * This is useful to avoid having the bytes to be added all
1352 * in a contiguous buffer. Its use can save memory. A good
1353 * example is in the COSE encrypt implementation where
1354 * the output of the symmetric cipher can go directly
1355 * into the output buffer, rather than having to go into
1356 * an intermediate buffer.
1357 *
1358 * See UsefulOutBuf_Advance() which is used to tell
1359 * UsefulOutBuf how much was written.
1360 *
1361 * Warning: this bypasses the buffer safety provided by
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001362 * @ref UsefulOutBuf!
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001363 */
1364static inline UsefulBuf
1365UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1366
1367
1368/**
1369 * @brief Advance the amount output assuming it was written by the caller.
1370 *
1371 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1372 * @param[in] uAmount The amount to advance.
1373 *
1374 * This advances the position in the output buffer
Laurence Lundblade88ba5662024-11-03 02:10:24 -08001375 * by @c uAmount. This assumes that the
1376 * caller has written @c uAmount to the pointer obtained
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001377 * with UsefulOutBuf_GetOutPlace().
1378 *
1379 * Warning: this bypasses the buffer safety provided by
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001380 * @ref UsefulOutBuf!
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001381 */
1382void
1383UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1384
1385
1386/**
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001387 * @brief Returns the data put into a @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001388 *
1389 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1390 *
1391 * @return The valid data in @ref UsefulOutBuf or
1392 * @ref NULLUsefulBufC if there was an error adding data.
1393 *
1394 * The storage for the returned data is the @c Storage parameter
1395 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1396 *
1397 * This can be called anytime and many times to get intermediate
1398 * results. It doesn't change the data or reset the current position,
1399 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001400 */
1401UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1402
1403
1404/**
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001405 * @brief Copy out the data put into a @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001406 *
1407 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1408 * @param[out] Dest The destination buffer to copy into.
1409 *
1410 * @return Pointer and length of copied data or @c NULLUsefulBufC
1411 * if it will not fit in the @c Dest buffer or the error
1412 * state was entered.
1413 *
1414 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001415 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001416 */
Michael Eckel5c531332020-03-02 01:35:30 +01001417UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1418
1419
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001420/**
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001421 * @brief Returns data starting at an offset that was put into a @ref UsefulOutBuf.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001422 *
1423 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1424 * @param[in] uOffset Offset to bytes to return.
1425 *
1426 * @return NULLUsefulBufC or the bytes at the offset.
1427 *
1428 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1429 * maybe specified. It returns the bytes starting at @c uOffset to the
1430 * end of what was encoded so far. Calling this with @c uOffset 0 is
1431 * equivalent to UsefulOutBuf_OutUBuf().
1432 *
1433 * If there's nothing at @c uOffset or it is past the in the output
1434 * buffer, a \ref NULLUsefulBufC is returned.
1435 *
1436 * This is typically not needed in typical use. It is used by QCBOR
1437 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1438 * sorting CBOR maps.
1439 */
1440UsefulBufC
1441UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1442
1443
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001444/**
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001445 * @brief Return a substring of the output data.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001446 *
1447 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1448 * @param[in] uStart Offset of start of substring.
1449 * @param[in] uLen Length of substring.
1450 *
1451 * This is the same as UsefulOutBuf_OutUBuf(), but returns a
1452 * substring. @c NULLUsefulBufC is returned if the requested substring
1453 * is off the end of the output bytes or if in error state.
1454 */
1455UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pUOutBuf,
1456 const size_t uStart,
1457 const size_t uLen);
1458
1459
1460/**
1461 * @brief Retrieve the storage buffer passed in to UsefulOutBuf_Init().
1462 *
1463 * @param[in] pUOutBuf The encoding context.
1464 *
1465 * @return The output storage buffer passed to UsefulOutBuf_Init().
1466 *
1467 * This doesn't give any information about how much has been encoded
1468 * or the error state. It just returns the exact @ref UsefulOutBuf given
1469 * to UsefulOutBuf_Init().
1470 */
1471static UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pUOutBuf);
1472
Michael Eckel5c531332020-03-02 01:35:30 +01001473
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001474/**
1475 * @brief Compare bytes at offsets.
1476 *
1477 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1478 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001479 * @param[in] uLen1 Length of first bytes to compare.
1480 * @param[in] uStart2 Offset of second bytes to compare.
1481 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001482 *
1483 * @return 0 for equality, positive if uStart1 is lexographically larger,
1484 * negative if uStart2 is lexographically larger.
Laurence Lundblade926ccfc2024-12-05 20:34:55 -08001485 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001486 * This looks into bytes that have been output at the offsets @c start1
1487 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001488 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1489 * length of the string given is off the end of the output data, the
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001490 * string will be effectively truncated to the data in the output
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001491 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001492 *
1493 * This returns positive when @c uStart1 lexographically sorts ahead
1494 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001495 * compare equally.
1496 *
1497 * If lengths are unequal and the first bytes are an exact subset of
1498 * the second string, then a positve value will be returned and vice
1499 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001500 *
1501 * If either start is past the end of data in the output buffer, 0
1502 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001503 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001504 * being made. No data will ever be read off the end of the buffer so
1505 * this safe no matter what offsets are passed.
1506 *
1507 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001508 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1509 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001510 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001511int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1512 size_t uStart1, size_t uLen1,
1513 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001514
1515/**
1516 * @brief Swap two regions of output bytes.
1517 *
1518 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1519 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1520 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1521 * @param[in] uEndOffset Offset to end of region to be swappe.
1522 *
1523 * This reaches into bytes that have been output and swaps two
1524 * adjacent regions.
1525 *
1526 * If any of the offsets are outside the range of valid data, no
1527 * swapping will be performed. If the start is not the smallest and
1528 * the pivot is not in the middle no swapping will be performed.
1529 *
1530 * The byte at @c uStartOffset will participate in the swapping. The
1531 * byte at @c uEndOffset will not participate in the swapping, only
1532 * the byte before it.
1533 *
1534 * This is a relatively odd function in that it works on data in the
1535 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1536 * maps.
1537 */
1538void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1539 size_t uStartOffset,
1540 size_t uPivotOffset,
1541 size_t uEndOffset);
1542
1543
Michael Eckel5c531332020-03-02 01:35:30 +01001544
1545
1546/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001547 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1548 * for parsing data received. Initialize it with the data from the
1549 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1550 * get data chunks of various types. A position cursor is maintained
1551 * internally.
1552 *
1553 * As long as the functions here are used, there will never be any
1554 * reference off the end of the given buffer (except
1555 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1556 * called incorrectly, an attempt is made to seek off the end of the
1557 * buffer or such. This makes it easier to write safe and correct
1558 * code. For example, the QCBOR decoder implementation is safer and
1559 * easier to review through its use of @ref UsefulInputBuf.
1560 *
1561 * @ref UsefulInputBuf maintains an internal error state. The
1562 * intended use is fetching data chunks without any error checks until
1563 * the end. If there was any error, such as an attempt to fetch data
1564 * off the end, the error state is entered and no further data will be
1565 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1566 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1567 * null is not dereferenced, the error check can be put off until the
1568 * end, simplifying the calling code.
1569 *
1570 * The integer and float parsing expects network byte order (big
1571 * endian). Network byte order is what is used by TCP/IP, CBOR and
1572 * most internet protocols.
1573 *
1574 * Lots of inline functions are used to keep code size down. The
1575 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1576 * code size a lot. The only non-inline code is
1577 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1578 * @ref UsefulInputBuf doesn't add much code for all the messy
1579 * hard-to-get right issues with parsing binary protocols in C that it
1580 * solves.
1581 *
1582 * The parse context size is:
1583 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1584 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001585 */
1586typedef struct useful_input_buf {
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001587 /** @private Data being parsed */
1588 UsefulBufC UB;
1589 /** @private Current offset in data being parse */
1590 size_t cursor;
1591 /** @private Check for corrupted or uninitialized UsefulInputBuf */
1592 uint16_t magic;
1593 /** @private Set if request goes off end or magic number is bad */
1594 uint8_t err;
Michael Eckel5c531332020-03-02 01:35:30 +01001595} UsefulInputBuf;
1596
Laurence Lundblade9b244a32025-01-01 12:12:17 -07001597/** @private The actual value of @c magic in UsefulInputBuf. */
Michael Eckel5c531332020-03-02 01:35:30 +01001598#define UIB_MAGIC (0xB00F)
1599
1600
1601/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001602 * @brief Initialize the @ref UsefulInputBuf structure before use.
1603 *
1604 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1605 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001606 */
1607static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1608
1609
1610/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001611 * @brief Returns current position in input buffer.
1612 *
1613 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1614 *
1615 * @return Integer position of the cursor.
1616 *
1617 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001618 */
1619static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1620
1621
1622/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001623 * @brief Sets the current position in input buffer.
1624 *
1625 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1626 * @param[in] uPos Position to set to.
1627 *
1628 * If the position is off the end of the input buffer, the error state
1629 * is entered.
1630 *
1631 * Seeking to a valid position in the buffer will not reset the error
1632 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001633 */
1634static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1635
1636
1637/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001638 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1639 * the unconsumed bytes.
1640 *
1641 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1642 *
1643 * @return Number of bytes unconsumed or 0 on error.
1644 *
1645 * Returns 0 if the cursor is invalid or corruption of the
1646 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001647 */
1648static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1649
1650
1651/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001652 * @brief Check if there are unconsumed bytes.
1653 *
1654 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1655 * @param[in] uLen Number of bytes to check availability for.
1656 *
1657 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001658 */
1659static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1660
1661
1662/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001663 * @brief Convert a pointer to an offset with bounds checking.
1664 *
1665 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1666 * @param[in] p Pointer to convert to offset.
1667 *
1668 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1669 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001670static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1671
1672
1673/**
1674 * @brief Convert an offset to a pointer with bounds checking.
1675 *
1676 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1677 * @param[in] uOffset Offset in @c pUInBuf.
1678 *
1679 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1680 */
1681static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001682
1683
1684/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001685 * @brief Get pointer to bytes out of the input buffer.
1686 *
1687 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1688 * @param[in] uNum Number of bytes to get.
1689 *
1690 * @return Pointer to bytes.
1691 *
1692 * This consumes @c uNum bytes from the input buffer. This returns a
1693 * pointer to the start of the @c uNum bytes.
1694 *
1695 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1696 * returned and the error state is entered.
1697 *
1698 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001699 */
1700const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1701
1702
1703/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001704 * @brief Get @ref UsefulBuf out of the input buffer.
1705 *
1706 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1707 * @param[in] uNum Number of bytes to get.
1708 *
1709 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1710 *
1711 * This consumes @c uNum bytes from the input buffer and returns the
1712 * pointer and length for them as a @ref UsefulBufC. The length
1713 * returned will always be @c uNum. The position cursor is advanced by
1714 * @c uNum bytes.
1715 *
1716 * If there are not @c uNum bytes in the input buffer, @ref
1717 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001718 */
1719static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1720
1721
1722/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001723 * @brief Get a byte out of the input buffer.
1724 *
1725 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1726 *
1727 * @return The byte.
1728 *
1729 * This consumes 1 byte from the input buffer, returns it and advances
1730 * the position cursor by 1.
1731 *
1732 * If there is not 1 byte in the buffer, 0 will be returned for the
1733 * byte and the error state is entered. To know if the 0 returned was
1734 * in error or the real value, the error state must be checked. If
1735 * possible, put this off until all values are retrieved to have
1736 * smaller and simpler code, but if not possible
1737 * UsefulInputBuf_GetError() can be called. Also, in the error state
1738 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1739 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001740 */
1741static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1742
1743
1744/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001745 * @brief Get a @c uint16_t out of the input buffer.
1746 *
1747 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1748 *
1749 * @return The @c uint16_t.
1750 *
1751 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1752 * a @c uint16_t and two bytes are consumed.
1753 *
1754 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001755 */
1756static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1757
1758
1759/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001760 * @brief Get a @c uint32_t out of the input buffer.
1761 *
1762 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1763 *
1764 * @return The @c uint32_t.
1765 *
1766 * See UsefulInputBuf_GetByte(). This works the same, except it
1767 * returns a @c uint32_t and four bytes are consumed.
1768 *
1769 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001770 */
1771static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1772
1773
1774/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001775 * @brief Get a @c uint64_t out of the input buffer.
1776 *
1777 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1778 *
1779 * @return The uint64_t.
1780 *
1781 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1782 * a @c uint64_t and eight bytes are consumed.
1783 *
1784 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001785 */
1786static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1787
1788
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001789#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001790/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001791 * @brief Get a float out of the input buffer.
1792 *
1793 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1794 *
1795 * @return The float.
1796 *
1797 * See UsefulInputBuf_GetByte(). This works the same, except it
1798 * returns a float and four bytes are consumed.
1799 *
1800 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001801 */
1802static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1803
1804
1805/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001806 * @brief Get a double out of the input buffer.
1807 *
1808 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1809 *
1810 * @return The double.
1811 *
1812 * See UsefulInputBuf_GetByte(). This works the same, except it
1813 * returns a double and eight bytes are consumed.
1814 *
1815 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001816 */
1817static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001818#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001819
1820
1821/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001822 * @brief Get the error status.
1823 *
1824 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1825 *
1826 * @return 0 if not in the error state, 1 if in the error state.
1827 *
1828 * This returns whether the @ref UsefulInputBuf is in the
1829 * error state or not.
1830 *
1831 * The error state is entered for one of these reasons:
1832 * - Attempt to fetch data past the end of the buffer
1833 * - Attempt to seek to a position past the end of the buffer
1834 * - Attempt to get data from an uninitialized or corrupt instance
1835 * of @ref UsefulInputBuf
1836 *
1837 * Once in the error state, it can only be cleared by calling
1838 * UsefulInputBuf_Init().
1839 *
1840 * For many use cases, it is possible to only call this once after all
1841 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1842 * possible if no reference to the data returned are needed before the
1843 * error state is checked.
1844 *
1845 * In some cases UsefulInputBuf_GetUsefulBuf() or
1846 * UsefulInputBuf_GetBytes() can stand in for this because they return
1847 * @c NULL if the error state has been entered. (The others can't stand
1848 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001849 */
1850static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1851
1852
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001853/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001854 * @brief Gets the input buffer length.
1855 *
1856 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1857 *
1858 * @return The length of the input buffer.
1859 *
1860 * This returns the length of the input buffer set by
1861 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001862 */
1863static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1864
1865
1866/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001867 * @brief Alters the input buffer length (use with caution).
1868 *
1869 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1870 * @param[in] uNewLen The new length of the input buffer.
1871 *
1872 * This alters the internal remembered length of the input buffer set
1873 * when UsefulInputBuf_Init() was called.
1874 *
1875 * The new length given here should always be equal to or less than
1876 * the length given when UsefulInputBuf_Init() was called. Making it
1877 * larger allows @ref UsefulInputBuf to run off the input buffer.
1878 *
1879 * The typical use is to set a length shorter than that when
1880 * initialized to constrain parsing. If
1881 * UsefulInputBuf_GetBufferLength() was called before this, then the
1882 * original length can be restored with another call to this.
1883 *
1884 * This should be used with caution. It is the only
1885 * @ref UsefulInputBuf method that can violate the safety of input
1886 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001887 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001888static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001889
1890
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001891/** @brief Retrieve the undecoded input buffer.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001892 *
1893 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1894 *
1895 * @return The input that was given to UsefulInputBuf_Init().
1896 *
1897 * A simple convenience method, should it be useful to get the original input back.
1898 */
1899static UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pUInBuf);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001900
1901
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001902/**
1903 * @brief Compare two ranges of bytes somewhere in the input buffer.
1904 *
1905 * @param[in] pUInBuf The input buffer.
1906 * @param[in] uOffset1 Offset of first range of bytes.
1907 * @param[in] uLen1 Length of first range of bytes.
1908 * @param[in] uOffset2 Offset of second range of bytes.
1909 * @param[in] uLen2 Length of second range of bytes.
1910 *
1911 * This returns the same as UsefulBuf_Compare().
Laurence Lundblade926ccfc2024-12-05 20:34:55 -08001912 *
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001913 * If the offset or the length plus offset or a range extends outside
1914 * the input buffer, that range of bytes will be considered greater
1915 * than the other string. If both are outside this is considered a
1916 * degenerate condition and the first string is considered larger.
1917 *
1918 * This is a somewhat odd function of UsefulInputBuf as it is not used
1919 * for consuming data. QCBOR uses it for map order and duplicate
1920 * checking.
1921 */
1922int
1923UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
1924 const size_t uOffset1,
1925 const size_t uLen1,
1926 const size_t uOffset2,
1927 const size_t uLen2);
Michael Eckel5c531332020-03-02 01:35:30 +01001928
1929
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001930
1931
Michael Eckel5c531332020-03-02 01:35:30 +01001932/*----------------------------------------------------------
1933 Inline implementations.
1934 */
1935static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1936{
1937 return !UB.ptr;
1938}
1939
1940
1941static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1942{
1943 return !UB.ptr;
1944}
1945
1946
1947static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1948{
1949 return !UB.len;
1950}
1951
1952
1953static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1954{
1955 return !UB.len;
1956}
1957
1958
1959static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1960{
1961 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1962}
1963
1964
1965static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1966{
1967 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1968}
1969
1970
1971static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1972{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001973 UsefulBufC UBC;
1974 UBC.ptr = UB.ptr;
1975 UBC.len = UB.len;
1976
1977 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001978}
1979
Michael Eckel5c531332020-03-02 01:35:30 +01001980static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1981{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001982 UsefulBuf UB;
1983
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001984 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001985 * the one place in UsefulBuf where it needs to be quieted.
1986 */
1987 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001988
1989 UB.len = UBC.len;
1990
1991 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001992}
1993
1994
1995static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1996{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001997 UsefulBufC UBC;
1998 UBC.ptr = szString;
1999 UBC.len = strlen(szString);
2000 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002001}
2002
2003
2004static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
2005{
2006 return UsefulBuf_CopyOffset(Dest, 0, Src);
2007}
2008
2009
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002010static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01002011{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002012 memset(Dest.ptr, value, Dest.len);
2013
2014 UsefulBufC UBC;
2015 UBC.ptr = Dest.ptr;
2016 UBC.len = Dest.len;
2017
2018 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002019}
2020
2021
2022static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
2023{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002024 UsefulBufC UBC;
2025 UBC.ptr = ptr;
2026 UBC.len = len;
2027 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002028}
2029
2030
2031static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
2032{
2033 if(uAmount > UB.len) {
2034 return NULLUsefulBufC;
2035 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002036 UsefulBufC UBC;
2037
2038 UBC.ptr = UB.ptr;
2039 UBC.len = uAmount;
2040
2041 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002042}
2043
2044
2045static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
2046{
2047 UsefulBufC ReturnValue;
2048
2049 if(uAmount > UB.len) {
2050 ReturnValue = NULLUsefulBufC;
2051 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002052 ReturnValue.ptr = NULL;
2053 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002054 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002055 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
2056 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002057 }
2058
2059 return ReturnValue;
2060}
2061
2062
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002063static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
2064{
2065 if(UB.ptr == NULL) {
2066 return SIZE_MAX;
2067 }
2068
2069 if(p < UB.ptr) {
2070 /* given pointer is before start of buffer */
2071 return SIZE_MAX;
2072 }
2073
Laurence Lundblade3eead482023-12-16 20:53:22 -07002074 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002075 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002076
2077 if(uOffset >= UB.len) {
2078 /* given pointer is off the end of the buffer */
2079 return SIZE_MAX;
2080 }
2081
2082 return uOffset;
2083}
2084
Michael Eckel5c531332020-03-02 01:35:30 +01002085
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002086static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
2087{
2088 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
2089 return NULL;
2090 }
2091
2092 return (const uint8_t *)UB.ptr + uOffset;
2093}
2094
2095
2096
2097
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002098#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002099static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
2100{
2101 uint32_t u32;
2102 memcpy(&u32, &f, sizeof(uint32_t));
2103 return u32;
2104}
2105
2106static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2107{
2108 uint64_t u64;
2109 memcpy(&u64, &d, sizeof(uint64_t));
2110 return u64;
2111}
2112
2113static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2114{
2115 double d;
2116 memcpy(&d, &u64, sizeof(uint64_t));
2117 return d;
2118}
2119
2120static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2121{
2122 float f;
2123 memcpy(&f, &u32, sizeof(uint32_t));
2124 return f;
2125}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002126#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002127
2128
2129
2130
2131static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2132{
2133 pMe->data_len = 0;
2134 pMe->err = 0;
2135}
2136
2137
2138static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2139{
2140 return pMe->data_len;
2141}
2142
2143
2144static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2145{
2146 return 0 == pMe->data_len;
2147}
2148
2149
2150static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2151 const void *pBytes,
2152 size_t uLen,
2153 size_t uPos)
2154{
2155 UsefulBufC Data = {pBytes, uLen};
2156 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2157}
2158
2159
2160static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2161 const char *szString,
2162 size_t uPos)
2163{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002164 UsefulBufC UBC;
2165 UBC.ptr = szString;
2166 UBC.len = strlen(szString);
2167
2168 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002169}
2170
2171
2172static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2173 uint8_t byte,
2174 size_t uPos)
2175{
2176 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2177}
2178
2179
2180static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2181 uint16_t uInteger16,
2182 size_t uPos)
2183{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002184 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002185
2186 const void *pBytes;
2187
2188#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2189 pBytes = &uInteger16;
2190
2191#elif defined(USEFULBUF_CONFIG_HTON)
2192 uint16_t uTmp = htons(uInteger16);
2193 pBytes = &uTmp;
2194
2195#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2196 uint16_t uTmp = __builtin_bswap16(uInteger16);
2197 pBytes = &uTmp;
2198
2199#else
2200 uint8_t aTmp[2];
2201
2202 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2203 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2204
2205 pBytes = aTmp;
2206#endif
2207
2208 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2209}
2210
2211
2212static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2213 uint32_t uInteger32,
2214 size_t uPos)
2215{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002216 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002217
2218 const void *pBytes;
2219
2220#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2221 pBytes = &uInteger32;
2222
2223#elif defined(USEFULBUF_CONFIG_HTON)
2224 uint32_t uTmp = htonl(uInteger32);
2225 pBytes = &uTmp;
2226
2227#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2228 uint32_t uTmp = __builtin_bswap32(uInteger32);
2229
2230 pBytes = &uTmp;
2231
2232#else
2233 uint8_t aTmp[4];
2234
2235 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2236 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2237 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2238 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2239
2240 pBytes = aTmp;
2241#endif
2242
2243 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2244}
2245
2246static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002247 uint64_t uInteger64,
2248 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002249{
2250 const void *pBytes;
2251
2252#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002253 /* We have been told explicitly we are running on a big-endian
2254 * machine. Network byte order is big endian, so just copy. There
2255 * is no issue with alignment here because uInteger64 is always
2256 * aligned (and it doesn't matter if pBytes is aligned).
2257 */
Michael Eckel5c531332020-03-02 01:35:30 +01002258 pBytes = &uInteger64;
2259
2260#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002261 /* Use system function to handle big- and little-endian. This works
2262 * on both big- and little-endian machines, but hton() is not
2263 * always available or in a standard place so it is not used by
2264 * default. With some compilers and CPUs the code for this is very
2265 * compact through use of a special swap instruction and on
2266 * big-endian machines hton() will reduce to nothing.
2267 */
Michael Eckel5c531332020-03-02 01:35:30 +01002268 uint64_t uTmp = htonll(uInteger64);
2269
2270 pBytes = &uTmp;
2271
2272#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002273 /* Use built-in function for byte swapping. This usually compiles
2274 * to an efficient special byte swap instruction. Unlike hton() it
2275 * does not do this conditionally on the CPU endianness, so this
2276 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2277 */
Michael Eckel5c531332020-03-02 01:35:30 +01002278 uint64_t uTmp = __builtin_bswap64(uInteger64);
2279
2280 pBytes = &uTmp;
2281
2282#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002283 /* Default which works on every CPU with no dependency on anything
2284 * from the CPU, compiler, libraries or OS. This always works, but
2285 * it is usually a little larger and slower than hton().
2286 */
Michael Eckel5c531332020-03-02 01:35:30 +01002287 uint8_t aTmp[8];
2288
2289 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2290 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2291 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2292 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2293 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2294 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2295 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2296 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2297
2298 pBytes = aTmp;
2299#endif
2300
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002301 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002302 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2303}
2304
2305
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002306#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002307static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2308 float f,
2309 size_t uPos)
2310{
2311 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2312}
2313
2314
2315static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2316 double d,
2317 size_t uPos)
2318{
2319 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2320}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002321#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002322
2323
2324static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2325 UsefulBufC NewData)
2326{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002327 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002328 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2329}
2330
2331
2332static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2333 const void *pBytes,
2334 size_t uLen)
2335{
2336 UsefulBufC Data = {pBytes, uLen};
2337 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2338}
2339
2340
2341static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2342 const char *szString)
2343{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002344 UsefulBufC UBC;
2345 UBC.ptr = szString;
2346 UBC.len = strlen(szString);
2347
2348 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002349}
2350
2351
2352static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2353 uint8_t byte)
2354{
2355 UsefulOutBuf_AppendData(pMe, &byte, 1);
2356}
2357
2358
2359static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2360 uint16_t uInteger16)
2361{
2362 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2363}
2364
2365static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2366 uint32_t uInteger32)
2367{
2368 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2369}
2370
2371
2372static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2373 uint64_t uInteger64)
2374{
2375 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2376}
2377
2378
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002379#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002380static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2381 float f)
2382{
2383 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2384}
2385
2386
2387static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2388 double d)
2389{
2390 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2391}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002392#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002393
2394
2395static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2396{
2397 return pMe->err;
2398}
2399
2400
2401static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2402{
2403 return pMe->UB.len - pMe->data_len;
2404}
2405
2406
2407static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2408{
2409 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2410}
2411
2412
2413static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2414{
2415 return pMe->UB.ptr == NULL;
2416}
2417
2418
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002419static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2420{
2421 UsefulBuf R;
2422
2423 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002424 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002425 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2426 } else {
2427 R.ptr = NULL;
2428 }
2429
2430 return R;
2431}
2432
2433
Laurence Lundbladee2226742024-08-16 10:50:23 -07002434static inline UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pMe)
2435{
2436 return pMe->UB;
2437}
2438
2439
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002440
Michael Eckel5c531332020-03-02 01:35:30 +01002441
2442static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2443{
2444 pMe->cursor = 0;
2445 pMe->err = 0;
2446 pMe->magic = UIB_MAGIC;
2447 pMe->UB = UB;
2448}
2449
2450static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2451{
2452 return pMe->cursor;
2453}
2454
2455
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002456static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002457{
2458 return pMe->UB.len;
2459}
2460
2461
Michael Eckel5c531332020-03-02 01:35:30 +01002462static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2463{
2464 if(uPos > pMe->UB.len) {
2465 pMe->err = 1;
2466 } else {
2467 pMe->cursor = uPos;
2468 }
2469}
2470
2471
2472static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2473{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002474 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002475
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002476 /* Magic number is messed up. Either the structure got overwritten
2477 * or was never initialized.
2478 */
Michael Eckel5c531332020-03-02 01:35:30 +01002479 if(pMe->magic != UIB_MAGIC) {
2480 return 0;
2481 }
2482
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002483 /* The cursor is off the end of the input buffer given.
2484 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002485 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002486 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002487 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002488 */
Michael Eckel5c531332020-03-02 01:35:30 +01002489 if(pMe->cursor > pMe->UB.len) {
2490 return 0;
2491 }
2492
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002493 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002494 return pMe->UB.len - pMe->cursor;
2495}
2496
2497
2498static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2499{
2500 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2501}
2502
2503
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002504static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2505{
2506 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2507}
2508
2509
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002510static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2511 {
2512 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2513 }
2514
2515
Michael Eckel5c531332020-03-02 01:35:30 +01002516static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2517{
2518 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2519 if(!pResult) {
2520 return NULLUsefulBufC;
2521 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002522 UsefulBufC UBC;
2523 UBC.ptr = pResult;
2524 UBC.len = uNum;
2525 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002526 }
2527}
2528
2529
2530static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2531{
2532 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2533
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002534 /* The ternary operator is subject to integer promotion, because
2535 * the operands are smaller than int, so cast back to uint8_t is
2536 * needed to be completely explicit about types (for static
2537 * analyzers).
2538 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002539 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002540}
2541
2542static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2543{
2544 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2545
2546 if(!pResult) {
2547 return 0;
2548 }
2549
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002550 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002551#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2552 uint16_t uTmp;
2553 memcpy(&uTmp, pResult, sizeof(uint16_t));
2554
2555#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2556 return uTmp;
2557
2558#elif defined(USEFULBUF_CONFIG_HTON)
2559 return ntohs(uTmp);
2560
2561#else
2562 return __builtin_bswap16(uTmp);
2563
2564#endif
2565
2566#else
2567
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002568 /* The operations here are subject to integer promotion because the
2569 * operands are smaller than int. They will be promoted to unsigned
2570 * int for the shift and addition. The cast back to uint16_t is is
2571 * needed to be completely explicit about types (for static
2572 * analyzers).
2573 */
Michael Eckel5c531332020-03-02 01:35:30 +01002574 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2575
2576#endif
2577}
2578
2579
2580static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2581{
2582 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2583
2584 if(!pResult) {
2585 return 0;
2586 }
2587
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002588 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002589#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2590 uint32_t uTmp;
2591 memcpy(&uTmp, pResult, sizeof(uint32_t));
2592
2593#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2594 return uTmp;
2595
2596#elif defined(USEFULBUF_CONFIG_HTON)
2597 return ntohl(uTmp);
2598
2599#else
2600 return __builtin_bswap32(uTmp);
2601
2602#endif
2603
2604#else
2605 return ((uint32_t)pResult[0]<<24) +
2606 ((uint32_t)pResult[1]<<16) +
2607 ((uint32_t)pResult[2]<<8) +
2608 (uint32_t)pResult[3];
2609#endif
2610}
2611
2612
2613static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2614{
2615 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2616
2617 if(!pResult) {
2618 return 0;
2619 }
2620
2621#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002622 /* pResult will probably not be aligned. This memcpy() moves the
2623 * bytes into a temp variable safely for CPUs that can or can't do
2624 * unaligned memory access. Many compilers will optimize the
2625 * memcpy() into a simple move instruction.
2626 */
Michael Eckel5c531332020-03-02 01:35:30 +01002627 uint64_t uTmp;
2628 memcpy(&uTmp, pResult, sizeof(uint64_t));
2629
2630#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002631 /* We have been told expliclity this is a big-endian CPU. Since
2632 * network byte order is big-endian, there is nothing to do.
2633 */
Michael Eckel5c531332020-03-02 01:35:30 +01002634
2635 return uTmp;
2636
2637#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002638 /* We have been told to use ntoh(), the system function to handle
2639 * big- and little-endian. This works on both big- and
2640 * little-endian machines, but ntoh() is not always available or in
2641 * a standard place so it is not used by default. On some CPUs the
2642 * code for this is very compact through use of a special swap
2643 * instruction.
2644 */
Michael Eckel5c531332020-03-02 01:35:30 +01002645
2646 return ntohll(uTmp);
2647
2648#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002649 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2650 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2651 * __builtin_bswap64() and friends are not conditional on CPU
2652 * endianness so this must only be used on little-endian machines.
2653 */
Michael Eckel5c531332020-03-02 01:35:30 +01002654
2655 return __builtin_bswap64(uTmp);
2656
2657
2658#endif
2659
2660#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002661 /* This is the default code that works on every CPU and every
2662 * endianness with no dependency on ntoh(). This works on CPUs
2663 * that either allow or do not allow unaligned access. It will
2664 * always work, but usually is a little less efficient than ntoh().
2665 */
Michael Eckel5c531332020-03-02 01:35:30 +01002666
2667 return ((uint64_t)pResult[0]<<56) +
2668 ((uint64_t)pResult[1]<<48) +
2669 ((uint64_t)pResult[2]<<40) +
2670 ((uint64_t)pResult[3]<<32) +
2671 ((uint64_t)pResult[4]<<24) +
2672 ((uint64_t)pResult[5]<<16) +
2673 ((uint64_t)pResult[6]<<8) +
2674 (uint64_t)pResult[7];
2675#endif
2676}
2677
2678
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002679#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002680static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2681{
2682 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2683
2684 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2685}
2686
2687
2688static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2689{
2690 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2691
2692 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2693}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002694#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002695
2696
2697static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2698{
2699 return pMe->err;
2700}
2701
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002702
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002703static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002704{
2705 pMe->UB.len = uNewLen;
2706}
2707
Laurence Lundbladee2226742024-08-16 10:50:23 -07002708static inline UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pMe)
2709{
2710 return pMe->UB;
2711}
2712
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002713
Michael Eckel5c531332020-03-02 01:35:30 +01002714#ifdef __cplusplus
2715}
2716#endif
2717
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002718#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002719
2720