blob: d67dd8585f41e567608aec1aea1415a968a4fd86 [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07003 * Copyright (c) 2018-2024, Laurence Lundblade.
Laurence Lundblade3eead482023-12-16 20:53:22 -07004 * Copyright (c) 2021, Arm Limited. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Michael Eckel5c531332020-03-02 01:35:30 +010033
34/*============================================================================
35 FILE: UsefulBuf.h
36
37 DESCRIPTION: General purpose input and output buffers
38
39 EDIT HISTORY FOR FILE:
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44 when who what, where, why
45 -------- ---- --------------------------------------------------
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -070046 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070047 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070048 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070049 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
50 19/11/2023 llundblade Add UsefulOutBuf_Swap().
51 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070052 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060053 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070054 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070055 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070056 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080057 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070058 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010059 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
60 5/21/2019 llundblade #define configs for efficient endianness handling.
61 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
62 3/23/2019 llundblade Big documentation & style update. No interface
63 change.
64 3/6/2019 llundblade Add UsefulBuf_IsValue()
65 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
66 12/13/2018 llundblade Documentation improvements
67 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
68 UsefulBufC.
69 02/02/18 llundbla Full support for integers in and out; fix pointer
70 alignment bug. Incompatible change: integers
71 in/out are now in network byte order.
72 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
73 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
74 comparison for < or > for unequal length buffers.
75 Added UsefulBuf_Set() function.
76 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
77 11/13/16 llundbla Initial Version.
78
79 =============================================================================*/
80
81#ifndef _UsefulBuf_h
82#define _UsefulBuf_h
83
84
85/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070086 * Endianness Configuration
87 *
88 * This code is written so it will work correctly on big- and
89 * little-endian CPUs without configuration or any auto-detection of
90 * endianness. All code here will run correctly regardless of the
91 * endianness of the CPU it is running on.
92 *
93 * There are four C preprocessor macros that can be set with #define
94 * to explicitly configure endianness handling. Setting them can
95 * reduce code size a little and improve efficiency a little.
96 *
97 * Note that most of QCBOR is unaffected by this configuration. Its
98 * endianness handling is integrated with the code that handles
99 * alignment and preferred serialization. This configuration does
100 * affect QCBOR's (planned) implementation of integer arrays (tagged
101 * arrays) and use of the functions here to serialize or deserialize
102 * integers and floating-point values.
103 *
104 * Following is the recipe for configuring the endianness-related
105 * #defines.
106 *
107 * The first option is to not define anything. This will work fine
108 * with all CPUs, OS's and compilers. The code for encoding integers
109 * may be a little larger and slower.
110 *
111 * If your CPU is big-endian then define
112 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
113 * for big-endian CPUs. It will be small and efficient because there
114 * will be no byte swapping.
115 *
116 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
117 * OS's and compilers, but not all. On big-endian CPUs this should
118 * give the most efficient code, the same as
119 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
120 * call the system-defined byte swapping method which is presumably
121 * implemented efficiently. In some cases, this will be a dedicated
122 * byte swap instruction like Intel's bswap.
123 *
124 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
125 * little-endian, it is also good to define
126 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
127 *
128 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
129 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
130 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
131 * system-defined byte swap method. However, note
132 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
133 * this is fixed now. Often hton() and ntoh() will call the built-in
134 * __builtin_bswapXX()() function, so this size issue could affect
135 * USEFULBUF_CONFIG_HTON.
136 *
137 * Last, run the tests. They must all pass.
138 *
139 * These #define config options affect the inline implementation of
140 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
141 * also affect the 16-, 32-bit, float and double versions of these
142 * functions. Since they are inline, the size effect is not in the
143 * UsefulBuf object code, but in the calling code.
144 *
145 * Summary:
146 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
147 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
148 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
149 * handle big and little-endian with system option.
150 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
151 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200152 *
153 * It is possible to run this code in environments where using floating point is
154 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
155 * that is related to handling floating point types, along with related
156 * interfaces. This makes it possible to compile the code with the compile
157 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100158 */
159
160#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
161#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
162#endif
163
164
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700165#include <stdint.h> /* for uint8_t, uint16_t.... */
166#include <string.h> /* for strlen, memcpy, memmove, memset */
167#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100168
169
170#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700171#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100172#endif
173
174#ifdef __cplusplus
175extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700176#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700177} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700178#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100179#endif
180
181/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700182 * @file UsefulBuf.h
183 *
184 * The goal of this code is to make buffer and pointer manipulation
185 * easier and safer when working with binary data.
186 *
187 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
188 * structures are used to represent buffers rather than ad hoc
189 * pointers and lengths.
190 *
191 * With these it is possible to write code that does little or no
192 * direct pointer manipulation for copying and formatting data. For
193 * example, the QCBOR encoder was written using these and has less
194 * pointer manipulation.
195 *
196 * While it is true that object code using these functions will be a
197 * little larger and slower than a white-knuckle clever use of
198 * pointers might be, but not by that much or enough to have an effect
199 * for most use cases. For security-oriented code this is highly
200 * worthwhile. Clarity, simplicity, reviewability and are more
201 * important.
202 *
203 * There are some extra sanity and double checks in this code to help
204 * catch coding errors and simple memory corruption. They are helpful,
205 * but not a substitute for proper code review, input validation and
206 * such.
207 *
208 * This code consists of a lot of inline functions and a few that are
209 * not. It should not generate very much object code, especially with
210 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100211 */
212
213
214/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700215 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
216 * hold a pointer and length for binary data. In C99 this data
217 * structure can be passed on the stack making a lot of code cleaner
218 * than carrying around a pointer and length as two parameters.
219 *
220 * This is also conducive to secure coding practice as the length is
221 * always carried with the pointer and the convention for handling a
222 * pointer and a length is clear.
223 *
224 * While it might be possible to write buffer and pointer code more
225 * efficiently in some use cases, the thought is that unless there is
226 * an extreme need for performance (e.g., you are building a
227 * gigabit-per-second IP router), it is probably better to have
228 * cleaner code you can be most certain about the security of.
229 *
230 * The non-const @ref UsefulBuf is usually used to refer an empty
231 * buffer to be filled in. The length is the size of the buffer.
232 *
233 * The const @ref UsefulBufC is usually used to refer to some data
234 * that has been filled in. The length is amount of valid data pointed
235 * to.
236 *
237 * A common use mode is to pass a @ref UsefulBuf to a function, the
238 * function puts some data in it, then the function returns a @ref
239 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
240 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
241 * so the constness stays correct. There is no single "in,out"
242 * parameter (if there was, it would have to be non-const). Note that
243 * the pointer returned in the @ref UsefulBufC usually ends up being
244 * the same pointer passed in as a @ref UsefulBuf, though this is not
245 * striclty required.
246 *
247 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
248 * @c NULL.
249 *
250 * There are functions and macros for the following:
251 * - Initializing
252 * - Create initialized const @ref UsefulBufC from compiler literals
253 * - Create initialized const @ref UsefulBufC from NULL-terminated string
254 * - Make an empty @ref UsefulBuf on the stack
255 * - Checking whether a @ref UsefulBuf is null, empty or both
256 * - Copying, copying with offset, copying head or tail
257 * - Comparing and finding substrings
258 *
259 * See also @ref UsefulOutBuf. It is a richer structure that has both
260 * the size of the valid data and the size of the buffer.
261 *
262 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
263 * it can go on the stack and be a function parameter or return value.
264 *
265 * Another way to look at it is this. C has the NULL-terminated string
266 * as a means for handling text strings, but no means or convention
267 * for binary strings. Other languages do have such means, Rust, an
268 * efficient compiled language, for example.
269 *
270 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
271 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
272 * out like anything".
273 */
Michael Eckel5c531332020-03-02 01:35:30 +0100274typedef struct q_useful_buf_c {
275 const void *ptr;
276 size_t len;
277} UsefulBufC;
278
279
280/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700281 * This non-const @ref UsefulBuf is typically used for some allocated
282 * memory that is to be filled in. The @c len is the amount of memory,
283 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100284 */
285typedef struct q_useful_buf {
286 void *ptr;
287 size_t len;
288} UsefulBuf;
289
290
291/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700292 * A null @ref UsefulBufC is one that has no value in the same way a
293 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
294 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
295 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100296 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700297/*
298 * NULLUsefulBufC and few other macros have to be
299 * definied differently in C than C++ because there
300 * is no common construct for a literal structure.
301 *
302 * In C compound literals are used.
303 *
304 * In C++ list initalization is used. This only works
305 * in C++11 and later.
306 *
307 * Note that some popular C++ compilers can handle compound
308 * literals with on-by-default extensions, however
309 * this code aims for full correctness with strict
310 * compilers so they are not used.
311 */
312#ifdef __cplusplus
313#define NULLUsefulBufC {NULL, 0}
314#else
315#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
316#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100317
318/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700319 * A null @ref UsefulBuf is one that has no memory associated the same
320 * way @c NULL points to nothing. It does not matter what @c len is.
321 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700322#ifdef __cplusplus
323#define NULLUsefulBuf {NULL, 0}
324#else
325#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
326#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100327
328
329/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700330 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
331 *
332 * @param[in] UB The UsefulBuf to check.
333 *
334 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100335 */
336static inline int UsefulBuf_IsNULL(UsefulBuf UB);
337
338
339/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700340 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
341 *
342 * @param[in] UB The @ref UsefulBufC to check.
343 *
344 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100345 */
346static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
347
348
349/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700350 * @brief Check if a @ref UsefulBuf is empty or not.
351 *
352 * @param[in] UB The @ref UsefulBuf to check.
353 *
354 * @return 1 if it is empty, 0 if not.
355 *
356 * An "empty" @ref UsefulBuf is one that has a value and can be
357 * considered to be set, but that value is of zero length. It is
358 * empty when @c len is zero. It doesn't matter what the @c ptr is.
359 *
360 * Many uses will not need to clearly distinguish a @c NULL @ref
361 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
362 * @c len 0. However if a use of @ref UsefulBuf needs to make a
363 * distinction then @c ptr should not be @c NULL when the @ref
364 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100365 */
366static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
367
368
369/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700370 * @brief Check if a @ref UsefulBufC is empty or not.
371 *
372 * @param[in] UB The @ref UsefulBufC to check.
373 *
374 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100375 */
376static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
377
378
379/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700380 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
381 *
382 * @param[in] UB The @ref UsefulBuf to check.
383 *
384 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100385 */
386static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
387
388
389/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700390 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
391 *
392 * @param[in] UB The @ref UsefulBufC to check.
393 *
394 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100395 */
396static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
397
398
399/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700400 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
401 *
402 * @param[in] UB The @ref UsefulBuf to convert.
403 *
404 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100405 */
406static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
407
408
409/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700410 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
411 *
412 * @param[in] UBC The @ref UsefulBuf to convert.
413 *
414 * @return A non-const @ref UsefulBuf struct.
415 *
416 * Use of this is not necessary for the intended use mode of @ref
417 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
418 * created to describe a buffer that has not had any data put in
419 * it. Then the data is put in it. Then a @ref UsefulBufC is create
420 * to describe the part with the data in it. This goes from non-const
421 * to const, so this function is not needed.
422 *
423 * If the -Wcast-qual warning is enabled, this function can be used to
424 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100425 */
426static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
427
428
429/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700430 * Convert a literal string to a @ref UsefulBufC.
431 *
432 * @c szString must be a literal string that @c sizeof() works on.
433 * This is better for literal strings than UsefulBuf_FromSZ() because
434 * it generates less code. It will not work on non-literal strings.
435 *
436 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100437 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700438#ifdef __cplusplus
439#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
440#else
Michael Eckel5c531332020-03-02 01:35:30 +0100441#define UsefulBuf_FROM_SZ_LITERAL(szString) \
442 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700443#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100444
445
446/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700447 * Convert a literal byte array to a @ref UsefulBufC.
448 *
449 * @c pBytes must be a literal string that @c sizeof() works on. It
450 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100451 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700452#ifdef __cplusplus
453#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
454#else
Michael Eckel5c531332020-03-02 01:35:30 +0100455#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700456 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
457#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100458
459/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700460 * Make an automatic variable named @c name of type @ref UsefulBuf and
461 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100462 */
463#define UsefulBuf_MAKE_STACK_UB(name, size) \
464 uint8_t __pBuf##name[(size)];\
465 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
466
467
468/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700469 * Make a byte array in to a @ref UsefulBuf. This is usually used on
470 * stack variables or static variables. Also see @ref
471 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100472 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700473#ifdef __cplusplus
474#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
475#else
Michael Eckel5c531332020-03-02 01:35:30 +0100476#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700477 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
478#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100479
480
481/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700482 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
483 *
484 * @param[in] szString The string to convert.
485 *
486 * @return A @ref UsefulBufC struct.
487 *
488 * @c UsefulBufC.ptr points to the string so its lifetime must be
489 * maintained.
490 *
491 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100492 */
493static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
494
495
496/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700497 * @brief Copy one @ref UsefulBuf into another at an offset.
498 *
499 * @param[in] Dest Destination buffer to copy into.
500 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
501 * @param[in] Src The bytes to copy.
502 *
503 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
504 *
505 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
506 * size of @c Dest.
507 *
508 * This fails and returns @ref NULLUsefulBufC if the @c Src length
509 * plus @c uOffset is greater than the length of @c Dest.
510 *
511 * The results are undefined if @c Dest and @c Src overlap.
512 *
513 * This assumes that there is valid data in @c Dest up to @c
514 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
515 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100516 */
517UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
518
519
520/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700521 * @brief Copy one @ref UsefulBuf into another.
522 *
523 * @param[in] Dest The destination buffer to copy into.
524 * @param[out] Src The source to copy from.
525 *
526 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
527 * on failure.
528 *
529 * This fails if @c Src.len is greater than @c Dest.len.
530 *
531 * Note that like @c memcpy(), the pointers are not checked and this
532 * will crash rather than return @ref NULLUsefulBufC if they are @c
533 * NULL or invalid.
534 *
535 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100536 */
537static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
538
539
540/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700541 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
542 *
543 * @param[in] pDest The destination buffer to copy into.
544 * @param[in] value The value to set the bytes to.
545 *
546 * Note that like @c memset(), the pointer in @c pDest is not checked
547 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100548 */
549static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
550
551
552/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700553 * @brief Copy a pointer into a @ref UsefulBuf.
554 *
555 * @param[in,out] Dest The destination buffer to copy into.
556 * @param[in] ptr The source to copy from.
557 * @param[in] uLen Length of the source; amount to copy.
558 *
559 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
560 * on failure.
561 *
562 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
563 * than @c pDest->len.
564 *
565 * Note that like @c memcpy(), the pointers are not checked and this
566 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100567 */
568static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
569 const void *ptr,
570 size_t uLen);
571
572
573/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700574 * @brief Returns a truncation of a @ref UsefulBufC.
575 *
576 * @param[in] UB The buffer to get the head of.
577 * @param[in] uAmount The number of bytes in the head.
578 *
579 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100580 */
581static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
582
583
584/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700585 * @brief Returns bytes from the end of a @ref UsefulBufC.
586 *
587 * @param[in] UB The buffer to get the tail of.
588 * @param[in] uAmount The offset from the start where the tail is to begin.
589 *
590 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
591 * if @c uAmount is greater than the length of the @ref UsefulBufC.
592 *
593 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
594 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
595 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100596 */
597static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
598
599
600/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700601 * @brief Compare one @ref UsefulBufC to another.
602 *
603 * @param[in] UB1 The first buffer to compare.
604 * @param[in] UB2 The second buffer to compare.
605 *
606 * @return 0, positive or negative value.
607 *
608 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
609 * less than @c UB2 if it is shorter or the first byte that is not the
610 * same is less.
611 *
612 * Returns 0 if the inputs are the same.
613 *
614 * Returns a positive value if @c UB2 is less than @c UB1.
615 *
616 * All that is of significance is that the result is positive, negative
617 * or 0. (This doesn't return the difference between the first
618 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100619 */
620int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
621
622
623/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700624 * @brief Find first byte that is not a particular byte value.
625 *
626 * @param[in] UB The destination buffer for byte comparison.
627 * @param[in] uValue The byte value to compare to.
628 *
629 * @return Offset of first byte that isn't @c uValue or
630 * @c SIZE_MAX if all bytes are @c uValue.
631 *
632 * Note that unlike most comparison functions, 0
633 * does not indicate a successful comparison, so the
634 * test for match is:
635 *
636 * UsefulBuf_IsValue(...) == SIZE_MAX
637 *
638 * If @c UB is null or empty, there is no match
639 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100640 */
641size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
642
643
644/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700645 * @brief Find one @ref UsefulBufC in another.
646 *
647 * @param[in] BytesToSearch Buffer to search through.
648 * @param[in] BytesToFind Buffer with bytes to be found.
649 *
650 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100651 */
652size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
653
654
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700655/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700656 * @brief Convert a pointer to an offset with bounds checking.
657 *
658 * @param[in] UB A UsefulBuf.
659 * @param[in] p Pointer to convert to offset.
660 *
661 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700662*/
663static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
664
665
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700666/**
667 * @brief Convert an offset to a pointer with bounds checking.
668 *
669 * @param[in] UB A UsefulBuf.
670 * @param[in] uOffset Offset in @c pUInBuf.
671 *
672 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
673 */
674static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
675
676
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800677#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100678/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700679#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100680
681/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
682#define MakeUsefulBufOnStack(name, size) \
683 uint8_t __pBuf##name[(size)];\
684 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
685
686/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
687#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700688 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100689
690/** Deprecated function; use UsefulBuf_Unconst() instead */
691static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
692{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700693 UsefulBuf UB;
694
Laurence Lundblade3eead482023-12-16 20:53:22 -0700695 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300696 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700697
698 UB.len = UBC.len;
699
700 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100701}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800702#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100703
704
705
706
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200707#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100708/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700709 * @brief Copy a @c float to a @c uint32_t.
710 *
711 * @param[in] f Float value to copy.
712 *
713 * @return A @c uint32_t with the float bits.
714 *
715 * Convenience function to avoid type punning, compiler warnings and
716 * such. The optimizer usually reduces this to a simple assignment. This
717 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100718 */
719static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
720
721
722/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700723 * @brief Copy a @c double to a @c uint64_t.
724 *
725 * @param[in] d Double value to copy.
726 *
727 * @return A @c uint64_t with the double bits.
728 *
729 * Convenience function to avoid type punning, compiler warnings and
730 * such. The optimizer usually reduces this to a simple assignment. This
731 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100732 */
733static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
734
735
736/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700737 * @brief Copy a @c uint32_t to a @c float.
738 *
739 * @param[in] u32 Integer value to copy.
740 *
741 * @return The value as a @c float.
742 *
743 * Convenience function to avoid type punning, compiler warnings and
744 * such. The optimizer usually reduces this to a simple assignment. This
745 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100746 */
747static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
748
749
750/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700751 * @brief Copy a @c uint64_t to a @c double.
752 *
753 * @param[in] u64 Integer value to copy.
754 *
755 * @return The value as a @c double.
756 *
757 * Convenience function to avoid type punning, compiler warnings and
758 * such. The optimizer usually reduces this to a simple assignment. This
759 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100760 */
761static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200762#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100763
764
765
766
767/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700768 * UsefulOutBuf is a structure and functions (an object) for
769 * serializing data into a buffer to encode for a network protocol or
770 * write data to a file.
771 *
772 * The main idea is that all the pointer manipulation is performed by
773 * @ref UsefulOutBuf functions so the caller doesn't have to do any
774 * pointer manipulation. The pointer manipulation is centralized.
775 * This code has been reviewed and written carefully so it
776 * spares the caller of much of this work and results in safer code
777 * with less effort.
778 *
779 * The @ref UsefulOutBuf methods that add data to the output buffer
780 * always check the length and will never write off the end of the
781 * output buffer. If an attempt to add data that will not fit is made,
782 * an internal error flag will be set and further attempts to add data
783 * will not do anything.
784 *
785 * There is no way to ever write off the end of that buffer when
786 * calling the @c UsefulOutBuf_AddXxx() and
787 * @c UsefulOutBuf_InsertXxx() functions.
788 *
789 * The functions to add data do not report success of failure. The
790 * caller only needs to check for an error in the final call, either
791 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
792 * result. This makes the calling code cleaner.
793 *
794 * There is a utility function to get the error status anytime along
795 * the way for a special circumstance. There are functions to see how
796 * much room is left and see if some data will fit too, but their use
797 * is generally unnecessary.
798 *
799 * The general call flow is:
800 *
801 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
802 * buffer given to it can be from the heap, stack or
803 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
804 * macro that makes a buffer on the stack and initializes it.
805 *
806 * - Call methods like UsefulOutBuf_InsertString(),
807 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
808 * to output data. The append calls add data to the end of the
809 * valid data. The insert calls take a position argument.
810 *
811 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
812 * there were no errors and to get the serialized output bytes.
813 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700814 * @ref UsefulOutBuf can be used in a mode to calculate the size of
815 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700816 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700817 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700818 *
819 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700820 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700821 *
822 * The possible errors are:
823 *
824 * - The @ref UsefulOutBuf was not initialized or was corrupted.
825 *
826 * - An attempt was made to add data that will not fit.
827 *
828 * - An attempt was made to insert data at a position beyond the end of
829 * the buffer.
830 *
831 * - An attempt was made to insert data at a position beyond the valid
832 * data in the buffer.
833 *
834 * Some inexpensive simple sanity checks are performed before every
835 * data addition to guard against use of an uninitialized or corrupted
836 * UsefulOutBuf.
837 *
838 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
839 * encoder has almost no pointer manipulation in it, is easier to
840 * read, and easier to review.
841 *
842 * A @ref UsefulOutBuf is small and can go on the stack:
843 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
844 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100845 */
846typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700847 /* PRIVATE DATA STRUCTURE */
848 UsefulBuf UB; /* Memory that is being output to */
849 size_t data_len; /* length of the valid data, the insertion point */
850 uint16_t magic; /* Used to detect corruption and lack
851 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100852 uint8_t err;
853} UsefulOutBuf;
854
855
856/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700857 * This is a @ref UsefulBuf value that can be passed to
858 * UsefulOutBuf_Init() to have it calculate the size of the output
859 * buffer needed. Pass this for @c Storage, call all the append and
860 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
861 * returned @ref UsefulBufC has the size.
862 *
863 * As one can see, this is just a NULL pointer and very large size.
864 * The NULL pointer tells UsefulOutputBuf to not copy any data.
865 */
866#ifdef __cplusplus
867#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
868#else
869#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
870#endif
871
872
873/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700874 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700875 *
876 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
877 * @param[in] Storage Buffer to output into.
878 *
879 * This initializes the @ref UsefulOutBuf with storage, sets the
880 * current position to the beginning of the buffer and clears the
881 * error state.
882 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700883 * See @ref SizeCalculateUsefulBuf for instructions on how to
884 * initialize a @ref UsefulOutBuf to calculate the size that would be
885 * output without actually outputting.
886 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700887 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100888 */
889void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
890
891
892/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700893 * Convenience macro to make a @ref UsefulOutBuf on the stack and
894 * initialize it with a stack buffer of the given size. The variable
895 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100896 */
897#define UsefulOutBuf_MakeOnStack(name, size) \
898 uint8_t __pBuf##name[(size)];\
899 UsefulOutBuf name;\
900 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
901
902
903/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700904 * @brief Reset a @ref UsefulOutBuf for re use.
905 *
906 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
907 *
908 * This sets the amount of data in the output buffer to none and
909 * clears the error state.
910 *
911 * The output buffer is still the same one and size as from the
912 * UsefulOutBuf_Init() call.
913 *
914 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100915 */
916static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
917
918
919/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700920 * @brief Returns position of end of data in the @ref UsefulOutBuf.
921 *
922 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
923 *
924 * @return position of end of data.
925 *
926 * On a freshly initialized @ref UsefulOutBuf with no data added, this
927 * will return 0. After 10 bytes have been added, it will return 10
928 * and so on.
929 *
930 * Generally, there is no need to call this for most uses of @ref
931 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100932 */
933static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
934
935
936/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700937 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
938 *
939 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
940 *
941 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100942 */
943static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
944
945
946/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700947 * @brief Inserts bytes into the @ref UsefulOutBuf.
948 *
949 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
950 * @param[in] NewData The bytes to insert.
951 * @param[in] uPos Index in output buffer at which to insert.
952 *
953 * @c NewData is the pointer and length for the bytes to be added to
954 * the output buffer. There must be room in the output buffer for all
955 * of @c NewData or an error will occur.
956 *
957 * The insertion point must be between 0 and the current valid
958 * data. If not, an error will occur. Appending data to the output
959 * buffer is achieved by inserting at the end of the valid data. This
960 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
961 *
962 * When insertion is performed, the bytes between the insertion point
963 * and the end of data previously added to the output buffer are slid
964 * to the right to make room for the new data.
965 *
966 * Overlapping buffers are OK. @c NewData can point to data in the
967 * output buffer.
968 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700969 * NewData.len may be 0 in which case nothing will be inserted.
970 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700971 * If an error occurs, an error state is set in the @ref
972 * UsefulOutBuf. No error is returned. All subsequent attempts to add
973 * data will do nothing.
974 *
975 * The intended use is that all additions are made without checking
976 * for an error. The error will be taken into account when
977 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
978 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100979 */
980void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
981 UsefulBufC NewData,
982 size_t uPos);
983
984
985/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700986 * @brief Insert a data buffer into the @ref UsefulOutBuf.
987 *
988 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
989 * @param[in] pBytes Pointer to the bytes to insert
990 * @param[in] uLen Length of the bytes to insert
991 * @param[in] uPos Index in output buffer at which to insert
992 *
993 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
994 * the difference being a pointer and length is passed in rather than an
995 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100996 */
997static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
998 const void *pBytes,
999 size_t uLen,
1000 size_t uPos);
1001
1002
1003/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001004 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1005 *
1006 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1007 * @param[in] szString NULL-terminated string to insert.
1008 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001009 */
1010static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1011 const char *szString,
1012 size_t uPos);
1013
1014
1015/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001016 * @brief Insert a byte into the @ref UsefulOutBuf.
1017 *
1018 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1019 * @param[in] byte Bytes to insert.
1020 * @param[in] uPos Index in output buffer at which to insert.
1021 *
1022 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1023 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001024 */
1025static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1026 uint8_t byte,
1027 size_t uPos);
1028
1029
1030/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001031 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1032 *
1033 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1034 * @param[in] uInteger16 Integer to insert.
1035 * @param[in] uPos Index in output buffer at which to insert.
1036 *
1037 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1038 * with the difference being a two-byte integer is to be inserted.
1039 *
1040 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001041 */
1042static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1043 uint16_t uInteger16,
1044 size_t uPos);
1045
1046
1047/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001048 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1049 *
1050 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1051 * @param[in] uInteger32 Integer to insert.
1052 * @param[in] uPos Index in output buffer at which to insert.
1053 *
1054 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1055 * with the difference being a four-byte integer is to be inserted.
1056 *
1057 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001058 */
1059static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1060 uint32_t uInteger32,
1061 size_t uPos);
1062
1063
1064/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001065 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1066 *
1067 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1068 * @param[in] uInteger64 Integer to insert.
1069 * @param[in] uPos Index in output buffer at which to insert.
1070 *
1071 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1072 * with the difference being an eight-byte integer is to be inserted.
1073 *
1074 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001075 */
1076static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1077 uint64_t uInteger64,
1078 size_t uPos);
1079
1080
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001081#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001082/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001083 * @brief Insert a @c float into the @ref UsefulOutBuf.
1084 *
1085 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1086 * @param[in] f @c float to insert.
1087 * @param[in] uPos Index in output buffer at which to insert.
1088 *
1089 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1090 * with the difference being a @c float is to be inserted.
1091 *
1092 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001093 */
1094static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1095 float f,
1096 size_t uPos);
1097
1098
1099/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001100 * @brief Insert a @c double into the @ref UsefulOutBuf.
1101 *
1102 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1103 * @param[in] d @c double to insert.
1104 * @param[in] uPos Index in output buffer at which to insert.
1105 *
1106 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1107 * with the difference being a @c double is to be inserted.
1108 *
1109 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001110 */
1111static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1112 double d,
1113 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001114#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001115
1116
1117/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001118 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1119 *
1120 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1121 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1122 *
1123 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1124 * with the insertion point at the end of the valid data.
1125 */
Michael Eckel5c531332020-03-02 01:35:30 +01001126static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1127 UsefulBufC NewData);
1128
1129
1130/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001131 * @brief Append bytes to the @ref UsefulOutBuf.
1132 *
1133 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1134 * @param[in] pBytes Pointer to bytes to append.
1135 * @param[in] uLen Length of @c pBytes to append.
1136 *
1137 * See UsefulOutBuf_InsertData() for details. This does the same with
1138 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001139 */
1140static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1141 const void *pBytes,
1142 size_t uLen);
1143
1144
1145/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001146 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1147 *
1148 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1149 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001150 */
1151static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1152 const char *szString);
1153
1154
1155/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001156 * @brief Append a byte to the @ref UsefulOutBuf
1157 *
1158 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1159 * @param[in] byte Bytes to append.
1160 *
1161 * See UsefulOutBuf_InsertByte() for details. This does the same
1162 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001163 */
1164static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1165 uint8_t byte);
1166
1167
1168/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001169 * @brief Append an integer to the @ref UsefulOutBuf
1170 *
1171 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1172 * @param[in] uInteger16 Integer to append.
1173 *
1174 * See UsefulOutBuf_InsertUint16() for details. This does the same
1175 * with the insertion point at the end of the valid data.
1176 *
1177 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001178 */
1179static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1180 uint16_t uInteger16);
1181
1182
1183/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001184 * @brief Append an integer to the @ref UsefulOutBuf
1185 *
1186 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1187 * @param[in] uInteger32 Integer to append.
1188 *
1189 * See UsefulOutBuf_InsertUint32() for details. This does the same
1190 * with the insertion point at the end of the valid data.
1191 *
1192 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001193 */
1194static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1195 uint32_t uInteger32);
1196
1197
1198/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001199 * @brief Append an integer to the @ref UsefulOutBuf
1200 *
1201 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1202 * @param[in] uInteger64 Integer to append.
1203 *
1204 * See UsefulOutBuf_InsertUint64() for details. This does the same
1205 * with the insertion point at the end of the valid data.
1206 *
1207 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001208 */
1209static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1210 uint64_t uInteger64);
1211
1212
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001213#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001214/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001215 * @brief Append a @c float to the @ref UsefulOutBuf
1216 *
1217 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1218 * @param[in] f @c float to append.
1219 *
1220 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1221 * the insertion point at the end of the valid data.
1222 *
1223 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001224 */
1225static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1226 float f);
1227
1228
1229/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001230 * @brief Append a @c double to the @ref UsefulOutBuf
1231 *
1232 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1233 * @param[in] d @c double to append.
1234 *
1235 * See UsefulOutBuf_InsertDouble() for details. This does the same
1236 * with the insertion point at the end of the valid data.
1237 *
1238 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001239 */
1240static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1241 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001242#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001243
1244
1245/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001246 * @brief Returns the current error status.
1247 *
1248 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1249 *
1250 * @return 0 if all OK, 1 on error.
1251 *
1252 * This returns the error status since a call to either
1253 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1254 * goes into the error state, it will stay until one of those
1255 * functions is called.
1256 *
1257 * Possible error conditions are:
1258 * - bytes to be inserted will not fit
1259 * - insertion point is out of buffer or past valid data
1260 * - current position is off end of buffer (probably corrupted or uninitialized)
1261 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001262 */
1263static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1264
1265
1266/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001267 * @brief Returns number of bytes unused used in the output buffer.
1268 *
1269 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1270 *
1271 * @return Number of unused bytes or zero.
1272 *
1273 * Because of the error handling strategy and checks in
1274 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1275 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001276 */
1277static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1278
1279
1280/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001281 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1282 *
1283 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1284 * @param[in] uLen Number of bytes for which to check
1285 *
1286 * @return 1 if @c uLen bytes will fit, 0 if not.
1287 *
1288 * Because of the error handling strategy and checks in
1289 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1290 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001291 */
1292static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1293
1294
1295 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001296 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1297 *
1298 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1299 *
1300 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1301 *
1302 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1303 * just calculating the length of the encoded data.
1304 */
Michael Eckel5c531332020-03-02 01:35:30 +01001305static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1306
1307
1308/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001309 * @brief Returns pointer and length of the output buffer not yet used.
1310 *
1311 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1312 *
1313 * @return pointer and length of output buffer not used.
1314 *
1315 * This is an escape that allows the caller to write directly
1316 * to the output buffer without any checks. This doesn't
1317 * change the output buffer or state. It just returns a pointer
1318 * and length of the bytes remaining.
1319 *
1320 * This is useful to avoid having the bytes to be added all
1321 * in a contiguous buffer. Its use can save memory. A good
1322 * example is in the COSE encrypt implementation where
1323 * the output of the symmetric cipher can go directly
1324 * into the output buffer, rather than having to go into
1325 * an intermediate buffer.
1326 *
1327 * See UsefulOutBuf_Advance() which is used to tell
1328 * UsefulOutBuf how much was written.
1329 *
1330 * Warning: this bypasses the buffer safety provided by
1331 * UsefulOutBuf!
1332 */
1333static inline UsefulBuf
1334UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1335
1336
1337/**
1338 * @brief Advance the amount output assuming it was written by the caller.
1339 *
1340 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1341 * @param[in] uAmount The amount to advance.
1342 *
1343 * This advances the position in the output buffer
1344 * by \c uAmount. This assumes that the
1345 * caller has written \c uAmount to the pointer obtained
1346 * with UsefulOutBuf_GetOutPlace().
1347 *
1348 * Warning: this bypasses the buffer safety provided by
1349 * UsefulOutBuf!
1350 */
1351void
1352UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1353
1354
1355/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001356 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001357 *
1358 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1359 *
1360 * @return The valid data in @ref UsefulOutBuf or
1361 * @ref NULLUsefulBufC if there was an error adding data.
1362 *
1363 * The storage for the returned data is the @c Storage parameter
1364 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1365 *
1366 * This can be called anytime and many times to get intermediate
1367 * results. It doesn't change the data or reset the current position,
1368 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001369 */
1370UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1371
1372
1373/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001374 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001375 *
1376 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1377 * @param[out] Dest The destination buffer to copy into.
1378 *
1379 * @return Pointer and length of copied data or @c NULLUsefulBufC
1380 * if it will not fit in the @c Dest buffer or the error
1381 * state was entered.
1382 *
1383 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001384 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001385 */
Michael Eckel5c531332020-03-02 01:35:30 +01001386UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1387
1388
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001389/**
1390 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1391 *
1392 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1393 * @param[in] uOffset Offset to bytes to return.
1394 *
1395 * @return NULLUsefulBufC or the bytes at the offset.
1396 *
1397 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1398 * maybe specified. It returns the bytes starting at @c uOffset to the
1399 * end of what was encoded so far. Calling this with @c uOffset 0 is
1400 * equivalent to UsefulOutBuf_OutUBuf().
1401 *
1402 * If there's nothing at @c uOffset or it is past the in the output
1403 * buffer, a \ref NULLUsefulBufC is returned.
1404 *
1405 * This is typically not needed in typical use. It is used by QCBOR
1406 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1407 * sorting CBOR maps.
1408 */
1409UsefulBufC
1410UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1411
1412
1413/**
1414 * @brief Compare bytes at offsets.
1415 *
1416 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1417 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001418 * @param[in] uLen1 Length of first bytes to compare.
1419 * @param[in] uStart2 Offset of second bytes to compare.
1420 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001421 *
1422 * @return 0 for equality, positive if uStart1 is lexographically larger,
1423 * negative if uStart2 is lexographically larger.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001424 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001425 * This looks into bytes that have been output at the offsets @c start1
1426 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001427 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1428 * length of the string given is off the end of the output data, the
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001429 * string will be effectively truncated to the data in the output
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001430 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001431 *
1432 * This returns positive when @c uStart1 lexographically sorts ahead
1433 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001434 * compare equally.
1435 *
1436 * If lengths are unequal and the first bytes are an exact subset of
1437 * the second string, then a positve value will be returned and vice
1438 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001439 *
1440 * If either start is past the end of data in the output buffer, 0
1441 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001442 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001443 * being made. No data will ever be read off the end of the buffer so
1444 * this safe no matter what offsets are passed.
1445 *
1446 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001447 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1448 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001449 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001450int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1451 size_t uStart1, size_t uLen1,
1452 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001453
1454/**
1455 * @brief Swap two regions of output bytes.
1456 *
1457 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1458 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1459 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1460 * @param[in] uEndOffset Offset to end of region to be swappe.
1461 *
1462 * This reaches into bytes that have been output and swaps two
1463 * adjacent regions.
1464 *
1465 * If any of the offsets are outside the range of valid data, no
1466 * swapping will be performed. If the start is not the smallest and
1467 * the pivot is not in the middle no swapping will be performed.
1468 *
1469 * The byte at @c uStartOffset will participate in the swapping. The
1470 * byte at @c uEndOffset will not participate in the swapping, only
1471 * the byte before it.
1472 *
1473 * This is a relatively odd function in that it works on data in the
1474 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1475 * maps.
1476 */
1477void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1478 size_t uStartOffset,
1479 size_t uPivotOffset,
1480 size_t uEndOffset);
1481
1482
Michael Eckel5c531332020-03-02 01:35:30 +01001483
1484
1485/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001486 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1487 * for parsing data received. Initialize it with the data from the
1488 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1489 * get data chunks of various types. A position cursor is maintained
1490 * internally.
1491 *
1492 * As long as the functions here are used, there will never be any
1493 * reference off the end of the given buffer (except
1494 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1495 * called incorrectly, an attempt is made to seek off the end of the
1496 * buffer or such. This makes it easier to write safe and correct
1497 * code. For example, the QCBOR decoder implementation is safer and
1498 * easier to review through its use of @ref UsefulInputBuf.
1499 *
1500 * @ref UsefulInputBuf maintains an internal error state. The
1501 * intended use is fetching data chunks without any error checks until
1502 * the end. If there was any error, such as an attempt to fetch data
1503 * off the end, the error state is entered and no further data will be
1504 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1505 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1506 * null is not dereferenced, the error check can be put off until the
1507 * end, simplifying the calling code.
1508 *
1509 * The integer and float parsing expects network byte order (big
1510 * endian). Network byte order is what is used by TCP/IP, CBOR and
1511 * most internet protocols.
1512 *
1513 * Lots of inline functions are used to keep code size down. The
1514 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1515 * code size a lot. The only non-inline code is
1516 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1517 * @ref UsefulInputBuf doesn't add much code for all the messy
1518 * hard-to-get right issues with parsing binary protocols in C that it
1519 * solves.
1520 *
1521 * The parse context size is:
1522 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1523 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001524 */
1525typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001526 /* PRIVATE DATA STRUCTURE */
1527 UsefulBufC UB; /* Data being parsed */
1528 size_t cursor; /* Current offset in data being parse */
1529 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1530 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001531} UsefulInputBuf;
1532
1533#define UIB_MAGIC (0xB00F)
1534
1535
1536/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001537 * @brief Initialize the @ref UsefulInputBuf structure before use.
1538 *
1539 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1540 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001541 */
1542static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1543
1544
1545/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001546 * @brief Returns current position in input buffer.
1547 *
1548 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1549 *
1550 * @return Integer position of the cursor.
1551 *
1552 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001553 */
1554static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1555
1556
1557/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001558 * @brief Sets the current position in input buffer.
1559 *
1560 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1561 * @param[in] uPos Position to set to.
1562 *
1563 * If the position is off the end of the input buffer, the error state
1564 * is entered.
1565 *
1566 * Seeking to a valid position in the buffer will not reset the error
1567 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001568 */
1569static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1570
1571
1572/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001573 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1574 * the unconsumed bytes.
1575 *
1576 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1577 *
1578 * @return Number of bytes unconsumed or 0 on error.
1579 *
1580 * Returns 0 if the cursor is invalid or corruption of the
1581 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001582 */
1583static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1584
1585
1586/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001587 * @brief Check if there are unconsumed bytes.
1588 *
1589 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1590 * @param[in] uLen Number of bytes to check availability for.
1591 *
1592 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001593 */
1594static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1595
1596
1597/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001598 * @brief Convert a pointer to an offset with bounds checking.
1599 *
1600 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1601 * @param[in] p Pointer to convert to offset.
1602 *
1603 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1604 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001605static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1606
1607
1608/**
1609 * @brief Convert an offset to a pointer with bounds checking.
1610 *
1611 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1612 * @param[in] uOffset Offset in @c pUInBuf.
1613 *
1614 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1615 */
1616static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001617
1618
1619/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001620 * @brief Get pointer to bytes out of the input buffer.
1621 *
1622 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1623 * @param[in] uNum Number of bytes to get.
1624 *
1625 * @return Pointer to bytes.
1626 *
1627 * This consumes @c uNum bytes from the input buffer. This returns a
1628 * pointer to the start of the @c uNum bytes.
1629 *
1630 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1631 * returned and the error state is entered.
1632 *
1633 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001634 */
1635const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1636
1637
1638/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001639 * @brief Get @ref UsefulBuf out of the input buffer.
1640 *
1641 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1642 * @param[in] uNum Number of bytes to get.
1643 *
1644 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1645 *
1646 * This consumes @c uNum bytes from the input buffer and returns the
1647 * pointer and length for them as a @ref UsefulBufC. The length
1648 * returned will always be @c uNum. The position cursor is advanced by
1649 * @c uNum bytes.
1650 *
1651 * If there are not @c uNum bytes in the input buffer, @ref
1652 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001653 */
1654static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1655
1656
1657/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001658 * @brief Get a byte out of the input buffer.
1659 *
1660 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1661 *
1662 * @return The byte.
1663 *
1664 * This consumes 1 byte from the input buffer, returns it and advances
1665 * the position cursor by 1.
1666 *
1667 * If there is not 1 byte in the buffer, 0 will be returned for the
1668 * byte and the error state is entered. To know if the 0 returned was
1669 * in error or the real value, the error state must be checked. If
1670 * possible, put this off until all values are retrieved to have
1671 * smaller and simpler code, but if not possible
1672 * UsefulInputBuf_GetError() can be called. Also, in the error state
1673 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1674 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001675 */
1676static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1677
1678
1679/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001680 * @brief Get a @c uint16_t out of the input buffer.
1681 *
1682 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1683 *
1684 * @return The @c uint16_t.
1685 *
1686 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1687 * a @c uint16_t and two bytes are consumed.
1688 *
1689 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001690 */
1691static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1692
1693
1694/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001695 * @brief Get a @c uint32_t out of the input buffer.
1696 *
1697 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1698 *
1699 * @return The @c uint32_t.
1700 *
1701 * See UsefulInputBuf_GetByte(). This works the same, except it
1702 * returns a @c uint32_t and four bytes are consumed.
1703 *
1704 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001705 */
1706static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1707
1708
1709/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001710 * @brief Get a @c uint64_t out of the input buffer.
1711 *
1712 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1713 *
1714 * @return The uint64_t.
1715 *
1716 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1717 * a @c uint64_t and eight bytes are consumed.
1718 *
1719 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001720 */
1721static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1722
1723
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001724#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001725/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001726 * @brief Get a float out of the input buffer.
1727 *
1728 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1729 *
1730 * @return The float.
1731 *
1732 * See UsefulInputBuf_GetByte(). This works the same, except it
1733 * returns a float and four bytes are consumed.
1734 *
1735 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001736 */
1737static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1738
1739
1740/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001741 * @brief Get a double out of the input buffer.
1742 *
1743 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1744 *
1745 * @return The double.
1746 *
1747 * See UsefulInputBuf_GetByte(). This works the same, except it
1748 * returns a double and eight bytes are consumed.
1749 *
1750 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001751 */
1752static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001753#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001754
1755
1756/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001757 * @brief Get the error status.
1758 *
1759 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1760 *
1761 * @return 0 if not in the error state, 1 if in the error state.
1762 *
1763 * This returns whether the @ref UsefulInputBuf is in the
1764 * error state or not.
1765 *
1766 * The error state is entered for one of these reasons:
1767 * - Attempt to fetch data past the end of the buffer
1768 * - Attempt to seek to a position past the end of the buffer
1769 * - Attempt to get data from an uninitialized or corrupt instance
1770 * of @ref UsefulInputBuf
1771 *
1772 * Once in the error state, it can only be cleared by calling
1773 * UsefulInputBuf_Init().
1774 *
1775 * For many use cases, it is possible to only call this once after all
1776 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1777 * possible if no reference to the data returned are needed before the
1778 * error state is checked.
1779 *
1780 * In some cases UsefulInputBuf_GetUsefulBuf() or
1781 * UsefulInputBuf_GetBytes() can stand in for this because they return
1782 * @c NULL if the error state has been entered. (The others can't stand
1783 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001784 */
1785static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1786
1787
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001788/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001789 * @brief Gets the input buffer length.
1790 *
1791 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1792 *
1793 * @return The length of the input buffer.
1794 *
1795 * This returns the length of the input buffer set by
1796 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001797 */
1798static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1799
1800
1801/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001802 * @brief Alters the input buffer length (use with caution).
1803 *
1804 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1805 * @param[in] uNewLen The new length of the input buffer.
1806 *
1807 * This alters the internal remembered length of the input buffer set
1808 * when UsefulInputBuf_Init() was called.
1809 *
1810 * The new length given here should always be equal to or less than
1811 * the length given when UsefulInputBuf_Init() was called. Making it
1812 * larger allows @ref UsefulInputBuf to run off the input buffer.
1813 *
1814 * The typical use is to set a length shorter than that when
1815 * initialized to constrain parsing. If
1816 * UsefulInputBuf_GetBufferLength() was called before this, then the
1817 * original length can be restored with another call to this.
1818 *
1819 * This should be used with caution. It is the only
1820 * @ref UsefulInputBuf method that can violate the safety of input
1821 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001822 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001823static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001824
1825
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001826/**
1827 * @brief Compare two ranges of bytes somewhere in the input buffer.
1828 *
1829 * @param[in] pUInBuf The input buffer.
1830 * @param[in] uOffset1 Offset of first range of bytes.
1831 * @param[in] uLen1 Length of first range of bytes.
1832 * @param[in] uOffset2 Offset of second range of bytes.
1833 * @param[in] uLen2 Length of second range of bytes.
1834 *
1835 * This returns the same as UsefulBuf_Compare().
1836 *
1837 * If the offset or the length plus offset or a range extends outside
1838 * the input buffer, that range of bytes will be considered greater
1839 * than the other string. If both are outside this is considered a
1840 * degenerate condition and the first string is considered larger.
1841 *
1842 * This is a somewhat odd function of UsefulInputBuf as it is not used
1843 * for consuming data. QCBOR uses it for map order and duplicate
1844 * checking.
1845 */
1846int
1847UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
1848 const size_t uOffset1,
1849 const size_t uLen1,
1850 const size_t uOffset2,
1851 const size_t uLen2);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001852
1853
Michael Eckel5c531332020-03-02 01:35:30 +01001854/*----------------------------------------------------------
1855 Inline implementations.
1856 */
1857static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1858{
1859 return !UB.ptr;
1860}
1861
1862
1863static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1864{
1865 return !UB.ptr;
1866}
1867
1868
1869static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1870{
1871 return !UB.len;
1872}
1873
1874
1875static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1876{
1877 return !UB.len;
1878}
1879
1880
1881static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1882{
1883 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1884}
1885
1886
1887static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1888{
1889 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1890}
1891
1892
1893static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1894{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001895 UsefulBufC UBC;
1896 UBC.ptr = UB.ptr;
1897 UBC.len = UB.len;
1898
1899 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001900}
1901
Michael Eckel5c531332020-03-02 01:35:30 +01001902static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1903{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001904 UsefulBuf UB;
1905
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001906 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001907 * the one place in UsefulBuf where it needs to be quieted.
1908 */
1909 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001910
1911 UB.len = UBC.len;
1912
1913 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001914}
1915
1916
1917static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1918{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001919 UsefulBufC UBC;
1920 UBC.ptr = szString;
1921 UBC.len = strlen(szString);
1922 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001923}
1924
1925
1926static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1927{
1928 return UsefulBuf_CopyOffset(Dest, 0, Src);
1929}
1930
1931
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001932static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001933{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001934 memset(Dest.ptr, value, Dest.len);
1935
1936 UsefulBufC UBC;
1937 UBC.ptr = Dest.ptr;
1938 UBC.len = Dest.len;
1939
1940 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001941}
1942
1943
1944static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1945{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001946 UsefulBufC UBC;
1947 UBC.ptr = ptr;
1948 UBC.len = len;
1949 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001950}
1951
1952
1953static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1954{
1955 if(uAmount > UB.len) {
1956 return NULLUsefulBufC;
1957 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001958 UsefulBufC UBC;
1959
1960 UBC.ptr = UB.ptr;
1961 UBC.len = uAmount;
1962
1963 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001964}
1965
1966
1967static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1968{
1969 UsefulBufC ReturnValue;
1970
1971 if(uAmount > UB.len) {
1972 ReturnValue = NULLUsefulBufC;
1973 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001974 ReturnValue.ptr = NULL;
1975 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001976 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001977 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1978 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001979 }
1980
1981 return ReturnValue;
1982}
1983
1984
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001985static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1986{
1987 if(UB.ptr == NULL) {
1988 return SIZE_MAX;
1989 }
1990
1991 if(p < UB.ptr) {
1992 /* given pointer is before start of buffer */
1993 return SIZE_MAX;
1994 }
1995
Laurence Lundblade3eead482023-12-16 20:53:22 -07001996 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001997 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001998
1999 if(uOffset >= UB.len) {
2000 /* given pointer is off the end of the buffer */
2001 return SIZE_MAX;
2002 }
2003
2004 return uOffset;
2005}
2006
Michael Eckel5c531332020-03-02 01:35:30 +01002007
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002008static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
2009{
2010 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
2011 return NULL;
2012 }
2013
2014 return (const uint8_t *)UB.ptr + uOffset;
2015}
2016
2017
2018
2019
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002020#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002021static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
2022{
2023 uint32_t u32;
2024 memcpy(&u32, &f, sizeof(uint32_t));
2025 return u32;
2026}
2027
2028static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2029{
2030 uint64_t u64;
2031 memcpy(&u64, &d, sizeof(uint64_t));
2032 return u64;
2033}
2034
2035static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2036{
2037 double d;
2038 memcpy(&d, &u64, sizeof(uint64_t));
2039 return d;
2040}
2041
2042static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2043{
2044 float f;
2045 memcpy(&f, &u32, sizeof(uint32_t));
2046 return f;
2047}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002048#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002049
2050
2051
2052
2053static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2054{
2055 pMe->data_len = 0;
2056 pMe->err = 0;
2057}
2058
2059
2060static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2061{
2062 return pMe->data_len;
2063}
2064
2065
2066static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2067{
2068 return 0 == pMe->data_len;
2069}
2070
2071
2072static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2073 const void *pBytes,
2074 size_t uLen,
2075 size_t uPos)
2076{
2077 UsefulBufC Data = {pBytes, uLen};
2078 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2079}
2080
2081
2082static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2083 const char *szString,
2084 size_t uPos)
2085{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002086 UsefulBufC UBC;
2087 UBC.ptr = szString;
2088 UBC.len = strlen(szString);
2089
2090 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002091}
2092
2093
2094static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2095 uint8_t byte,
2096 size_t uPos)
2097{
2098 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2099}
2100
2101
2102static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2103 uint16_t uInteger16,
2104 size_t uPos)
2105{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002106 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002107
2108 const void *pBytes;
2109
2110#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2111 pBytes = &uInteger16;
2112
2113#elif defined(USEFULBUF_CONFIG_HTON)
2114 uint16_t uTmp = htons(uInteger16);
2115 pBytes = &uTmp;
2116
2117#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2118 uint16_t uTmp = __builtin_bswap16(uInteger16);
2119 pBytes = &uTmp;
2120
2121#else
2122 uint8_t aTmp[2];
2123
2124 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2125 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2126
2127 pBytes = aTmp;
2128#endif
2129
2130 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2131}
2132
2133
2134static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2135 uint32_t uInteger32,
2136 size_t uPos)
2137{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002138 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002139
2140 const void *pBytes;
2141
2142#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2143 pBytes = &uInteger32;
2144
2145#elif defined(USEFULBUF_CONFIG_HTON)
2146 uint32_t uTmp = htonl(uInteger32);
2147 pBytes = &uTmp;
2148
2149#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2150 uint32_t uTmp = __builtin_bswap32(uInteger32);
2151
2152 pBytes = &uTmp;
2153
2154#else
2155 uint8_t aTmp[4];
2156
2157 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2158 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2159 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2160 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2161
2162 pBytes = aTmp;
2163#endif
2164
2165 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2166}
2167
2168static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002169 uint64_t uInteger64,
2170 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002171{
2172 const void *pBytes;
2173
2174#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002175 /* We have been told explicitly we are running on a big-endian
2176 * machine. Network byte order is big endian, so just copy. There
2177 * is no issue with alignment here because uInteger64 is always
2178 * aligned (and it doesn't matter if pBytes is aligned).
2179 */
Michael Eckel5c531332020-03-02 01:35:30 +01002180 pBytes = &uInteger64;
2181
2182#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002183 /* Use system function to handle big- and little-endian. This works
2184 * on both big- and little-endian machines, but hton() is not
2185 * always available or in a standard place so it is not used by
2186 * default. With some compilers and CPUs the code for this is very
2187 * compact through use of a special swap instruction and on
2188 * big-endian machines hton() will reduce to nothing.
2189 */
Michael Eckel5c531332020-03-02 01:35:30 +01002190 uint64_t uTmp = htonll(uInteger64);
2191
2192 pBytes = &uTmp;
2193
2194#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002195 /* Use built-in function for byte swapping. This usually compiles
2196 * to an efficient special byte swap instruction. Unlike hton() it
2197 * does not do this conditionally on the CPU endianness, so this
2198 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2199 */
Michael Eckel5c531332020-03-02 01:35:30 +01002200 uint64_t uTmp = __builtin_bswap64(uInteger64);
2201
2202 pBytes = &uTmp;
2203
2204#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002205 /* Default which works on every CPU with no dependency on anything
2206 * from the CPU, compiler, libraries or OS. This always works, but
2207 * it is usually a little larger and slower than hton().
2208 */
Michael Eckel5c531332020-03-02 01:35:30 +01002209 uint8_t aTmp[8];
2210
2211 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2212 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2213 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2214 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2215 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2216 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2217 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2218 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2219
2220 pBytes = aTmp;
2221#endif
2222
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002223 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002224 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2225}
2226
2227
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002228#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002229static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2230 float f,
2231 size_t uPos)
2232{
2233 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2234}
2235
2236
2237static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2238 double d,
2239 size_t uPos)
2240{
2241 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2242}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002243#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002244
2245
2246static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2247 UsefulBufC NewData)
2248{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002249 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002250 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2251}
2252
2253
2254static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2255 const void *pBytes,
2256 size_t uLen)
2257{
2258 UsefulBufC Data = {pBytes, uLen};
2259 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2260}
2261
2262
2263static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2264 const char *szString)
2265{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002266 UsefulBufC UBC;
2267 UBC.ptr = szString;
2268 UBC.len = strlen(szString);
2269
2270 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002271}
2272
2273
2274static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2275 uint8_t byte)
2276{
2277 UsefulOutBuf_AppendData(pMe, &byte, 1);
2278}
2279
2280
2281static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2282 uint16_t uInteger16)
2283{
2284 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2285}
2286
2287static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2288 uint32_t uInteger32)
2289{
2290 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2291}
2292
2293
2294static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2295 uint64_t uInteger64)
2296{
2297 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2298}
2299
2300
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002301#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002302static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2303 float f)
2304{
2305 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2306}
2307
2308
2309static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2310 double d)
2311{
2312 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2313}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002314#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002315
2316
2317static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2318{
2319 return pMe->err;
2320}
2321
2322
2323static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2324{
2325 return pMe->UB.len - pMe->data_len;
2326}
2327
2328
2329static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2330{
2331 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2332}
2333
2334
2335static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2336{
2337 return pMe->UB.ptr == NULL;
2338}
2339
2340
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002341static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2342{
2343 UsefulBuf R;
2344
2345 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002346 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002347 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2348 } else {
2349 R.ptr = NULL;
2350 }
2351
2352 return R;
2353}
2354
2355
2356
Michael Eckel5c531332020-03-02 01:35:30 +01002357
2358static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2359{
2360 pMe->cursor = 0;
2361 pMe->err = 0;
2362 pMe->magic = UIB_MAGIC;
2363 pMe->UB = UB;
2364}
2365
2366static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2367{
2368 return pMe->cursor;
2369}
2370
2371
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002372static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002373{
2374 return pMe->UB.len;
2375}
2376
2377
Michael Eckel5c531332020-03-02 01:35:30 +01002378static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2379{
2380 if(uPos > pMe->UB.len) {
2381 pMe->err = 1;
2382 } else {
2383 pMe->cursor = uPos;
2384 }
2385}
2386
2387
2388static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2389{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002390 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002391
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002392 /* Magic number is messed up. Either the structure got overwritten
2393 * or was never initialized.
2394 */
Michael Eckel5c531332020-03-02 01:35:30 +01002395 if(pMe->magic != UIB_MAGIC) {
2396 return 0;
2397 }
2398
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002399 /* The cursor is off the end of the input buffer given.
2400 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002401 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002402 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002403 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002404 */
Michael Eckel5c531332020-03-02 01:35:30 +01002405 if(pMe->cursor > pMe->UB.len) {
2406 return 0;
2407 }
2408
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002409 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002410 return pMe->UB.len - pMe->cursor;
2411}
2412
2413
2414static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2415{
2416 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2417}
2418
2419
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002420static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2421{
2422 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2423}
2424
2425
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002426static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2427 {
2428 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2429 }
2430
2431
Michael Eckel5c531332020-03-02 01:35:30 +01002432static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2433{
2434 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2435 if(!pResult) {
2436 return NULLUsefulBufC;
2437 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002438 UsefulBufC UBC;
2439 UBC.ptr = pResult;
2440 UBC.len = uNum;
2441 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002442 }
2443}
2444
2445
2446static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2447{
2448 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2449
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002450 /* The ternary operator is subject to integer promotion, because
2451 * the operands are smaller than int, so cast back to uint8_t is
2452 * needed to be completely explicit about types (for static
2453 * analyzers).
2454 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002455 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002456}
2457
2458static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2459{
2460 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2461
2462 if(!pResult) {
2463 return 0;
2464 }
2465
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002466 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002467#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2468 uint16_t uTmp;
2469 memcpy(&uTmp, pResult, sizeof(uint16_t));
2470
2471#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2472 return uTmp;
2473
2474#elif defined(USEFULBUF_CONFIG_HTON)
2475 return ntohs(uTmp);
2476
2477#else
2478 return __builtin_bswap16(uTmp);
2479
2480#endif
2481
2482#else
2483
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002484 /* The operations here are subject to integer promotion because the
2485 * operands are smaller than int. They will be promoted to unsigned
2486 * int for the shift and addition. The cast back to uint16_t is is
2487 * needed to be completely explicit about types (for static
2488 * analyzers).
2489 */
Michael Eckel5c531332020-03-02 01:35:30 +01002490 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2491
2492#endif
2493}
2494
2495
2496static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2497{
2498 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2499
2500 if(!pResult) {
2501 return 0;
2502 }
2503
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002504 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002505#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2506 uint32_t uTmp;
2507 memcpy(&uTmp, pResult, sizeof(uint32_t));
2508
2509#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2510 return uTmp;
2511
2512#elif defined(USEFULBUF_CONFIG_HTON)
2513 return ntohl(uTmp);
2514
2515#else
2516 return __builtin_bswap32(uTmp);
2517
2518#endif
2519
2520#else
2521 return ((uint32_t)pResult[0]<<24) +
2522 ((uint32_t)pResult[1]<<16) +
2523 ((uint32_t)pResult[2]<<8) +
2524 (uint32_t)pResult[3];
2525#endif
2526}
2527
2528
2529static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2530{
2531 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2532
2533 if(!pResult) {
2534 return 0;
2535 }
2536
2537#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002538 /* pResult will probably not be aligned. This memcpy() moves the
2539 * bytes into a temp variable safely for CPUs that can or can't do
2540 * unaligned memory access. Many compilers will optimize the
2541 * memcpy() into a simple move instruction.
2542 */
Michael Eckel5c531332020-03-02 01:35:30 +01002543 uint64_t uTmp;
2544 memcpy(&uTmp, pResult, sizeof(uint64_t));
2545
2546#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002547 /* We have been told expliclity this is a big-endian CPU. Since
2548 * network byte order is big-endian, there is nothing to do.
2549 */
Michael Eckel5c531332020-03-02 01:35:30 +01002550
2551 return uTmp;
2552
2553#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002554 /* We have been told to use ntoh(), the system function to handle
2555 * big- and little-endian. This works on both big- and
2556 * little-endian machines, but ntoh() is not always available or in
2557 * a standard place so it is not used by default. On some CPUs the
2558 * code for this is very compact through use of a special swap
2559 * instruction.
2560 */
Michael Eckel5c531332020-03-02 01:35:30 +01002561
2562 return ntohll(uTmp);
2563
2564#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002565 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2566 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2567 * __builtin_bswap64() and friends are not conditional on CPU
2568 * endianness so this must only be used on little-endian machines.
2569 */
Michael Eckel5c531332020-03-02 01:35:30 +01002570
2571 return __builtin_bswap64(uTmp);
2572
2573
2574#endif
2575
2576#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002577 /* This is the default code that works on every CPU and every
2578 * endianness with no dependency on ntoh(). This works on CPUs
2579 * that either allow or do not allow unaligned access. It will
2580 * always work, but usually is a little less efficient than ntoh().
2581 */
Michael Eckel5c531332020-03-02 01:35:30 +01002582
2583 return ((uint64_t)pResult[0]<<56) +
2584 ((uint64_t)pResult[1]<<48) +
2585 ((uint64_t)pResult[2]<<40) +
2586 ((uint64_t)pResult[3]<<32) +
2587 ((uint64_t)pResult[4]<<24) +
2588 ((uint64_t)pResult[5]<<16) +
2589 ((uint64_t)pResult[6]<<8) +
2590 (uint64_t)pResult[7];
2591#endif
2592}
2593
2594
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002595#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002596static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2597{
2598 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2599
2600 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2601}
2602
2603
2604static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2605{
2606 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2607
2608 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2609}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002610#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002611
2612
2613static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2614{
2615 return pMe->err;
2616}
2617
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002618
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002619static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002620{
2621 pMe->UB.len = uNewLen;
2622}
2623
2624
Michael Eckel5c531332020-03-02 01:35:30 +01002625#ifdef __cplusplus
2626}
2627#endif
2628
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002629#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002630
2631