blob: 819a0d595754787ee4c338f8358c1070ed43d8fb [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 Lundbladee2226742024-08-16 10:50:23 -070046 08/14/2024 llundblade Add UsefulOutBuf_RetrieveOutputStorage().
47 08/13/2024 llundblade Add UsefulInputBuf_RetrieveUndecodedInput().
48 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070049 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070050 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladede2e1502024-08-26 11:37:05 -070051 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070052 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
53 19/11/2023 llundblade Add UsefulOutBuf_Swap().
54 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070055 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060056 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070057 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070058 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070059 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080060 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070061 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010062 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
63 5/21/2019 llundblade #define configs for efficient endianness handling.
64 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
65 3/23/2019 llundblade Big documentation & style update. No interface
66 change.
67 3/6/2019 llundblade Add UsefulBuf_IsValue()
68 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
69 12/13/2018 llundblade Documentation improvements
70 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
71 UsefulBufC.
72 02/02/18 llundbla Full support for integers in and out; fix pointer
73 alignment bug. Incompatible change: integers
74 in/out are now in network byte order.
75 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
76 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
77 comparison for < or > for unequal length buffers.
78 Added UsefulBuf_Set() function.
79 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
80 11/13/16 llundbla Initial Version.
81
82 =============================================================================*/
83
84#ifndef _UsefulBuf_h
85#define _UsefulBuf_h
86
87
88/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070089 * Endianness Configuration
90 *
91 * This code is written so it will work correctly on big- and
92 * little-endian CPUs without configuration or any auto-detection of
93 * endianness. All code here will run correctly regardless of the
94 * endianness of the CPU it is running on.
95 *
96 * There are four C preprocessor macros that can be set with #define
97 * to explicitly configure endianness handling. Setting them can
98 * reduce code size a little and improve efficiency a little.
99 *
100 * Note that most of QCBOR is unaffected by this configuration. Its
101 * endianness handling is integrated with the code that handles
102 * alignment and preferred serialization. This configuration does
103 * affect QCBOR's (planned) implementation of integer arrays (tagged
104 * arrays) and use of the functions here to serialize or deserialize
105 * integers and floating-point values.
106 *
107 * Following is the recipe for configuring the endianness-related
108 * #defines.
109 *
110 * The first option is to not define anything. This will work fine
111 * with all CPUs, OS's and compilers. The code for encoding integers
112 * may be a little larger and slower.
113 *
114 * If your CPU is big-endian then define
115 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
116 * for big-endian CPUs. It will be small and efficient because there
117 * will be no byte swapping.
118 *
119 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
120 * OS's and compilers, but not all. On big-endian CPUs this should
121 * give the most efficient code, the same as
122 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
123 * call the system-defined byte swapping method which is presumably
124 * implemented efficiently. In some cases, this will be a dedicated
125 * byte swap instruction like Intel's bswap.
126 *
127 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
128 * little-endian, it is also good to define
129 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
130 *
131 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
132 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
133 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
134 * system-defined byte swap method. However, note
135 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
136 * this is fixed now. Often hton() and ntoh() will call the built-in
137 * __builtin_bswapXX()() function, so this size issue could affect
138 * USEFULBUF_CONFIG_HTON.
139 *
140 * Last, run the tests. They must all pass.
141 *
142 * These #define config options affect the inline implementation of
143 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
144 * also affect the 16-, 32-bit, float and double versions of these
145 * functions. Since they are inline, the size effect is not in the
146 * UsefulBuf object code, but in the calling code.
147 *
148 * Summary:
149 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
150 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
151 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
152 * handle big and little-endian with system option.
153 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
154 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200155 *
156 * It is possible to run this code in environments where using floating point is
157 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
158 * that is related to handling floating point types, along with related
159 * interfaces. This makes it possible to compile the code with the compile
160 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100161 */
162
163#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
164#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
165#endif
166
167
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700168#include <stdint.h> /* for uint8_t, uint16_t.... */
169#include <string.h> /* for strlen, memcpy, memmove, memset */
170#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100171
172
173#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700174#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100175#endif
176
177#ifdef __cplusplus
178extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700179#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700180} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700181#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100182#endif
183
184/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700185 * @file UsefulBuf.h
186 *
187 * The goal of this code is to make buffer and pointer manipulation
188 * easier and safer when working with binary data.
189 *
190 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
191 * structures are used to represent buffers rather than ad hoc
192 * pointers and lengths.
193 *
194 * With these it is possible to write code that does little or no
195 * direct pointer manipulation for copying and formatting data. For
196 * example, the QCBOR encoder was written using these and has less
197 * pointer manipulation.
198 *
199 * While it is true that object code using these functions will be a
200 * little larger and slower than a white-knuckle clever use of
201 * pointers might be, but not by that much or enough to have an effect
202 * for most use cases. For security-oriented code this is highly
203 * worthwhile. Clarity, simplicity, reviewability and are more
204 * important.
205 *
206 * There are some extra sanity and double checks in this code to help
207 * catch coding errors and simple memory corruption. They are helpful,
208 * but not a substitute for proper code review, input validation and
209 * such.
210 *
211 * This code consists of a lot of inline functions and a few that are
212 * not. It should not generate very much object code, especially with
213 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100214 */
215
216
217/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700218 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
219 * hold a pointer and length for binary data. In C99 this data
220 * structure can be passed on the stack making a lot of code cleaner
221 * than carrying around a pointer and length as two parameters.
222 *
223 * This is also conducive to secure coding practice as the length is
224 * always carried with the pointer and the convention for handling a
225 * pointer and a length is clear.
226 *
227 * While it might be possible to write buffer and pointer code more
228 * efficiently in some use cases, the thought is that unless there is
229 * an extreme need for performance (e.g., you are building a
230 * gigabit-per-second IP router), it is probably better to have
231 * cleaner code you can be most certain about the security of.
232 *
233 * The non-const @ref UsefulBuf is usually used to refer an empty
234 * buffer to be filled in. The length is the size of the buffer.
235 *
236 * The const @ref UsefulBufC is usually used to refer to some data
237 * that has been filled in. The length is amount of valid data pointed
238 * to.
239 *
240 * A common use mode is to pass a @ref UsefulBuf to a function, the
241 * function puts some data in it, then the function returns a @ref
242 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
243 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
244 * so the constness stays correct. There is no single "in,out"
245 * parameter (if there was, it would have to be non-const). Note that
246 * the pointer returned in the @ref UsefulBufC usually ends up being
247 * the same pointer passed in as a @ref UsefulBuf, though this is not
248 * striclty required.
249 *
250 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
251 * @c NULL.
252 *
253 * There are functions and macros for the following:
254 * - Initializing
255 * - Create initialized const @ref UsefulBufC from compiler literals
256 * - Create initialized const @ref UsefulBufC from NULL-terminated string
257 * - Make an empty @ref UsefulBuf on the stack
258 * - Checking whether a @ref UsefulBuf is null, empty or both
259 * - Copying, copying with offset, copying head or tail
260 * - Comparing and finding substrings
261 *
262 * See also @ref UsefulOutBuf. It is a richer structure that has both
263 * the size of the valid data and the size of the buffer.
264 *
265 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
266 * it can go on the stack and be a function parameter or return value.
267 *
268 * Another way to look at it is this. C has the NULL-terminated string
269 * as a means for handling text strings, but no means or convention
270 * for binary strings. Other languages do have such means, Rust, an
271 * efficient compiled language, for example.
272 *
273 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
274 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
275 * out like anything".
276 */
Michael Eckel5c531332020-03-02 01:35:30 +0100277typedef struct q_useful_buf_c {
278 const void *ptr;
279 size_t len;
280} UsefulBufC;
281
282
283/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700284 * This non-const @ref UsefulBuf is typically used for some allocated
285 * memory that is to be filled in. The @c len is the amount of memory,
286 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100287 */
288typedef struct q_useful_buf {
289 void *ptr;
290 size_t len;
291} UsefulBuf;
292
293
294/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700295 * A null @ref UsefulBufC is one that has no value in the same way a
296 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
297 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
298 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100299 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700300/*
301 * NULLUsefulBufC and few other macros have to be
302 * definied differently in C than C++ because there
303 * is no common construct for a literal structure.
304 *
305 * In C compound literals are used.
306 *
307 * In C++ list initalization is used. This only works
308 * in C++11 and later.
309 *
310 * Note that some popular C++ compilers can handle compound
311 * literals with on-by-default extensions, however
312 * this code aims for full correctness with strict
313 * compilers so they are not used.
314 */
315#ifdef __cplusplus
316#define NULLUsefulBufC {NULL, 0}
317#else
318#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
319#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100320
321/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700322 * A null @ref UsefulBuf is one that has no memory associated the same
323 * way @c NULL points to nothing. It does not matter what @c len is.
324 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700325#ifdef __cplusplus
326#define NULLUsefulBuf {NULL, 0}
327#else
328#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
329#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100330
331
332/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700333 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
334 *
335 * @param[in] UB The UsefulBuf to check.
336 *
337 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100338 */
339static inline int UsefulBuf_IsNULL(UsefulBuf UB);
340
341
342/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700343 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
344 *
345 * @param[in] UB The @ref UsefulBufC to check.
346 *
347 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100348 */
349static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
350
351
352/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700353 * @brief Check if a @ref UsefulBuf is empty or not.
354 *
355 * @param[in] UB The @ref UsefulBuf to check.
356 *
357 * @return 1 if it is empty, 0 if not.
358 *
359 * An "empty" @ref UsefulBuf is one that has a value and can be
360 * considered to be set, but that value is of zero length. It is
361 * empty when @c len is zero. It doesn't matter what the @c ptr is.
362 *
363 * Many uses will not need to clearly distinguish a @c NULL @ref
364 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
365 * @c len 0. However if a use of @ref UsefulBuf needs to make a
366 * distinction then @c ptr should not be @c NULL when the @ref
367 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100368 */
369static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
370
371
372/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700373 * @brief Check if a @ref UsefulBufC is empty or not.
374 *
375 * @param[in] UB The @ref UsefulBufC to check.
376 *
377 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100378 */
379static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
380
381
382/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700383 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
384 *
385 * @param[in] UB The @ref UsefulBuf to check.
386 *
387 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100388 */
389static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
390
391
392/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700393 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
394 *
395 * @param[in] UB The @ref UsefulBufC to check.
396 *
397 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100398 */
399static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
400
401
402/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700403 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
404 *
405 * @param[in] UB The @ref UsefulBuf to convert.
406 *
407 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100408 */
409static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
410
411
412/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700413 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
414 *
415 * @param[in] UBC The @ref UsefulBuf to convert.
416 *
417 * @return A non-const @ref UsefulBuf struct.
418 *
419 * Use of this is not necessary for the intended use mode of @ref
420 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
421 * created to describe a buffer that has not had any data put in
422 * it. Then the data is put in it. Then a @ref UsefulBufC is create
423 * to describe the part with the data in it. This goes from non-const
424 * to const, so this function is not needed.
425 *
426 * If the -Wcast-qual warning is enabled, this function can be used to
427 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100428 */
429static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
430
431
432/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700433 * Convert a literal string to a @ref UsefulBufC.
434 *
435 * @c szString must be a literal string that @c sizeof() works on.
436 * This is better for literal strings than UsefulBuf_FromSZ() because
437 * it generates less code. It will not work on non-literal strings.
438 *
439 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100440 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700441#ifdef __cplusplus
442#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
443#else
Michael Eckel5c531332020-03-02 01:35:30 +0100444#define UsefulBuf_FROM_SZ_LITERAL(szString) \
445 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700446#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100447
448
449/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700450 * Convert a literal byte array to a @ref UsefulBufC.
451 *
452 * @c pBytes must be a literal string that @c sizeof() works on. It
453 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100454 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700455#ifdef __cplusplus
456#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
457#else
Michael Eckel5c531332020-03-02 01:35:30 +0100458#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700459 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
460#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100461
462/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700463 * Make an automatic variable named @c name of type @ref UsefulBuf and
464 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100465 */
466#define UsefulBuf_MAKE_STACK_UB(name, size) \
467 uint8_t __pBuf##name[(size)];\
468 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
469
470
471/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700472 * Make a byte array in to a @ref UsefulBuf. This is usually used on
473 * stack variables or static variables. Also see @ref
474 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100475 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700476#ifdef __cplusplus
477#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
478#else
Michael Eckel5c531332020-03-02 01:35:30 +0100479#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700480 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
481#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100482
483
484/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700485 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
486 *
487 * @param[in] szString The string to convert.
488 *
489 * @return A @ref UsefulBufC struct.
490 *
491 * @c UsefulBufC.ptr points to the string so its lifetime must be
492 * maintained.
493 *
494 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100495 */
496static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
497
498
499/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700500 * @brief Copy one @ref UsefulBuf into another at an offset.
501 *
502 * @param[in] Dest Destination buffer to copy into.
503 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
504 * @param[in] Src The bytes to copy.
505 *
506 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
507 *
508 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
509 * size of @c Dest.
510 *
511 * This fails and returns @ref NULLUsefulBufC if the @c Src length
512 * plus @c uOffset is greater than the length of @c Dest.
513 *
514 * The results are undefined if @c Dest and @c Src overlap.
515 *
516 * This assumes that there is valid data in @c Dest up to @c
517 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
518 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100519 */
520UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
521
522
523/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700524 * @brief Copy one @ref UsefulBuf into another.
525 *
526 * @param[in] Dest The destination buffer to copy into.
527 * @param[out] Src The source to copy from.
528 *
529 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
530 * on failure.
531 *
532 * This fails if @c Src.len is greater than @c Dest.len.
533 *
534 * Note that like @c memcpy(), the pointers are not checked and this
535 * will crash rather than return @ref NULLUsefulBufC if they are @c
536 * NULL or invalid.
537 *
538 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100539 */
540static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
541
542
543/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700544 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
545 *
546 * @param[in] pDest The destination buffer to copy into.
547 * @param[in] value The value to set the bytes to.
548 *
549 * Note that like @c memset(), the pointer in @c pDest is not checked
550 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100551 */
552static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
553
554
555/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700556 * @brief Copy a pointer into a @ref UsefulBuf.
557 *
558 * @param[in,out] Dest The destination buffer to copy into.
559 * @param[in] ptr The source to copy from.
560 * @param[in] uLen Length of the source; amount to copy.
561 *
562 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
563 * on failure.
564 *
565 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
566 * than @c pDest->len.
567 *
568 * Note that like @c memcpy(), the pointers are not checked and this
569 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100570 */
571static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
572 const void *ptr,
573 size_t uLen);
574
575
576/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700577 * @brief Returns a truncation of a @ref UsefulBufC.
578 *
579 * @param[in] UB The buffer to get the head of.
580 * @param[in] uAmount The number of bytes in the head.
581 *
582 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100583 */
584static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
585
586
587/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700588 * @brief Returns bytes from the end of a @ref UsefulBufC.
589 *
590 * @param[in] UB The buffer to get the tail of.
591 * @param[in] uAmount The offset from the start where the tail is to begin.
592 *
593 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
594 * if @c uAmount is greater than the length of the @ref UsefulBufC.
595 *
596 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
597 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
598 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100599 */
600static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
601
602
603/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700604 * @brief Compare one @ref UsefulBufC to another.
605 *
606 * @param[in] UB1 The first buffer to compare.
607 * @param[in] UB2 The second buffer to compare.
608 *
609 * @return 0, positive or negative value.
610 *
611 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
612 * less than @c UB2 if it is shorter or the first byte that is not the
613 * same is less.
614 *
615 * Returns 0 if the inputs are the same.
616 *
617 * Returns a positive value if @c UB2 is less than @c UB1.
618 *
619 * All that is of significance is that the result is positive, negative
620 * or 0. (This doesn't return the difference between the first
621 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100622 */
623int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
624
625
626/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700627 * @brief Find first byte that is not a particular byte value.
628 *
629 * @param[in] UB The destination buffer for byte comparison.
630 * @param[in] uValue The byte value to compare to.
631 *
632 * @return Offset of first byte that isn't @c uValue or
633 * @c SIZE_MAX if all bytes are @c uValue.
634 *
635 * Note that unlike most comparison functions, 0
636 * does not indicate a successful comparison, so the
637 * test for match is:
638 *
639 * UsefulBuf_IsValue(...) == SIZE_MAX
640 *
641 * If @c UB is null or empty, there is no match
642 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100643 */
644size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
645
646
647/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700648 * @brief Find one @ref UsefulBufC in another.
649 *
650 * @param[in] BytesToSearch Buffer to search through.
651 * @param[in] BytesToFind Buffer with bytes to be found.
652 *
653 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100654 */
655size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
656
657
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700658/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700659 * @brief Convert a pointer to an offset with bounds checking.
660 *
661 * @param[in] UB A UsefulBuf.
662 * @param[in] p Pointer to convert to offset.
663 *
664 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700665*/
666static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
667
668
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700669/**
670 * @brief Convert an offset to a pointer with bounds checking.
671 *
672 * @param[in] UB A UsefulBuf.
673 * @param[in] uOffset Offset in @c pUInBuf.
674 *
675 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
676 */
677static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
678
679
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800680#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100681/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700682#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100683
684/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
685#define MakeUsefulBufOnStack(name, size) \
686 uint8_t __pBuf##name[(size)];\
687 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
688
689/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
690#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700691 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100692
693/** Deprecated function; use UsefulBuf_Unconst() instead */
694static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
695{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700696 UsefulBuf UB;
697
Laurence Lundblade3eead482023-12-16 20:53:22 -0700698 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300699 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700700
701 UB.len = UBC.len;
702
703 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100704}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800705#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100706
707
708
709
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200710#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100711/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700712 * @brief Copy a @c float to a @c uint32_t.
713 *
714 * @param[in] f Float value to copy.
715 *
716 * @return A @c uint32_t with the float bits.
717 *
718 * Convenience function to avoid type punning, compiler warnings and
719 * such. The optimizer usually reduces this to a simple assignment. This
720 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100721 */
722static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
723
724
725/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700726 * @brief Copy a @c double to a @c uint64_t.
727 *
728 * @param[in] d Double value to copy.
729 *
730 * @return A @c uint64_t with the double bits.
731 *
732 * Convenience function to avoid type punning, compiler warnings and
733 * such. The optimizer usually reduces this to a simple assignment. This
734 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100735 */
736static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
737
738
739/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700740 * @brief Copy a @c uint32_t to a @c float.
741 *
742 * @param[in] u32 Integer value to copy.
743 *
744 * @return The value as a @c float.
745 *
746 * Convenience function to avoid type punning, compiler warnings and
747 * such. The optimizer usually reduces this to a simple assignment. This
748 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100749 */
750static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
751
752
753/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700754 * @brief Copy a @c uint64_t to a @c double.
755 *
756 * @param[in] u64 Integer value to copy.
757 *
758 * @return The value as a @c double.
759 *
760 * Convenience function to avoid type punning, compiler warnings and
761 * such. The optimizer usually reduces this to a simple assignment. This
762 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100763 */
764static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200765#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100766
767
768
769
770/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700771 * UsefulOutBuf is a structure and functions (an object) for
772 * serializing data into a buffer to encode for a network protocol or
773 * write data to a file.
774 *
775 * The main idea is that all the pointer manipulation is performed by
776 * @ref UsefulOutBuf functions so the caller doesn't have to do any
777 * pointer manipulation. The pointer manipulation is centralized.
778 * This code has been reviewed and written carefully so it
779 * spares the caller of much of this work and results in safer code
780 * with less effort.
781 *
782 * The @ref UsefulOutBuf methods that add data to the output buffer
783 * always check the length and will never write off the end of the
784 * output buffer. If an attempt to add data that will not fit is made,
785 * an internal error flag will be set and further attempts to add data
786 * will not do anything.
787 *
788 * There is no way to ever write off the end of that buffer when
789 * calling the @c UsefulOutBuf_AddXxx() and
790 * @c UsefulOutBuf_InsertXxx() functions.
791 *
792 * The functions to add data do not report success of failure. The
793 * caller only needs to check for an error in the final call, either
794 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
795 * result. This makes the calling code cleaner.
796 *
797 * There is a utility function to get the error status anytime along
798 * the way for a special circumstance. There are functions to see how
799 * much room is left and see if some data will fit too, but their use
800 * is generally unnecessary.
801 *
802 * The general call flow is:
803 *
804 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
805 * buffer given to it can be from the heap, stack or
806 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
807 * macro that makes a buffer on the stack and initializes it.
808 *
809 * - Call methods like UsefulOutBuf_InsertString(),
810 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
811 * to output data. The append calls add data to the end of the
812 * valid data. The insert calls take a position argument.
813 *
814 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
815 * there were no errors and to get the serialized output bytes.
816 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700817 * @ref UsefulOutBuf can be used in a mode to calculate the size of
818 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700819 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700820 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700821 *
822 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700823 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700824 *
825 * The possible errors are:
826 *
827 * - The @ref UsefulOutBuf was not initialized or was corrupted.
828 *
829 * - An attempt was made to add data that will not fit.
830 *
831 * - An attempt was made to insert data at a position beyond the end of
832 * the buffer.
833 *
834 * - An attempt was made to insert data at a position beyond the valid
835 * data in the buffer.
836 *
837 * Some inexpensive simple sanity checks are performed before every
838 * data addition to guard against use of an uninitialized or corrupted
839 * UsefulOutBuf.
840 *
841 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
842 * encoder has almost no pointer manipulation in it, is easier to
843 * read, and easier to review.
844 *
845 * A @ref UsefulOutBuf is small and can go on the stack:
846 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
847 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100848 */
849typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700850 /* PRIVATE DATA STRUCTURE */
851 UsefulBuf UB; /* Memory that is being output to */
852 size_t data_len; /* length of the valid data, the insertion point */
853 uint16_t magic; /* Used to detect corruption and lack
854 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100855 uint8_t err;
856} UsefulOutBuf;
857
858
859/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700860 * This is a @ref UsefulBuf value that can be passed to
861 * UsefulOutBuf_Init() to have it calculate the size of the output
862 * buffer needed. Pass this for @c Storage, call all the append and
863 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
864 * returned @ref UsefulBufC has the size.
865 *
866 * As one can see, this is just a NULL pointer and very large size.
867 * The NULL pointer tells UsefulOutputBuf to not copy any data.
868 */
869#ifdef __cplusplus
870#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
871#else
872#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
873#endif
874
875
876/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700877 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700878 *
879 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
880 * @param[in] Storage Buffer to output into.
881 *
882 * This initializes the @ref UsefulOutBuf with storage, sets the
883 * current position to the beginning of the buffer and clears the
884 * error state.
885 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700886 * See @ref SizeCalculateUsefulBuf for instructions on how to
887 * initialize a @ref UsefulOutBuf to calculate the size that would be
888 * output without actually outputting.
889 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700890 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100891 */
892void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
893
894
895/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700896 * Convenience macro to make a @ref UsefulOutBuf on the stack and
897 * initialize it with a stack buffer of the given size. The variable
898 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100899 */
900#define UsefulOutBuf_MakeOnStack(name, size) \
901 uint8_t __pBuf##name[(size)];\
902 UsefulOutBuf name;\
903 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
904
905
906/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700907 * @brief Reset a @ref UsefulOutBuf for re use.
908 *
909 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
910 *
911 * This sets the amount of data in the output buffer to none and
912 * clears the error state.
913 *
914 * The output buffer is still the same one and size as from the
915 * UsefulOutBuf_Init() call.
916 *
917 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100918 */
919static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
920
921
922/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700923 * @brief Returns position of end of data in the @ref UsefulOutBuf.
924 *
925 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
926 *
927 * @return position of end of data.
928 *
929 * On a freshly initialized @ref UsefulOutBuf with no data added, this
930 * will return 0. After 10 bytes have been added, it will return 10
931 * and so on.
932 *
933 * Generally, there is no need to call this for most uses of @ref
934 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100935 */
936static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
937
938
939/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700940 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
941 *
942 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
943 *
944 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100945 */
946static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
947
948
949/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700950 * @brief Inserts bytes into the @ref UsefulOutBuf.
951 *
952 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
953 * @param[in] NewData The bytes to insert.
954 * @param[in] uPos Index in output buffer at which to insert.
955 *
956 * @c NewData is the pointer and length for the bytes to be added to
957 * the output buffer. There must be room in the output buffer for all
958 * of @c NewData or an error will occur.
959 *
960 * The insertion point must be between 0 and the current valid
961 * data. If not, an error will occur. Appending data to the output
962 * buffer is achieved by inserting at the end of the valid data. This
963 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
964 *
965 * When insertion is performed, the bytes between the insertion point
966 * and the end of data previously added to the output buffer are slid
967 * to the right to make room for the new data.
968 *
969 * Overlapping buffers are OK. @c NewData can point to data in the
970 * output buffer.
971 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700972 * NewData.len may be 0 in which case nothing will be inserted.
973 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700974 * If an error occurs, an error state is set in the @ref
975 * UsefulOutBuf. No error is returned. All subsequent attempts to add
976 * data will do nothing.
977 *
978 * The intended use is that all additions are made without checking
979 * for an error. The error will be taken into account when
980 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
981 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100982 */
983void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
984 UsefulBufC NewData,
985 size_t uPos);
986
987
988/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700989 * @brief Insert a data buffer into the @ref UsefulOutBuf.
990 *
991 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
992 * @param[in] pBytes Pointer to the bytes to insert
993 * @param[in] uLen Length of the bytes to insert
994 * @param[in] uPos Index in output buffer at which to insert
995 *
996 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
997 * the difference being a pointer and length is passed in rather than an
998 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100999 */
1000static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
1001 const void *pBytes,
1002 size_t uLen,
1003 size_t uPos);
1004
1005
1006/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001007 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1008 *
1009 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1010 * @param[in] szString NULL-terminated string to insert.
1011 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001012 */
1013static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1014 const char *szString,
1015 size_t uPos);
1016
1017
1018/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001019 * @brief Insert a byte into the @ref UsefulOutBuf.
1020 *
1021 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1022 * @param[in] byte Bytes to insert.
1023 * @param[in] uPos Index in output buffer at which to insert.
1024 *
1025 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1026 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001027 */
1028static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1029 uint8_t byte,
1030 size_t uPos);
1031
1032
1033/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001034 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1035 *
1036 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1037 * @param[in] uInteger16 Integer to insert.
1038 * @param[in] uPos Index in output buffer at which to insert.
1039 *
1040 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1041 * with the difference being a two-byte integer is to be inserted.
1042 *
1043 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001044 */
1045static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1046 uint16_t uInteger16,
1047 size_t uPos);
1048
1049
1050/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001051 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1052 *
1053 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1054 * @param[in] uInteger32 Integer to insert.
1055 * @param[in] uPos Index in output buffer at which to insert.
1056 *
1057 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1058 * with the difference being a four-byte integer is to be inserted.
1059 *
1060 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001061 */
1062static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1063 uint32_t uInteger32,
1064 size_t uPos);
1065
1066
1067/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001068 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1069 *
1070 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1071 * @param[in] uInteger64 Integer to insert.
1072 * @param[in] uPos Index in output buffer at which to insert.
1073 *
1074 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1075 * with the difference being an eight-byte integer is to be inserted.
1076 *
1077 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001078 */
1079static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1080 uint64_t uInteger64,
1081 size_t uPos);
1082
1083
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001084#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001085/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001086 * @brief Insert a @c float into the @ref UsefulOutBuf.
1087 *
1088 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1089 * @param[in] f @c float to insert.
1090 * @param[in] uPos Index in output buffer at which to insert.
1091 *
1092 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1093 * with the difference being a @c float is to be inserted.
1094 *
1095 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001096 */
1097static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1098 float f,
1099 size_t uPos);
1100
1101
1102/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001103 * @brief Insert a @c double into the @ref UsefulOutBuf.
1104 *
1105 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1106 * @param[in] d @c double to insert.
1107 * @param[in] uPos Index in output buffer at which to insert.
1108 *
1109 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1110 * with the difference being a @c double is to be inserted.
1111 *
1112 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001113 */
1114static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1115 double d,
1116 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001117#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001118
1119
1120/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001121 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1122 *
1123 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1124 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1125 *
1126 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1127 * with the insertion point at the end of the valid data.
1128 */
Michael Eckel5c531332020-03-02 01:35:30 +01001129static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1130 UsefulBufC NewData);
1131
1132
1133/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001134 * @brief Append bytes to the @ref UsefulOutBuf.
1135 *
1136 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1137 * @param[in] pBytes Pointer to bytes to append.
1138 * @param[in] uLen Length of @c pBytes to append.
1139 *
1140 * See UsefulOutBuf_InsertData() for details. This does the same with
1141 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001142 */
1143static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1144 const void *pBytes,
1145 size_t uLen);
1146
1147
1148/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001149 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1150 *
1151 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1152 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001153 */
1154static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1155 const char *szString);
1156
1157
1158/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001159 * @brief Append a byte to the @ref UsefulOutBuf
1160 *
1161 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1162 * @param[in] byte Bytes to append.
1163 *
1164 * See UsefulOutBuf_InsertByte() for details. This does the same
1165 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001166 */
1167static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1168 uint8_t byte);
1169
1170
1171/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001172 * @brief Append an integer to the @ref UsefulOutBuf
1173 *
1174 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1175 * @param[in] uInteger16 Integer to append.
1176 *
1177 * See UsefulOutBuf_InsertUint16() for details. This does the same
1178 * with the insertion point at the end of the valid data.
1179 *
1180 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001181 */
1182static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1183 uint16_t uInteger16);
1184
1185
1186/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001187 * @brief Append an integer to the @ref UsefulOutBuf
1188 *
1189 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1190 * @param[in] uInteger32 Integer to append.
1191 *
1192 * See UsefulOutBuf_InsertUint32() for details. This does the same
1193 * with the insertion point at the end of the valid data.
1194 *
1195 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001196 */
1197static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1198 uint32_t uInteger32);
1199
1200
1201/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001202 * @brief Append an integer to the @ref UsefulOutBuf
1203 *
1204 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1205 * @param[in] uInteger64 Integer to append.
1206 *
1207 * See UsefulOutBuf_InsertUint64() for details. This does the same
1208 * with the insertion point at the end of the valid data.
1209 *
1210 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001211 */
1212static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1213 uint64_t uInteger64);
1214
1215
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001216#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001217/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001218 * @brief Append a @c float to the @ref UsefulOutBuf
1219 *
1220 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1221 * @param[in] f @c float to append.
1222 *
1223 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1224 * the insertion point at the end of the valid data.
1225 *
1226 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001227 */
1228static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1229 float f);
1230
1231
1232/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001233 * @brief Append a @c double to the @ref UsefulOutBuf
1234 *
1235 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1236 * @param[in] d @c double to append.
1237 *
1238 * See UsefulOutBuf_InsertDouble() for details. This does the same
1239 * with the insertion point at the end of the valid data.
1240 *
1241 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001242 */
1243static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1244 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001245#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001246
1247
1248/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001249 * @brief Returns the current error status.
1250 *
1251 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1252 *
1253 * @return 0 if all OK, 1 on error.
1254 *
1255 * This returns the error status since a call to either
1256 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1257 * goes into the error state, it will stay until one of those
1258 * functions is called.
1259 *
1260 * Possible error conditions are:
1261 * - bytes to be inserted will not fit
1262 * - insertion point is out of buffer or past valid data
1263 * - current position is off end of buffer (probably corrupted or uninitialized)
1264 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001265 */
1266static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1267
1268
1269/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001270 * @brief Returns number of bytes unused used in the output buffer.
1271 *
1272 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1273 *
1274 * @return Number of unused bytes or zero.
1275 *
1276 * Because of the error handling strategy and checks in
1277 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1278 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001279 */
1280static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1281
1282
1283/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001284 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1285 *
1286 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1287 * @param[in] uLen Number of bytes for which to check
1288 *
1289 * @return 1 if @c uLen bytes will fit, 0 if not.
1290 *
1291 * Because of the error handling strategy and checks in
1292 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1293 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001294 */
1295static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1296
1297
1298 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001299 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1300 *
1301 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1302 *
1303 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1304 *
1305 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1306 * just calculating the length of the encoded data.
1307 */
Michael Eckel5c531332020-03-02 01:35:30 +01001308static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1309
1310
1311/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001312 * @brief Returns pointer and length of the output buffer not yet used.
1313 *
1314 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1315 *
1316 * @return pointer and length of output buffer not used.
1317 *
1318 * This is an escape that allows the caller to write directly
1319 * to the output buffer without any checks. This doesn't
1320 * change the output buffer or state. It just returns a pointer
1321 * and length of the bytes remaining.
1322 *
1323 * This is useful to avoid having the bytes to be added all
1324 * in a contiguous buffer. Its use can save memory. A good
1325 * example is in the COSE encrypt implementation where
1326 * the output of the symmetric cipher can go directly
1327 * into the output buffer, rather than having to go into
1328 * an intermediate buffer.
1329 *
1330 * See UsefulOutBuf_Advance() which is used to tell
1331 * UsefulOutBuf how much was written.
1332 *
1333 * Warning: this bypasses the buffer safety provided by
1334 * UsefulOutBuf!
1335 */
1336static inline UsefulBuf
1337UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1338
1339
1340/**
1341 * @brief Advance the amount output assuming it was written by the caller.
1342 *
1343 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1344 * @param[in] uAmount The amount to advance.
1345 *
1346 * This advances the position in the output buffer
1347 * by \c uAmount. This assumes that the
1348 * caller has written \c uAmount to the pointer obtained
1349 * with UsefulOutBuf_GetOutPlace().
1350 *
1351 * Warning: this bypasses the buffer safety provided by
1352 * UsefulOutBuf!
1353 */
1354void
1355UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1356
1357
1358/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001359 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001360 *
1361 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1362 *
1363 * @return The valid data in @ref UsefulOutBuf or
1364 * @ref NULLUsefulBufC if there was an error adding data.
1365 *
1366 * The storage for the returned data is the @c Storage parameter
1367 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1368 *
1369 * This can be called anytime and many times to get intermediate
1370 * results. It doesn't change the data or reset the current position,
1371 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001372 */
1373UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1374
1375
1376/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001377 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001378 *
1379 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1380 * @param[out] Dest The destination buffer to copy into.
1381 *
1382 * @return Pointer and length of copied data or @c NULLUsefulBufC
1383 * if it will not fit in the @c Dest buffer or the error
1384 * state was entered.
1385 *
1386 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001387 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001388 */
Michael Eckel5c531332020-03-02 01:35:30 +01001389UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1390
1391
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001392/**
1393 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1394 *
1395 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1396 * @param[in] uOffset Offset to bytes to return.
1397 *
1398 * @return NULLUsefulBufC or the bytes at the offset.
1399 *
1400 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1401 * maybe specified. It returns the bytes starting at @c uOffset to the
1402 * end of what was encoded so far. Calling this with @c uOffset 0 is
1403 * equivalent to UsefulOutBuf_OutUBuf().
1404 *
1405 * If there's nothing at @c uOffset or it is past the in the output
1406 * buffer, a \ref NULLUsefulBufC is returned.
1407 *
1408 * This is typically not needed in typical use. It is used by QCBOR
1409 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1410 * sorting CBOR maps.
1411 */
1412UsefulBufC
1413UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1414
1415
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001416/*
1417 * @brief Return a substring of the output data.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001418 *
1419 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1420 * @param[in] uStart Offset of start of substring.
1421 * @param[in] uLen Length of substring.
1422 *
1423 * This is the same as UsefulOutBuf_OutUBuf(), but returns a
1424 * substring. @c NULLUsefulBufC is returned if the requested substring
1425 * is off the end of the output bytes or if in error state.
1426 */
1427UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pUOutBuf,
1428 const size_t uStart,
1429 const size_t uLen);
1430
1431
1432/**
1433 * @brief Retrieve the storage buffer passed in to UsefulOutBuf_Init().
1434 *
1435 * @param[in] pUOutBuf The encoding context.
1436 *
1437 * @return The output storage buffer passed to UsefulOutBuf_Init().
1438 *
1439 * This doesn't give any information about how much has been encoded
1440 * or the error state. It just returns the exact @ref UsefulOutBuf given
1441 * to UsefulOutBuf_Init().
1442 */
1443static UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pUOutBuf);
1444
Michael Eckel5c531332020-03-02 01:35:30 +01001445
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001446/**
1447 * @brief Compare bytes at offsets.
1448 *
1449 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1450 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001451 * @param[in] uLen1 Length of first bytes to compare.
1452 * @param[in] uStart2 Offset of second bytes to compare.
1453 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001454 *
1455 * @return 0 for equality, positive if uStart1 is lexographically larger,
1456 * negative if uStart2 is lexographically larger.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001457 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001458 * This looks into bytes that have been output at the offsets @c start1
1459 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001460 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1461 * length of the string given is off the end of the output data, the
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001462 * string will be effectively truncated to the data in the output
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001463 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001464 *
1465 * This returns positive when @c uStart1 lexographically sorts ahead
1466 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001467 * compare equally.
1468 *
1469 * If lengths are unequal and the first bytes are an exact subset of
1470 * the second string, then a positve value will be returned and vice
1471 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001472 *
1473 * If either start is past the end of data in the output buffer, 0
1474 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001475 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001476 * being made. No data will ever be read off the end of the buffer so
1477 * this safe no matter what offsets are passed.
1478 *
1479 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001480 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1481 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001482 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001483int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1484 size_t uStart1, size_t uLen1,
1485 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001486
1487/**
1488 * @brief Swap two regions of output bytes.
1489 *
1490 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1491 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1492 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1493 * @param[in] uEndOffset Offset to end of region to be swappe.
1494 *
1495 * This reaches into bytes that have been output and swaps two
1496 * adjacent regions.
1497 *
1498 * If any of the offsets are outside the range of valid data, no
1499 * swapping will be performed. If the start is not the smallest and
1500 * the pivot is not in the middle no swapping will be performed.
1501 *
1502 * The byte at @c uStartOffset will participate in the swapping. The
1503 * byte at @c uEndOffset will not participate in the swapping, only
1504 * the byte before it.
1505 *
1506 * This is a relatively odd function in that it works on data in the
1507 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1508 * maps.
1509 */
1510void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1511 size_t uStartOffset,
1512 size_t uPivotOffset,
1513 size_t uEndOffset);
1514
1515
Michael Eckel5c531332020-03-02 01:35:30 +01001516
1517
1518/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001519 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1520 * for parsing data received. Initialize it with the data from the
1521 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1522 * get data chunks of various types. A position cursor is maintained
1523 * internally.
1524 *
1525 * As long as the functions here are used, there will never be any
1526 * reference off the end of the given buffer (except
1527 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1528 * called incorrectly, an attempt is made to seek off the end of the
1529 * buffer or such. This makes it easier to write safe and correct
1530 * code. For example, the QCBOR decoder implementation is safer and
1531 * easier to review through its use of @ref UsefulInputBuf.
1532 *
1533 * @ref UsefulInputBuf maintains an internal error state. The
1534 * intended use is fetching data chunks without any error checks until
1535 * the end. If there was any error, such as an attempt to fetch data
1536 * off the end, the error state is entered and no further data will be
1537 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1538 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1539 * null is not dereferenced, the error check can be put off until the
1540 * end, simplifying the calling code.
1541 *
1542 * The integer and float parsing expects network byte order (big
1543 * endian). Network byte order is what is used by TCP/IP, CBOR and
1544 * most internet protocols.
1545 *
1546 * Lots of inline functions are used to keep code size down. The
1547 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1548 * code size a lot. The only non-inline code is
1549 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1550 * @ref UsefulInputBuf doesn't add much code for all the messy
1551 * hard-to-get right issues with parsing binary protocols in C that it
1552 * solves.
1553 *
1554 * The parse context size is:
1555 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1556 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001557 */
1558typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001559 /* PRIVATE DATA STRUCTURE */
1560 UsefulBufC UB; /* Data being parsed */
1561 size_t cursor; /* Current offset in data being parse */
1562 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1563 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001564} UsefulInputBuf;
1565
1566#define UIB_MAGIC (0xB00F)
1567
1568
1569/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001570 * @brief Initialize the @ref UsefulInputBuf structure before use.
1571 *
1572 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1573 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001574 */
1575static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1576
1577
1578/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001579 * @brief Returns current position in input buffer.
1580 *
1581 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1582 *
1583 * @return Integer position of the cursor.
1584 *
1585 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001586 */
1587static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1588
1589
1590/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001591 * @brief Sets the current position in input buffer.
1592 *
1593 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1594 * @param[in] uPos Position to set to.
1595 *
1596 * If the position is off the end of the input buffer, the error state
1597 * is entered.
1598 *
1599 * Seeking to a valid position in the buffer will not reset the error
1600 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001601 */
1602static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1603
1604
1605/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001606 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1607 * the unconsumed bytes.
1608 *
1609 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1610 *
1611 * @return Number of bytes unconsumed or 0 on error.
1612 *
1613 * Returns 0 if the cursor is invalid or corruption of the
1614 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001615 */
1616static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1617
1618
1619/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001620 * @brief Check if there are unconsumed bytes.
1621 *
1622 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1623 * @param[in] uLen Number of bytes to check availability for.
1624 *
1625 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001626 */
1627static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1628
1629
1630/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001631 * @brief Convert a pointer to an offset with bounds checking.
1632 *
1633 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1634 * @param[in] p Pointer to convert to offset.
1635 *
1636 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1637 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001638static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1639
1640
1641/**
1642 * @brief Convert an offset to a pointer with bounds checking.
1643 *
1644 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1645 * @param[in] uOffset Offset in @c pUInBuf.
1646 *
1647 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1648 */
1649static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001650
1651
1652/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001653 * @brief Get pointer to bytes out of the input buffer.
1654 *
1655 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1656 * @param[in] uNum Number of bytes to get.
1657 *
1658 * @return Pointer to bytes.
1659 *
1660 * This consumes @c uNum bytes from the input buffer. This returns a
1661 * pointer to the start of the @c uNum bytes.
1662 *
1663 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1664 * returned and the error state is entered.
1665 *
1666 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001667 */
1668const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1669
1670
1671/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001672 * @brief Get @ref UsefulBuf out of the input buffer.
1673 *
1674 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1675 * @param[in] uNum Number of bytes to get.
1676 *
1677 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1678 *
1679 * This consumes @c uNum bytes from the input buffer and returns the
1680 * pointer and length for them as a @ref UsefulBufC. The length
1681 * returned will always be @c uNum. The position cursor is advanced by
1682 * @c uNum bytes.
1683 *
1684 * If there are not @c uNum bytes in the input buffer, @ref
1685 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001686 */
1687static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1688
1689
1690/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001691 * @brief Get a byte out of the input buffer.
1692 *
1693 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1694 *
1695 * @return The byte.
1696 *
1697 * This consumes 1 byte from the input buffer, returns it and advances
1698 * the position cursor by 1.
1699 *
1700 * If there is not 1 byte in the buffer, 0 will be returned for the
1701 * byte and the error state is entered. To know if the 0 returned was
1702 * in error or the real value, the error state must be checked. If
1703 * possible, put this off until all values are retrieved to have
1704 * smaller and simpler code, but if not possible
1705 * UsefulInputBuf_GetError() can be called. Also, in the error state
1706 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1707 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001708 */
1709static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1710
1711
1712/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001713 * @brief Get a @c uint16_t out of the input buffer.
1714 *
1715 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1716 *
1717 * @return The @c uint16_t.
1718 *
1719 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1720 * a @c uint16_t and two bytes are consumed.
1721 *
1722 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001723 */
1724static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1725
1726
1727/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001728 * @brief Get a @c uint32_t out of the input buffer.
1729 *
1730 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1731 *
1732 * @return The @c uint32_t.
1733 *
1734 * See UsefulInputBuf_GetByte(). This works the same, except it
1735 * returns a @c uint32_t and four bytes are consumed.
1736 *
1737 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001738 */
1739static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1740
1741
1742/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001743 * @brief Get a @c uint64_t out of the input buffer.
1744 *
1745 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1746 *
1747 * @return The uint64_t.
1748 *
1749 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1750 * a @c uint64_t and eight bytes are consumed.
1751 *
1752 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001753 */
1754static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1755
1756
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001757#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001758/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001759 * @brief Get a float out of the input buffer.
1760 *
1761 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1762 *
1763 * @return The float.
1764 *
1765 * See UsefulInputBuf_GetByte(). This works the same, except it
1766 * returns a float and four bytes are consumed.
1767 *
1768 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001769 */
1770static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1771
1772
1773/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001774 * @brief Get a double out of the input buffer.
1775 *
1776 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1777 *
1778 * @return The double.
1779 *
1780 * See UsefulInputBuf_GetByte(). This works the same, except it
1781 * returns a double and eight bytes are consumed.
1782 *
1783 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001784 */
1785static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001786#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001787
1788
1789/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001790 * @brief Get the error status.
1791 *
1792 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1793 *
1794 * @return 0 if not in the error state, 1 if in the error state.
1795 *
1796 * This returns whether the @ref UsefulInputBuf is in the
1797 * error state or not.
1798 *
1799 * The error state is entered for one of these reasons:
1800 * - Attempt to fetch data past the end of the buffer
1801 * - Attempt to seek to a position past the end of the buffer
1802 * - Attempt to get data from an uninitialized or corrupt instance
1803 * of @ref UsefulInputBuf
1804 *
1805 * Once in the error state, it can only be cleared by calling
1806 * UsefulInputBuf_Init().
1807 *
1808 * For many use cases, it is possible to only call this once after all
1809 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1810 * possible if no reference to the data returned are needed before the
1811 * error state is checked.
1812 *
1813 * In some cases UsefulInputBuf_GetUsefulBuf() or
1814 * UsefulInputBuf_GetBytes() can stand in for this because they return
1815 * @c NULL if the error state has been entered. (The others can't stand
1816 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001817 */
1818static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1819
1820
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001821/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001822 * @brief Gets the input buffer length.
1823 *
1824 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1825 *
1826 * @return The length of the input buffer.
1827 *
1828 * This returns the length of the input buffer set by
1829 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001830 */
1831static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1832
1833
1834/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001835 * @brief Alters the input buffer length (use with caution).
1836 *
1837 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1838 * @param[in] uNewLen The new length of the input buffer.
1839 *
1840 * This alters the internal remembered length of the input buffer set
1841 * when UsefulInputBuf_Init() was called.
1842 *
1843 * The new length given here should always be equal to or less than
1844 * the length given when UsefulInputBuf_Init() was called. Making it
1845 * larger allows @ref UsefulInputBuf to run off the input buffer.
1846 *
1847 * The typical use is to set a length shorter than that when
1848 * initialized to constrain parsing. If
1849 * UsefulInputBuf_GetBufferLength() was called before this, then the
1850 * original length can be restored with another call to this.
1851 *
1852 * This should be used with caution. It is the only
1853 * @ref UsefulInputBuf method that can violate the safety of input
1854 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001855 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001856static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001857
1858
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001859/** @brief Retrieve the undecoded input buffer.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001860 *
1861 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1862 *
1863 * @return The input that was given to UsefulInputBuf_Init().
1864 *
1865 * A simple convenience method, should it be useful to get the original input back.
1866 */
1867static UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pUInBuf);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001868
1869
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001870/**
1871 * @brief Compare two ranges of bytes somewhere in the input buffer.
1872 *
1873 * @param[in] pUInBuf The input buffer.
1874 * @param[in] uOffset1 Offset of first range of bytes.
1875 * @param[in] uLen1 Length of first range of bytes.
1876 * @param[in] uOffset2 Offset of second range of bytes.
1877 * @param[in] uLen2 Length of second range of bytes.
1878 *
1879 * This returns the same as UsefulBuf_Compare().
1880 *
1881 * If the offset or the length plus offset or a range extends outside
1882 * the input buffer, that range of bytes will be considered greater
1883 * than the other string. If both are outside this is considered a
1884 * degenerate condition and the first string is considered larger.
1885 *
1886 * This is a somewhat odd function of UsefulInputBuf as it is not used
1887 * for consuming data. QCBOR uses it for map order and duplicate
1888 * checking.
1889 */
1890int
1891UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
1892 const size_t uOffset1,
1893 const size_t uLen1,
1894 const size_t uOffset2,
1895 const size_t uLen2);
Michael Eckel5c531332020-03-02 01:35:30 +01001896
1897
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001898
1899
Michael Eckel5c531332020-03-02 01:35:30 +01001900/*----------------------------------------------------------
1901 Inline implementations.
1902 */
1903static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1904{
1905 return !UB.ptr;
1906}
1907
1908
1909static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1910{
1911 return !UB.ptr;
1912}
1913
1914
1915static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1916{
1917 return !UB.len;
1918}
1919
1920
1921static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1922{
1923 return !UB.len;
1924}
1925
1926
1927static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1928{
1929 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1930}
1931
1932
1933static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1934{
1935 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1936}
1937
1938
1939static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1940{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001941 UsefulBufC UBC;
1942 UBC.ptr = UB.ptr;
1943 UBC.len = UB.len;
1944
1945 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001946}
1947
Michael Eckel5c531332020-03-02 01:35:30 +01001948static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1949{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001950 UsefulBuf UB;
1951
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001952 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001953 * the one place in UsefulBuf where it needs to be quieted.
1954 */
1955 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001956
1957 UB.len = UBC.len;
1958
1959 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001960}
1961
1962
1963static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1964{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001965 UsefulBufC UBC;
1966 UBC.ptr = szString;
1967 UBC.len = strlen(szString);
1968 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001969}
1970
1971
1972static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1973{
1974 return UsefulBuf_CopyOffset(Dest, 0, Src);
1975}
1976
1977
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001978static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001979{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001980 memset(Dest.ptr, value, Dest.len);
1981
1982 UsefulBufC UBC;
1983 UBC.ptr = Dest.ptr;
1984 UBC.len = Dest.len;
1985
1986 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001987}
1988
1989
1990static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1991{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001992 UsefulBufC UBC;
1993 UBC.ptr = ptr;
1994 UBC.len = len;
1995 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001996}
1997
1998
1999static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
2000{
2001 if(uAmount > UB.len) {
2002 return NULLUsefulBufC;
2003 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002004 UsefulBufC UBC;
2005
2006 UBC.ptr = UB.ptr;
2007 UBC.len = uAmount;
2008
2009 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002010}
2011
2012
2013static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
2014{
2015 UsefulBufC ReturnValue;
2016
2017 if(uAmount > UB.len) {
2018 ReturnValue = NULLUsefulBufC;
2019 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002020 ReturnValue.ptr = NULL;
2021 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002022 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002023 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
2024 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002025 }
2026
2027 return ReturnValue;
2028}
2029
2030
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002031static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
2032{
2033 if(UB.ptr == NULL) {
2034 return SIZE_MAX;
2035 }
2036
2037 if(p < UB.ptr) {
2038 /* given pointer is before start of buffer */
2039 return SIZE_MAX;
2040 }
2041
Laurence Lundblade3eead482023-12-16 20:53:22 -07002042 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002043 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002044
2045 if(uOffset >= UB.len) {
2046 /* given pointer is off the end of the buffer */
2047 return SIZE_MAX;
2048 }
2049
2050 return uOffset;
2051}
2052
Michael Eckel5c531332020-03-02 01:35:30 +01002053
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002054static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
2055{
2056 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
2057 return NULL;
2058 }
2059
2060 return (const uint8_t *)UB.ptr + uOffset;
2061}
2062
2063
2064
2065
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002066#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002067static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
2068{
2069 uint32_t u32;
2070 memcpy(&u32, &f, sizeof(uint32_t));
2071 return u32;
2072}
2073
2074static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2075{
2076 uint64_t u64;
2077 memcpy(&u64, &d, sizeof(uint64_t));
2078 return u64;
2079}
2080
2081static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2082{
2083 double d;
2084 memcpy(&d, &u64, sizeof(uint64_t));
2085 return d;
2086}
2087
2088static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2089{
2090 float f;
2091 memcpy(&f, &u32, sizeof(uint32_t));
2092 return f;
2093}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002094#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002095
2096
2097
2098
2099static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2100{
2101 pMe->data_len = 0;
2102 pMe->err = 0;
2103}
2104
2105
2106static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2107{
2108 return pMe->data_len;
2109}
2110
2111
2112static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2113{
2114 return 0 == pMe->data_len;
2115}
2116
2117
2118static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2119 const void *pBytes,
2120 size_t uLen,
2121 size_t uPos)
2122{
2123 UsefulBufC Data = {pBytes, uLen};
2124 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2125}
2126
2127
2128static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2129 const char *szString,
2130 size_t uPos)
2131{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002132 UsefulBufC UBC;
2133 UBC.ptr = szString;
2134 UBC.len = strlen(szString);
2135
2136 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002137}
2138
2139
2140static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2141 uint8_t byte,
2142 size_t uPos)
2143{
2144 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2145}
2146
2147
2148static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2149 uint16_t uInteger16,
2150 size_t uPos)
2151{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002152 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002153
2154 const void *pBytes;
2155
2156#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2157 pBytes = &uInteger16;
2158
2159#elif defined(USEFULBUF_CONFIG_HTON)
2160 uint16_t uTmp = htons(uInteger16);
2161 pBytes = &uTmp;
2162
2163#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2164 uint16_t uTmp = __builtin_bswap16(uInteger16);
2165 pBytes = &uTmp;
2166
2167#else
2168 uint8_t aTmp[2];
2169
2170 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2171 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2172
2173 pBytes = aTmp;
2174#endif
2175
2176 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2177}
2178
2179
2180static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2181 uint32_t uInteger32,
2182 size_t uPos)
2183{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002184 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002185
2186 const void *pBytes;
2187
2188#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2189 pBytes = &uInteger32;
2190
2191#elif defined(USEFULBUF_CONFIG_HTON)
2192 uint32_t uTmp = htonl(uInteger32);
2193 pBytes = &uTmp;
2194
2195#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2196 uint32_t uTmp = __builtin_bswap32(uInteger32);
2197
2198 pBytes = &uTmp;
2199
2200#else
2201 uint8_t aTmp[4];
2202
2203 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2204 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2205 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2206 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2207
2208 pBytes = aTmp;
2209#endif
2210
2211 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2212}
2213
2214static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002215 uint64_t uInteger64,
2216 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002217{
2218 const void *pBytes;
2219
2220#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002221 /* We have been told explicitly we are running on a big-endian
2222 * machine. Network byte order is big endian, so just copy. There
2223 * is no issue with alignment here because uInteger64 is always
2224 * aligned (and it doesn't matter if pBytes is aligned).
2225 */
Michael Eckel5c531332020-03-02 01:35:30 +01002226 pBytes = &uInteger64;
2227
2228#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002229 /* Use system function to handle big- and little-endian. This works
2230 * on both big- and little-endian machines, but hton() is not
2231 * always available or in a standard place so it is not used by
2232 * default. With some compilers and CPUs the code for this is very
2233 * compact through use of a special swap instruction and on
2234 * big-endian machines hton() will reduce to nothing.
2235 */
Michael Eckel5c531332020-03-02 01:35:30 +01002236 uint64_t uTmp = htonll(uInteger64);
2237
2238 pBytes = &uTmp;
2239
2240#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002241 /* Use built-in function for byte swapping. This usually compiles
2242 * to an efficient special byte swap instruction. Unlike hton() it
2243 * does not do this conditionally on the CPU endianness, so this
2244 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2245 */
Michael Eckel5c531332020-03-02 01:35:30 +01002246 uint64_t uTmp = __builtin_bswap64(uInteger64);
2247
2248 pBytes = &uTmp;
2249
2250#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002251 /* Default which works on every CPU with no dependency on anything
2252 * from the CPU, compiler, libraries or OS. This always works, but
2253 * it is usually a little larger and slower than hton().
2254 */
Michael Eckel5c531332020-03-02 01:35:30 +01002255 uint8_t aTmp[8];
2256
2257 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2258 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2259 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2260 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2261 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2262 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2263 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2264 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2265
2266 pBytes = aTmp;
2267#endif
2268
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002269 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002270 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2271}
2272
2273
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002274#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002275static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2276 float f,
2277 size_t uPos)
2278{
2279 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2280}
2281
2282
2283static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2284 double d,
2285 size_t uPos)
2286{
2287 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2288}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002289#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002290
2291
2292static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2293 UsefulBufC NewData)
2294{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002295 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002296 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2297}
2298
2299
2300static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2301 const void *pBytes,
2302 size_t uLen)
2303{
2304 UsefulBufC Data = {pBytes, uLen};
2305 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2306}
2307
2308
2309static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2310 const char *szString)
2311{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002312 UsefulBufC UBC;
2313 UBC.ptr = szString;
2314 UBC.len = strlen(szString);
2315
2316 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002317}
2318
2319
2320static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2321 uint8_t byte)
2322{
2323 UsefulOutBuf_AppendData(pMe, &byte, 1);
2324}
2325
2326
2327static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2328 uint16_t uInteger16)
2329{
2330 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2331}
2332
2333static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2334 uint32_t uInteger32)
2335{
2336 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2337}
2338
2339
2340static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2341 uint64_t uInteger64)
2342{
2343 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2344}
2345
2346
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002347#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002348static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2349 float f)
2350{
2351 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2352}
2353
2354
2355static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2356 double d)
2357{
2358 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2359}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002360#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002361
2362
2363static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2364{
2365 return pMe->err;
2366}
2367
2368
2369static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2370{
2371 return pMe->UB.len - pMe->data_len;
2372}
2373
2374
2375static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2376{
2377 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2378}
2379
2380
2381static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2382{
2383 return pMe->UB.ptr == NULL;
2384}
2385
2386
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002387static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2388{
2389 UsefulBuf R;
2390
2391 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002392 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002393 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2394 } else {
2395 R.ptr = NULL;
2396 }
2397
2398 return R;
2399}
2400
2401
Laurence Lundbladee2226742024-08-16 10:50:23 -07002402static inline UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pMe)
2403{
2404 return pMe->UB;
2405}
2406
2407
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002408
Michael Eckel5c531332020-03-02 01:35:30 +01002409
2410static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2411{
2412 pMe->cursor = 0;
2413 pMe->err = 0;
2414 pMe->magic = UIB_MAGIC;
2415 pMe->UB = UB;
2416}
2417
2418static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2419{
2420 return pMe->cursor;
2421}
2422
2423
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002424static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002425{
2426 return pMe->UB.len;
2427}
2428
2429
Michael Eckel5c531332020-03-02 01:35:30 +01002430static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2431{
2432 if(uPos > pMe->UB.len) {
2433 pMe->err = 1;
2434 } else {
2435 pMe->cursor = uPos;
2436 }
2437}
2438
2439
2440static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2441{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002442 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002443
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002444 /* Magic number is messed up. Either the structure got overwritten
2445 * or was never initialized.
2446 */
Michael Eckel5c531332020-03-02 01:35:30 +01002447 if(pMe->magic != UIB_MAGIC) {
2448 return 0;
2449 }
2450
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002451 /* The cursor is off the end of the input buffer given.
2452 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002453 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002454 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002455 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002456 */
Michael Eckel5c531332020-03-02 01:35:30 +01002457 if(pMe->cursor > pMe->UB.len) {
2458 return 0;
2459 }
2460
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002461 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002462 return pMe->UB.len - pMe->cursor;
2463}
2464
2465
2466static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2467{
2468 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2469}
2470
2471
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002472static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2473{
2474 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2475}
2476
2477
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002478static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2479 {
2480 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2481 }
2482
2483
Michael Eckel5c531332020-03-02 01:35:30 +01002484static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2485{
2486 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2487 if(!pResult) {
2488 return NULLUsefulBufC;
2489 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002490 UsefulBufC UBC;
2491 UBC.ptr = pResult;
2492 UBC.len = uNum;
2493 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002494 }
2495}
2496
2497
2498static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2499{
2500 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2501
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002502 /* The ternary operator is subject to integer promotion, because
2503 * the operands are smaller than int, so cast back to uint8_t is
2504 * needed to be completely explicit about types (for static
2505 * analyzers).
2506 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002507 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002508}
2509
2510static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2511{
2512 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2513
2514 if(!pResult) {
2515 return 0;
2516 }
2517
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002518 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002519#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2520 uint16_t uTmp;
2521 memcpy(&uTmp, pResult, sizeof(uint16_t));
2522
2523#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2524 return uTmp;
2525
2526#elif defined(USEFULBUF_CONFIG_HTON)
2527 return ntohs(uTmp);
2528
2529#else
2530 return __builtin_bswap16(uTmp);
2531
2532#endif
2533
2534#else
2535
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002536 /* The operations here are subject to integer promotion because the
2537 * operands are smaller than int. They will be promoted to unsigned
2538 * int for the shift and addition. The cast back to uint16_t is is
2539 * needed to be completely explicit about types (for static
2540 * analyzers).
2541 */
Michael Eckel5c531332020-03-02 01:35:30 +01002542 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2543
2544#endif
2545}
2546
2547
2548static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2549{
2550 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2551
2552 if(!pResult) {
2553 return 0;
2554 }
2555
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002556 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002557#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2558 uint32_t uTmp;
2559 memcpy(&uTmp, pResult, sizeof(uint32_t));
2560
2561#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2562 return uTmp;
2563
2564#elif defined(USEFULBUF_CONFIG_HTON)
2565 return ntohl(uTmp);
2566
2567#else
2568 return __builtin_bswap32(uTmp);
2569
2570#endif
2571
2572#else
2573 return ((uint32_t)pResult[0]<<24) +
2574 ((uint32_t)pResult[1]<<16) +
2575 ((uint32_t)pResult[2]<<8) +
2576 (uint32_t)pResult[3];
2577#endif
2578}
2579
2580
2581static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2582{
2583 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2584
2585 if(!pResult) {
2586 return 0;
2587 }
2588
2589#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002590 /* pResult will probably not be aligned. This memcpy() moves the
2591 * bytes into a temp variable safely for CPUs that can or can't do
2592 * unaligned memory access. Many compilers will optimize the
2593 * memcpy() into a simple move instruction.
2594 */
Michael Eckel5c531332020-03-02 01:35:30 +01002595 uint64_t uTmp;
2596 memcpy(&uTmp, pResult, sizeof(uint64_t));
2597
2598#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002599 /* We have been told expliclity this is a big-endian CPU. Since
2600 * network byte order is big-endian, there is nothing to do.
2601 */
Michael Eckel5c531332020-03-02 01:35:30 +01002602
2603 return uTmp;
2604
2605#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002606 /* We have been told to use ntoh(), the system function to handle
2607 * big- and little-endian. This works on both big- and
2608 * little-endian machines, but ntoh() is not always available or in
2609 * a standard place so it is not used by default. On some CPUs the
2610 * code for this is very compact through use of a special swap
2611 * instruction.
2612 */
Michael Eckel5c531332020-03-02 01:35:30 +01002613
2614 return ntohll(uTmp);
2615
2616#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002617 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2618 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2619 * __builtin_bswap64() and friends are not conditional on CPU
2620 * endianness so this must only be used on little-endian machines.
2621 */
Michael Eckel5c531332020-03-02 01:35:30 +01002622
2623 return __builtin_bswap64(uTmp);
2624
2625
2626#endif
2627
2628#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002629 /* This is the default code that works on every CPU and every
2630 * endianness with no dependency on ntoh(). This works on CPUs
2631 * that either allow or do not allow unaligned access. It will
2632 * always work, but usually is a little less efficient than ntoh().
2633 */
Michael Eckel5c531332020-03-02 01:35:30 +01002634
2635 return ((uint64_t)pResult[0]<<56) +
2636 ((uint64_t)pResult[1]<<48) +
2637 ((uint64_t)pResult[2]<<40) +
2638 ((uint64_t)pResult[3]<<32) +
2639 ((uint64_t)pResult[4]<<24) +
2640 ((uint64_t)pResult[5]<<16) +
2641 ((uint64_t)pResult[6]<<8) +
2642 (uint64_t)pResult[7];
2643#endif
2644}
2645
2646
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002647#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002648static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2649{
2650 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2651
2652 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2653}
2654
2655
2656static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2657{
2658 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2659
2660 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2661}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002662#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002663
2664
2665static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2666{
2667 return pMe->err;
2668}
2669
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002670
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002671static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002672{
2673 pMe->UB.len = uNewLen;
2674}
2675
Laurence Lundbladee2226742024-08-16 10:50:23 -07002676static inline UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pMe)
2677{
2678 return pMe->UB;
2679}
2680
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002681
Michael Eckel5c531332020-03-02 01:35:30 +01002682#ifdef __cplusplus
2683}
2684#endif
2685
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002686#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002687
2688