blob: 94688dbe4cc834a476cb7579e13542ea52851290 [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladed6e13022023-11-26 10:14:02 -07003 Copyright (c) 2018-2023, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited. All rights reserved.
Michael Eckel5c531332020-03-02 01:35:30 +01005
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =============================================================================*/
32
33/*============================================================================
34 FILE: UsefulBuf.h
35
36 DESCRIPTION: General purpose input and output buffers
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- --------------------------------------------------
Laurence Lundbladed6e13022023-11-26 10:14:02 -070045 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
46 19/11/2023 llundblade Add UsefulOutBuf_Swap().
47 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070048 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060049 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070050 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070051 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070052 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080053 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070054 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010055 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
56 5/21/2019 llundblade #define configs for efficient endianness handling.
57 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
58 3/23/2019 llundblade Big documentation & style update. No interface
59 change.
60 3/6/2019 llundblade Add UsefulBuf_IsValue()
61 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
62 12/13/2018 llundblade Documentation improvements
63 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
64 UsefulBufC.
65 02/02/18 llundbla Full support for integers in and out; fix pointer
66 alignment bug. Incompatible change: integers
67 in/out are now in network byte order.
68 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
69 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
70 comparison for < or > for unequal length buffers.
71 Added UsefulBuf_Set() function.
72 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
73 11/13/16 llundbla Initial Version.
74
75 =============================================================================*/
76
77#ifndef _UsefulBuf_h
78#define _UsefulBuf_h
79
80
81/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070082 * Endianness Configuration
83 *
84 * This code is written so it will work correctly on big- and
85 * little-endian CPUs without configuration or any auto-detection of
86 * endianness. All code here will run correctly regardless of the
87 * endianness of the CPU it is running on.
88 *
89 * There are four C preprocessor macros that can be set with #define
90 * to explicitly configure endianness handling. Setting them can
91 * reduce code size a little and improve efficiency a little.
92 *
93 * Note that most of QCBOR is unaffected by this configuration. Its
94 * endianness handling is integrated with the code that handles
95 * alignment and preferred serialization. This configuration does
96 * affect QCBOR's (planned) implementation of integer arrays (tagged
97 * arrays) and use of the functions here to serialize or deserialize
98 * integers and floating-point values.
99 *
100 * Following is the recipe for configuring the endianness-related
101 * #defines.
102 *
103 * The first option is to not define anything. This will work fine
104 * with all CPUs, OS's and compilers. The code for encoding integers
105 * may be a little larger and slower.
106 *
107 * If your CPU is big-endian then define
108 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
109 * for big-endian CPUs. It will be small and efficient because there
110 * will be no byte swapping.
111 *
112 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
113 * OS's and compilers, but not all. On big-endian CPUs this should
114 * give the most efficient code, the same as
115 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
116 * call the system-defined byte swapping method which is presumably
117 * implemented efficiently. In some cases, this will be a dedicated
118 * byte swap instruction like Intel's bswap.
119 *
120 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
121 * little-endian, it is also good to define
122 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
123 *
124 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
125 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
126 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
127 * system-defined byte swap method. However, note
128 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
129 * this is fixed now. Often hton() and ntoh() will call the built-in
130 * __builtin_bswapXX()() function, so this size issue could affect
131 * USEFULBUF_CONFIG_HTON.
132 *
133 * Last, run the tests. They must all pass.
134 *
135 * These #define config options affect the inline implementation of
136 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
137 * also affect the 16-, 32-bit, float and double versions of these
138 * functions. Since they are inline, the size effect is not in the
139 * UsefulBuf object code, but in the calling code.
140 *
141 * Summary:
142 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
143 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
144 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
145 * handle big and little-endian with system option.
146 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
147 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200148 *
149 * It is possible to run this code in environments where using floating point is
150 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
151 * that is related to handling floating point types, along with related
152 * interfaces. This makes it possible to compile the code with the compile
153 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100154 */
155
156#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
157#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
158#endif
159
160
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700161#include <stdint.h> /* for uint8_t, uint16_t.... */
162#include <string.h> /* for strlen, memcpy, memmove, memset */
163#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100164
165
166#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700167#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100168#endif
169
170#ifdef __cplusplus
171extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700172#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700173} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700174#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100175#endif
176
177/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700178 * @file UsefulBuf.h
179 *
180 * The goal of this code is to make buffer and pointer manipulation
181 * easier and safer when working with binary data.
182 *
183 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
184 * structures are used to represent buffers rather than ad hoc
185 * pointers and lengths.
186 *
187 * With these it is possible to write code that does little or no
188 * direct pointer manipulation for copying and formatting data. For
189 * example, the QCBOR encoder was written using these and has less
190 * pointer manipulation.
191 *
192 * While it is true that object code using these functions will be a
193 * little larger and slower than a white-knuckle clever use of
194 * pointers might be, but not by that much or enough to have an effect
195 * for most use cases. For security-oriented code this is highly
196 * worthwhile. Clarity, simplicity, reviewability and are more
197 * important.
198 *
199 * There are some extra sanity and double checks in this code to help
200 * catch coding errors and simple memory corruption. They are helpful,
201 * but not a substitute for proper code review, input validation and
202 * such.
203 *
204 * This code consists of a lot of inline functions and a few that are
205 * not. It should not generate very much object code, especially with
206 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100207 */
208
209
210/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700211 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
212 * hold a pointer and length for binary data. In C99 this data
213 * structure can be passed on the stack making a lot of code cleaner
214 * than carrying around a pointer and length as two parameters.
215 *
216 * This is also conducive to secure coding practice as the length is
217 * always carried with the pointer and the convention for handling a
218 * pointer and a length is clear.
219 *
220 * While it might be possible to write buffer and pointer code more
221 * efficiently in some use cases, the thought is that unless there is
222 * an extreme need for performance (e.g., you are building a
223 * gigabit-per-second IP router), it is probably better to have
224 * cleaner code you can be most certain about the security of.
225 *
226 * The non-const @ref UsefulBuf is usually used to refer an empty
227 * buffer to be filled in. The length is the size of the buffer.
228 *
229 * The const @ref UsefulBufC is usually used to refer to some data
230 * that has been filled in. The length is amount of valid data pointed
231 * to.
232 *
233 * A common use mode is to pass a @ref UsefulBuf to a function, the
234 * function puts some data in it, then the function returns a @ref
235 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
236 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
237 * so the constness stays correct. There is no single "in,out"
238 * parameter (if there was, it would have to be non-const). Note that
239 * the pointer returned in the @ref UsefulBufC usually ends up being
240 * the same pointer passed in as a @ref UsefulBuf, though this is not
241 * striclty required.
242 *
243 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
244 * @c NULL.
245 *
246 * There are functions and macros for the following:
247 * - Initializing
248 * - Create initialized const @ref UsefulBufC from compiler literals
249 * - Create initialized const @ref UsefulBufC from NULL-terminated string
250 * - Make an empty @ref UsefulBuf on the stack
251 * - Checking whether a @ref UsefulBuf is null, empty or both
252 * - Copying, copying with offset, copying head or tail
253 * - Comparing and finding substrings
254 *
255 * See also @ref UsefulOutBuf. It is a richer structure that has both
256 * the size of the valid data and the size of the buffer.
257 *
258 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
259 * it can go on the stack and be a function parameter or return value.
260 *
261 * Another way to look at it is this. C has the NULL-terminated string
262 * as a means for handling text strings, but no means or convention
263 * for binary strings. Other languages do have such means, Rust, an
264 * efficient compiled language, for example.
265 *
266 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
267 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
268 * out like anything".
269 */
Michael Eckel5c531332020-03-02 01:35:30 +0100270typedef struct q_useful_buf_c {
271 const void *ptr;
272 size_t len;
273} UsefulBufC;
274
275
276/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700277 * This non-const @ref UsefulBuf is typically used for some allocated
278 * memory that is to be filled in. The @c len is the amount of memory,
279 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100280 */
281typedef struct q_useful_buf {
282 void *ptr;
283 size_t len;
284} UsefulBuf;
285
286
287/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700288 * A null @ref UsefulBufC is one that has no value in the same way a
289 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
290 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
291 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100292 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700293/*
294 * NULLUsefulBufC and few other macros have to be
295 * definied differently in C than C++ because there
296 * is no common construct for a literal structure.
297 *
298 * In C compound literals are used.
299 *
300 * In C++ list initalization is used. This only works
301 * in C++11 and later.
302 *
303 * Note that some popular C++ compilers can handle compound
304 * literals with on-by-default extensions, however
305 * this code aims for full correctness with strict
306 * compilers so they are not used.
307 */
308#ifdef __cplusplus
309#define NULLUsefulBufC {NULL, 0}
310#else
311#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
312#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100313
314/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700315 * A null @ref UsefulBuf is one that has no memory associated the same
316 * way @c NULL points to nothing. It does not matter what @c len is.
317 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700318#ifdef __cplusplus
319#define NULLUsefulBuf {NULL, 0}
320#else
321#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
322#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100323
324
325/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700326 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
327 *
328 * @param[in] UB The UsefulBuf to check.
329 *
330 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100331 */
332static inline int UsefulBuf_IsNULL(UsefulBuf UB);
333
334
335/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700336 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
337 *
338 * @param[in] UB The @ref UsefulBufC to check.
339 *
340 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100341 */
342static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
343
344
345/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700346 * @brief Check if a @ref UsefulBuf is empty or not.
347 *
348 * @param[in] UB The @ref UsefulBuf to check.
349 *
350 * @return 1 if it is empty, 0 if not.
351 *
352 * An "empty" @ref UsefulBuf is one that has a value and can be
353 * considered to be set, but that value is of zero length. It is
354 * empty when @c len is zero. It doesn't matter what the @c ptr is.
355 *
356 * Many uses will not need to clearly distinguish a @c NULL @ref
357 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
358 * @c len 0. However if a use of @ref UsefulBuf needs to make a
359 * distinction then @c ptr should not be @c NULL when the @ref
360 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100361 */
362static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
363
364
365/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700366 * @brief Check if a @ref UsefulBufC is empty or not.
367 *
368 * @param[in] UB The @ref UsefulBufC to check.
369 *
370 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100371 */
372static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
373
374
375/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700376 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
377 *
378 * @param[in] UB The @ref UsefulBuf to check.
379 *
380 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100381 */
382static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
383
384
385/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700386 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
387 *
388 * @param[in] UB The @ref UsefulBufC to check.
389 *
390 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100391 */
392static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
393
394
395/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700396 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
397 *
398 * @param[in] UB The @ref UsefulBuf to convert.
399 *
400 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100401 */
402static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
403
404
405/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700406 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
407 *
408 * @param[in] UBC The @ref UsefulBuf to convert.
409 *
410 * @return A non-const @ref UsefulBuf struct.
411 *
412 * Use of this is not necessary for the intended use mode of @ref
413 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
414 * created to describe a buffer that has not had any data put in
415 * it. Then the data is put in it. Then a @ref UsefulBufC is create
416 * to describe the part with the data in it. This goes from non-const
417 * to const, so this function is not needed.
418 *
419 * If the -Wcast-qual warning is enabled, this function can be used to
420 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100421 */
422static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
423
424
425/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700426 * Convert a literal string to a @ref UsefulBufC.
427 *
428 * @c szString must be a literal string that @c sizeof() works on.
429 * This is better for literal strings than UsefulBuf_FromSZ() because
430 * it generates less code. It will not work on non-literal strings.
431 *
432 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100433 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700434#ifdef __cplusplus
435#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
436#else
Michael Eckel5c531332020-03-02 01:35:30 +0100437#define UsefulBuf_FROM_SZ_LITERAL(szString) \
438 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700439#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100440
441
442/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700443 * Convert a literal byte array to a @ref UsefulBufC.
444 *
445 * @c pBytes must be a literal string that @c sizeof() works on. It
446 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100447 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700448#ifdef __cplusplus
449#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
450#else
Michael Eckel5c531332020-03-02 01:35:30 +0100451#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700452 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
453#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100454
455/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700456 * Make an automatic variable named @c name of type @ref UsefulBuf and
457 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100458 */
459#define UsefulBuf_MAKE_STACK_UB(name, size) \
460 uint8_t __pBuf##name[(size)];\
461 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
462
463
464/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700465 * Make a byte array in to a @ref UsefulBuf. This is usually used on
466 * stack variables or static variables. Also see @ref
467 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100468 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700469#ifdef __cplusplus
470#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
471#else
Michael Eckel5c531332020-03-02 01:35:30 +0100472#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700473 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
474#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100475
476
477/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700478 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
479 *
480 * @param[in] szString The string to convert.
481 *
482 * @return A @ref UsefulBufC struct.
483 *
484 * @c UsefulBufC.ptr points to the string so its lifetime must be
485 * maintained.
486 *
487 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100488 */
489static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
490
491
492/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700493 * @brief Copy one @ref UsefulBuf into another at an offset.
494 *
495 * @param[in] Dest Destination buffer to copy into.
496 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
497 * @param[in] Src The bytes to copy.
498 *
499 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
500 *
501 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
502 * size of @c Dest.
503 *
504 * This fails and returns @ref NULLUsefulBufC if the @c Src length
505 * plus @c uOffset is greater than the length of @c Dest.
506 *
507 * The results are undefined if @c Dest and @c Src overlap.
508 *
509 * This assumes that there is valid data in @c Dest up to @c
510 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
511 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100512 */
513UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
514
515
516/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700517 * @brief Copy one @ref UsefulBuf into another.
518 *
519 * @param[in] Dest The destination buffer to copy into.
520 * @param[out] Src The source to copy from.
521 *
522 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
523 * on failure.
524 *
525 * This fails if @c Src.len is greater than @c Dest.len.
526 *
527 * Note that like @c memcpy(), the pointers are not checked and this
528 * will crash rather than return @ref NULLUsefulBufC if they are @c
529 * NULL or invalid.
530 *
531 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100532 */
533static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
534
535
536/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700537 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
538 *
539 * @param[in] pDest The destination buffer to copy into.
540 * @param[in] value The value to set the bytes to.
541 *
542 * Note that like @c memset(), the pointer in @c pDest is not checked
543 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100544 */
545static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
546
547
548/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700549 * @brief Copy a pointer into a @ref UsefulBuf.
550 *
551 * @param[in,out] Dest The destination buffer to copy into.
552 * @param[in] ptr The source to copy from.
553 * @param[in] uLen Length of the source; amount to copy.
554 *
555 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
556 * on failure.
557 *
558 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
559 * than @c pDest->len.
560 *
561 * Note that like @c memcpy(), the pointers are not checked and this
562 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100563 */
564static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
565 const void *ptr,
566 size_t uLen);
567
568
569/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700570 * @brief Returns a truncation of a @ref UsefulBufC.
571 *
572 * @param[in] UB The buffer to get the head of.
573 * @param[in] uAmount The number of bytes in the head.
574 *
575 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100576 */
577static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
578
579
580/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700581 * @brief Returns bytes from the end of a @ref UsefulBufC.
582 *
583 * @param[in] UB The buffer to get the tail of.
584 * @param[in] uAmount The offset from the start where the tail is to begin.
585 *
586 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
587 * if @c uAmount is greater than the length of the @ref UsefulBufC.
588 *
589 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
590 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
591 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100592 */
593static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
594
595
596/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700597 * @brief Compare one @ref UsefulBufC to another.
598 *
599 * @param[in] UB1 The first buffer to compare.
600 * @param[in] UB2 The second buffer to compare.
601 *
602 * @return 0, positive or negative value.
603 *
604 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
605 * less than @c UB2 if it is shorter or the first byte that is not the
606 * same is less.
607 *
608 * Returns 0 if the inputs are the same.
609 *
610 * Returns a positive value if @c UB2 is less than @c UB1.
611 *
612 * All that is of significance is that the result is positive, negative
613 * or 0. (This doesn't return the difference between the first
614 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100615 */
616int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
617
618
619/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700620 * @brief Find first byte that is not a particular byte value.
621 *
622 * @param[in] UB The destination buffer for byte comparison.
623 * @param[in] uValue The byte value to compare to.
624 *
625 * @return Offset of first byte that isn't @c uValue or
626 * @c SIZE_MAX if all bytes are @c uValue.
627 *
628 * Note that unlike most comparison functions, 0
629 * does not indicate a successful comparison, so the
630 * test for match is:
631 *
632 * UsefulBuf_IsValue(...) == SIZE_MAX
633 *
634 * If @c UB is null or empty, there is no match
635 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100636 */
637size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
638
639
640/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700641 * @brief Find one @ref UsefulBufC in another.
642 *
643 * @param[in] BytesToSearch Buffer to search through.
644 * @param[in] BytesToFind Buffer with bytes to be found.
645 *
646 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100647 */
648size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
649
650
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700651/**
652 @brief Convert a pointer to an offset with bounds checking.
653
654 @param[in] UB Pointer to the UsefulInputBuf.
655 @param[in] p Pointer to convert to offset.
656
657 @return SIZE_MAX if @c p is out of range, the byte offset if not.
658*/
659static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
660
661
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800662#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100663/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700664#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100665
666/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
667#define MakeUsefulBufOnStack(name, size) \
668 uint8_t __pBuf##name[(size)];\
669 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
670
671/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
672#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700673 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100674
675/** Deprecated function; use UsefulBuf_Unconst() instead */
676static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
677{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700678 UsefulBuf UB;
679
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300680 // See UsefulBuf_Unconst() implementation for comment
681 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700682
683 UB.len = UBC.len;
684
685 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100686}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800687#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100688
689
690
691
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200692#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100693/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700694 * @brief Copy a @c float to a @c uint32_t.
695 *
696 * @param[in] f Float value to copy.
697 *
698 * @return A @c uint32_t with the float bits.
699 *
700 * Convenience function to avoid type punning, compiler warnings and
701 * such. The optimizer usually reduces this to a simple assignment. This
702 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100703 */
704static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
705
706
707/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700708 * @brief Copy a @c double to a @c uint64_t.
709 *
710 * @param[in] d Double value to copy.
711 *
712 * @return A @c uint64_t with the double bits.
713 *
714 * Convenience function to avoid type punning, compiler warnings and
715 * such. The optimizer usually reduces this to a simple assignment. This
716 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100717 */
718static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
719
720
721/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700722 * @brief Copy a @c uint32_t to a @c float.
723 *
724 * @param[in] u32 Integer value to copy.
725 *
726 * @return The value as a @c float.
727 *
728 * Convenience function to avoid type punning, compiler warnings and
729 * such. The optimizer usually reduces this to a simple assignment. This
730 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100731 */
732static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
733
734
735/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700736 * @brief Copy a @c uint64_t to a @c double.
737 *
738 * @param[in] u64 Integer value to copy.
739 *
740 * @return The value as a @c double.
741 *
742 * Convenience function to avoid type punning, compiler warnings and
743 * such. The optimizer usually reduces this to a simple assignment. This
744 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100745 */
746static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200747#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100748
749
750
751
752/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700753 * UsefulOutBuf is a structure and functions (an object) for
754 * serializing data into a buffer to encode for a network protocol or
755 * write data to a file.
756 *
757 * The main idea is that all the pointer manipulation is performed by
758 * @ref UsefulOutBuf functions so the caller doesn't have to do any
759 * pointer manipulation. The pointer manipulation is centralized.
760 * This code has been reviewed and written carefully so it
761 * spares the caller of much of this work and results in safer code
762 * with less effort.
763 *
764 * The @ref UsefulOutBuf methods that add data to the output buffer
765 * always check the length and will never write off the end of the
766 * output buffer. If an attempt to add data that will not fit is made,
767 * an internal error flag will be set and further attempts to add data
768 * will not do anything.
769 *
770 * There is no way to ever write off the end of that buffer when
771 * calling the @c UsefulOutBuf_AddXxx() and
772 * @c UsefulOutBuf_InsertXxx() functions.
773 *
774 * The functions to add data do not report success of failure. The
775 * caller only needs to check for an error in the final call, either
776 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
777 * result. This makes the calling code cleaner.
778 *
779 * There is a utility function to get the error status anytime along
780 * the way for a special circumstance. There are functions to see how
781 * much room is left and see if some data will fit too, but their use
782 * is generally unnecessary.
783 *
784 * The general call flow is:
785 *
786 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
787 * buffer given to it can be from the heap, stack or
788 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
789 * macro that makes a buffer on the stack and initializes it.
790 *
791 * - Call methods like UsefulOutBuf_InsertString(),
792 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
793 * to output data. The append calls add data to the end of the
794 * valid data. The insert calls take a position argument.
795 *
796 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
797 * there were no errors and to get the serialized output bytes.
798 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700799 * @ref UsefulOutBuf can be used in a mode to calculate the size of
800 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700801 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700802 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700803 *
804 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700805 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700806 *
807 * The possible errors are:
808 *
809 * - The @ref UsefulOutBuf was not initialized or was corrupted.
810 *
811 * - An attempt was made to add data that will not fit.
812 *
813 * - An attempt was made to insert data at a position beyond the end of
814 * the buffer.
815 *
816 * - An attempt was made to insert data at a position beyond the valid
817 * data in the buffer.
818 *
819 * Some inexpensive simple sanity checks are performed before every
820 * data addition to guard against use of an uninitialized or corrupted
821 * UsefulOutBuf.
822 *
823 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
824 * encoder has almost no pointer manipulation in it, is easier to
825 * read, and easier to review.
826 *
827 * A @ref UsefulOutBuf is small and can go on the stack:
828 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
829 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100830 */
831typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700832 /* PRIVATE DATA STRUCTURE */
833 UsefulBuf UB; /* Memory that is being output to */
834 size_t data_len; /* length of the valid data, the insertion point */
835 uint16_t magic; /* Used to detect corruption and lack
836 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100837 uint8_t err;
838} UsefulOutBuf;
839
840
841/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700842 * This is a @ref UsefulBuf value that can be passed to
843 * UsefulOutBuf_Init() to have it calculate the size of the output
844 * buffer needed. Pass this for @c Storage, call all the append and
845 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
846 * returned @ref UsefulBufC has the size.
847 *
848 * As one can see, this is just a NULL pointer and very large size.
849 * The NULL pointer tells UsefulOutputBuf to not copy any data.
850 */
851#ifdef __cplusplus
852#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
853#else
854#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
855#endif
856
857
858/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700859 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700860 *
861 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
862 * @param[in] Storage Buffer to output into.
863 *
864 * This initializes the @ref UsefulOutBuf with storage, sets the
865 * current position to the beginning of the buffer and clears the
866 * error state.
867 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700868 * See @ref SizeCalculateUsefulBuf for instructions on how to
869 * initialize a @ref UsefulOutBuf to calculate the size that would be
870 * output without actually outputting.
871 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700872 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100873 */
874void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
875
876
877/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700878 * Convenience macro to make a @ref UsefulOutBuf on the stack and
879 * initialize it with a stack buffer of the given size. The variable
880 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100881 */
882#define UsefulOutBuf_MakeOnStack(name, size) \
883 uint8_t __pBuf##name[(size)];\
884 UsefulOutBuf name;\
885 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
886
887
888/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700889 * @brief Reset a @ref UsefulOutBuf for re use.
890 *
891 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
892 *
893 * This sets the amount of data in the output buffer to none and
894 * clears the error state.
895 *
896 * The output buffer is still the same one and size as from the
897 * UsefulOutBuf_Init() call.
898 *
899 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100900 */
901static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
902
903
904/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700905 * @brief Returns position of end of data in the @ref UsefulOutBuf.
906 *
907 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
908 *
909 * @return position of end of data.
910 *
911 * On a freshly initialized @ref UsefulOutBuf with no data added, this
912 * will return 0. After 10 bytes have been added, it will return 10
913 * and so on.
914 *
915 * Generally, there is no need to call this for most uses of @ref
916 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100917 */
918static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
919
920
921/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700922 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
923 *
924 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
925 *
926 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100927 */
928static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
929
930
931/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700932 * @brief Inserts bytes into the @ref UsefulOutBuf.
933 *
934 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
935 * @param[in] NewData The bytes to insert.
936 * @param[in] uPos Index in output buffer at which to insert.
937 *
938 * @c NewData is the pointer and length for the bytes to be added to
939 * the output buffer. There must be room in the output buffer for all
940 * of @c NewData or an error will occur.
941 *
942 * The insertion point must be between 0 and the current valid
943 * data. If not, an error will occur. Appending data to the output
944 * buffer is achieved by inserting at the end of the valid data. This
945 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
946 *
947 * When insertion is performed, the bytes between the insertion point
948 * and the end of data previously added to the output buffer are slid
949 * to the right to make room for the new data.
950 *
951 * Overlapping buffers are OK. @c NewData can point to data in the
952 * output buffer.
953 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700954 * NewData.len may be 0 in which case nothing will be inserted.
955 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700956 * If an error occurs, an error state is set in the @ref
957 * UsefulOutBuf. No error is returned. All subsequent attempts to add
958 * data will do nothing.
959 *
960 * The intended use is that all additions are made without checking
961 * for an error. The error will be taken into account when
962 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
963 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100964 */
965void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
966 UsefulBufC NewData,
967 size_t uPos);
968
969
970/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700971 * @brief Insert a data buffer into the @ref UsefulOutBuf.
972 *
973 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
974 * @param[in] pBytes Pointer to the bytes to insert
975 * @param[in] uLen Length of the bytes to insert
976 * @param[in] uPos Index in output buffer at which to insert
977 *
978 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
979 * the difference being a pointer and length is passed in rather than an
980 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100981 */
982static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
983 const void *pBytes,
984 size_t uLen,
985 size_t uPos);
986
987
988/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700989 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
990 *
991 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
992 * @param[in] szString NULL-terminated string to insert.
993 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100994 */
995static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
996 const char *szString,
997 size_t uPos);
998
999
1000/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001001 * @brief Insert a byte into the @ref UsefulOutBuf.
1002 *
1003 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1004 * @param[in] byte Bytes to insert.
1005 * @param[in] uPos Index in output buffer at which to insert.
1006 *
1007 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1008 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001009 */
1010static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1011 uint8_t byte,
1012 size_t uPos);
1013
1014
1015/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001016 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1017 *
1018 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1019 * @param[in] uInteger16 Integer to insert.
1020 * @param[in] uPos Index in output buffer at which to insert.
1021 *
1022 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1023 * with the difference being a two-byte integer is to be inserted.
1024 *
1025 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001026 */
1027static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1028 uint16_t uInteger16,
1029 size_t uPos);
1030
1031
1032/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001033 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1034 *
1035 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1036 * @param[in] uInteger32 Integer to insert.
1037 * @param[in] uPos Index in output buffer at which to insert.
1038 *
1039 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1040 * with the difference being a four-byte integer is to be inserted.
1041 *
1042 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001043 */
1044static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1045 uint32_t uInteger32,
1046 size_t uPos);
1047
1048
1049/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001050 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1051 *
1052 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1053 * @param[in] uInteger64 Integer to insert.
1054 * @param[in] uPos Index in output buffer at which to insert.
1055 *
1056 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1057 * with the difference being an eight-byte integer is to be inserted.
1058 *
1059 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001060 */
1061static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1062 uint64_t uInteger64,
1063 size_t uPos);
1064
1065
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001066#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001067/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001068 * @brief Insert a @c float into the @ref UsefulOutBuf.
1069 *
1070 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1071 * @param[in] f @c float 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 @c float is to be inserted.
1076 *
1077 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001078 */
1079static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1080 float f,
1081 size_t uPos);
1082
1083
1084/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001085 * @brief Insert a @c double into the @ref UsefulOutBuf.
1086 *
1087 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1088 * @param[in] d @c double 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 a @c double is to be inserted.
1093 *
1094 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001095 */
1096static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1097 double d,
1098 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001099#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001100
1101
1102/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001103 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1104 *
1105 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1106 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1107 *
1108 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1109 * with the insertion point at the end of the valid data.
1110 */
Michael Eckel5c531332020-03-02 01:35:30 +01001111static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1112 UsefulBufC NewData);
1113
1114
1115/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001116 * @brief Append bytes to the @ref UsefulOutBuf.
1117 *
1118 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1119 * @param[in] pBytes Pointer to bytes to append.
1120 * @param[in] uLen Length of @c pBytes to append.
1121 *
1122 * See UsefulOutBuf_InsertData() for details. This does the same with
1123 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001124 */
1125static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1126 const void *pBytes,
1127 size_t uLen);
1128
1129
1130/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001131 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1132 *
1133 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1134 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001135 */
1136static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1137 const char *szString);
1138
1139
1140/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001141 * @brief Append a byte to the @ref UsefulOutBuf
1142 *
1143 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1144 * @param[in] byte Bytes to append.
1145 *
1146 * See UsefulOutBuf_InsertByte() for details. This does the same
1147 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001148 */
1149static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1150 uint8_t byte);
1151
1152
1153/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001154 * @brief Append an integer to the @ref UsefulOutBuf
1155 *
1156 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1157 * @param[in] uInteger16 Integer to append.
1158 *
1159 * See UsefulOutBuf_InsertUint16() for details. This does the same
1160 * with the insertion point at the end of the valid data.
1161 *
1162 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001163 */
1164static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1165 uint16_t uInteger16);
1166
1167
1168/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001169 * @brief Append an integer to the @ref UsefulOutBuf
1170 *
1171 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1172 * @param[in] uInteger32 Integer to append.
1173 *
1174 * See UsefulOutBuf_InsertUint32() for details. This does the same
1175 * with the insertion point at the end of the valid data.
1176 *
1177 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001178 */
1179static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1180 uint32_t uInteger32);
1181
1182
1183/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001184 * @brief Append an integer to the @ref UsefulOutBuf
1185 *
1186 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1187 * @param[in] uInteger64 Integer to append.
1188 *
1189 * See UsefulOutBuf_InsertUint64() for details. This does the same
1190 * with the insertion point at the end of the valid data.
1191 *
1192 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001193 */
1194static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1195 uint64_t uInteger64);
1196
1197
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001198#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001199/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001200 * @brief Append a @c float to the @ref UsefulOutBuf
1201 *
1202 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1203 * @param[in] f @c float to append.
1204 *
1205 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1206 * the insertion point at the end of the valid data.
1207 *
1208 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001209 */
1210static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1211 float f);
1212
1213
1214/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001215 * @brief Append a @c double to the @ref UsefulOutBuf
1216 *
1217 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1218 * @param[in] d @c double to append.
1219 *
1220 * See UsefulOutBuf_InsertDouble() for details. This does the same
1221 * with the insertion point at the end of the valid data.
1222 *
1223 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001224 */
1225static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1226 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001227#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001228
1229
1230/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001231 * @brief Returns the current error status.
1232 *
1233 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1234 *
1235 * @return 0 if all OK, 1 on error.
1236 *
1237 * This returns the error status since a call to either
1238 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1239 * goes into the error state, it will stay until one of those
1240 * functions is called.
1241 *
1242 * Possible error conditions are:
1243 * - bytes to be inserted will not fit
1244 * - insertion point is out of buffer or past valid data
1245 * - current position is off end of buffer (probably corrupted or uninitialized)
1246 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001247 */
1248static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1249
1250
1251/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001252 * @brief Returns number of bytes unused used in the output buffer.
1253 *
1254 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1255 *
1256 * @return Number of unused bytes or zero.
1257 *
1258 * Because of the error handling strategy and checks in
1259 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1260 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001261 */
1262static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1263
1264
1265/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001266 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1267 *
1268 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1269 * @param[in] uLen Number of bytes for which to check
1270 *
1271 * @return 1 if @c uLen bytes will fit, 0 if not.
1272 *
1273 * Because of the error handling strategy and checks in
1274 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1275 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001276 */
1277static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1278
1279
1280 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001281 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1282 *
1283 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1284 *
1285 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1286 *
1287 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1288 * just calculating the length of the encoded data.
1289 */
Michael Eckel5c531332020-03-02 01:35:30 +01001290static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1291
1292
1293/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001294 * @brief Returns pointer and length of the output buffer not yet used.
1295 *
1296 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1297 *
1298 * @return pointer and length of output buffer not used.
1299 *
1300 * This is an escape that allows the caller to write directly
1301 * to the output buffer without any checks. This doesn't
1302 * change the output buffer or state. It just returns a pointer
1303 * and length of the bytes remaining.
1304 *
1305 * This is useful to avoid having the bytes to be added all
1306 * in a contiguous buffer. Its use can save memory. A good
1307 * example is in the COSE encrypt implementation where
1308 * the output of the symmetric cipher can go directly
1309 * into the output buffer, rather than having to go into
1310 * an intermediate buffer.
1311 *
1312 * See UsefulOutBuf_Advance() which is used to tell
1313 * UsefulOutBuf how much was written.
1314 *
1315 * Warning: this bypasses the buffer safety provided by
1316 * UsefulOutBuf!
1317 */
1318static inline UsefulBuf
1319UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1320
1321
1322/**
1323 * @brief Advance the amount output assuming it was written by the caller.
1324 *
1325 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1326 * @param[in] uAmount The amount to advance.
1327 *
1328 * This advances the position in the output buffer
1329 * by \c uAmount. This assumes that the
1330 * caller has written \c uAmount to the pointer obtained
1331 * with UsefulOutBuf_GetOutPlace().
1332 *
1333 * Warning: this bypasses the buffer safety provided by
1334 * UsefulOutBuf!
1335 */
1336void
1337UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1338
1339
1340/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001341 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001342 *
1343 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1344 *
1345 * @return The valid data in @ref UsefulOutBuf or
1346 * @ref NULLUsefulBufC if there was an error adding data.
1347 *
1348 * The storage for the returned data is the @c Storage parameter
1349 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1350 *
1351 * This can be called anytime and many times to get intermediate
1352 * results. It doesn't change the data or reset the current position,
1353 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001354 */
1355UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1356
1357
1358/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001359 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001360 *
1361 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1362 * @param[out] Dest The destination buffer to copy into.
1363 *
1364 * @return Pointer and length of copied data or @c NULLUsefulBufC
1365 * if it will not fit in the @c Dest buffer or the error
1366 * state was entered.
1367 *
1368 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001369 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001370 */
Michael Eckel5c531332020-03-02 01:35:30 +01001371UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1372
1373
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001374/**
1375 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1376 *
1377 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1378 * @param[in] uOffset Offset to bytes to return.
1379 *
1380 * @return NULLUsefulBufC or the bytes at the offset.
1381 *
1382 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1383 * maybe specified. It returns the bytes starting at @c uOffset to the
1384 * end of what was encoded so far. Calling this with @c uOffset 0 is
1385 * equivalent to UsefulOutBuf_OutUBuf().
1386 *
1387 * If there's nothing at @c uOffset or it is past the in the output
1388 * buffer, a \ref NULLUsefulBufC is returned.
1389 *
1390 * This is typically not needed in typical use. It is used by QCBOR
1391 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1392 * sorting CBOR maps.
1393 */
1394UsefulBufC
1395UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1396
1397
1398/**
1399 * @brief Compare bytes at offsets.
1400 *
1401 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1402 * @param[in] uStart1 Offset of first bytes to compare.
1403 * @param[in] uStart2 Offset of second bytes to compare.
1404 *
1405 * @return 0 for equality, positive if uStart1 is lexographically larger,
1406 * negative if uStart2 is lexographically larger.
1407 *
1408 * This looks into bytes that have been output at the offsets @c start1
1409 * and @c start2. It compares bytes at those two starting points until
1410 * they are not equal or the end of the output data is reached from
1411 * one of the starting points.
1412 *
1413 * This returns positive when @c uStart1 lexographically sorts ahead
1414 * of @c uStart2 and vice versa. Zero is returned if the strings
1415 * compare equally. This only happens when the end of the valid data
1416 * is reached from one of the starting points and the comparison up to
1417 * that point is equality.
1418 *
1419 * If either start is past the end of data in the output buffer, 0
1420 * will be returned. It is the caller's responsibility to make sure
1421 * the offsets are not off the end such that a comparison is actually
1422 * being made. No data will ever be read off the end of the buffer so
1423 * this safe no matter what offsets are passed.
1424 *
1425 * This is a relatively odd function in that it works on data in the
1426 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps that
1427 * are in the output buffer.
1428 */
1429int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf, size_t uStart1, size_t uStart2);
1430
1431
1432/**
1433 * @brief Swap two regions of output bytes.
1434 *
1435 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1436 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1437 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1438 * @param[in] uEndOffset Offset to end of region to be swappe.
1439 *
1440 * This reaches into bytes that have been output and swaps two
1441 * adjacent regions.
1442 *
1443 * If any of the offsets are outside the range of valid data, no
1444 * swapping will be performed. If the start is not the smallest and
1445 * the pivot is not in the middle no swapping will be performed.
1446 *
1447 * The byte at @c uStartOffset will participate in the swapping. The
1448 * byte at @c uEndOffset will not participate in the swapping, only
1449 * the byte before it.
1450 *
1451 * This is a relatively odd function in that it works on data in the
1452 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1453 * maps.
1454 */
1455void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1456 size_t uStartOffset,
1457 size_t uPivotOffset,
1458 size_t uEndOffset);
1459
1460
Michael Eckel5c531332020-03-02 01:35:30 +01001461
1462
1463/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001464 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1465 * for parsing data received. Initialize it with the data from the
1466 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1467 * get data chunks of various types. A position cursor is maintained
1468 * internally.
1469 *
1470 * As long as the functions here are used, there will never be any
1471 * reference off the end of the given buffer (except
1472 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1473 * called incorrectly, an attempt is made to seek off the end of the
1474 * buffer or such. This makes it easier to write safe and correct
1475 * code. For example, the QCBOR decoder implementation is safer and
1476 * easier to review through its use of @ref UsefulInputBuf.
1477 *
1478 * @ref UsefulInputBuf maintains an internal error state. The
1479 * intended use is fetching data chunks without any error checks until
1480 * the end. If there was any error, such as an attempt to fetch data
1481 * off the end, the error state is entered and no further data will be
1482 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1483 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1484 * null is not dereferenced, the error check can be put off until the
1485 * end, simplifying the calling code.
1486 *
1487 * The integer and float parsing expects network byte order (big
1488 * endian). Network byte order is what is used by TCP/IP, CBOR and
1489 * most internet protocols.
1490 *
1491 * Lots of inline functions are used to keep code size down. The
1492 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1493 * code size a lot. The only non-inline code is
1494 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1495 * @ref UsefulInputBuf doesn't add much code for all the messy
1496 * hard-to-get right issues with parsing binary protocols in C that it
1497 * solves.
1498 *
1499 * The parse context size is:
1500 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1501 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001502 */
1503typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001504 /* PRIVATE DATA STRUCTURE */
1505 UsefulBufC UB; /* Data being parsed */
1506 size_t cursor; /* Current offset in data being parse */
1507 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1508 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001509} UsefulInputBuf;
1510
1511#define UIB_MAGIC (0xB00F)
1512
1513
1514/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001515 * @brief Initialize the @ref UsefulInputBuf structure before use.
1516 *
1517 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1518 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001519 */
1520static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1521
1522
1523/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001524 * @brief Returns current position in input buffer.
1525 *
1526 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1527 *
1528 * @return Integer position of the cursor.
1529 *
1530 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001531 */
1532static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1533
1534
1535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001536 * @brief Sets the current position in input buffer.
1537 *
1538 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1539 * @param[in] uPos Position to set to.
1540 *
1541 * If the position is off the end of the input buffer, the error state
1542 * is entered.
1543 *
1544 * Seeking to a valid position in the buffer will not reset the error
1545 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001546 */
1547static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1548
1549
1550/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001551 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1552 * the unconsumed bytes.
1553 *
1554 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1555 *
1556 * @return Number of bytes unconsumed or 0 on error.
1557 *
1558 * Returns 0 if the cursor is invalid or corruption of the
1559 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001560 */
1561static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1562
1563
1564/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001565 * @brief Check if there are unconsumed bytes.
1566 *
1567 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1568 * @param[in] uLen Number of bytes to check availability for.
1569 *
1570 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001571 */
1572static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1573
1574
1575/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001576 * @brief Convert a pointer to an offset with bounds checking.
1577 *
1578 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1579 * @param[in] p Pointer to convert to offset.
1580 *
1581 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1582 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001583static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1584
1585
1586/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001587 * @brief Get pointer to bytes out of the input buffer.
1588 *
1589 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1590 * @param[in] uNum Number of bytes to get.
1591 *
1592 * @return Pointer to bytes.
1593 *
1594 * This consumes @c uNum bytes from the input buffer. This returns a
1595 * pointer to the start of the @c uNum bytes.
1596 *
1597 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1598 * returned and the error state is entered.
1599 *
1600 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001601 */
1602const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1603
1604
1605/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001606 * @brief Get @ref UsefulBuf out of the input buffer.
1607 *
1608 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1609 * @param[in] uNum Number of bytes to get.
1610 *
1611 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1612 *
1613 * This consumes @c uNum bytes from the input buffer and returns the
1614 * pointer and length for them as a @ref UsefulBufC. The length
1615 * returned will always be @c uNum. The position cursor is advanced by
1616 * @c uNum bytes.
1617 *
1618 * If there are not @c uNum bytes in the input buffer, @ref
1619 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001620 */
1621static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1622
1623
1624/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001625 * @brief Get a byte out of the input buffer.
1626 *
1627 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1628 *
1629 * @return The byte.
1630 *
1631 * This consumes 1 byte from the input buffer, returns it and advances
1632 * the position cursor by 1.
1633 *
1634 * If there is not 1 byte in the buffer, 0 will be returned for the
1635 * byte and the error state is entered. To know if the 0 returned was
1636 * in error or the real value, the error state must be checked. If
1637 * possible, put this off until all values are retrieved to have
1638 * smaller and simpler code, but if not possible
1639 * UsefulInputBuf_GetError() can be called. Also, in the error state
1640 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1641 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001642 */
1643static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1644
1645
1646/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001647 * @brief Get a @c uint16_t out of the input buffer.
1648 *
1649 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1650 *
1651 * @return The @c uint16_t.
1652 *
1653 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1654 * a @c uint16_t and two bytes are consumed.
1655 *
1656 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001657 */
1658static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1659
1660
1661/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001662 * @brief Get a @c uint32_t out of the input buffer.
1663 *
1664 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1665 *
1666 * @return The @c uint32_t.
1667 *
1668 * See UsefulInputBuf_GetByte(). This works the same, except it
1669 * returns a @c uint32_t and four bytes are consumed.
1670 *
1671 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001672 */
1673static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1674
1675
1676/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001677 * @brief Get a @c uint64_t out of the input buffer.
1678 *
1679 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1680 *
1681 * @return The uint64_t.
1682 *
1683 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1684 * a @c uint64_t and eight bytes are consumed.
1685 *
1686 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001687 */
1688static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1689
1690
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001691#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001692/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001693 * @brief Get a float out of the input buffer.
1694 *
1695 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1696 *
1697 * @return The float.
1698 *
1699 * See UsefulInputBuf_GetByte(). This works the same, except it
1700 * returns a float and four bytes are consumed.
1701 *
1702 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001703 */
1704static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1705
1706
1707/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001708 * @brief Get a double out of the input buffer.
1709 *
1710 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1711 *
1712 * @return The double.
1713 *
1714 * See UsefulInputBuf_GetByte(). This works the same, except it
1715 * returns a double and eight bytes are consumed.
1716 *
1717 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001718 */
1719static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001720#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001721
1722
1723/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001724 * @brief Get the error status.
1725 *
1726 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1727 *
1728 * @return 0 if not in the error state, 1 if in the error state.
1729 *
1730 * This returns whether the @ref UsefulInputBuf is in the
1731 * error state or not.
1732 *
1733 * The error state is entered for one of these reasons:
1734 * - Attempt to fetch data past the end of the buffer
1735 * - Attempt to seek to a position past the end of the buffer
1736 * - Attempt to get data from an uninitialized or corrupt instance
1737 * of @ref UsefulInputBuf
1738 *
1739 * Once in the error state, it can only be cleared by calling
1740 * UsefulInputBuf_Init().
1741 *
1742 * For many use cases, it is possible to only call this once after all
1743 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1744 * possible if no reference to the data returned are needed before the
1745 * error state is checked.
1746 *
1747 * In some cases UsefulInputBuf_GetUsefulBuf() or
1748 * UsefulInputBuf_GetBytes() can stand in for this because they return
1749 * @c NULL if the error state has been entered. (The others can't stand
1750 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001751 */
1752static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1753
1754
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001755/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001756 * @brief Gets the input buffer length.
1757 *
1758 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1759 *
1760 * @return The length of the input buffer.
1761 *
1762 * This returns the length of the input buffer set by
1763 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001764 */
1765static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1766
1767
1768/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001769 * @brief Alters the input buffer length (use with caution).
1770 *
1771 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1772 * @param[in] uNewLen The new length of the input buffer.
1773 *
1774 * This alters the internal remembered length of the input buffer set
1775 * when UsefulInputBuf_Init() was called.
1776 *
1777 * The new length given here should always be equal to or less than
1778 * the length given when UsefulInputBuf_Init() was called. Making it
1779 * larger allows @ref UsefulInputBuf to run off the input buffer.
1780 *
1781 * The typical use is to set a length shorter than that when
1782 * initialized to constrain parsing. If
1783 * UsefulInputBuf_GetBufferLength() was called before this, then the
1784 * original length can be restored with another call to this.
1785 *
1786 * This should be used with caution. It is the only
1787 * @ref UsefulInputBuf method that can violate the safety of input
1788 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001789 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001790static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001791
1792
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001793
1794
Michael Eckel5c531332020-03-02 01:35:30 +01001795/*----------------------------------------------------------
1796 Inline implementations.
1797 */
1798static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1799{
1800 return !UB.ptr;
1801}
1802
1803
1804static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1805{
1806 return !UB.ptr;
1807}
1808
1809
1810static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1811{
1812 return !UB.len;
1813}
1814
1815
1816static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1817{
1818 return !UB.len;
1819}
1820
1821
1822static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1823{
1824 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1825}
1826
1827
1828static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1829{
1830 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1831}
1832
1833
1834static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1835{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001836 UsefulBufC UBC;
1837 UBC.ptr = UB.ptr;
1838 UBC.len = UB.len;
1839
1840 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001841}
1842
Michael Eckel5c531332020-03-02 01:35:30 +01001843static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1844{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001845 UsefulBuf UB;
1846
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001847 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001848 * the one place in UsefulBuf where it needs to be quieted.
1849 */
1850 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001851
1852 UB.len = UBC.len;
1853
1854 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001855}
1856
1857
1858static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1859{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001860 UsefulBufC UBC;
1861 UBC.ptr = szString;
1862 UBC.len = strlen(szString);
1863 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001864}
1865
1866
1867static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1868{
1869 return UsefulBuf_CopyOffset(Dest, 0, Src);
1870}
1871
1872
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001873static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001874{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001875 memset(Dest.ptr, value, Dest.len);
1876
1877 UsefulBufC UBC;
1878 UBC.ptr = Dest.ptr;
1879 UBC.len = Dest.len;
1880
1881 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001882}
1883
1884
1885static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1886{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001887 UsefulBufC UBC;
1888 UBC.ptr = ptr;
1889 UBC.len = len;
1890 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001891}
1892
1893
1894static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1895{
1896 if(uAmount > UB.len) {
1897 return NULLUsefulBufC;
1898 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001899 UsefulBufC UBC;
1900
1901 UBC.ptr = UB.ptr;
1902 UBC.len = uAmount;
1903
1904 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001905}
1906
1907
1908static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1909{
1910 UsefulBufC ReturnValue;
1911
1912 if(uAmount > UB.len) {
1913 ReturnValue = NULLUsefulBufC;
1914 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001915 ReturnValue.ptr = NULL;
1916 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001917 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001918 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1919 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001920 }
1921
1922 return ReturnValue;
1923}
1924
1925
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001926static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1927{
1928 if(UB.ptr == NULL) {
1929 return SIZE_MAX;
1930 }
1931
1932 if(p < UB.ptr) {
1933 /* given pointer is before start of buffer */
1934 return SIZE_MAX;
1935 }
1936
1937 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001938 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001939
1940 if(uOffset >= UB.len) {
1941 /* given pointer is off the end of the buffer */
1942 return SIZE_MAX;
1943 }
1944
1945 return uOffset;
1946}
1947
Michael Eckel5c531332020-03-02 01:35:30 +01001948
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001949#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001950static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1951{
1952 uint32_t u32;
1953 memcpy(&u32, &f, sizeof(uint32_t));
1954 return u32;
1955}
1956
1957static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1958{
1959 uint64_t u64;
1960 memcpy(&u64, &d, sizeof(uint64_t));
1961 return u64;
1962}
1963
1964static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1965{
1966 double d;
1967 memcpy(&d, &u64, sizeof(uint64_t));
1968 return d;
1969}
1970
1971static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1972{
1973 float f;
1974 memcpy(&f, &u32, sizeof(uint32_t));
1975 return f;
1976}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001977#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001978
1979
1980
1981
1982static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1983{
1984 pMe->data_len = 0;
1985 pMe->err = 0;
1986}
1987
1988
1989static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1990{
1991 return pMe->data_len;
1992}
1993
1994
1995static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1996{
1997 return 0 == pMe->data_len;
1998}
1999
2000
2001static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2002 const void *pBytes,
2003 size_t uLen,
2004 size_t uPos)
2005{
2006 UsefulBufC Data = {pBytes, uLen};
2007 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2008}
2009
2010
2011static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2012 const char *szString,
2013 size_t uPos)
2014{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002015 UsefulBufC UBC;
2016 UBC.ptr = szString;
2017 UBC.len = strlen(szString);
2018
2019 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002020}
2021
2022
2023static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2024 uint8_t byte,
2025 size_t uPos)
2026{
2027 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2028}
2029
2030
2031static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2032 uint16_t uInteger16,
2033 size_t uPos)
2034{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002035 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002036
2037 const void *pBytes;
2038
2039#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2040 pBytes = &uInteger16;
2041
2042#elif defined(USEFULBUF_CONFIG_HTON)
2043 uint16_t uTmp = htons(uInteger16);
2044 pBytes = &uTmp;
2045
2046#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2047 uint16_t uTmp = __builtin_bswap16(uInteger16);
2048 pBytes = &uTmp;
2049
2050#else
2051 uint8_t aTmp[2];
2052
2053 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2054 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2055
2056 pBytes = aTmp;
2057#endif
2058
2059 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2060}
2061
2062
2063static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2064 uint32_t uInteger32,
2065 size_t uPos)
2066{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002067 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002068
2069 const void *pBytes;
2070
2071#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2072 pBytes = &uInteger32;
2073
2074#elif defined(USEFULBUF_CONFIG_HTON)
2075 uint32_t uTmp = htonl(uInteger32);
2076 pBytes = &uTmp;
2077
2078#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2079 uint32_t uTmp = __builtin_bswap32(uInteger32);
2080
2081 pBytes = &uTmp;
2082
2083#else
2084 uint8_t aTmp[4];
2085
2086 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2087 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2088 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2089 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2090
2091 pBytes = aTmp;
2092#endif
2093
2094 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2095}
2096
2097static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002098 uint64_t uInteger64,
2099 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002100{
2101 const void *pBytes;
2102
2103#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002104 /* We have been told explicitly we are running on a big-endian
2105 * machine. Network byte order is big endian, so just copy. There
2106 * is no issue with alignment here because uInteger64 is always
2107 * aligned (and it doesn't matter if pBytes is aligned).
2108 */
Michael Eckel5c531332020-03-02 01:35:30 +01002109 pBytes = &uInteger64;
2110
2111#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002112 /* Use system function to handle big- and little-endian. This works
2113 * on both big- and little-endian machines, but hton() is not
2114 * always available or in a standard place so it is not used by
2115 * default. With some compilers and CPUs the code for this is very
2116 * compact through use of a special swap instruction and on
2117 * big-endian machines hton() will reduce to nothing.
2118 */
Michael Eckel5c531332020-03-02 01:35:30 +01002119 uint64_t uTmp = htonll(uInteger64);
2120
2121 pBytes = &uTmp;
2122
2123#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002124 /* Use built-in function for byte swapping. This usually compiles
2125 * to an efficient special byte swap instruction. Unlike hton() it
2126 * does not do this conditionally on the CPU endianness, so this
2127 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2128 */
Michael Eckel5c531332020-03-02 01:35:30 +01002129 uint64_t uTmp = __builtin_bswap64(uInteger64);
2130
2131 pBytes = &uTmp;
2132
2133#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002134 /* Default which works on every CPU with no dependency on anything
2135 * from the CPU, compiler, libraries or OS. This always works, but
2136 * it is usually a little larger and slower than hton().
2137 */
Michael Eckel5c531332020-03-02 01:35:30 +01002138 uint8_t aTmp[8];
2139
2140 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2141 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2142 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2143 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2144 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2145 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2146 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2147 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2148
2149 pBytes = aTmp;
2150#endif
2151
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002152 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002153 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2154}
2155
2156
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002157#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002158static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2159 float f,
2160 size_t uPos)
2161{
2162 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2163}
2164
2165
2166static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2167 double d,
2168 size_t uPos)
2169{
2170 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2171}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002172#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002173
2174
2175static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2176 UsefulBufC NewData)
2177{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002178 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002179 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2180}
2181
2182
2183static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2184 const void *pBytes,
2185 size_t uLen)
2186{
2187 UsefulBufC Data = {pBytes, uLen};
2188 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2189}
2190
2191
2192static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2193 const char *szString)
2194{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002195 UsefulBufC UBC;
2196 UBC.ptr = szString;
2197 UBC.len = strlen(szString);
2198
2199 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002200}
2201
2202
2203static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2204 uint8_t byte)
2205{
2206 UsefulOutBuf_AppendData(pMe, &byte, 1);
2207}
2208
2209
2210static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2211 uint16_t uInteger16)
2212{
2213 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2214}
2215
2216static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2217 uint32_t uInteger32)
2218{
2219 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2220}
2221
2222
2223static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2224 uint64_t uInteger64)
2225{
2226 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2227}
2228
2229
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002230#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002231static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2232 float f)
2233{
2234 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2235}
2236
2237
2238static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2239 double d)
2240{
2241 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2242}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002243#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002244
2245
2246static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2247{
2248 return pMe->err;
2249}
2250
2251
2252static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2253{
2254 return pMe->UB.len - pMe->data_len;
2255}
2256
2257
2258static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2259{
2260 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2261}
2262
2263
2264static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2265{
2266 return pMe->UB.ptr == NULL;
2267}
2268
2269
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002270static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2271{
2272 UsefulBuf R;
2273
2274 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002275 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002276 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2277 } else {
2278 R.ptr = NULL;
2279 }
2280
2281 return R;
2282}
2283
2284
2285
Michael Eckel5c531332020-03-02 01:35:30 +01002286
2287static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2288{
2289 pMe->cursor = 0;
2290 pMe->err = 0;
2291 pMe->magic = UIB_MAGIC;
2292 pMe->UB = UB;
2293}
2294
2295static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2296{
2297 return pMe->cursor;
2298}
2299
2300
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002301static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002302{
2303 return pMe->UB.len;
2304}
2305
2306
Michael Eckel5c531332020-03-02 01:35:30 +01002307static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2308{
2309 if(uPos > pMe->UB.len) {
2310 pMe->err = 1;
2311 } else {
2312 pMe->cursor = uPos;
2313 }
2314}
2315
2316
2317static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2318{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002319 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002320
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002321 /* Magic number is messed up. Either the structure got overwritten
2322 * or was never initialized.
2323 */
Michael Eckel5c531332020-03-02 01:35:30 +01002324 if(pMe->magic != UIB_MAGIC) {
2325 return 0;
2326 }
2327
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002328 /* The cursor is off the end of the input buffer given.
2329 * Presuming there are no bugs in this code, this should never happen.
2330 * If it so, the struct was corrupted. The check is retained as
2331 * as a defense in case there is a bug in this code or the struct is
2332 * corrupted.
2333 */
Michael Eckel5c531332020-03-02 01:35:30 +01002334 if(pMe->cursor > pMe->UB.len) {
2335 return 0;
2336 }
2337
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002338 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002339 return pMe->UB.len - pMe->cursor;
2340}
2341
2342
2343static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2344{
2345 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2346}
2347
2348
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002349static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2350{
2351 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2352}
2353
2354
Michael Eckel5c531332020-03-02 01:35:30 +01002355static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2356{
2357 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2358 if(!pResult) {
2359 return NULLUsefulBufC;
2360 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002361 UsefulBufC UBC;
2362 UBC.ptr = pResult;
2363 UBC.len = uNum;
2364 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002365 }
2366}
2367
2368
2369static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2370{
2371 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2372
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002373 /* The ternary operator is subject to integer promotion, because
2374 * the operands are smaller than int, so cast back to uint8_t is
2375 * needed to be completely explicit about types (for static
2376 * analyzers).
2377 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002378 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002379}
2380
2381static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2382{
2383 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2384
2385 if(!pResult) {
2386 return 0;
2387 }
2388
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002389 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002390#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2391 uint16_t uTmp;
2392 memcpy(&uTmp, pResult, sizeof(uint16_t));
2393
2394#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2395 return uTmp;
2396
2397#elif defined(USEFULBUF_CONFIG_HTON)
2398 return ntohs(uTmp);
2399
2400#else
2401 return __builtin_bswap16(uTmp);
2402
2403#endif
2404
2405#else
2406
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002407 /* The operations here are subject to integer promotion because the
2408 * operands are smaller than int. They will be promoted to unsigned
2409 * int for the shift and addition. The cast back to uint16_t is is
2410 * needed to be completely explicit about types (for static
2411 * analyzers).
2412 */
Michael Eckel5c531332020-03-02 01:35:30 +01002413 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2414
2415#endif
2416}
2417
2418
2419static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2420{
2421 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2422
2423 if(!pResult) {
2424 return 0;
2425 }
2426
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002427 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002428#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2429 uint32_t uTmp;
2430 memcpy(&uTmp, pResult, sizeof(uint32_t));
2431
2432#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2433 return uTmp;
2434
2435#elif defined(USEFULBUF_CONFIG_HTON)
2436 return ntohl(uTmp);
2437
2438#else
2439 return __builtin_bswap32(uTmp);
2440
2441#endif
2442
2443#else
2444 return ((uint32_t)pResult[0]<<24) +
2445 ((uint32_t)pResult[1]<<16) +
2446 ((uint32_t)pResult[2]<<8) +
2447 (uint32_t)pResult[3];
2448#endif
2449}
2450
2451
2452static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2453{
2454 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2455
2456 if(!pResult) {
2457 return 0;
2458 }
2459
2460#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002461 /* pResult will probably not be aligned. This memcpy() moves the
2462 * bytes into a temp variable safely for CPUs that can or can't do
2463 * unaligned memory access. Many compilers will optimize the
2464 * memcpy() into a simple move instruction.
2465 */
Michael Eckel5c531332020-03-02 01:35:30 +01002466 uint64_t uTmp;
2467 memcpy(&uTmp, pResult, sizeof(uint64_t));
2468
2469#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002470 /* We have been told expliclity this is a big-endian CPU. Since
2471 * network byte order is big-endian, there is nothing to do.
2472 */
Michael Eckel5c531332020-03-02 01:35:30 +01002473
2474 return uTmp;
2475
2476#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002477 /* We have been told to use ntoh(), the system function to handle
2478 * big- and little-endian. This works on both big- and
2479 * little-endian machines, but ntoh() is not always available or in
2480 * a standard place so it is not used by default. On some CPUs the
2481 * code for this is very compact through use of a special swap
2482 * instruction.
2483 */
Michael Eckel5c531332020-03-02 01:35:30 +01002484
2485 return ntohll(uTmp);
2486
2487#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002488 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2489 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2490 * __builtin_bswap64() and friends are not conditional on CPU
2491 * endianness so this must only be used on little-endian machines.
2492 */
Michael Eckel5c531332020-03-02 01:35:30 +01002493
2494 return __builtin_bswap64(uTmp);
2495
2496
2497#endif
2498
2499#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002500 /* This is the default code that works on every CPU and every
2501 * endianness with no dependency on ntoh(). This works on CPUs
2502 * that either allow or do not allow unaligned access. It will
2503 * always work, but usually is a little less efficient than ntoh().
2504 */
Michael Eckel5c531332020-03-02 01:35:30 +01002505
2506 return ((uint64_t)pResult[0]<<56) +
2507 ((uint64_t)pResult[1]<<48) +
2508 ((uint64_t)pResult[2]<<40) +
2509 ((uint64_t)pResult[3]<<32) +
2510 ((uint64_t)pResult[4]<<24) +
2511 ((uint64_t)pResult[5]<<16) +
2512 ((uint64_t)pResult[6]<<8) +
2513 (uint64_t)pResult[7];
2514#endif
2515}
2516
2517
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002518#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002519static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2520{
2521 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2522
2523 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2524}
2525
2526
2527static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2528{
2529 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2530
2531 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2532}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002533#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002534
2535
2536static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2537{
2538 return pMe->err;
2539}
2540
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002541
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002542static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002543{
2544 pMe->UB.len = uNewLen;
2545}
2546
2547
Michael Eckel5c531332020-03-02 01:35:30 +01002548#ifdef __cplusplus
2549}
2550#endif
2551
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002552#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002553
2554