blob: 888891de6d5065dfbd6899ca8cd9c2c3be97637a [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade534112f2025-02-26 15:12:47 -07003 * Copyright (c) 2018-2025, 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 Lundblade534112f2025-02-26 15:12:47 -070046 02/21/2025 llundblade Correct documentaion for UsefulOutBuf_Compare()
47 02/21/2025 llundblade Rename to UsefulOutBuf_OutSubString().
Laurence Lundblade89f926d2025-01-01 19:37:09 -070048 12/31/2024 llundblade Minor documentation tweaks for Doxygen.
Laurence Lundblade68769332024-11-03 13:09:20 -080049 08/31/2024 llundblade Add UsefulBufC_NTH_BYTE().
Laurence Lundbladee2226742024-08-16 10:50:23 -070050 08/14/2024 llundblade Add UsefulOutBuf_RetrieveOutputStorage().
51 08/13/2024 llundblade Add UsefulInputBuf_RetrieveUndecodedInput().
Laurence Lundblade68769332024-11-03 13:09:20 -080052 8/10/2024 llundblade Add UsefulBuf_SkipLeading().
Laurence Lundbladee2226742024-08-16 10:50:23 -070053 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070054 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070055 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladede2e1502024-08-26 11:37:05 -070056 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070057 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
58 19/11/2023 llundblade Add UsefulOutBuf_Swap().
59 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070060 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060061 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070062 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070063 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070064 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080065 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070066 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010067 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
68 5/21/2019 llundblade #define configs for efficient endianness handling.
69 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
70 3/23/2019 llundblade Big documentation & style update. No interface
71 change.
72 3/6/2019 llundblade Add UsefulBuf_IsValue()
73 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
74 12/13/2018 llundblade Documentation improvements
75 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
76 UsefulBufC.
77 02/02/18 llundbla Full support for integers in and out; fix pointer
78 alignment bug. Incompatible change: integers
79 in/out are now in network byte order.
80 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
81 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
82 comparison for < or > for unequal length buffers.
83 Added UsefulBuf_Set() function.
84 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
85 11/13/16 llundbla Initial Version.
86
87 =============================================================================*/
88
89#ifndef _UsefulBuf_h
90#define _UsefulBuf_h
91
92
93/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070094 * Endianness Configuration
95 *
96 * This code is written so it will work correctly on big- and
97 * little-endian CPUs without configuration or any auto-detection of
98 * endianness. All code here will run correctly regardless of the
99 * endianness of the CPU it is running on.
100 *
101 * There are four C preprocessor macros that can be set with #define
102 * to explicitly configure endianness handling. Setting them can
103 * reduce code size a little and improve efficiency a little.
104 *
105 * Note that most of QCBOR is unaffected by this configuration. Its
106 * endianness handling is integrated with the code that handles
107 * alignment and preferred serialization. This configuration does
108 * affect QCBOR's (planned) implementation of integer arrays (tagged
109 * arrays) and use of the functions here to serialize or deserialize
110 * integers and floating-point values.
111 *
112 * Following is the recipe for configuring the endianness-related
113 * #defines.
114 *
115 * The first option is to not define anything. This will work fine
116 * with all CPUs, OS's and compilers. The code for encoding integers
117 * may be a little larger and slower.
118 *
119 * If your CPU is big-endian then define
120 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
121 * for big-endian CPUs. It will be small and efficient because there
122 * will be no byte swapping.
123 *
124 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
125 * OS's and compilers, but not all. On big-endian CPUs this should
126 * give the most efficient code, the same as
127 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
128 * call the system-defined byte swapping method which is presumably
129 * implemented efficiently. In some cases, this will be a dedicated
130 * byte swap instruction like Intel's bswap.
131 *
132 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
133 * little-endian, it is also good to define
134 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
135 *
136 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
137 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
138 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
139 * system-defined byte swap method. However, note
140 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
141 * this is fixed now. Often hton() and ntoh() will call the built-in
142 * __builtin_bswapXX()() function, so this size issue could affect
143 * USEFULBUF_CONFIG_HTON.
144 *
145 * Last, run the tests. They must all pass.
146 *
147 * These #define config options affect the inline implementation of
148 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
149 * also affect the 16-, 32-bit, float and double versions of these
150 * functions. Since they are inline, the size effect is not in the
151 * UsefulBuf object code, but in the calling code.
152 *
153 * Summary:
154 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
155 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
156 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
157 * handle big and little-endian with system option.
158 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
159 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200160 *
161 * It is possible to run this code in environments where using floating point is
162 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
163 * that is related to handling floating point types, along with related
164 * interfaces. This makes it possible to compile the code with the compile
165 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100166 */
167
168#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
169#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
170#endif
171
172
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700173#include <stdint.h> /* for uint8_t, uint16_t.... */
174#include <string.h> /* for strlen, memcpy, memmove, memset */
175#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100176
177
178#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700179#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100180#endif
181
182#ifdef __cplusplus
183extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700184#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700185} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700186#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100187#endif
188
189/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700190 * @file UsefulBuf.h
191 *
192 * The goal of this code is to make buffer and pointer manipulation
193 * easier and safer when working with binary data.
194 *
195 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
196 * structures are used to represent buffers rather than ad hoc
197 * pointers and lengths.
198 *
199 * With these it is possible to write code that does little or no
200 * direct pointer manipulation for copying and formatting data. For
201 * example, the QCBOR encoder was written using these and has less
202 * pointer manipulation.
203 *
204 * While it is true that object code using these functions will be a
205 * little larger and slower than a white-knuckle clever use of
206 * pointers might be, but not by that much or enough to have an effect
207 * for most use cases. For security-oriented code this is highly
208 * worthwhile. Clarity, simplicity, reviewability and are more
209 * important.
210 *
211 * There are some extra sanity and double checks in this code to help
212 * catch coding errors and simple memory corruption. They are helpful,
213 * but not a substitute for proper code review, input validation and
214 * such.
215 *
216 * This code consists of a lot of inline functions and a few that are
217 * not. It should not generate very much object code, especially with
218 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100219 */
220
221
222/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700223 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
224 * hold a pointer and length for binary data. In C99 this data
225 * structure can be passed on the stack making a lot of code cleaner
226 * than carrying around a pointer and length as two parameters.
227 *
228 * This is also conducive to secure coding practice as the length is
229 * always carried with the pointer and the convention for handling a
230 * pointer and a length is clear.
231 *
232 * While it might be possible to write buffer and pointer code more
233 * efficiently in some use cases, the thought is that unless there is
234 * an extreme need for performance (e.g., you are building a
235 * gigabit-per-second IP router), it is probably better to have
236 * cleaner code you can be most certain about the security of.
237 *
238 * The non-const @ref UsefulBuf is usually used to refer an empty
239 * buffer to be filled in. The length is the size of the buffer.
240 *
241 * The const @ref UsefulBufC is usually used to refer to some data
242 * that has been filled in. The length is amount of valid data pointed
243 * to.
244 *
245 * A common use mode is to pass a @ref UsefulBuf to a function, the
246 * function puts some data in it, then the function returns a @ref
247 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
248 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
249 * so the constness stays correct. There is no single "in,out"
250 * parameter (if there was, it would have to be non-const). Note that
251 * the pointer returned in the @ref UsefulBufC usually ends up being
252 * the same pointer passed in as a @ref UsefulBuf, though this is not
253 * striclty required.
254 *
255 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
256 * @c NULL.
257 *
258 * There are functions and macros for the following:
259 * - Initializing
260 * - Create initialized const @ref UsefulBufC from compiler literals
261 * - Create initialized const @ref UsefulBufC from NULL-terminated string
262 * - Make an empty @ref UsefulBuf on the stack
263 * - Checking whether a @ref UsefulBuf is null, empty or both
264 * - Copying, copying with offset, copying head or tail
265 * - Comparing and finding substrings
266 *
267 * See also @ref UsefulOutBuf. It is a richer structure that has both
268 * the size of the valid data and the size of the buffer.
269 *
270 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
271 * it can go on the stack and be a function parameter or return value.
272 *
273 * Another way to look at it is this. C has the NULL-terminated string
274 * as a means for handling text strings, but no means or convention
275 * for binary strings. Other languages do have such means, Rust, an
276 * efficient compiled language, for example.
277 *
278 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
279 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
280 * out like anything".
281 */
Michael Eckel5c531332020-03-02 01:35:30 +0100282typedef struct q_useful_buf_c {
283 const void *ptr;
284 size_t len;
285} UsefulBufC;
286
287
288/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700289 * This non-const @ref UsefulBuf is typically used for some allocated
290 * memory that is to be filled in. The @c len is the amount of memory,
291 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100292 */
293typedef struct q_useful_buf {
294 void *ptr;
295 size_t len;
296} UsefulBuf;
297
298
299/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700300 * A null @ref UsefulBufC is one that has no value in the same way a
301 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
302 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
303 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100304 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700305/*
306 * NULLUsefulBufC and few other macros have to be
307 * definied differently in C than C++ because there
308 * is no common construct for a literal structure.
309 *
310 * In C compound literals are used.
311 *
312 * In C++ list initalization is used. This only works
313 * in C++11 and later.
314 *
315 * Note that some popular C++ compilers can handle compound
316 * literals with on-by-default extensions, however
317 * this code aims for full correctness with strict
318 * compilers so they are not used.
319 */
320#ifdef __cplusplus
321#define NULLUsefulBufC {NULL, 0}
322#else
323#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
324#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100325
326/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700327 * A null @ref UsefulBuf is one that has no memory associated the same
328 * way @c NULL points to nothing. It does not matter what @c len is.
329 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700330#ifdef __cplusplus
331#define NULLUsefulBuf {NULL, 0}
332#else
333#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
334#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100335
336
337/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700338 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
339 *
340 * @param[in] UB The UsefulBuf to check.
341 *
342 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100343 */
344static inline int UsefulBuf_IsNULL(UsefulBuf UB);
345
346
347/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700348 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
349 *
350 * @param[in] UB The @ref UsefulBufC to check.
351 *
352 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100353 */
354static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
355
356
357/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700358 * @brief Check if a @ref UsefulBuf is empty or not.
359 *
360 * @param[in] UB The @ref UsefulBuf to check.
361 *
362 * @return 1 if it is empty, 0 if not.
363 *
364 * An "empty" @ref UsefulBuf is one that has a value and can be
365 * considered to be set, but that value is of zero length. It is
366 * empty when @c len is zero. It doesn't matter what the @c ptr is.
367 *
368 * Many uses will not need to clearly distinguish a @c NULL @ref
369 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
370 * @c len 0. However if a use of @ref UsefulBuf needs to make a
371 * distinction then @c ptr should not be @c NULL when the @ref
372 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100373 */
374static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
375
376
377/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700378 * @brief Check if a @ref UsefulBufC is empty or not.
379 *
380 * @param[in] UB The @ref UsefulBufC to check.
381 *
382 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100383 */
384static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
385
386
387/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700388 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
389 *
390 * @param[in] UB The @ref UsefulBuf to check.
391 *
392 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100393 */
394static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
395
396
397/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700398 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
399 *
400 * @param[in] UB The @ref UsefulBufC to check.
401 *
402 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100403 */
404static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
405
406
407/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700408 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
409 *
410 * @param[in] UB The @ref UsefulBuf to convert.
411 *
412 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100413 */
414static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
415
416
417/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700418 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
419 *
420 * @param[in] UBC The @ref UsefulBuf to convert.
421 *
422 * @return A non-const @ref UsefulBuf struct.
423 *
424 * Use of this is not necessary for the intended use mode of @ref
425 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
426 * created to describe a buffer that has not had any data put in
427 * it. Then the data is put in it. Then a @ref UsefulBufC is create
428 * to describe the part with the data in it. This goes from non-const
429 * to const, so this function is not needed.
430 *
431 * If the -Wcast-qual warning is enabled, this function can be used to
432 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100433 */
434static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
435
436
437/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700438 * Convert a literal string to a @ref UsefulBufC.
439 *
440 * @c szString must be a literal string that @c sizeof() works on.
441 * This is better for literal strings than UsefulBuf_FromSZ() because
442 * it generates less code. It will not work on non-literal strings.
443 *
444 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100445 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700446#ifdef __cplusplus
447#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
448#else
Michael Eckel5c531332020-03-02 01:35:30 +0100449#define UsefulBuf_FROM_SZ_LITERAL(szString) \
450 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700451#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100452
453
454/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700455 * Convert a literal byte array to a @ref UsefulBufC.
456 *
457 * @c pBytes must be a literal string that @c sizeof() works on. It
458 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100459 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700460#ifdef __cplusplus
461#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
462#else
Michael Eckel5c531332020-03-02 01:35:30 +0100463#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700464 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
465#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100466
467/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700468 * Make an automatic variable named @c name of type @ref UsefulBuf and
469 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100470 */
471#define UsefulBuf_MAKE_STACK_UB(name, size) \
472 uint8_t __pBuf##name[(size)];\
473 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
474
475
476/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700477 * Make a byte array in to a @ref UsefulBuf. This is usually used on
478 * stack variables or static variables. Also see @ref
479 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100480 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700481#ifdef __cplusplus
482#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
483#else
Michael Eckel5c531332020-03-02 01:35:30 +0100484#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700485 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
486#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100487
488
489/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700490 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
491 *
492 * @param[in] szString The string to convert.
493 *
494 * @return A @ref UsefulBufC struct.
495 *
496 * @c UsefulBufC.ptr points to the string so its lifetime must be
497 * maintained.
498 *
499 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100500 */
501static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
502
503
Laurence Lundblade89f926d2025-01-01 19:37:09 -0700504/**
505 * @brief Get the nth byte from a UsefulBufC.
506 *
507 * @param[in] UBC UsefulBufC from which to get byte
508 * @param[in] n Index of byte to get
509 *
510 * WARNING: this doesn't check that @c is within the UsefulBufC. This point
511 * of this is to have the ugly cast in just one place.
512 */
Laurence Lundblade68769332024-11-03 13:09:20 -0800513#define UsefulBufC_NTH_BYTE(UBC, n) (((const uint8_t *)(UBC.ptr))[n])
514
515
Michael Eckel5c531332020-03-02 01:35:30 +0100516/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700517 * @brief Copy one @ref UsefulBuf into another at an offset.
518 *
519 * @param[in] Dest Destination buffer to copy into.
520 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
521 * @param[in] Src The bytes to copy.
522 *
523 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
524 *
525 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
526 * size of @c Dest.
527 *
528 * This fails and returns @ref NULLUsefulBufC if the @c Src length
529 * plus @c uOffset is greater than the length of @c Dest.
530 *
531 * The results are undefined if @c Dest and @c Src overlap.
532 *
533 * This assumes that there is valid data in @c Dest up to @c
534 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
535 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100536 */
537UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
538
539
540/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700541 * @brief Copy one @ref UsefulBuf into another.
542 *
543 * @param[in] Dest The destination buffer to copy into.
544 * @param[out] Src The source to copy from.
545 *
546 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
547 * on failure.
548 *
549 * This fails if @c Src.len is greater than @c Dest.len.
550 *
551 * Note that like @c memcpy(), the pointers are not checked and this
552 * will crash rather than return @ref NULLUsefulBufC if they are @c
553 * NULL or invalid.
554 *
555 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100556 */
557static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
558
559
560/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700561 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
562 *
563 * @param[in] pDest The destination buffer to copy into.
564 * @param[in] value The value to set the bytes to.
565 *
566 * Note that like @c memset(), the pointer in @c pDest is not checked
567 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100568 */
569static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
570
571
572/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700573 * @brief Copy a pointer into a @ref UsefulBuf.
574 *
575 * @param[in,out] Dest The destination buffer to copy into.
576 * @param[in] ptr The source to copy from.
577 * @param[in] uLen Length of the source; amount to copy.
578 *
579 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
580 * on failure.
581 *
582 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
583 * than @c pDest->len.
584 *
585 * Note that like @c memcpy(), the pointers are not checked and this
586 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100587 */
588static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
589 const void *ptr,
590 size_t uLen);
591
592
593/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700594 * @brief Returns a truncation of a @ref UsefulBufC.
595 *
596 * @param[in] UB The buffer to get the head of.
597 * @param[in] uAmount The number of bytes in the head.
598 *
599 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100600 */
601static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
602
603
604/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700605 * @brief Returns bytes from the end of a @ref UsefulBufC.
606 *
607 * @param[in] UB The buffer to get the tail of.
608 * @param[in] uAmount The offset from the start where the tail is to begin.
609 *
610 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
611 * if @c uAmount is greater than the length of the @ref UsefulBufC.
612 *
613 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
614 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
615 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100616 */
617static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
618
619
620/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700621 * @brief Compare one @ref UsefulBufC to another.
622 *
623 * @param[in] UB1 The first buffer to compare.
624 * @param[in] UB2 The second buffer to compare.
625 *
626 * @return 0, positive or negative value.
627 *
628 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
629 * less than @c UB2 if it is shorter or the first byte that is not the
630 * same is less.
631 *
632 * Returns 0 if the inputs are the same.
633 *
634 * Returns a positive value if @c UB2 is less than @c UB1.
635 *
636 * All that is of significance is that the result is positive, negative
637 * or 0. (This doesn't return the difference between the first
638 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100639 */
640int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
641
642
643/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700644 * @brief Find first byte that is not a particular byte value.
645 *
646 * @param[in] UB The destination buffer for byte comparison.
647 * @param[in] uValue The byte value to compare to.
648 *
649 * @return Offset of first byte that isn't @c uValue or
650 * @c SIZE_MAX if all bytes are @c uValue.
651 *
652 * Note that unlike most comparison functions, 0
653 * does not indicate a successful comparison, so the
654 * test for match is:
655 *
656 * UsefulBuf_IsValue(...) == SIZE_MAX
657 *
658 * If @c UB is null or empty, there is no match
659 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100660 */
661size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
662
663
664/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700665 * @brief Find one @ref UsefulBufC in another.
666 *
667 * @param[in] BytesToSearch Buffer to search through.
668 * @param[in] BytesToFind Buffer with bytes to be found.
669 *
670 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100671 */
672size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
673
674
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700675/**
Laurence Lundblade68769332024-11-03 13:09:20 -0800676 * @brief Skip leading bytes of a particular value in a string.
677 *
678 * @param[in] String The input string. String.ptr must not be @c NULL.
679 * @param[in] uByte The byte value.
680 *
681 * @return Substring with leading bytes with value @c uByte removed.
682 */
683UsefulBufC UsefulBuf_SkipLeading(UsefulBufC String, uint8_t uByte);
684
685
686/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700687 * @brief Convert a pointer to an offset with bounds checking.
688 *
689 * @param[in] UB A UsefulBuf.
690 * @param[in] p Pointer to convert to offset.
691 *
692 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700693*/
694static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
695
696
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700697/**
698 * @brief Convert an offset to a pointer with bounds checking.
699 *
700 * @param[in] UB A UsefulBuf.
701 * @param[in] uOffset Offset in @c pUInBuf.
702 *
703 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
704 */
705static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
706
707
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800708#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100709/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700710#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100711
712/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
713#define MakeUsefulBufOnStack(name, size) \
714 uint8_t __pBuf##name[(size)];\
715 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
716
717/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
718#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700719 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100720
721/** Deprecated function; use UsefulBuf_Unconst() instead */
722static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
723{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700724 UsefulBuf UB;
725
Laurence Lundblade3eead482023-12-16 20:53:22 -0700726 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300727 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700728
729 UB.len = UBC.len;
730
731 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100732}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800733#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100734
735
736
737
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200738#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100739/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700740 * @brief Copy a @c float to a @c uint32_t.
741 *
742 * @param[in] f Float value to copy.
743 *
744 * @return A @c uint32_t with the float bits.
745 *
746 * Convenience function to avoid type punning, compiler warnings and
747 * such. The optimizer usually reduces this to a simple assignment. This
748 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100749 */
750static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
751
752
753/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700754 * @brief Copy a @c double to a @c uint64_t.
755 *
756 * @param[in] d Double value to copy.
757 *
758 * @return A @c uint64_t with the double bits.
759 *
760 * Convenience function to avoid type punning, compiler warnings and
761 * such. The optimizer usually reduces this to a simple assignment. This
762 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100763 */
764static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
765
766
767/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700768 * @brief Copy a @c uint32_t to a @c float.
769 *
770 * @param[in] u32 Integer value to copy.
771 *
772 * @return The value as a @c float.
773 *
774 * Convenience function to avoid type punning, compiler warnings and
775 * such. The optimizer usually reduces this to a simple assignment. This
776 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100777 */
778static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
779
780
781/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700782 * @brief Copy a @c uint64_t to a @c double.
783 *
784 * @param[in] u64 Integer value to copy.
785 *
786 * @return The value as a @c double.
787 *
788 * Convenience function to avoid type punning, compiler warnings and
789 * such. The optimizer usually reduces this to a simple assignment. This
790 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100791 */
792static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200793#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100794
795
796
797
798/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700799 * UsefulOutBuf is a structure and functions (an object) for
800 * serializing data into a buffer to encode for a network protocol or
801 * write data to a file.
802 *
803 * The main idea is that all the pointer manipulation is performed by
804 * @ref UsefulOutBuf functions so the caller doesn't have to do any
805 * pointer manipulation. The pointer manipulation is centralized.
806 * This code has been reviewed and written carefully so it
807 * spares the caller of much of this work and results in safer code
808 * with less effort.
809 *
810 * The @ref UsefulOutBuf methods that add data to the output buffer
811 * always check the length and will never write off the end of the
812 * output buffer. If an attempt to add data that will not fit is made,
813 * an internal error flag will be set and further attempts to add data
814 * will not do anything.
815 *
816 * There is no way to ever write off the end of that buffer when
817 * calling the @c UsefulOutBuf_AddXxx() and
818 * @c UsefulOutBuf_InsertXxx() functions.
819 *
820 * The functions to add data do not report success of failure. The
821 * caller only needs to check for an error in the final call, either
822 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
823 * result. This makes the calling code cleaner.
824 *
825 * There is a utility function to get the error status anytime along
826 * the way for a special circumstance. There are functions to see how
827 * much room is left and see if some data will fit too, but their use
828 * is generally unnecessary.
829 *
830 * The general call flow is:
831 *
832 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
833 * buffer given to it can be from the heap, stack or
834 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
835 * macro that makes a buffer on the stack and initializes it.
836 *
837 * - Call methods like UsefulOutBuf_InsertString(),
838 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
839 * to output data. The append calls add data to the end of the
840 * valid data. The insert calls take a position argument.
841 *
842 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
843 * there were no errors and to get the serialized output bytes.
844 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700845 * @ref UsefulOutBuf can be used in a mode to calculate the size of
846 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700847 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700848 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700849 *
850 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700851 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700852 *
853 * The possible errors are:
854 *
855 * - The @ref UsefulOutBuf was not initialized or was corrupted.
856 *
857 * - An attempt was made to add data that will not fit.
858 *
859 * - An attempt was made to insert data at a position beyond the end of
860 * the buffer.
861 *
862 * - An attempt was made to insert data at a position beyond the valid
863 * data in the buffer.
864 *
865 * Some inexpensive simple sanity checks are performed before every
866 * data addition to guard against use of an uninitialized or corrupted
867 * UsefulOutBuf.
868 *
869 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
870 * encoder has almost no pointer manipulation in it, is easier to
871 * read, and easier to review.
872 *
873 * A @ref UsefulOutBuf is small and can go on the stack:
874 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
875 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100876 */
877typedef struct useful_out_buf {
Laurence Lundblade89f926d2025-01-01 19:37:09 -0700878 /** @private Memory that is being output to */
879 UsefulBuf UB;
880 /** @private length of the valid data, the insertion point */
881 size_t data_len;
882 /** @private Magic number to detect lack of initalization/corruption */
883 uint16_t magic;
884 /** @private Used to detect corruption and lack of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100885 uint8_t err;
886} UsefulOutBuf;
887
888
889/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700890 * This is a @ref UsefulBuf value that can be passed to
891 * UsefulOutBuf_Init() to have it calculate the size of the output
892 * buffer needed. Pass this for @c Storage, call all the append and
893 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
894 * returned @ref UsefulBufC has the size.
895 *
896 * As one can see, this is just a NULL pointer and very large size.
Laurence Lundblade89f926d2025-01-01 19:37:09 -0700897 * The NULL pointer tells @ref UsefulOutBuf to not copy any data.
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700898 */
899#ifdef __cplusplus
900#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
901#else
902#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
903#endif
904
905
906/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700907 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700908 *
909 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
910 * @param[in] Storage Buffer to output into.
911 *
912 * This initializes the @ref UsefulOutBuf with storage, sets the
913 * current position to the beginning of the buffer and clears the
914 * error state.
915 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700916 * See @ref SizeCalculateUsefulBuf for instructions on how to
917 * initialize a @ref UsefulOutBuf to calculate the size that would be
918 * output without actually outputting.
919 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700920 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100921 */
922void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
923
924
925/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700926 * Convenience macro to make a @ref UsefulOutBuf on the stack and
927 * initialize it with a stack buffer of the given size. The variable
928 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100929 */
930#define UsefulOutBuf_MakeOnStack(name, size) \
931 uint8_t __pBuf##name[(size)];\
932 UsefulOutBuf name;\
933 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
934
935
936/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700937 * @brief Reset a @ref UsefulOutBuf for re use.
938 *
939 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
940 *
941 * This sets the amount of data in the output buffer to none and
942 * clears the error state.
943 *
944 * The output buffer is still the same one and size as from the
945 * UsefulOutBuf_Init() call.
946 *
947 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100948 */
949static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
950
951
952/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700953 * @brief Returns position of end of data in the @ref UsefulOutBuf.
954 *
955 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
956 *
957 * @return position of end of data.
958 *
959 * On a freshly initialized @ref UsefulOutBuf with no data added, this
960 * will return 0. After 10 bytes have been added, it will return 10
961 * and so on.
962 *
963 * Generally, there is no need to call this for most uses of @ref
964 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100965 */
966static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
967
968
969/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700970 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
971 *
972 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
973 *
974 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100975 */
976static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
977
978
979/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700980 * @brief Inserts bytes into the @ref UsefulOutBuf.
981 *
982 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
983 * @param[in] NewData The bytes to insert.
984 * @param[in] uPos Index in output buffer at which to insert.
985 *
986 * @c NewData is the pointer and length for the bytes to be added to
987 * the output buffer. There must be room in the output buffer for all
988 * of @c NewData or an error will occur.
989 *
990 * The insertion point must be between 0 and the current valid
991 * data. If not, an error will occur. Appending data to the output
992 * buffer is achieved by inserting at the end of the valid data. This
993 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
994 *
995 * When insertion is performed, the bytes between the insertion point
996 * and the end of data previously added to the output buffer are slid
997 * to the right to make room for the new data.
998 *
999 * Overlapping buffers are OK. @c NewData can point to data in the
1000 * output buffer.
1001 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -07001002 * NewData.len may be 0 in which case nothing will be inserted.
1003 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001004 * If an error occurs, an error state is set in the @ref
1005 * UsefulOutBuf. No error is returned. All subsequent attempts to add
1006 * data will do nothing.
1007 *
1008 * The intended use is that all additions are made without checking
1009 * for an error. The error will be taken into account when
1010 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
1011 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +01001012 */
1013void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
1014 UsefulBufC NewData,
1015 size_t uPos);
1016
1017
1018/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001019 * @brief Insert a data buffer into the @ref UsefulOutBuf.
1020 *
1021 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1022 * @param[in] pBytes Pointer to the bytes to insert
1023 * @param[in] uLen Length of the bytes to insert
1024 * @param[in] uPos Index in output buffer at which to insert
1025 *
1026 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
1027 * the difference being a pointer and length is passed in rather than an
1028 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +01001029 */
1030static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
1031 const void *pBytes,
1032 size_t uLen,
1033 size_t uPos);
1034
1035
1036/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001037 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1038 *
1039 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1040 * @param[in] szString NULL-terminated string to insert.
1041 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001042 */
1043static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1044 const char *szString,
1045 size_t uPos);
1046
1047
1048/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001049 * @brief Insert a byte into the @ref UsefulOutBuf.
1050 *
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001051 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001052 * @param[in] byte Bytes to insert.
1053 * @param[in] uPos Index in output buffer at which to insert.
1054 *
1055 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1056 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001057 */
1058static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1059 uint8_t byte,
1060 size_t uPos);
1061
1062
1063/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001064 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1065 *
1066 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1067 * @param[in] uInteger16 Integer to insert.
1068 * @param[in] uPos Index in output buffer at which to insert.
1069 *
1070 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1071 * with the difference being a two-byte integer is to be inserted.
1072 *
1073 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001074 */
1075static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1076 uint16_t uInteger16,
1077 size_t uPos);
1078
1079
1080/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001081 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1082 *
1083 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1084 * @param[in] uInteger32 Integer to insert.
1085 * @param[in] uPos Index in output buffer at which to insert.
1086 *
1087 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1088 * with the difference being a four-byte integer is to be inserted.
1089 *
1090 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001091 */
1092static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1093 uint32_t uInteger32,
1094 size_t uPos);
1095
1096
1097/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001098 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1099 *
1100 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1101 * @param[in] uInteger64 Integer to insert.
1102 * @param[in] uPos Index in output buffer at which to insert.
1103 *
1104 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1105 * with the difference being an eight-byte integer is to be inserted.
1106 *
1107 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001108 */
1109static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1110 uint64_t uInteger64,
1111 size_t uPos);
1112
1113
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001114#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001115/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001116 * @brief Insert a @c float into the @ref UsefulOutBuf.
1117 *
1118 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1119 * @param[in] f @c float to insert.
1120 * @param[in] uPos Index in output buffer at which to insert.
1121 *
1122 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1123 * with the difference being a @c float is to be inserted.
1124 *
1125 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001126 */
1127static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1128 float f,
1129 size_t uPos);
1130
1131
1132/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001133 * @brief Insert a @c double into the @ref UsefulOutBuf.
1134 *
1135 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1136 * @param[in] d @c double to insert.
1137 * @param[in] uPos Index in output buffer at which to insert.
1138 *
1139 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1140 * with the difference being a @c double is to be inserted.
1141 *
1142 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001143 */
1144static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1145 double d,
1146 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001147#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001148
1149
1150/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001151 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1152 *
1153 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1154 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1155 *
1156 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1157 * with the insertion point at the end of the valid data.
1158 */
Michael Eckel5c531332020-03-02 01:35:30 +01001159static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1160 UsefulBufC NewData);
1161
1162
1163/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001164 * @brief Append bytes to the @ref UsefulOutBuf.
1165 *
1166 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1167 * @param[in] pBytes Pointer to bytes to append.
1168 * @param[in] uLen Length of @c pBytes to append.
1169 *
1170 * See UsefulOutBuf_InsertData() for details. This does the same with
1171 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001172 */
1173static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1174 const void *pBytes,
1175 size_t uLen);
1176
1177
1178/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001179 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1180 *
1181 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1182 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001183 */
1184static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1185 const char *szString);
1186
1187
1188/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001189 * @brief Append a byte to the @ref UsefulOutBuf
1190 *
1191 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1192 * @param[in] byte Bytes to append.
1193 *
1194 * See UsefulOutBuf_InsertByte() for details. This does the same
1195 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001196 */
1197static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1198 uint8_t byte);
1199
1200
1201/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001202 * @brief Append an integer to the @ref UsefulOutBuf
1203 *
1204 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1205 * @param[in] uInteger16 Integer to append.
1206 *
1207 * See UsefulOutBuf_InsertUint16() for details. This does the same
1208 * with the insertion point at the end of the valid data.
1209 *
1210 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001211 */
1212static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1213 uint16_t uInteger16);
1214
1215
1216/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001217 * @brief Append an integer to the @ref UsefulOutBuf
1218 *
1219 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1220 * @param[in] uInteger32 Integer to append.
1221 *
1222 * See UsefulOutBuf_InsertUint32() for details. This does the same
1223 * with the insertion point at the end of the valid data.
1224 *
1225 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001226 */
1227static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1228 uint32_t uInteger32);
1229
1230
1231/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001232 * @brief Append an integer to the @ref UsefulOutBuf
1233 *
1234 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1235 * @param[in] uInteger64 Integer to append.
1236 *
1237 * See UsefulOutBuf_InsertUint64() for details. This does the same
1238 * with the insertion point at the end of the valid data.
1239 *
1240 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001241 */
1242static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1243 uint64_t uInteger64);
1244
1245
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001246#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001247/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001248 * @brief Append a @c float to the @ref UsefulOutBuf
1249 *
1250 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1251 * @param[in] f @c float to append.
1252 *
1253 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1254 * the insertion point at the end of the valid data.
1255 *
1256 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001257 */
1258static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1259 float f);
1260
1261
1262/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001263 * @brief Append a @c double to the @ref UsefulOutBuf
1264 *
1265 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1266 * @param[in] d @c double to append.
1267 *
1268 * See UsefulOutBuf_InsertDouble() for details. This does the same
1269 * with the insertion point at the end of the valid data.
1270 *
1271 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001272 */
1273static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1274 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001275#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001276
1277
1278/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001279 * @brief Returns the current error status.
1280 *
1281 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1282 *
1283 * @return 0 if all OK, 1 on error.
1284 *
1285 * This returns the error status since a call to either
1286 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1287 * goes into the error state, it will stay until one of those
1288 * functions is called.
1289 *
1290 * Possible error conditions are:
1291 * - bytes to be inserted will not fit
1292 * - insertion point is out of buffer or past valid data
1293 * - current position is off end of buffer (probably corrupted or uninitialized)
1294 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001295 */
1296static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1297
1298
1299/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001300 * @brief Returns number of bytes unused used in the output buffer.
1301 *
1302 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1303 *
1304 * @return Number of unused bytes or zero.
1305 *
1306 * Because of the error handling strategy and checks in
1307 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1308 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001309 */
1310static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1311
1312
1313/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001314 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1315 *
1316 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1317 * @param[in] uLen Number of bytes for which to check
1318 *
1319 * @return 1 if @c uLen bytes will fit, 0 if not.
1320 *
1321 * Because of the error handling strategy and checks in
1322 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1323 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001324 */
1325static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1326
1327
1328 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001329 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1330 *
1331 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1332 *
1333 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1334 *
1335 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1336 * just calculating the length of the encoded data.
1337 */
Michael Eckel5c531332020-03-02 01:35:30 +01001338static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1339
1340
1341/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001342 * @brief Returns pointer and length of the output buffer not yet used.
1343 *
1344 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1345 *
1346 * @return pointer and length of output buffer not used.
1347 *
1348 * This is an escape that allows the caller to write directly
1349 * to the output buffer without any checks. This doesn't
1350 * change the output buffer or state. It just returns a pointer
1351 * and length of the bytes remaining.
1352 *
1353 * This is useful to avoid having the bytes to be added all
1354 * in a contiguous buffer. Its use can save memory. A good
1355 * example is in the COSE encrypt implementation where
1356 * the output of the symmetric cipher can go directly
1357 * into the output buffer, rather than having to go into
1358 * an intermediate buffer.
1359 *
1360 * See UsefulOutBuf_Advance() which is used to tell
1361 * UsefulOutBuf how much was written.
1362 *
1363 * Warning: this bypasses the buffer safety provided by
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001364 * @ref UsefulOutBuf!
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001365 */
1366static inline UsefulBuf
1367UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1368
1369
1370/**
1371 * @brief Advance the amount output assuming it was written by the caller.
1372 *
1373 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1374 * @param[in] uAmount The amount to advance.
1375 *
1376 * This advances the position in the output buffer
Laurence Lundblade88ba5662024-11-03 02:10:24 -08001377 * by @c uAmount. This assumes that the
1378 * caller has written @c uAmount to the pointer obtained
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001379 * with UsefulOutBuf_GetOutPlace().
1380 *
1381 * Warning: this bypasses the buffer safety provided by
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001382 * @ref UsefulOutBuf!
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001383 */
1384void
1385UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1386
1387
1388/**
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001389 * @brief Returns the data put into a @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001390 *
1391 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1392 *
1393 * @return The valid data in @ref UsefulOutBuf or
1394 * @ref NULLUsefulBufC if there was an error adding data.
1395 *
1396 * The storage for the returned data is the @c Storage parameter
1397 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1398 *
1399 * This can be called anytime and many times to get intermediate
1400 * results. It doesn't change the data or reset the current position,
1401 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001402 */
1403UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1404
1405
1406/**
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001407 * @brief Copy out the data put into a @ref UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001408 *
1409 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1410 * @param[out] Dest The destination buffer to copy into.
1411 *
1412 * @return Pointer and length of copied data or @c NULLUsefulBufC
1413 * if it will not fit in the @c Dest buffer or the error
1414 * state was entered.
1415 *
1416 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001417 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001418 */
Michael Eckel5c531332020-03-02 01:35:30 +01001419UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1420
1421
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001422/**
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001423 * @brief Returns data starting at an offset that was put into a @ref UsefulOutBuf.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001424 *
1425 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1426 * @param[in] uOffset Offset to bytes to return.
1427 *
1428 * @return NULLUsefulBufC or the bytes at the offset.
1429 *
1430 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1431 * maybe specified. It returns the bytes starting at @c uOffset to the
1432 * end of what was encoded so far. Calling this with @c uOffset 0 is
1433 * equivalent to UsefulOutBuf_OutUBuf().
1434 *
1435 * If there's nothing at @c uOffset or it is past the in the output
1436 * buffer, a \ref NULLUsefulBufC is returned.
1437 *
1438 * This is typically not needed in typical use. It is used by QCBOR
1439 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1440 * sorting CBOR maps.
1441 */
1442UsefulBufC
1443UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1444
1445
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001446/**
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001447 * @brief Return a substring of the output data.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001448 *
1449 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1450 * @param[in] uStart Offset of start of substring.
1451 * @param[in] uLen Length of substring.
1452 *
1453 * This is the same as UsefulOutBuf_OutUBuf(), but returns a
1454 * substring. @c NULLUsefulBufC is returned if the requested substring
1455 * is off the end of the output bytes or if in error state.
1456 */
Laurence Lundblade534112f2025-02-26 15:12:47 -07001457UsefulBufC UsefulOutBuf_OutSubString(UsefulOutBuf *pUOutBuf,
1458 const size_t uStart,
1459 const size_t uLen);
Laurence Lundbladee2226742024-08-16 10:50:23 -07001460
1461
1462/**
1463 * @brief Retrieve the storage buffer passed in to UsefulOutBuf_Init().
1464 *
1465 * @param[in] pUOutBuf The encoding context.
1466 *
1467 * @return The output storage buffer passed to UsefulOutBuf_Init().
1468 *
1469 * This doesn't give any information about how much has been encoded
1470 * or the error state. It just returns the exact @ref UsefulOutBuf given
1471 * to UsefulOutBuf_Init().
1472 */
1473static UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pUOutBuf);
1474
Michael Eckel5c531332020-03-02 01:35:30 +01001475
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001476/**
1477 * @brief Compare bytes at offsets.
1478 *
1479 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1480 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001481 * @param[in] uLen1 Length of first bytes to compare.
1482 * @param[in] uStart2 Offset of second bytes to compare.
1483 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001484 *
1485 * @return 0 for equality, positive if uStart1 is lexographically larger,
1486 * negative if uStart2 is lexographically larger.
Laurence Lundblade926ccfc2024-12-05 20:34:55 -08001487 *
Laurence Lundblade534112f2025-02-26 15:12:47 -07001488 * This looks into bytes that have been output at the offsets
1489 * @c start1 and @c start2. It compares bytes at those two starting
1490 * points until they are not equal or @c uLen1 or @c uLen2 is
1491 * reached. If the length of the string given is off the end of the
1492 * output data, the string will be effectively (not actually)
1493 * truncated to the data in the output buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001494 *
Laurence Lundblade534112f2025-02-26 15:12:47 -07001495 * This function returns a positive value if the first string
1496 * lexicographically precedes the second and a negative value if the
1497 * second precedes the first. If the strings are equal, it returns
1498 * zero.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001499 *
Laurence Lundblade534112f2025-02-26 15:12:47 -07001500 * If one string is a substring of the other, the shorter string is
1501 * considered smaller. For example, if the first string is "ab" and
1502 * the second is "abc", a positive value is returned. The empty string
1503 * is always the smallest and sorts ahead of all others.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001504 *
Laurence Lundblade534112f2025-02-26 15:12:47 -07001505 * If either starting offset is beyond the end of the output buffer,
1506 * the function returns zero. It is the caller’s responsibility to
1507 * ensure that offsets are within bounds so that a valid comparison is
1508 * performed. No data will ever be read beyond the buffer’s end,
1509 * making the function safe regardless of the provided offsets.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001510 *
1511 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001512 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1513 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001514 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001515int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1516 size_t uStart1, size_t uLen1,
1517 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001518
1519/**
1520 * @brief Swap two regions of output bytes.
1521 *
1522 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1523 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1524 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1525 * @param[in] uEndOffset Offset to end of region to be swappe.
1526 *
1527 * This reaches into bytes that have been output and swaps two
1528 * adjacent regions.
1529 *
1530 * If any of the offsets are outside the range of valid data, no
1531 * swapping will be performed. If the start is not the smallest and
1532 * the pivot is not in the middle no swapping will be performed.
1533 *
1534 * The byte at @c uStartOffset will participate in the swapping. The
1535 * byte at @c uEndOffset will not participate in the swapping, only
1536 * the byte before it.
1537 *
1538 * This is a relatively odd function in that it works on data in the
1539 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1540 * maps.
1541 */
1542void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1543 size_t uStartOffset,
1544 size_t uPivotOffset,
1545 size_t uEndOffset);
1546
1547
Michael Eckel5c531332020-03-02 01:35:30 +01001548
1549
1550/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001551 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1552 * for parsing data received. Initialize it with the data from the
1553 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1554 * get data chunks of various types. A position cursor is maintained
1555 * internally.
1556 *
1557 * As long as the functions here are used, there will never be any
1558 * reference off the end of the given buffer (except
1559 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1560 * called incorrectly, an attempt is made to seek off the end of the
1561 * buffer or such. This makes it easier to write safe and correct
1562 * code. For example, the QCBOR decoder implementation is safer and
1563 * easier to review through its use of @ref UsefulInputBuf.
1564 *
1565 * @ref UsefulInputBuf maintains an internal error state. The
1566 * intended use is fetching data chunks without any error checks until
1567 * the end. If there was any error, such as an attempt to fetch data
1568 * off the end, the error state is entered and no further data will be
1569 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1570 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1571 * null is not dereferenced, the error check can be put off until the
1572 * end, simplifying the calling code.
1573 *
1574 * The integer and float parsing expects network byte order (big
1575 * endian). Network byte order is what is used by TCP/IP, CBOR and
1576 * most internet protocols.
1577 *
1578 * Lots of inline functions are used to keep code size down. The
1579 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1580 * code size a lot. The only non-inline code is
1581 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1582 * @ref UsefulInputBuf doesn't add much code for all the messy
1583 * hard-to-get right issues with parsing binary protocols in C that it
1584 * solves.
1585 *
1586 * The parse context size is:
1587 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1588 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001589 */
1590typedef struct useful_input_buf {
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001591 /** @private Data being parsed */
1592 UsefulBufC UB;
1593 /** @private Current offset in data being parse */
1594 size_t cursor;
1595 /** @private Check for corrupted or uninitialized UsefulInputBuf */
1596 uint16_t magic;
1597 /** @private Set if request goes off end or magic number is bad */
1598 uint8_t err;
Michael Eckel5c531332020-03-02 01:35:30 +01001599} UsefulInputBuf;
1600
Laurence Lundblade89f926d2025-01-01 19:37:09 -07001601/** @private The actual value of @c magic in UsefulInputBuf. */
Michael Eckel5c531332020-03-02 01:35:30 +01001602#define UIB_MAGIC (0xB00F)
1603
1604
1605/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001606 * @brief Initialize the @ref UsefulInputBuf structure before use.
1607 *
1608 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1609 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001610 */
1611static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1612
1613
1614/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001615 * @brief Returns current position in input buffer.
1616 *
1617 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1618 *
1619 * @return Integer position of the cursor.
1620 *
1621 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001622 */
1623static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1624
1625
1626/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001627 * @brief Sets the current position in input buffer.
1628 *
1629 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1630 * @param[in] uPos Position to set to.
1631 *
1632 * If the position is off the end of the input buffer, the error state
1633 * is entered.
1634 *
1635 * Seeking to a valid position in the buffer will not reset the error
1636 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001637 */
1638static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1639
1640
1641/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001642 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1643 * the unconsumed bytes.
1644 *
1645 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1646 *
1647 * @return Number of bytes unconsumed or 0 on error.
1648 *
1649 * Returns 0 if the cursor is invalid or corruption of the
1650 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001651 */
1652static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1653
1654
1655/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001656 * @brief Check if there are unconsumed bytes.
1657 *
1658 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1659 * @param[in] uLen Number of bytes to check availability for.
1660 *
1661 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001662 */
1663static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1664
1665
1666/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001667 * @brief Convert a pointer to an offset with bounds checking.
1668 *
1669 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1670 * @param[in] p Pointer to convert to offset.
1671 *
1672 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1673 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001674static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1675
1676
1677/**
1678 * @brief Convert an offset to a pointer with bounds checking.
1679 *
1680 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1681 * @param[in] uOffset Offset in @c pUInBuf.
1682 *
1683 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1684 */
1685static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001686
1687
1688/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001689 * @brief Get pointer to bytes out of the input buffer.
1690 *
1691 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1692 * @param[in] uNum Number of bytes to get.
1693 *
1694 * @return Pointer to bytes.
1695 *
1696 * This consumes @c uNum bytes from the input buffer. This returns a
1697 * pointer to the start of the @c uNum bytes.
1698 *
1699 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1700 * returned and the error state is entered.
1701 *
1702 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001703 */
1704const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1705
1706
1707/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001708 * @brief Get @ref UsefulBuf out of the input buffer.
1709 *
1710 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1711 * @param[in] uNum Number of bytes to get.
1712 *
1713 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1714 *
1715 * This consumes @c uNum bytes from the input buffer and returns the
1716 * pointer and length for them as a @ref UsefulBufC. The length
1717 * returned will always be @c uNum. The position cursor is advanced by
1718 * @c uNum bytes.
1719 *
1720 * If there are not @c uNum bytes in the input buffer, @ref
1721 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001722 */
1723static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1724
1725
1726/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001727 * @brief Get a byte out of the input buffer.
1728 *
1729 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1730 *
1731 * @return The byte.
1732 *
1733 * This consumes 1 byte from the input buffer, returns it and advances
1734 * the position cursor by 1.
1735 *
1736 * If there is not 1 byte in the buffer, 0 will be returned for the
1737 * byte and the error state is entered. To know if the 0 returned was
1738 * in error or the real value, the error state must be checked. If
1739 * possible, put this off until all values are retrieved to have
1740 * smaller and simpler code, but if not possible
1741 * UsefulInputBuf_GetError() can be called. Also, in the error state
1742 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1743 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001744 */
1745static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1746
1747
1748/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001749 * @brief Get a @c uint16_t out of the input buffer.
1750 *
1751 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1752 *
1753 * @return The @c uint16_t.
1754 *
1755 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1756 * a @c uint16_t and two bytes are consumed.
1757 *
1758 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001759 */
1760static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1761
1762
1763/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001764 * @brief Get a @c uint32_t out of the input buffer.
1765 *
1766 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1767 *
1768 * @return The @c uint32_t.
1769 *
1770 * See UsefulInputBuf_GetByte(). This works the same, except it
1771 * returns a @c uint32_t and four bytes are consumed.
1772 *
1773 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001774 */
1775static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1776
1777
1778/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001779 * @brief Get a @c uint64_t out of the input buffer.
1780 *
1781 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1782 *
1783 * @return The uint64_t.
1784 *
1785 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1786 * a @c uint64_t and eight bytes are consumed.
1787 *
1788 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001789 */
1790static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1791
1792
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001793#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001794/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001795 * @brief Get a float out of the input buffer.
1796 *
1797 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1798 *
1799 * @return The float.
1800 *
1801 * See UsefulInputBuf_GetByte(). This works the same, except it
1802 * returns a float and four bytes are consumed.
1803 *
1804 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001805 */
1806static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1807
1808
1809/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001810 * @brief Get a double out of the input buffer.
1811 *
1812 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1813 *
1814 * @return The double.
1815 *
1816 * See UsefulInputBuf_GetByte(). This works the same, except it
1817 * returns a double and eight bytes are consumed.
1818 *
1819 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001820 */
1821static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001822#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001823
1824
1825/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001826 * @brief Get the error status.
1827 *
1828 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1829 *
1830 * @return 0 if not in the error state, 1 if in the error state.
1831 *
1832 * This returns whether the @ref UsefulInputBuf is in the
1833 * error state or not.
1834 *
1835 * The error state is entered for one of these reasons:
1836 * - Attempt to fetch data past the end of the buffer
1837 * - Attempt to seek to a position past the end of the buffer
1838 * - Attempt to get data from an uninitialized or corrupt instance
1839 * of @ref UsefulInputBuf
1840 *
1841 * Once in the error state, it can only be cleared by calling
1842 * UsefulInputBuf_Init().
1843 *
1844 * For many use cases, it is possible to only call this once after all
1845 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1846 * possible if no reference to the data returned are needed before the
1847 * error state is checked.
1848 *
1849 * In some cases UsefulInputBuf_GetUsefulBuf() or
1850 * UsefulInputBuf_GetBytes() can stand in for this because they return
1851 * @c NULL if the error state has been entered. (The others can't stand
1852 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001853 */
1854static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1855
1856
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001857/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001858 * @brief Gets the input buffer length.
1859 *
1860 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1861 *
1862 * @return The length of the input buffer.
1863 *
1864 * This returns the length of the input buffer set by
1865 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001866 */
1867static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1868
1869
1870/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001871 * @brief Alters the input buffer length (use with caution).
1872 *
1873 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1874 * @param[in] uNewLen The new length of the input buffer.
1875 *
1876 * This alters the internal remembered length of the input buffer set
1877 * when UsefulInputBuf_Init() was called.
1878 *
1879 * The new length given here should always be equal to or less than
1880 * the length given when UsefulInputBuf_Init() was called. Making it
1881 * larger allows @ref UsefulInputBuf to run off the input buffer.
1882 *
1883 * The typical use is to set a length shorter than that when
1884 * initialized to constrain parsing. If
1885 * UsefulInputBuf_GetBufferLength() was called before this, then the
1886 * original length can be restored with another call to this.
1887 *
1888 * This should be used with caution. It is the only
1889 * @ref UsefulInputBuf method that can violate the safety of input
1890 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001891 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001892static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001893
1894
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001895/** @brief Retrieve the undecoded input buffer.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001896 *
1897 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1898 *
1899 * @return The input that was given to UsefulInputBuf_Init().
1900 *
1901 * A simple convenience method, should it be useful to get the original input back.
1902 */
1903static UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pUInBuf);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001904
1905
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001906/**
1907 * @brief Compare two ranges of bytes somewhere in the input buffer.
1908 *
1909 * @param[in] pUInBuf The input buffer.
1910 * @param[in] uOffset1 Offset of first range of bytes.
1911 * @param[in] uLen1 Length of first range of bytes.
1912 * @param[in] uOffset2 Offset of second range of bytes.
1913 * @param[in] uLen2 Length of second range of bytes.
1914 *
1915 * This returns the same as UsefulBuf_Compare().
Laurence Lundblade926ccfc2024-12-05 20:34:55 -08001916 *
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001917 * If the offset or the length plus offset or a range extends outside
1918 * the input buffer, that range of bytes will be considered greater
1919 * than the other string. If both are outside this is considered a
1920 * degenerate condition and the first string is considered larger.
1921 *
1922 * This is a somewhat odd function of UsefulInputBuf as it is not used
1923 * for consuming data. QCBOR uses it for map order and duplicate
1924 * checking.
1925 */
1926int
1927UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
1928 const size_t uOffset1,
1929 const size_t uLen1,
1930 const size_t uOffset2,
1931 const size_t uLen2);
Michael Eckel5c531332020-03-02 01:35:30 +01001932
1933
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001934
1935
Michael Eckel5c531332020-03-02 01:35:30 +01001936/*----------------------------------------------------------
1937 Inline implementations.
1938 */
1939static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1940{
1941 return !UB.ptr;
1942}
1943
1944
1945static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1946{
1947 return !UB.ptr;
1948}
1949
1950
1951static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1952{
1953 return !UB.len;
1954}
1955
1956
1957static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1958{
1959 return !UB.len;
1960}
1961
1962
1963static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1964{
1965 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1966}
1967
1968
1969static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1970{
1971 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1972}
1973
1974
1975static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1976{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001977 UsefulBufC UBC;
1978 UBC.ptr = UB.ptr;
1979 UBC.len = UB.len;
1980
1981 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001982}
1983
Michael Eckel5c531332020-03-02 01:35:30 +01001984static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1985{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001986 UsefulBuf UB;
1987
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001988 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001989 * the one place in UsefulBuf where it needs to be quieted.
1990 */
1991 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001992
1993 UB.len = UBC.len;
1994
1995 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001996}
1997
1998
1999static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
2000{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002001 UsefulBufC UBC;
2002 UBC.ptr = szString;
2003 UBC.len = strlen(szString);
2004 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002005}
2006
2007
2008static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
2009{
2010 return UsefulBuf_CopyOffset(Dest, 0, Src);
2011}
2012
2013
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002014static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01002015{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002016 memset(Dest.ptr, value, Dest.len);
2017
2018 UsefulBufC UBC;
2019 UBC.ptr = Dest.ptr;
2020 UBC.len = Dest.len;
2021
2022 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002023}
2024
2025
2026static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
2027{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002028 UsefulBufC UBC;
2029 UBC.ptr = ptr;
2030 UBC.len = len;
2031 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002032}
2033
2034
2035static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
2036{
2037 if(uAmount > UB.len) {
2038 return NULLUsefulBufC;
2039 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002040 UsefulBufC UBC;
2041
2042 UBC.ptr = UB.ptr;
2043 UBC.len = uAmount;
2044
2045 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002046}
2047
2048
2049static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
2050{
2051 UsefulBufC ReturnValue;
2052
2053 if(uAmount > UB.len) {
2054 ReturnValue = NULLUsefulBufC;
2055 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002056 ReturnValue.ptr = NULL;
2057 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002058 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002059 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
2060 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002061 }
2062
2063 return ReturnValue;
2064}
2065
2066
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002067static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
2068{
2069 if(UB.ptr == NULL) {
2070 return SIZE_MAX;
2071 }
2072
2073 if(p < UB.ptr) {
2074 /* given pointer is before start of buffer */
2075 return SIZE_MAX;
2076 }
2077
Laurence Lundblade3eead482023-12-16 20:53:22 -07002078 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002079 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002080
2081 if(uOffset >= UB.len) {
2082 /* given pointer is off the end of the buffer */
2083 return SIZE_MAX;
2084 }
2085
2086 return uOffset;
2087}
2088
Michael Eckel5c531332020-03-02 01:35:30 +01002089
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002090static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
2091{
2092 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
2093 return NULL;
2094 }
2095
2096 return (const uint8_t *)UB.ptr + uOffset;
2097}
2098
2099
2100
2101
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002102#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002103static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
2104{
2105 uint32_t u32;
2106 memcpy(&u32, &f, sizeof(uint32_t));
2107 return u32;
2108}
2109
2110static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2111{
2112 uint64_t u64;
2113 memcpy(&u64, &d, sizeof(uint64_t));
2114 return u64;
2115}
2116
2117static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2118{
2119 double d;
2120 memcpy(&d, &u64, sizeof(uint64_t));
2121 return d;
2122}
2123
2124static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2125{
2126 float f;
2127 memcpy(&f, &u32, sizeof(uint32_t));
2128 return f;
2129}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002130#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002131
2132
2133
2134
2135static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2136{
2137 pMe->data_len = 0;
2138 pMe->err = 0;
2139}
2140
2141
2142static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2143{
2144 return pMe->data_len;
2145}
2146
2147
2148static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2149{
2150 return 0 == pMe->data_len;
2151}
2152
2153
2154static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2155 const void *pBytes,
2156 size_t uLen,
2157 size_t uPos)
2158{
2159 UsefulBufC Data = {pBytes, uLen};
2160 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2161}
2162
2163
2164static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2165 const char *szString,
2166 size_t uPos)
2167{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002168 UsefulBufC UBC;
2169 UBC.ptr = szString;
2170 UBC.len = strlen(szString);
2171
2172 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002173}
2174
2175
2176static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2177 uint8_t byte,
2178 size_t uPos)
2179{
2180 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2181}
2182
2183
2184static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2185 uint16_t uInteger16,
2186 size_t uPos)
2187{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002188 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002189
2190 const void *pBytes;
2191
2192#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2193 pBytes = &uInteger16;
2194
2195#elif defined(USEFULBUF_CONFIG_HTON)
2196 uint16_t uTmp = htons(uInteger16);
2197 pBytes = &uTmp;
2198
2199#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2200 uint16_t uTmp = __builtin_bswap16(uInteger16);
2201 pBytes = &uTmp;
2202
2203#else
2204 uint8_t aTmp[2];
2205
2206 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2207 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2208
2209 pBytes = aTmp;
2210#endif
2211
2212 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2213}
2214
2215
2216static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2217 uint32_t uInteger32,
2218 size_t uPos)
2219{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002220 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002221
2222 const void *pBytes;
2223
2224#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2225 pBytes = &uInteger32;
2226
2227#elif defined(USEFULBUF_CONFIG_HTON)
2228 uint32_t uTmp = htonl(uInteger32);
2229 pBytes = &uTmp;
2230
2231#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2232 uint32_t uTmp = __builtin_bswap32(uInteger32);
2233
2234 pBytes = &uTmp;
2235
2236#else
2237 uint8_t aTmp[4];
2238
2239 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2240 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2241 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2242 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2243
2244 pBytes = aTmp;
2245#endif
2246
2247 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2248}
2249
2250static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002251 uint64_t uInteger64,
2252 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002253{
2254 const void *pBytes;
2255
2256#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002257 /* We have been told explicitly we are running on a big-endian
2258 * machine. Network byte order is big endian, so just copy. There
2259 * is no issue with alignment here because uInteger64 is always
2260 * aligned (and it doesn't matter if pBytes is aligned).
2261 */
Michael Eckel5c531332020-03-02 01:35:30 +01002262 pBytes = &uInteger64;
2263
2264#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002265 /* Use system function to handle big- and little-endian. This works
2266 * on both big- and little-endian machines, but hton() is not
2267 * always available or in a standard place so it is not used by
2268 * default. With some compilers and CPUs the code for this is very
2269 * compact through use of a special swap instruction and on
2270 * big-endian machines hton() will reduce to nothing.
2271 */
Michael Eckel5c531332020-03-02 01:35:30 +01002272 uint64_t uTmp = htonll(uInteger64);
2273
2274 pBytes = &uTmp;
2275
2276#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002277 /* Use built-in function for byte swapping. This usually compiles
2278 * to an efficient special byte swap instruction. Unlike hton() it
2279 * does not do this conditionally on the CPU endianness, so this
2280 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2281 */
Michael Eckel5c531332020-03-02 01:35:30 +01002282 uint64_t uTmp = __builtin_bswap64(uInteger64);
2283
2284 pBytes = &uTmp;
2285
2286#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002287 /* Default which works on every CPU with no dependency on anything
2288 * from the CPU, compiler, libraries or OS. This always works, but
2289 * it is usually a little larger and slower than hton().
2290 */
Michael Eckel5c531332020-03-02 01:35:30 +01002291 uint8_t aTmp[8];
2292
2293 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2294 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2295 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2296 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2297 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2298 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2299 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2300 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2301
2302 pBytes = aTmp;
2303#endif
2304
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002305 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002306 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2307}
2308
2309
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002310#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002311static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2312 float f,
2313 size_t uPos)
2314{
2315 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2316}
2317
2318
2319static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2320 double d,
2321 size_t uPos)
2322{
2323 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2324}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002325#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002326
2327
2328static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2329 UsefulBufC NewData)
2330{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002331 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002332 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2333}
2334
2335
2336static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2337 const void *pBytes,
2338 size_t uLen)
2339{
2340 UsefulBufC Data = {pBytes, uLen};
2341 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2342}
2343
2344
2345static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2346 const char *szString)
2347{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002348 UsefulBufC UBC;
2349 UBC.ptr = szString;
2350 UBC.len = strlen(szString);
2351
2352 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002353}
2354
2355
2356static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2357 uint8_t byte)
2358{
2359 UsefulOutBuf_AppendData(pMe, &byte, 1);
2360}
2361
2362
2363static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2364 uint16_t uInteger16)
2365{
2366 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2367}
2368
2369static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2370 uint32_t uInteger32)
2371{
2372 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2373}
2374
2375
2376static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2377 uint64_t uInteger64)
2378{
2379 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2380}
2381
2382
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002383#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002384static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2385 float f)
2386{
2387 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2388}
2389
2390
2391static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2392 double d)
2393{
2394 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2395}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002396#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002397
2398
2399static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2400{
2401 return pMe->err;
2402}
2403
2404
2405static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2406{
2407 return pMe->UB.len - pMe->data_len;
2408}
2409
2410
2411static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2412{
2413 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2414}
2415
2416
2417static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2418{
2419 return pMe->UB.ptr == NULL;
2420}
2421
2422
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002423static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2424{
2425 UsefulBuf R;
2426
2427 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002428 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002429 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2430 } else {
2431 R.ptr = NULL;
2432 }
2433
2434 return R;
2435}
2436
2437
Laurence Lundbladee2226742024-08-16 10:50:23 -07002438static inline UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pMe)
2439{
2440 return pMe->UB;
2441}
2442
2443
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002444
Michael Eckel5c531332020-03-02 01:35:30 +01002445
2446static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2447{
2448 pMe->cursor = 0;
2449 pMe->err = 0;
2450 pMe->magic = UIB_MAGIC;
2451 pMe->UB = UB;
2452}
2453
2454static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2455{
2456 return pMe->cursor;
2457}
2458
2459
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002460static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002461{
2462 return pMe->UB.len;
2463}
2464
2465
Michael Eckel5c531332020-03-02 01:35:30 +01002466static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2467{
2468 if(uPos > pMe->UB.len) {
2469 pMe->err = 1;
2470 } else {
2471 pMe->cursor = uPos;
2472 }
2473}
2474
2475
2476static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2477{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002478 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002479
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002480 /* Magic number is messed up. Either the structure got overwritten
2481 * or was never initialized.
2482 */
Michael Eckel5c531332020-03-02 01:35:30 +01002483 if(pMe->magic != UIB_MAGIC) {
Laurence Lundblade534112f2025-02-26 15:12:47 -07002484 /* Strangely gcov thinks the line is not covered by tests even
2485 * though it clearly is (tested with break point and printf) */
Michael Eckel5c531332020-03-02 01:35:30 +01002486 return 0;
2487 }
2488
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002489 /* The cursor is off the end of the input buffer given.
2490 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002491 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002492 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002493 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002494 */
Michael Eckel5c531332020-03-02 01:35:30 +01002495 if(pMe->cursor > pMe->UB.len) {
2496 return 0;
2497 }
2498
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002499 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002500 return pMe->UB.len - pMe->cursor;
2501}
2502
2503
2504static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2505{
2506 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2507}
2508
2509
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002510static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2511{
2512 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2513}
2514
2515
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002516static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2517 {
2518 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2519 }
2520
2521
Michael Eckel5c531332020-03-02 01:35:30 +01002522static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2523{
2524 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2525 if(!pResult) {
2526 return NULLUsefulBufC;
2527 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002528 UsefulBufC UBC;
2529 UBC.ptr = pResult;
2530 UBC.len = uNum;
2531 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002532 }
2533}
2534
2535
2536static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2537{
2538 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2539
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002540 /* The ternary operator is subject to integer promotion, because
2541 * the operands are smaller than int, so cast back to uint8_t is
2542 * needed to be completely explicit about types (for static
2543 * analyzers).
2544 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002545 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002546}
2547
2548static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2549{
2550 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2551
2552 if(!pResult) {
2553 return 0;
2554 }
2555
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002556 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002557#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2558 uint16_t uTmp;
2559 memcpy(&uTmp, pResult, sizeof(uint16_t));
2560
2561#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2562 return uTmp;
2563
2564#elif defined(USEFULBUF_CONFIG_HTON)
2565 return ntohs(uTmp);
2566
2567#else
2568 return __builtin_bswap16(uTmp);
2569
2570#endif
2571
2572#else
2573
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002574 /* The operations here are subject to integer promotion because the
2575 * operands are smaller than int. They will be promoted to unsigned
2576 * int for the shift and addition. The cast back to uint16_t is is
2577 * needed to be completely explicit about types (for static
2578 * analyzers).
2579 */
Michael Eckel5c531332020-03-02 01:35:30 +01002580 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2581
2582#endif
2583}
2584
2585
2586static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2587{
2588 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2589
2590 if(!pResult) {
2591 return 0;
2592 }
2593
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002594 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002595#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2596 uint32_t uTmp;
2597 memcpy(&uTmp, pResult, sizeof(uint32_t));
2598
2599#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2600 return uTmp;
2601
2602#elif defined(USEFULBUF_CONFIG_HTON)
2603 return ntohl(uTmp);
2604
2605#else
2606 return __builtin_bswap32(uTmp);
2607
2608#endif
2609
2610#else
2611 return ((uint32_t)pResult[0]<<24) +
2612 ((uint32_t)pResult[1]<<16) +
2613 ((uint32_t)pResult[2]<<8) +
2614 (uint32_t)pResult[3];
2615#endif
2616}
2617
2618
2619static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2620{
2621 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2622
2623 if(!pResult) {
2624 return 0;
2625 }
2626
2627#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002628 /* pResult will probably not be aligned. This memcpy() moves the
2629 * bytes into a temp variable safely for CPUs that can or can't do
2630 * unaligned memory access. Many compilers will optimize the
2631 * memcpy() into a simple move instruction.
2632 */
Michael Eckel5c531332020-03-02 01:35:30 +01002633 uint64_t uTmp;
2634 memcpy(&uTmp, pResult, sizeof(uint64_t));
2635
2636#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002637 /* We have been told expliclity this is a big-endian CPU. Since
2638 * network byte order is big-endian, there is nothing to do.
2639 */
Michael Eckel5c531332020-03-02 01:35:30 +01002640
2641 return uTmp;
2642
2643#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002644 /* We have been told to use ntoh(), the system function to handle
2645 * big- and little-endian. This works on both big- and
2646 * little-endian machines, but ntoh() is not always available or in
2647 * a standard place so it is not used by default. On some CPUs the
2648 * code for this is very compact through use of a special swap
2649 * instruction.
2650 */
Michael Eckel5c531332020-03-02 01:35:30 +01002651
2652 return ntohll(uTmp);
2653
2654#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002655 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2656 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2657 * __builtin_bswap64() and friends are not conditional on CPU
2658 * endianness so this must only be used on little-endian machines.
2659 */
Michael Eckel5c531332020-03-02 01:35:30 +01002660
2661 return __builtin_bswap64(uTmp);
2662
2663
2664#endif
2665
2666#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002667 /* This is the default code that works on every CPU and every
2668 * endianness with no dependency on ntoh(). This works on CPUs
2669 * that either allow or do not allow unaligned access. It will
2670 * always work, but usually is a little less efficient than ntoh().
2671 */
Michael Eckel5c531332020-03-02 01:35:30 +01002672
2673 return ((uint64_t)pResult[0]<<56) +
2674 ((uint64_t)pResult[1]<<48) +
2675 ((uint64_t)pResult[2]<<40) +
2676 ((uint64_t)pResult[3]<<32) +
2677 ((uint64_t)pResult[4]<<24) +
2678 ((uint64_t)pResult[5]<<16) +
2679 ((uint64_t)pResult[6]<<8) +
2680 (uint64_t)pResult[7];
2681#endif
2682}
2683
2684
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002685#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002686static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2687{
2688 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2689
2690 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2691}
2692
2693
2694static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2695{
2696 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2697
2698 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2699}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002700#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002701
2702
2703static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2704{
2705 return pMe->err;
2706}
2707
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002708
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002709static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002710{
2711 pMe->UB.len = uNewLen;
2712}
2713
Laurence Lundbladee2226742024-08-16 10:50:23 -07002714static inline UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pMe)
2715{
2716 return pMe->UB;
2717}
2718
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002719
Laurence Lundblade534112f2025-02-26 15:12:47 -07002720/* For backwards compatibility */
2721static inline UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pMe, const size_t uStart, const size_t uLen)
2722{
2723 return UsefulOutBuf_OutSubString(pMe, uStart, uLen);
2724}
2725
Michael Eckel5c531332020-03-02 01:35:30 +01002726#ifdef __cplusplus
2727}
2728#endif
2729
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002730#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002731
2732