blob: 24b087b33556acbb18d4928dac68fb3743aabaa5 [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 Lundblade68769332024-11-03 13:09:20 -080046 08/31/2024 llundblade Add UsefulBufC_NTH_BYTE().
Laurence Lundbladee2226742024-08-16 10:50:23 -070047 08/14/2024 llundblade Add UsefulOutBuf_RetrieveOutputStorage().
48 08/13/2024 llundblade Add UsefulInputBuf_RetrieveUndecodedInput().
Laurence Lundblade68769332024-11-03 13:09:20 -080049 8/10/2024 llundblade Add UsefulBuf_SkipLeading().
Laurence Lundbladee2226742024-08-16 10:50:23 -070050 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladea29f45a2024-05-14 15:55:19 -070051 10/05/2024 llundblade Add Xxx_OffsetToPointer.
Laurence Lundbladed62b8a72024-05-14 17:48:30 -070052 28/02/2024 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladede2e1502024-08-26 11:37:05 -070053 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070054 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
55 19/11/2023 llundblade Add UsefulOutBuf_Swap().
56 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070057 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060058 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070059 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070060 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070061 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080062 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070063 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010064 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
65 5/21/2019 llundblade #define configs for efficient endianness handling.
66 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
67 3/23/2019 llundblade Big documentation & style update. No interface
68 change.
69 3/6/2019 llundblade Add UsefulBuf_IsValue()
70 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
71 12/13/2018 llundblade Documentation improvements
72 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
73 UsefulBufC.
74 02/02/18 llundbla Full support for integers in and out; fix pointer
75 alignment bug. Incompatible change: integers
76 in/out are now in network byte order.
77 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
78 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
79 comparison for < or > for unequal length buffers.
80 Added UsefulBuf_Set() function.
81 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
82 11/13/16 llundbla Initial Version.
83
84 =============================================================================*/
85
86#ifndef _UsefulBuf_h
87#define _UsefulBuf_h
88
89
90/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070091 * Endianness Configuration
92 *
93 * This code is written so it will work correctly on big- and
94 * little-endian CPUs without configuration or any auto-detection of
95 * endianness. All code here will run correctly regardless of the
96 * endianness of the CPU it is running on.
97 *
98 * There are four C preprocessor macros that can be set with #define
99 * to explicitly configure endianness handling. Setting them can
100 * reduce code size a little and improve efficiency a little.
101 *
102 * Note that most of QCBOR is unaffected by this configuration. Its
103 * endianness handling is integrated with the code that handles
104 * alignment and preferred serialization. This configuration does
105 * affect QCBOR's (planned) implementation of integer arrays (tagged
106 * arrays) and use of the functions here to serialize or deserialize
107 * integers and floating-point values.
108 *
109 * Following is the recipe for configuring the endianness-related
110 * #defines.
111 *
112 * The first option is to not define anything. This will work fine
113 * with all CPUs, OS's and compilers. The code for encoding integers
114 * may be a little larger and slower.
115 *
116 * If your CPU is big-endian then define
117 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
118 * for big-endian CPUs. It will be small and efficient because there
119 * will be no byte swapping.
120 *
121 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
122 * OS's and compilers, but not all. On big-endian CPUs this should
123 * give the most efficient code, the same as
124 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
125 * call the system-defined byte swapping method which is presumably
126 * implemented efficiently. In some cases, this will be a dedicated
127 * byte swap instruction like Intel's bswap.
128 *
129 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
130 * little-endian, it is also good to define
131 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
132 *
133 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
134 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
135 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
136 * system-defined byte swap method. However, note
137 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
138 * this is fixed now. Often hton() and ntoh() will call the built-in
139 * __builtin_bswapXX()() function, so this size issue could affect
140 * USEFULBUF_CONFIG_HTON.
141 *
142 * Last, run the tests. They must all pass.
143 *
144 * These #define config options affect the inline implementation of
145 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
146 * also affect the 16-, 32-bit, float and double versions of these
147 * functions. Since they are inline, the size effect is not in the
148 * UsefulBuf object code, but in the calling code.
149 *
150 * Summary:
151 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
152 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
153 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
154 * handle big and little-endian with system option.
155 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
156 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200157 *
158 * It is possible to run this code in environments where using floating point is
159 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
160 * that is related to handling floating point types, along with related
161 * interfaces. This makes it possible to compile the code with the compile
162 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100163 */
164
165#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
166#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
167#endif
168
169
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700170#include <stdint.h> /* for uint8_t, uint16_t.... */
171#include <string.h> /* for strlen, memcpy, memmove, memset */
172#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100173
174
175#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700176#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100177#endif
178
179#ifdef __cplusplus
180extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700181#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700182} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700183#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100184#endif
185
186/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700187 * @file UsefulBuf.h
188 *
189 * The goal of this code is to make buffer and pointer manipulation
190 * easier and safer when working with binary data.
191 *
192 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
193 * structures are used to represent buffers rather than ad hoc
194 * pointers and lengths.
195 *
196 * With these it is possible to write code that does little or no
197 * direct pointer manipulation for copying and formatting data. For
198 * example, the QCBOR encoder was written using these and has less
199 * pointer manipulation.
200 *
201 * While it is true that object code using these functions will be a
202 * little larger and slower than a white-knuckle clever use of
203 * pointers might be, but not by that much or enough to have an effect
204 * for most use cases. For security-oriented code this is highly
205 * worthwhile. Clarity, simplicity, reviewability and are more
206 * important.
207 *
208 * There are some extra sanity and double checks in this code to help
209 * catch coding errors and simple memory corruption. They are helpful,
210 * but not a substitute for proper code review, input validation and
211 * such.
212 *
213 * This code consists of a lot of inline functions and a few that are
214 * not. It should not generate very much object code, especially with
215 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100216 */
217
218
219/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700220 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
221 * hold a pointer and length for binary data. In C99 this data
222 * structure can be passed on the stack making a lot of code cleaner
223 * than carrying around a pointer and length as two parameters.
224 *
225 * This is also conducive to secure coding practice as the length is
226 * always carried with the pointer and the convention for handling a
227 * pointer and a length is clear.
228 *
229 * While it might be possible to write buffer and pointer code more
230 * efficiently in some use cases, the thought is that unless there is
231 * an extreme need for performance (e.g., you are building a
232 * gigabit-per-second IP router), it is probably better to have
233 * cleaner code you can be most certain about the security of.
234 *
235 * The non-const @ref UsefulBuf is usually used to refer an empty
236 * buffer to be filled in. The length is the size of the buffer.
237 *
238 * The const @ref UsefulBufC is usually used to refer to some data
239 * that has been filled in. The length is amount of valid data pointed
240 * to.
241 *
242 * A common use mode is to pass a @ref UsefulBuf to a function, the
243 * function puts some data in it, then the function returns a @ref
244 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
245 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
246 * so the constness stays correct. There is no single "in,out"
247 * parameter (if there was, it would have to be non-const). Note that
248 * the pointer returned in the @ref UsefulBufC usually ends up being
249 * the same pointer passed in as a @ref UsefulBuf, though this is not
250 * striclty required.
251 *
252 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
253 * @c NULL.
254 *
255 * There are functions and macros for the following:
256 * - Initializing
257 * - Create initialized const @ref UsefulBufC from compiler literals
258 * - Create initialized const @ref UsefulBufC from NULL-terminated string
259 * - Make an empty @ref UsefulBuf on the stack
260 * - Checking whether a @ref UsefulBuf is null, empty or both
261 * - Copying, copying with offset, copying head or tail
262 * - Comparing and finding substrings
263 *
264 * See also @ref UsefulOutBuf. It is a richer structure that has both
265 * the size of the valid data and the size of the buffer.
266 *
267 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
268 * it can go on the stack and be a function parameter or return value.
269 *
270 * Another way to look at it is this. C has the NULL-terminated string
271 * as a means for handling text strings, but no means or convention
272 * for binary strings. Other languages do have such means, Rust, an
273 * efficient compiled language, for example.
274 *
275 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
276 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
277 * out like anything".
278 */
Michael Eckel5c531332020-03-02 01:35:30 +0100279typedef struct q_useful_buf_c {
280 const void *ptr;
281 size_t len;
282} UsefulBufC;
283
284
285/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700286 * This non-const @ref UsefulBuf is typically used for some allocated
287 * memory that is to be filled in. The @c len is the amount of memory,
288 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100289 */
290typedef struct q_useful_buf {
291 void *ptr;
292 size_t len;
293} UsefulBuf;
294
295
296/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700297 * A null @ref UsefulBufC is one that has no value in the same way a
298 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
299 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
300 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100301 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700302/*
303 * NULLUsefulBufC and few other macros have to be
304 * definied differently in C than C++ because there
305 * is no common construct for a literal structure.
306 *
307 * In C compound literals are used.
308 *
309 * In C++ list initalization is used. This only works
310 * in C++11 and later.
311 *
312 * Note that some popular C++ compilers can handle compound
313 * literals with on-by-default extensions, however
314 * this code aims for full correctness with strict
315 * compilers so they are not used.
316 */
317#ifdef __cplusplus
318#define NULLUsefulBufC {NULL, 0}
319#else
320#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
321#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100322
323/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700324 * A null @ref UsefulBuf is one that has no memory associated the same
325 * way @c NULL points to nothing. It does not matter what @c len is.
326 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700327#ifdef __cplusplus
328#define NULLUsefulBuf {NULL, 0}
329#else
330#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
331#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100332
333
334/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700335 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
336 *
337 * @param[in] UB The UsefulBuf to check.
338 *
339 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100340 */
341static inline int UsefulBuf_IsNULL(UsefulBuf UB);
342
343
344/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700345 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
346 *
347 * @param[in] UB The @ref UsefulBufC to check.
348 *
349 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100350 */
351static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
352
353
354/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700355 * @brief Check if a @ref UsefulBuf is empty or not.
356 *
357 * @param[in] UB The @ref UsefulBuf to check.
358 *
359 * @return 1 if it is empty, 0 if not.
360 *
361 * An "empty" @ref UsefulBuf is one that has a value and can be
362 * considered to be set, but that value is of zero length. It is
363 * empty when @c len is zero. It doesn't matter what the @c ptr is.
364 *
365 * Many uses will not need to clearly distinguish a @c NULL @ref
366 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
367 * @c len 0. However if a use of @ref UsefulBuf needs to make a
368 * distinction then @c ptr should not be @c NULL when the @ref
369 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100370 */
371static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
372
373
374/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700375 * @brief Check if a @ref UsefulBufC is empty or not.
376 *
377 * @param[in] UB The @ref UsefulBufC to check.
378 *
379 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100380 */
381static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
382
383
384/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700385 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
386 *
387 * @param[in] UB The @ref UsefulBuf to check.
388 *
389 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100390 */
391static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
392
393
394/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700395 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
396 *
397 * @param[in] UB The @ref UsefulBufC to check.
398 *
399 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100400 */
401static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
402
403
404/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700405 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
406 *
407 * @param[in] UB The @ref UsefulBuf to convert.
408 *
409 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100410 */
411static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
412
413
414/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700415 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
416 *
417 * @param[in] UBC The @ref UsefulBuf to convert.
418 *
419 * @return A non-const @ref UsefulBuf struct.
420 *
421 * Use of this is not necessary for the intended use mode of @ref
422 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
423 * created to describe a buffer that has not had any data put in
424 * it. Then the data is put in it. Then a @ref UsefulBufC is create
425 * to describe the part with the data in it. This goes from non-const
426 * to const, so this function is not needed.
427 *
428 * If the -Wcast-qual warning is enabled, this function can be used to
429 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100430 */
431static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
432
433
434/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700435 * Convert a literal string to a @ref UsefulBufC.
436 *
437 * @c szString must be a literal string that @c sizeof() works on.
438 * This is better for literal strings than UsefulBuf_FromSZ() because
439 * it generates less code. It will not work on non-literal strings.
440 *
441 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100442 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700443#ifdef __cplusplus
444#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
445#else
Michael Eckel5c531332020-03-02 01:35:30 +0100446#define UsefulBuf_FROM_SZ_LITERAL(szString) \
447 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700448#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100449
450
451/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700452 * Convert a literal byte array to a @ref UsefulBufC.
453 *
454 * @c pBytes must be a literal string that @c sizeof() works on. It
455 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100456 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700457#ifdef __cplusplus
458#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
459#else
Michael Eckel5c531332020-03-02 01:35:30 +0100460#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700461 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
462#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100463
464/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700465 * Make an automatic variable named @c name of type @ref UsefulBuf and
466 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100467 */
468#define UsefulBuf_MAKE_STACK_UB(name, size) \
469 uint8_t __pBuf##name[(size)];\
470 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
471
472
473/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700474 * Make a byte array in to a @ref UsefulBuf. This is usually used on
475 * stack variables or static variables. Also see @ref
476 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100477 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700478#ifdef __cplusplus
479#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
480#else
Michael Eckel5c531332020-03-02 01:35:30 +0100481#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700482 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
483#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100484
485
486/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700487 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
488 *
489 * @param[in] szString The string to convert.
490 *
491 * @return A @ref UsefulBufC struct.
492 *
493 * @c UsefulBufC.ptr points to the string so its lifetime must be
494 * maintained.
495 *
496 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100497 */
498static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
499
500
Laurence Lundblade68769332024-11-03 13:09:20 -0800501/* Get the nth byte from a UsefulBufC. There's no length check! */
502#define UsefulBufC_NTH_BYTE(UBC, n) (((const uint8_t *)(UBC.ptr))[n])
503
504
Michael Eckel5c531332020-03-02 01:35:30 +0100505/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700506 * @brief Copy one @ref UsefulBuf into another at an offset.
507 *
508 * @param[in] Dest Destination buffer to copy into.
509 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
510 * @param[in] Src The bytes to copy.
511 *
512 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
513 *
514 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
515 * size of @c Dest.
516 *
517 * This fails and returns @ref NULLUsefulBufC if the @c Src length
518 * plus @c uOffset is greater than the length of @c Dest.
519 *
520 * The results are undefined if @c Dest and @c Src overlap.
521 *
522 * This assumes that there is valid data in @c Dest up to @c
523 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
524 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100525 */
526UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
527
528
529/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700530 * @brief Copy one @ref UsefulBuf into another.
531 *
532 * @param[in] Dest The destination buffer to copy into.
533 * @param[out] Src The source to copy from.
534 *
535 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
536 * on failure.
537 *
538 * This fails if @c Src.len is greater than @c Dest.len.
539 *
540 * Note that like @c memcpy(), the pointers are not checked and this
541 * will crash rather than return @ref NULLUsefulBufC if they are @c
542 * NULL or invalid.
543 *
544 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100545 */
546static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
547
548
549/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700550 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
551 *
552 * @param[in] pDest The destination buffer to copy into.
553 * @param[in] value The value to set the bytes to.
554 *
555 * Note that like @c memset(), the pointer in @c pDest is not checked
556 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100557 */
558static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
559
560
561/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700562 * @brief Copy a pointer into a @ref UsefulBuf.
563 *
564 * @param[in,out] Dest The destination buffer to copy into.
565 * @param[in] ptr The source to copy from.
566 * @param[in] uLen Length of the source; amount to copy.
567 *
568 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
569 * on failure.
570 *
571 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
572 * than @c pDest->len.
573 *
574 * Note that like @c memcpy(), the pointers are not checked and this
575 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100576 */
577static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
578 const void *ptr,
579 size_t uLen);
580
581
582/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700583 * @brief Returns a truncation of a @ref UsefulBufC.
584 *
585 * @param[in] UB The buffer to get the head of.
586 * @param[in] uAmount The number of bytes in the head.
587 *
588 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100589 */
590static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
591
592
593/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700594 * @brief Returns bytes from the end of a @ref UsefulBufC.
595 *
596 * @param[in] UB The buffer to get the tail of.
597 * @param[in] uAmount The offset from the start where the tail is to begin.
598 *
599 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
600 * if @c uAmount is greater than the length of the @ref UsefulBufC.
601 *
602 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
603 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
604 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100605 */
606static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
607
608
609/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700610 * @brief Compare one @ref UsefulBufC to another.
611 *
612 * @param[in] UB1 The first buffer to compare.
613 * @param[in] UB2 The second buffer to compare.
614 *
615 * @return 0, positive or negative value.
616 *
617 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
618 * less than @c UB2 if it is shorter or the first byte that is not the
619 * same is less.
620 *
621 * Returns 0 if the inputs are the same.
622 *
623 * Returns a positive value if @c UB2 is less than @c UB1.
624 *
625 * All that is of significance is that the result is positive, negative
626 * or 0. (This doesn't return the difference between the first
627 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100628 */
629int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
630
631
632/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700633 * @brief Find first byte that is not a particular byte value.
634 *
635 * @param[in] UB The destination buffer for byte comparison.
636 * @param[in] uValue The byte value to compare to.
637 *
638 * @return Offset of first byte that isn't @c uValue or
639 * @c SIZE_MAX if all bytes are @c uValue.
640 *
641 * Note that unlike most comparison functions, 0
642 * does not indicate a successful comparison, so the
643 * test for match is:
644 *
645 * UsefulBuf_IsValue(...) == SIZE_MAX
646 *
647 * If @c UB is null or empty, there is no match
648 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100649 */
650size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
651
652
653/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700654 * @brief Find one @ref UsefulBufC in another.
655 *
656 * @param[in] BytesToSearch Buffer to search through.
657 * @param[in] BytesToFind Buffer with bytes to be found.
658 *
659 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100660 */
661size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
662
663
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700664/**
Laurence Lundblade68769332024-11-03 13:09:20 -0800665 * @brief Skip leading bytes of a particular value in a string.
666 *
667 * @param[in] String The input string. String.ptr must not be @c NULL.
668 * @param[in] uByte The byte value.
669 *
670 * @return Substring with leading bytes with value @c uByte removed.
671 */
672UsefulBufC UsefulBuf_SkipLeading(UsefulBufC String, uint8_t uByte);
673
674
675/**
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700676 * @brief Convert a pointer to an offset with bounds checking.
677 *
678 * @param[in] UB A UsefulBuf.
679 * @param[in] p Pointer to convert to offset.
680 *
681 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700682*/
683static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
684
685
Laurence Lundbladea29f45a2024-05-14 15:55:19 -0700686/**
687 * @brief Convert an offset to a pointer with bounds checking.
688 *
689 * @param[in] UB A UsefulBuf.
690 * @param[in] uOffset Offset in @c pUInBuf.
691 *
692 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
693 */
694static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
695
696
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800697#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100698/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700699#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100700
701/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
702#define MakeUsefulBufOnStack(name, size) \
703 uint8_t __pBuf##name[(size)];\
704 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
705
706/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
707#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700708 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100709
710/** Deprecated function; use UsefulBuf_Unconst() instead */
711static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
712{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700713 UsefulBuf UB;
714
Laurence Lundblade3eead482023-12-16 20:53:22 -0700715 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300716 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700717
718 UB.len = UBC.len;
719
720 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100721}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800722#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100723
724
725
726
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200727#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100728/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700729 * @brief Copy a @c float to a @c uint32_t.
730 *
731 * @param[in] f Float value to copy.
732 *
733 * @return A @c uint32_t with the float bits.
734 *
735 * Convenience function to avoid type punning, compiler warnings and
736 * such. The optimizer usually reduces this to a simple assignment. This
737 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100738 */
739static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
740
741
742/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700743 * @brief Copy a @c double to a @c uint64_t.
744 *
745 * @param[in] d Double value to copy.
746 *
747 * @return A @c uint64_t with the double bits.
748 *
749 * Convenience function to avoid type punning, compiler warnings and
750 * such. The optimizer usually reduces this to a simple assignment. This
751 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100752 */
753static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
754
755
756/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700757 * @brief Copy a @c uint32_t to a @c float.
758 *
759 * @param[in] u32 Integer value to copy.
760 *
761 * @return The value as a @c float.
762 *
763 * Convenience function to avoid type punning, compiler warnings and
764 * such. The optimizer usually reduces this to a simple assignment. This
765 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100766 */
767static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
768
769
770/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700771 * @brief Copy a @c uint64_t to a @c double.
772 *
773 * @param[in] u64 Integer value to copy.
774 *
775 * @return The value as a @c double.
776 *
777 * Convenience function to avoid type punning, compiler warnings and
778 * such. The optimizer usually reduces this to a simple assignment. This
779 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100780 */
781static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200782#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100783
784
785
786
787/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700788 * UsefulOutBuf is a structure and functions (an object) for
789 * serializing data into a buffer to encode for a network protocol or
790 * write data to a file.
791 *
792 * The main idea is that all the pointer manipulation is performed by
793 * @ref UsefulOutBuf functions so the caller doesn't have to do any
794 * pointer manipulation. The pointer manipulation is centralized.
795 * This code has been reviewed and written carefully so it
796 * spares the caller of much of this work and results in safer code
797 * with less effort.
798 *
799 * The @ref UsefulOutBuf methods that add data to the output buffer
800 * always check the length and will never write off the end of the
801 * output buffer. If an attempt to add data that will not fit is made,
802 * an internal error flag will be set and further attempts to add data
803 * will not do anything.
804 *
805 * There is no way to ever write off the end of that buffer when
806 * calling the @c UsefulOutBuf_AddXxx() and
807 * @c UsefulOutBuf_InsertXxx() functions.
808 *
809 * The functions to add data do not report success of failure. The
810 * caller only needs to check for an error in the final call, either
811 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
812 * result. This makes the calling code cleaner.
813 *
814 * There is a utility function to get the error status anytime along
815 * the way for a special circumstance. There are functions to see how
816 * much room is left and see if some data will fit too, but their use
817 * is generally unnecessary.
818 *
819 * The general call flow is:
820 *
821 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
822 * buffer given to it can be from the heap, stack or
823 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
824 * macro that makes a buffer on the stack and initializes it.
825 *
826 * - Call methods like UsefulOutBuf_InsertString(),
827 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
828 * to output data. The append calls add data to the end of the
829 * valid data. The insert calls take a position argument.
830 *
831 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
832 * there were no errors and to get the serialized output bytes.
833 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700834 * @ref UsefulOutBuf can be used in a mode to calculate the size of
835 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700836 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700837 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700838 *
839 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700840 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700841 *
842 * The possible errors are:
843 *
844 * - The @ref UsefulOutBuf was not initialized or was corrupted.
845 *
846 * - An attempt was made to add data that will not fit.
847 *
848 * - An attempt was made to insert data at a position beyond the end of
849 * the buffer.
850 *
851 * - An attempt was made to insert data at a position beyond the valid
852 * data in the buffer.
853 *
854 * Some inexpensive simple sanity checks are performed before every
855 * data addition to guard against use of an uninitialized or corrupted
856 * UsefulOutBuf.
857 *
858 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
859 * encoder has almost no pointer manipulation in it, is easier to
860 * read, and easier to review.
861 *
862 * A @ref UsefulOutBuf is small and can go on the stack:
863 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
864 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100865 */
866typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700867 /* PRIVATE DATA STRUCTURE */
868 UsefulBuf UB; /* Memory that is being output to */
869 size_t data_len; /* length of the valid data, the insertion point */
870 uint16_t magic; /* Used to detect corruption and lack
871 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100872 uint8_t err;
873} UsefulOutBuf;
874
875
876/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700877 * This is a @ref UsefulBuf value that can be passed to
878 * UsefulOutBuf_Init() to have it calculate the size of the output
879 * buffer needed. Pass this for @c Storage, call all the append and
880 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
881 * returned @ref UsefulBufC has the size.
882 *
883 * As one can see, this is just a NULL pointer and very large size.
884 * The NULL pointer tells UsefulOutputBuf to not copy any data.
885 */
886#ifdef __cplusplus
887#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
888#else
889#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
890#endif
891
892
893/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700894 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700895 *
896 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
897 * @param[in] Storage Buffer to output into.
898 *
899 * This initializes the @ref UsefulOutBuf with storage, sets the
900 * current position to the beginning of the buffer and clears the
901 * error state.
902 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700903 * See @ref SizeCalculateUsefulBuf for instructions on how to
904 * initialize a @ref UsefulOutBuf to calculate the size that would be
905 * output without actually outputting.
906 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700907 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100908 */
909void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
910
911
912/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700913 * Convenience macro to make a @ref UsefulOutBuf on the stack and
914 * initialize it with a stack buffer of the given size. The variable
915 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100916 */
917#define UsefulOutBuf_MakeOnStack(name, size) \
918 uint8_t __pBuf##name[(size)];\
919 UsefulOutBuf name;\
920 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
921
922
923/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700924 * @brief Reset a @ref UsefulOutBuf for re use.
925 *
926 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
927 *
928 * This sets the amount of data in the output buffer to none and
929 * clears the error state.
930 *
931 * The output buffer is still the same one and size as from the
932 * UsefulOutBuf_Init() call.
933 *
934 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100935 */
936static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
937
938
939/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700940 * @brief Returns position of end of data in the @ref UsefulOutBuf.
941 *
942 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
943 *
944 * @return position of end of data.
945 *
946 * On a freshly initialized @ref UsefulOutBuf with no data added, this
947 * will return 0. After 10 bytes have been added, it will return 10
948 * and so on.
949 *
950 * Generally, there is no need to call this for most uses of @ref
951 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100952 */
953static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
954
955
956/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700957 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
958 *
959 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
960 *
961 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100962 */
963static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
964
965
966/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700967 * @brief Inserts bytes into the @ref UsefulOutBuf.
968 *
969 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
970 * @param[in] NewData The bytes to insert.
971 * @param[in] uPos Index in output buffer at which to insert.
972 *
973 * @c NewData is the pointer and length for the bytes to be added to
974 * the output buffer. There must be room in the output buffer for all
975 * of @c NewData or an error will occur.
976 *
977 * The insertion point must be between 0 and the current valid
978 * data. If not, an error will occur. Appending data to the output
979 * buffer is achieved by inserting at the end of the valid data. This
980 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
981 *
982 * When insertion is performed, the bytes between the insertion point
983 * and the end of data previously added to the output buffer are slid
984 * to the right to make room for the new data.
985 *
986 * Overlapping buffers are OK. @c NewData can point to data in the
987 * output buffer.
988 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700989 * NewData.len may be 0 in which case nothing will be inserted.
990 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700991 * If an error occurs, an error state is set in the @ref
992 * UsefulOutBuf. No error is returned. All subsequent attempts to add
993 * data will do nothing.
994 *
995 * The intended use is that all additions are made without checking
996 * for an error. The error will be taken into account when
997 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
998 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100999 */
1000void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
1001 UsefulBufC NewData,
1002 size_t uPos);
1003
1004
1005/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001006 * @brief Insert a data buffer into the @ref UsefulOutBuf.
1007 *
1008 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1009 * @param[in] pBytes Pointer to the bytes to insert
1010 * @param[in] uLen Length of the bytes to insert
1011 * @param[in] uPos Index in output buffer at which to insert
1012 *
1013 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
1014 * the difference being a pointer and length is passed in rather than an
1015 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +01001016 */
1017static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
1018 const void *pBytes,
1019 size_t uLen,
1020 size_t uPos);
1021
1022
1023/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001024 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
1025 *
1026 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1027 * @param[in] szString NULL-terminated string to insert.
1028 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001029 */
1030static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1031 const char *szString,
1032 size_t uPos);
1033
1034
1035/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001036 * @brief Insert a byte into the @ref UsefulOutBuf.
1037 *
1038 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1039 * @param[in] byte Bytes to insert.
1040 * @param[in] uPos Index in output buffer at which to insert.
1041 *
1042 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1043 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001044 */
1045static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1046 uint8_t byte,
1047 size_t uPos);
1048
1049
1050/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001051 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1052 *
1053 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1054 * @param[in] uInteger16 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 two-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_InsertUint16(UsefulOutBuf *pUOutBuf,
1063 uint16_t uInteger16,
1064 size_t uPos);
1065
1066
1067/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001068 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1069 *
1070 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1071 * @param[in] uInteger32 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 a four-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_InsertUint32(UsefulOutBuf *pUOutBuf,
1080 uint32_t uInteger32,
1081 size_t uPos);
1082
1083
1084/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001085 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1086 *
1087 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1088 * @param[in] uInteger64 Integer to insert.
1089 * @param[in] uPos Index in output buffer at which to insert.
1090 *
1091 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1092 * with the difference being an eight-byte integer is to be inserted.
1093 *
1094 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001095 */
1096static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1097 uint64_t uInteger64,
1098 size_t uPos);
1099
1100
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001101#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001102/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001103 * @brief Insert a @c float into the @ref UsefulOutBuf.
1104 *
1105 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1106 * @param[in] f @c float 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 float is to be inserted.
1111 *
1112 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001113 */
1114static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1115 float f,
1116 size_t uPos);
1117
1118
1119/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001120 * @brief Insert a @c double into the @ref UsefulOutBuf.
1121 *
1122 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1123 * @param[in] d @c double to insert.
1124 * @param[in] uPos Index in output buffer at which to insert.
1125 *
1126 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1127 * with the difference being a @c double is to be inserted.
1128 *
1129 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001130 */
1131static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1132 double d,
1133 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001134#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001135
1136
1137/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001138 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1139 *
1140 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1141 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1142 *
1143 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1144 * with the insertion point at the end of the valid data.
1145 */
Michael Eckel5c531332020-03-02 01:35:30 +01001146static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1147 UsefulBufC NewData);
1148
1149
1150/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001151 * @brief Append bytes to the @ref UsefulOutBuf.
1152 *
1153 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1154 * @param[in] pBytes Pointer to bytes to append.
1155 * @param[in] uLen Length of @c pBytes to append.
1156 *
1157 * See UsefulOutBuf_InsertData() for details. This does the same with
1158 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001159 */
1160static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1161 const void *pBytes,
1162 size_t uLen);
1163
1164
1165/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001166 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1167 *
1168 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1169 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001170 */
1171static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1172 const char *szString);
1173
1174
1175/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001176 * @brief Append a byte to the @ref UsefulOutBuf
1177 *
1178 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1179 * @param[in] byte Bytes to append.
1180 *
1181 * See UsefulOutBuf_InsertByte() for details. This does the same
1182 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001183 */
1184static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1185 uint8_t byte);
1186
1187
1188/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001189 * @brief Append an integer to the @ref UsefulOutBuf
1190 *
1191 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1192 * @param[in] uInteger16 Integer to append.
1193 *
1194 * See UsefulOutBuf_InsertUint16() for details. This does the same
1195 * with the insertion point at the end of the valid data.
1196 *
1197 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001198 */
1199static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1200 uint16_t uInteger16);
1201
1202
1203/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001204 * @brief Append an integer to the @ref UsefulOutBuf
1205 *
1206 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1207 * @param[in] uInteger32 Integer to append.
1208 *
1209 * See UsefulOutBuf_InsertUint32() for details. This does the same
1210 * with the insertion point at the end of the valid data.
1211 *
1212 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001213 */
1214static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1215 uint32_t uInteger32);
1216
1217
1218/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001219 * @brief Append an integer to the @ref UsefulOutBuf
1220 *
1221 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1222 * @param[in] uInteger64 Integer to append.
1223 *
1224 * See UsefulOutBuf_InsertUint64() for details. This does the same
1225 * with the insertion point at the end of the valid data.
1226 *
1227 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001228 */
1229static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1230 uint64_t uInteger64);
1231
1232
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001233#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001234/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001235 * @brief Append a @c float to the @ref UsefulOutBuf
1236 *
1237 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1238 * @param[in] f @c float to append.
1239 *
1240 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1241 * the insertion point at the end of the valid data.
1242 *
1243 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001244 */
1245static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1246 float f);
1247
1248
1249/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001250 * @brief Append a @c double to the @ref UsefulOutBuf
1251 *
1252 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1253 * @param[in] d @c double to append.
1254 *
1255 * See UsefulOutBuf_InsertDouble() for details. This does the same
1256 * with the insertion point at the end of the valid data.
1257 *
1258 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001259 */
1260static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1261 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001262#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001263
1264
1265/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001266 * @brief Returns the current error status.
1267 *
1268 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1269 *
1270 * @return 0 if all OK, 1 on error.
1271 *
1272 * This returns the error status since a call to either
1273 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1274 * goes into the error state, it will stay until one of those
1275 * functions is called.
1276 *
1277 * Possible error conditions are:
1278 * - bytes to be inserted will not fit
1279 * - insertion point is out of buffer or past valid data
1280 * - current position is off end of buffer (probably corrupted or uninitialized)
1281 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001282 */
1283static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1284
1285
1286/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001287 * @brief Returns number of bytes unused used in the output buffer.
1288 *
1289 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1290 *
1291 * @return Number of unused bytes or zero.
1292 *
1293 * Because of the error handling strategy and checks in
1294 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1295 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001296 */
1297static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1298
1299
1300/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001301 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1302 *
1303 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1304 * @param[in] uLen Number of bytes for which to check
1305 *
1306 * @return 1 if @c uLen bytes will fit, 0 if not.
1307 *
1308 * Because of the error handling strategy and checks in
1309 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1310 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001311 */
1312static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1313
1314
1315 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001316 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1317 *
1318 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1319 *
1320 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1321 *
1322 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1323 * just calculating the length of the encoded data.
1324 */
Michael Eckel5c531332020-03-02 01:35:30 +01001325static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1326
1327
1328/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001329 * @brief Returns pointer and length of the output buffer not yet used.
1330 *
1331 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1332 *
1333 * @return pointer and length of output buffer not used.
1334 *
1335 * This is an escape that allows the caller to write directly
1336 * to the output buffer without any checks. This doesn't
1337 * change the output buffer or state. It just returns a pointer
1338 * and length of the bytes remaining.
1339 *
1340 * This is useful to avoid having the bytes to be added all
1341 * in a contiguous buffer. Its use can save memory. A good
1342 * example is in the COSE encrypt implementation where
1343 * the output of the symmetric cipher can go directly
1344 * into the output buffer, rather than having to go into
1345 * an intermediate buffer.
1346 *
1347 * See UsefulOutBuf_Advance() which is used to tell
1348 * UsefulOutBuf how much was written.
1349 *
1350 * Warning: this bypasses the buffer safety provided by
1351 * UsefulOutBuf!
1352 */
1353static inline UsefulBuf
1354UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1355
1356
1357/**
1358 * @brief Advance the amount output assuming it was written by the caller.
1359 *
1360 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1361 * @param[in] uAmount The amount to advance.
1362 *
1363 * This advances the position in the output buffer
1364 * by \c uAmount. This assumes that the
1365 * caller has written \c uAmount to the pointer obtained
1366 * with UsefulOutBuf_GetOutPlace().
1367 *
1368 * Warning: this bypasses the buffer safety provided by
1369 * UsefulOutBuf!
1370 */
1371void
1372UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1373
1374
1375/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001376 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001377 *
1378 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1379 *
1380 * @return The valid data in @ref UsefulOutBuf or
1381 * @ref NULLUsefulBufC if there was an error adding data.
1382 *
1383 * The storage for the returned data is the @c Storage parameter
1384 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1385 *
1386 * This can be called anytime and many times to get intermediate
1387 * results. It doesn't change the data or reset the current position,
1388 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001389 */
1390UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1391
1392
1393/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001394 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001395 *
1396 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1397 * @param[out] Dest The destination buffer to copy into.
1398 *
1399 * @return Pointer and length of copied data or @c NULLUsefulBufC
1400 * if it will not fit in the @c Dest buffer or the error
1401 * state was entered.
1402 *
1403 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001404 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001405 */
Michael Eckel5c531332020-03-02 01:35:30 +01001406UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1407
1408
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001409/**
1410 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1411 *
1412 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1413 * @param[in] uOffset Offset to bytes to return.
1414 *
1415 * @return NULLUsefulBufC or the bytes at the offset.
1416 *
1417 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1418 * maybe specified. It returns the bytes starting at @c uOffset to the
1419 * end of what was encoded so far. Calling this with @c uOffset 0 is
1420 * equivalent to UsefulOutBuf_OutUBuf().
1421 *
1422 * If there's nothing at @c uOffset or it is past the in the output
1423 * buffer, a \ref NULLUsefulBufC is returned.
1424 *
1425 * This is typically not needed in typical use. It is used by QCBOR
1426 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1427 * sorting CBOR maps.
1428 */
1429UsefulBufC
1430UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1431
1432
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001433/*
1434 * @brief Return a substring of the output data.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001435 *
1436 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1437 * @param[in] uStart Offset of start of substring.
1438 * @param[in] uLen Length of substring.
1439 *
1440 * This is the same as UsefulOutBuf_OutUBuf(), but returns a
1441 * substring. @c NULLUsefulBufC is returned if the requested substring
1442 * is off the end of the output bytes or if in error state.
1443 */
1444UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pUOutBuf,
1445 const size_t uStart,
1446 const size_t uLen);
1447
1448
1449/**
1450 * @brief Retrieve the storage buffer passed in to UsefulOutBuf_Init().
1451 *
1452 * @param[in] pUOutBuf The encoding context.
1453 *
1454 * @return The output storage buffer passed to UsefulOutBuf_Init().
1455 *
1456 * This doesn't give any information about how much has been encoded
1457 * or the error state. It just returns the exact @ref UsefulOutBuf given
1458 * to UsefulOutBuf_Init().
1459 */
1460static UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pUOutBuf);
1461
Michael Eckel5c531332020-03-02 01:35:30 +01001462
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001463/**
1464 * @brief Compare bytes at offsets.
1465 *
1466 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1467 * @param[in] uStart1 Offset of first bytes to compare.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001468 * @param[in] uLen1 Length of first bytes to compare.
1469 * @param[in] uStart2 Offset of second bytes to compare.
1470 * @param[in] uLen2 Length of second bytes to compare.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001471 *
1472 * @return 0 for equality, positive if uStart1 is lexographically larger,
1473 * negative if uStart2 is lexographically larger.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001474 *
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001475 * This looks into bytes that have been output at the offsets @c start1
1476 * and @c start2. It compares bytes at those two starting points until
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001477 * they are not equal or @c uLen1 or @c uLen2 is reached. If the
1478 * length of the string given is off the end of the output data, the
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001479 * string will be effectively truncated to the data in the output
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001480 * buffer for the comparison.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001481 *
1482 * This returns positive when @c uStart1 lexographically sorts ahead
1483 * of @c uStart2 and vice versa. Zero is returned if the strings
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001484 * compare equally.
1485 *
1486 * If lengths are unequal and the first bytes are an exact subset of
1487 * the second string, then a positve value will be returned and vice
1488 * versa.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001489 *
1490 * If either start is past the end of data in the output buffer, 0
1491 * will be returned. It is the caller's responsibility to make sure
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001492 * the offsets are not off the end so that a comparison is actually
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001493 * being made. No data will ever be read off the end of the buffer so
1494 * this safe no matter what offsets are passed.
1495 *
1496 * This is a relatively odd function in that it works on data in the
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001497 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps
1498 * that are in the output buffer.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001499 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -07001500int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf,
1501 size_t uStart1, size_t uLen1,
1502 size_t uStart2, size_t uLen2);
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001503
1504/**
1505 * @brief Swap two regions of output bytes.
1506 *
1507 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1508 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1509 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1510 * @param[in] uEndOffset Offset to end of region to be swappe.
1511 *
1512 * This reaches into bytes that have been output and swaps two
1513 * adjacent regions.
1514 *
1515 * If any of the offsets are outside the range of valid data, no
1516 * swapping will be performed. If the start is not the smallest and
1517 * the pivot is not in the middle no swapping will be performed.
1518 *
1519 * The byte at @c uStartOffset will participate in the swapping. The
1520 * byte at @c uEndOffset will not participate in the swapping, only
1521 * the byte before it.
1522 *
1523 * This is a relatively odd function in that it works on data in the
1524 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1525 * maps.
1526 */
1527void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1528 size_t uStartOffset,
1529 size_t uPivotOffset,
1530 size_t uEndOffset);
1531
1532
Michael Eckel5c531332020-03-02 01:35:30 +01001533
1534
1535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001536 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1537 * for parsing data received. Initialize it with the data from the
1538 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1539 * get data chunks of various types. A position cursor is maintained
1540 * internally.
1541 *
1542 * As long as the functions here are used, there will never be any
1543 * reference off the end of the given buffer (except
1544 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1545 * called incorrectly, an attempt is made to seek off the end of the
1546 * buffer or such. This makes it easier to write safe and correct
1547 * code. For example, the QCBOR decoder implementation is safer and
1548 * easier to review through its use of @ref UsefulInputBuf.
1549 *
1550 * @ref UsefulInputBuf maintains an internal error state. The
1551 * intended use is fetching data chunks without any error checks until
1552 * the end. If there was any error, such as an attempt to fetch data
1553 * off the end, the error state is entered and no further data will be
1554 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1555 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1556 * null is not dereferenced, the error check can be put off until the
1557 * end, simplifying the calling code.
1558 *
1559 * The integer and float parsing expects network byte order (big
1560 * endian). Network byte order is what is used by TCP/IP, CBOR and
1561 * most internet protocols.
1562 *
1563 * Lots of inline functions are used to keep code size down. The
1564 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1565 * code size a lot. The only non-inline code is
1566 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1567 * @ref UsefulInputBuf doesn't add much code for all the messy
1568 * hard-to-get right issues with parsing binary protocols in C that it
1569 * solves.
1570 *
1571 * The parse context size is:
1572 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1573 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001574 */
1575typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001576 /* PRIVATE DATA STRUCTURE */
1577 UsefulBufC UB; /* Data being parsed */
1578 size_t cursor; /* Current offset in data being parse */
1579 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1580 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001581} UsefulInputBuf;
1582
1583#define UIB_MAGIC (0xB00F)
1584
1585
1586/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001587 * @brief Initialize the @ref UsefulInputBuf structure before use.
1588 *
1589 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1590 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001591 */
1592static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1593
1594
1595/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001596 * @brief Returns current position in input buffer.
1597 *
1598 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1599 *
1600 * @return Integer position of the cursor.
1601 *
1602 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001603 */
1604static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1605
1606
1607/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001608 * @brief Sets the current position in input buffer.
1609 *
1610 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1611 * @param[in] uPos Position to set to.
1612 *
1613 * If the position is off the end of the input buffer, the error state
1614 * is entered.
1615 *
1616 * Seeking to a valid position in the buffer will not reset the error
1617 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001618 */
1619static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1620
1621
1622/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001623 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1624 * the unconsumed bytes.
1625 *
1626 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1627 *
1628 * @return Number of bytes unconsumed or 0 on error.
1629 *
1630 * Returns 0 if the cursor is invalid or corruption of the
1631 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001632 */
1633static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1634
1635
1636/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001637 * @brief Check if there are unconsumed bytes.
1638 *
1639 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1640 * @param[in] uLen Number of bytes to check availability for.
1641 *
1642 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001643 */
1644static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1645
1646
1647/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001648 * @brief Convert a pointer to an offset with bounds checking.
1649 *
1650 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1651 * @param[in] p Pointer to convert to offset.
1652 *
1653 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1654 */
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07001655static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1656
1657
1658/**
1659 * @brief Convert an offset to a pointer with bounds checking.
1660 *
1661 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1662 * @param[in] uOffset Offset in @c pUInBuf.
1663 *
1664 * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
1665 */
1666static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001667
1668
1669/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001670 * @brief Get pointer to bytes out of the input buffer.
1671 *
1672 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1673 * @param[in] uNum Number of bytes to get.
1674 *
1675 * @return Pointer to bytes.
1676 *
1677 * This consumes @c uNum bytes from the input buffer. This returns a
1678 * pointer to the start of the @c uNum bytes.
1679 *
1680 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1681 * returned and the error state is entered.
1682 *
1683 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001684 */
1685const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1686
1687
1688/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001689 * @brief Get @ref UsefulBuf out of the input buffer.
1690 *
1691 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1692 * @param[in] uNum Number of bytes to get.
1693 *
1694 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1695 *
1696 * This consumes @c uNum bytes from the input buffer and returns the
1697 * pointer and length for them as a @ref UsefulBufC. The length
1698 * returned will always be @c uNum. The position cursor is advanced by
1699 * @c uNum bytes.
1700 *
1701 * If there are not @c uNum bytes in the input buffer, @ref
1702 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001703 */
1704static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1705
1706
1707/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001708 * @brief Get a byte out of the input buffer.
1709 *
1710 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1711 *
1712 * @return The byte.
1713 *
1714 * This consumes 1 byte from the input buffer, returns it and advances
1715 * the position cursor by 1.
1716 *
1717 * If there is not 1 byte in the buffer, 0 will be returned for the
1718 * byte and the error state is entered. To know if the 0 returned was
1719 * in error or the real value, the error state must be checked. If
1720 * possible, put this off until all values are retrieved to have
1721 * smaller and simpler code, but if not possible
1722 * UsefulInputBuf_GetError() can be called. Also, in the error state
1723 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1724 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001725 */
1726static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1727
1728
1729/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001730 * @brief Get a @c uint16_t out of the input buffer.
1731 *
1732 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1733 *
1734 * @return The @c uint16_t.
1735 *
1736 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1737 * a @c uint16_t and two bytes are consumed.
1738 *
1739 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001740 */
1741static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1742
1743
1744/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001745 * @brief Get a @c uint32_t out of the input buffer.
1746 *
1747 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1748 *
1749 * @return The @c uint32_t.
1750 *
1751 * See UsefulInputBuf_GetByte(). This works the same, except it
1752 * returns a @c uint32_t and four bytes are consumed.
1753 *
1754 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001755 */
1756static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1757
1758
1759/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001760 * @brief Get a @c uint64_t out of the input buffer.
1761 *
1762 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1763 *
1764 * @return The uint64_t.
1765 *
1766 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1767 * a @c uint64_t and eight bytes are consumed.
1768 *
1769 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001770 */
1771static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1772
1773
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001774#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001775/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001776 * @brief Get a float out of the input buffer.
1777 *
1778 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1779 *
1780 * @return The float.
1781 *
1782 * See UsefulInputBuf_GetByte(). This works the same, except it
1783 * returns a float and four bytes are consumed.
1784 *
1785 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001786 */
1787static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1788
1789
1790/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001791 * @brief Get a double out of the input buffer.
1792 *
1793 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1794 *
1795 * @return The double.
1796 *
1797 * See UsefulInputBuf_GetByte(). This works the same, except it
1798 * returns a double and eight bytes are consumed.
1799 *
1800 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001801 */
1802static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001803#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001804
1805
1806/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001807 * @brief Get the error status.
1808 *
1809 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1810 *
1811 * @return 0 if not in the error state, 1 if in the error state.
1812 *
1813 * This returns whether the @ref UsefulInputBuf is in the
1814 * error state or not.
1815 *
1816 * The error state is entered for one of these reasons:
1817 * - Attempt to fetch data past the end of the buffer
1818 * - Attempt to seek to a position past the end of the buffer
1819 * - Attempt to get data from an uninitialized or corrupt instance
1820 * of @ref UsefulInputBuf
1821 *
1822 * Once in the error state, it can only be cleared by calling
1823 * UsefulInputBuf_Init().
1824 *
1825 * For many use cases, it is possible to only call this once after all
1826 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1827 * possible if no reference to the data returned are needed before the
1828 * error state is checked.
1829 *
1830 * In some cases UsefulInputBuf_GetUsefulBuf() or
1831 * UsefulInputBuf_GetBytes() can stand in for this because they return
1832 * @c NULL if the error state has been entered. (The others can't stand
1833 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001834 */
1835static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1836
1837
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001838/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001839 * @brief Gets the input buffer length.
1840 *
1841 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1842 *
1843 * @return The length of the input buffer.
1844 *
1845 * This returns the length of the input buffer set by
1846 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001847 */
1848static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1849
1850
1851/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001852 * @brief Alters the input buffer length (use with caution).
1853 *
1854 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1855 * @param[in] uNewLen The new length of the input buffer.
1856 *
1857 * This alters the internal remembered length of the input buffer set
1858 * when UsefulInputBuf_Init() was called.
1859 *
1860 * The new length given here should always be equal to or less than
1861 * the length given when UsefulInputBuf_Init() was called. Making it
1862 * larger allows @ref UsefulInputBuf to run off the input buffer.
1863 *
1864 * The typical use is to set a length shorter than that when
1865 * initialized to constrain parsing. If
1866 * UsefulInputBuf_GetBufferLength() was called before this, then the
1867 * original length can be restored with another call to this.
1868 *
1869 * This should be used with caution. It is the only
1870 * @ref UsefulInputBuf method that can violate the safety of input
1871 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001872 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001873static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001874
1875
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001876/** @brief Retrieve the undecoded input buffer.
Laurence Lundbladee2226742024-08-16 10:50:23 -07001877 *
1878 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1879 *
1880 * @return The input that was given to UsefulInputBuf_Init().
1881 *
1882 * A simple convenience method, should it be useful to get the original input back.
1883 */
1884static UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pUInBuf);
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001885
1886
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -07001887/**
1888 * @brief Compare two ranges of bytes somewhere in the input buffer.
1889 *
1890 * @param[in] pUInBuf The input buffer.
1891 * @param[in] uOffset1 Offset of first range of bytes.
1892 * @param[in] uLen1 Length of first range of bytes.
1893 * @param[in] uOffset2 Offset of second range of bytes.
1894 * @param[in] uLen2 Length of second range of bytes.
1895 *
1896 * This returns the same as UsefulBuf_Compare().
1897 *
1898 * If the offset or the length plus offset or a range extends outside
1899 * the input buffer, that range of bytes will be considered greater
1900 * than the other string. If both are outside this is considered a
1901 * degenerate condition and the first string is considered larger.
1902 *
1903 * This is a somewhat odd function of UsefulInputBuf as it is not used
1904 * for consuming data. QCBOR uses it for map order and duplicate
1905 * checking.
1906 */
1907int
1908UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
1909 const size_t uOffset1,
1910 const size_t uLen1,
1911 const size_t uOffset2,
1912 const size_t uLen2);
Michael Eckel5c531332020-03-02 01:35:30 +01001913
1914
Laurence Lundbladede2e1502024-08-26 11:37:05 -07001915
1916
Michael Eckel5c531332020-03-02 01:35:30 +01001917/*----------------------------------------------------------
1918 Inline implementations.
1919 */
1920static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1921{
1922 return !UB.ptr;
1923}
1924
1925
1926static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1927{
1928 return !UB.ptr;
1929}
1930
1931
1932static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1933{
1934 return !UB.len;
1935}
1936
1937
1938static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1939{
1940 return !UB.len;
1941}
1942
1943
1944static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1945{
1946 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1947}
1948
1949
1950static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1951{
1952 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1953}
1954
1955
1956static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1957{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001958 UsefulBufC UBC;
1959 UBC.ptr = UB.ptr;
1960 UBC.len = UB.len;
1961
1962 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001963}
1964
Michael Eckel5c531332020-03-02 01:35:30 +01001965static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1966{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001967 UsefulBuf UB;
1968
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001969 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001970 * the one place in UsefulBuf where it needs to be quieted.
1971 */
1972 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001973
1974 UB.len = UBC.len;
1975
1976 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001977}
1978
1979
1980static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1981{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001982 UsefulBufC UBC;
1983 UBC.ptr = szString;
1984 UBC.len = strlen(szString);
1985 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001986}
1987
1988
1989static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1990{
1991 return UsefulBuf_CopyOffset(Dest, 0, Src);
1992}
1993
1994
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001995static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001996{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001997 memset(Dest.ptr, value, Dest.len);
1998
1999 UsefulBufC UBC;
2000 UBC.ptr = Dest.ptr;
2001 UBC.len = Dest.len;
2002
2003 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002004}
2005
2006
2007static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
2008{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002009 UsefulBufC UBC;
2010 UBC.ptr = ptr;
2011 UBC.len = len;
2012 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002013}
2014
2015
2016static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
2017{
2018 if(uAmount > UB.len) {
2019 return NULLUsefulBufC;
2020 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002021 UsefulBufC UBC;
2022
2023 UBC.ptr = UB.ptr;
2024 UBC.len = uAmount;
2025
2026 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002027}
2028
2029
2030static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
2031{
2032 UsefulBufC ReturnValue;
2033
2034 if(uAmount > UB.len) {
2035 ReturnValue = NULLUsefulBufC;
2036 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002037 ReturnValue.ptr = NULL;
2038 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002039 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002040 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
2041 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01002042 }
2043
2044 return ReturnValue;
2045}
2046
2047
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002048static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
2049{
2050 if(UB.ptr == NULL) {
2051 return SIZE_MAX;
2052 }
2053
2054 if(p < UB.ptr) {
2055 /* given pointer is before start of buffer */
2056 return SIZE_MAX;
2057 }
2058
Laurence Lundblade3eead482023-12-16 20:53:22 -07002059 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002060 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002061
2062 if(uOffset >= UB.len) {
2063 /* given pointer is off the end of the buffer */
2064 return SIZE_MAX;
2065 }
2066
2067 return uOffset;
2068}
2069
Michael Eckel5c531332020-03-02 01:35:30 +01002070
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002071static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
2072{
2073 if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
2074 return NULL;
2075 }
2076
2077 return (const uint8_t *)UB.ptr + uOffset;
2078}
2079
2080
2081
2082
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002083#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002084static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
2085{
2086 uint32_t u32;
2087 memcpy(&u32, &f, sizeof(uint32_t));
2088 return u32;
2089}
2090
2091static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
2092{
2093 uint64_t u64;
2094 memcpy(&u64, &d, sizeof(uint64_t));
2095 return u64;
2096}
2097
2098static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
2099{
2100 double d;
2101 memcpy(&d, &u64, sizeof(uint64_t));
2102 return d;
2103}
2104
2105static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
2106{
2107 float f;
2108 memcpy(&f, &u32, sizeof(uint32_t));
2109 return f;
2110}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002111#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002112
2113
2114
2115
2116static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
2117{
2118 pMe->data_len = 0;
2119 pMe->err = 0;
2120}
2121
2122
2123static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
2124{
2125 return pMe->data_len;
2126}
2127
2128
2129static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
2130{
2131 return 0 == pMe->data_len;
2132}
2133
2134
2135static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2136 const void *pBytes,
2137 size_t uLen,
2138 size_t uPos)
2139{
2140 UsefulBufC Data = {pBytes, uLen};
2141 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2142}
2143
2144
2145static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2146 const char *szString,
2147 size_t uPos)
2148{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002149 UsefulBufC UBC;
2150 UBC.ptr = szString;
2151 UBC.len = strlen(szString);
2152
2153 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002154}
2155
2156
2157static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2158 uint8_t byte,
2159 size_t uPos)
2160{
2161 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2162}
2163
2164
2165static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2166 uint16_t uInteger16,
2167 size_t uPos)
2168{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002169 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002170
2171 const void *pBytes;
2172
2173#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2174 pBytes = &uInteger16;
2175
2176#elif defined(USEFULBUF_CONFIG_HTON)
2177 uint16_t uTmp = htons(uInteger16);
2178 pBytes = &uTmp;
2179
2180#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2181 uint16_t uTmp = __builtin_bswap16(uInteger16);
2182 pBytes = &uTmp;
2183
2184#else
2185 uint8_t aTmp[2];
2186
2187 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2188 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2189
2190 pBytes = aTmp;
2191#endif
2192
2193 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2194}
2195
2196
2197static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2198 uint32_t uInteger32,
2199 size_t uPos)
2200{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002201 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002202
2203 const void *pBytes;
2204
2205#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2206 pBytes = &uInteger32;
2207
2208#elif defined(USEFULBUF_CONFIG_HTON)
2209 uint32_t uTmp = htonl(uInteger32);
2210 pBytes = &uTmp;
2211
2212#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2213 uint32_t uTmp = __builtin_bswap32(uInteger32);
2214
2215 pBytes = &uTmp;
2216
2217#else
2218 uint8_t aTmp[4];
2219
2220 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2221 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2222 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2223 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2224
2225 pBytes = aTmp;
2226#endif
2227
2228 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2229}
2230
2231static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002232 uint64_t uInteger64,
2233 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002234{
2235 const void *pBytes;
2236
2237#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002238 /* We have been told explicitly we are running on a big-endian
2239 * machine. Network byte order is big endian, so just copy. There
2240 * is no issue with alignment here because uInteger64 is always
2241 * aligned (and it doesn't matter if pBytes is aligned).
2242 */
Michael Eckel5c531332020-03-02 01:35:30 +01002243 pBytes = &uInteger64;
2244
2245#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002246 /* Use system function to handle big- and little-endian. This works
2247 * on both big- and little-endian machines, but hton() is not
2248 * always available or in a standard place so it is not used by
2249 * default. With some compilers and CPUs the code for this is very
2250 * compact through use of a special swap instruction and on
2251 * big-endian machines hton() will reduce to nothing.
2252 */
Michael Eckel5c531332020-03-02 01:35:30 +01002253 uint64_t uTmp = htonll(uInteger64);
2254
2255 pBytes = &uTmp;
2256
2257#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002258 /* Use built-in function for byte swapping. This usually compiles
2259 * to an efficient special byte swap instruction. Unlike hton() it
2260 * does not do this conditionally on the CPU endianness, so this
2261 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2262 */
Michael Eckel5c531332020-03-02 01:35:30 +01002263 uint64_t uTmp = __builtin_bswap64(uInteger64);
2264
2265 pBytes = &uTmp;
2266
2267#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002268 /* Default which works on every CPU with no dependency on anything
2269 * from the CPU, compiler, libraries or OS. This always works, but
2270 * it is usually a little larger and slower than hton().
2271 */
Michael Eckel5c531332020-03-02 01:35:30 +01002272 uint8_t aTmp[8];
2273
2274 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2275 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2276 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2277 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2278 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2279 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2280 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2281 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2282
2283 pBytes = aTmp;
2284#endif
2285
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002286 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002287 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2288}
2289
2290
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002291#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002292static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2293 float f,
2294 size_t uPos)
2295{
2296 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2297}
2298
2299
2300static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2301 double d,
2302 size_t uPos)
2303{
2304 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2305}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002306#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002307
2308
2309static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2310 UsefulBufC NewData)
2311{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002312 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002313 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2314}
2315
2316
2317static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2318 const void *pBytes,
2319 size_t uLen)
2320{
2321 UsefulBufC Data = {pBytes, uLen};
2322 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2323}
2324
2325
2326static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2327 const char *szString)
2328{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002329 UsefulBufC UBC;
2330 UBC.ptr = szString;
2331 UBC.len = strlen(szString);
2332
2333 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002334}
2335
2336
2337static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2338 uint8_t byte)
2339{
2340 UsefulOutBuf_AppendData(pMe, &byte, 1);
2341}
2342
2343
2344static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2345 uint16_t uInteger16)
2346{
2347 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2348}
2349
2350static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2351 uint32_t uInteger32)
2352{
2353 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2354}
2355
2356
2357static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2358 uint64_t uInteger64)
2359{
2360 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2361}
2362
2363
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002364#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002365static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2366 float f)
2367{
2368 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2369}
2370
2371
2372static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2373 double d)
2374{
2375 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2376}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002377#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002378
2379
2380static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2381{
2382 return pMe->err;
2383}
2384
2385
2386static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2387{
2388 return pMe->UB.len - pMe->data_len;
2389}
2390
2391
2392static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2393{
2394 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2395}
2396
2397
2398static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2399{
2400 return pMe->UB.ptr == NULL;
2401}
2402
2403
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002404static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2405{
2406 UsefulBuf R;
2407
2408 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002409 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002410 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2411 } else {
2412 R.ptr = NULL;
2413 }
2414
2415 return R;
2416}
2417
2418
Laurence Lundbladee2226742024-08-16 10:50:23 -07002419static inline UsefulBuf UsefulOutBuf_RetrieveOutputStorage(UsefulOutBuf *pMe)
2420{
2421 return pMe->UB;
2422}
2423
2424
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002425
Michael Eckel5c531332020-03-02 01:35:30 +01002426
2427static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2428{
2429 pMe->cursor = 0;
2430 pMe->err = 0;
2431 pMe->magic = UIB_MAGIC;
2432 pMe->UB = UB;
2433}
2434
2435static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2436{
2437 return pMe->cursor;
2438}
2439
2440
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002441static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002442{
2443 return pMe->UB.len;
2444}
2445
2446
Michael Eckel5c531332020-03-02 01:35:30 +01002447static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2448{
2449 if(uPos > pMe->UB.len) {
2450 pMe->err = 1;
2451 } else {
2452 pMe->cursor = uPos;
2453 }
2454}
2455
2456
2457static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2458{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002459 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002460
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002461 /* Magic number is messed up. Either the structure got overwritten
2462 * or was never initialized.
2463 */
Michael Eckel5c531332020-03-02 01:35:30 +01002464 if(pMe->magic != UIB_MAGIC) {
2465 return 0;
2466 }
2467
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002468 /* The cursor is off the end of the input buffer given.
2469 * Presuming there are no bugs in this code, this should never happen.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002470 * If it is so, the struct was corrupted. The check is retained as
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002471 * as a defense in case there is a bug in this code or the struct is
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002472 * corrupted by an attacker or accidentally.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002473 */
Michael Eckel5c531332020-03-02 01:35:30 +01002474 if(pMe->cursor > pMe->UB.len) {
2475 return 0;
2476 }
2477
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002478 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002479 return pMe->UB.len - pMe->cursor;
2480}
2481
2482
2483static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2484{
2485 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2486}
2487
2488
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002489static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2490{
2491 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2492}
2493
2494
Laurence Lundbladea29f45a2024-05-14 15:55:19 -07002495static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
2496 {
2497 return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
2498 }
2499
2500
Michael Eckel5c531332020-03-02 01:35:30 +01002501static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2502{
2503 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2504 if(!pResult) {
2505 return NULLUsefulBufC;
2506 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002507 UsefulBufC UBC;
2508 UBC.ptr = pResult;
2509 UBC.len = uNum;
2510 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002511 }
2512}
2513
2514
2515static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2516{
2517 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2518
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002519 /* The ternary operator is subject to integer promotion, because
2520 * the operands are smaller than int, so cast back to uint8_t is
2521 * needed to be completely explicit about types (for static
2522 * analyzers).
2523 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002524 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002525}
2526
2527static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2528{
2529 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2530
2531 if(!pResult) {
2532 return 0;
2533 }
2534
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002535 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002536#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2537 uint16_t uTmp;
2538 memcpy(&uTmp, pResult, sizeof(uint16_t));
2539
2540#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2541 return uTmp;
2542
2543#elif defined(USEFULBUF_CONFIG_HTON)
2544 return ntohs(uTmp);
2545
2546#else
2547 return __builtin_bswap16(uTmp);
2548
2549#endif
2550
2551#else
2552
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002553 /* The operations here are subject to integer promotion because the
2554 * operands are smaller than int. They will be promoted to unsigned
2555 * int for the shift and addition. The cast back to uint16_t is is
2556 * needed to be completely explicit about types (for static
2557 * analyzers).
2558 */
Michael Eckel5c531332020-03-02 01:35:30 +01002559 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2560
2561#endif
2562}
2563
2564
2565static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2566{
2567 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2568
2569 if(!pResult) {
2570 return 0;
2571 }
2572
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002573 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002574#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2575 uint32_t uTmp;
2576 memcpy(&uTmp, pResult, sizeof(uint32_t));
2577
2578#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2579 return uTmp;
2580
2581#elif defined(USEFULBUF_CONFIG_HTON)
2582 return ntohl(uTmp);
2583
2584#else
2585 return __builtin_bswap32(uTmp);
2586
2587#endif
2588
2589#else
2590 return ((uint32_t)pResult[0]<<24) +
2591 ((uint32_t)pResult[1]<<16) +
2592 ((uint32_t)pResult[2]<<8) +
2593 (uint32_t)pResult[3];
2594#endif
2595}
2596
2597
2598static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2599{
2600 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2601
2602 if(!pResult) {
2603 return 0;
2604 }
2605
2606#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002607 /* pResult will probably not be aligned. This memcpy() moves the
2608 * bytes into a temp variable safely for CPUs that can or can't do
2609 * unaligned memory access. Many compilers will optimize the
2610 * memcpy() into a simple move instruction.
2611 */
Michael Eckel5c531332020-03-02 01:35:30 +01002612 uint64_t uTmp;
2613 memcpy(&uTmp, pResult, sizeof(uint64_t));
2614
2615#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002616 /* We have been told expliclity this is a big-endian CPU. Since
2617 * network byte order is big-endian, there is nothing to do.
2618 */
Michael Eckel5c531332020-03-02 01:35:30 +01002619
2620 return uTmp;
2621
2622#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002623 /* We have been told to use ntoh(), the system function to handle
2624 * big- and little-endian. This works on both big- and
2625 * little-endian machines, but ntoh() is not always available or in
2626 * a standard place so it is not used by default. On some CPUs the
2627 * code for this is very compact through use of a special swap
2628 * instruction.
2629 */
Michael Eckel5c531332020-03-02 01:35:30 +01002630
2631 return ntohll(uTmp);
2632
2633#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002634 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2635 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2636 * __builtin_bswap64() and friends are not conditional on CPU
2637 * endianness so this must only be used on little-endian machines.
2638 */
Michael Eckel5c531332020-03-02 01:35:30 +01002639
2640 return __builtin_bswap64(uTmp);
2641
2642
2643#endif
2644
2645#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002646 /* This is the default code that works on every CPU and every
2647 * endianness with no dependency on ntoh(). This works on CPUs
2648 * that either allow or do not allow unaligned access. It will
2649 * always work, but usually is a little less efficient than ntoh().
2650 */
Michael Eckel5c531332020-03-02 01:35:30 +01002651
2652 return ((uint64_t)pResult[0]<<56) +
2653 ((uint64_t)pResult[1]<<48) +
2654 ((uint64_t)pResult[2]<<40) +
2655 ((uint64_t)pResult[3]<<32) +
2656 ((uint64_t)pResult[4]<<24) +
2657 ((uint64_t)pResult[5]<<16) +
2658 ((uint64_t)pResult[6]<<8) +
2659 (uint64_t)pResult[7];
2660#endif
2661}
2662
2663
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002664#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002665static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2666{
2667 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2668
2669 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2670}
2671
2672
2673static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2674{
2675 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2676
2677 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2678}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002679#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002680
2681
2682static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2683{
2684 return pMe->err;
2685}
2686
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002687
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002688static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002689{
2690 pMe->UB.len = uNewLen;
2691}
2692
Laurence Lundbladee2226742024-08-16 10:50:23 -07002693static inline UsefulBufC UsefulInputBuf_RetrieveUndecodedInput(UsefulInputBuf *pMe)
2694{
2695 return pMe->UB;
2696}
2697
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002698
Michael Eckel5c531332020-03-02 01:35:30 +01002699#ifdef __cplusplus
2700}
2701#endif
2702
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002703#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002704
2705