blob: eb0a69141be5a8530b73722347b3de858c04b184 [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
3 * Copyright (c) 2018-2022, Laurence Lundblade.
4 * Copyright (c) 2021, Arm Limited. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Michael Eckel5c531332020-03-02 01:35:30 +010033
34/*============================================================================
35 FILE: UsefulBuf.h
36
37 DESCRIPTION: General purpose input and output buffers
38
39 EDIT HISTORY FOR FILE:
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44 when who what, where, why
45 -------- ---- --------------------------------------------------
Laurence Lundbladed6e13022023-11-26 10:14:02 -070046 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
47 19/11/2023 llundblade Add UsefulOutBuf_Swap().
48 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070049 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060050 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070051 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070052 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070053 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080054 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070055 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010056 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
57 5/21/2019 llundblade #define configs for efficient endianness handling.
58 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
59 3/23/2019 llundblade Big documentation & style update. No interface
60 change.
61 3/6/2019 llundblade Add UsefulBuf_IsValue()
62 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
63 12/13/2018 llundblade Documentation improvements
64 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
65 UsefulBufC.
66 02/02/18 llundbla Full support for integers in and out; fix pointer
67 alignment bug. Incompatible change: integers
68 in/out are now in network byte order.
69 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
70 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
71 comparison for < or > for unequal length buffers.
72 Added UsefulBuf_Set() function.
73 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
74 11/13/16 llundbla Initial Version.
75
76 =============================================================================*/
77
78#ifndef _UsefulBuf_h
79#define _UsefulBuf_h
80
81
82/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070083 * Endianness Configuration
84 *
85 * This code is written so it will work correctly on big- and
86 * little-endian CPUs without configuration or any auto-detection of
87 * endianness. All code here will run correctly regardless of the
88 * endianness of the CPU it is running on.
89 *
90 * There are four C preprocessor macros that can be set with #define
91 * to explicitly configure endianness handling. Setting them can
92 * reduce code size a little and improve efficiency a little.
93 *
94 * Note that most of QCBOR is unaffected by this configuration. Its
95 * endianness handling is integrated with the code that handles
96 * alignment and preferred serialization. This configuration does
97 * affect QCBOR's (planned) implementation of integer arrays (tagged
98 * arrays) and use of the functions here to serialize or deserialize
99 * integers and floating-point values.
100 *
101 * Following is the recipe for configuring the endianness-related
102 * #defines.
103 *
104 * The first option is to not define anything. This will work fine
105 * with all CPUs, OS's and compilers. The code for encoding integers
106 * may be a little larger and slower.
107 *
108 * If your CPU is big-endian then define
109 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
110 * for big-endian CPUs. It will be small and efficient because there
111 * will be no byte swapping.
112 *
113 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
114 * OS's and compilers, but not all. On big-endian CPUs this should
115 * give the most efficient code, the same as
116 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
117 * call the system-defined byte swapping method which is presumably
118 * implemented efficiently. In some cases, this will be a dedicated
119 * byte swap instruction like Intel's bswap.
120 *
121 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
122 * little-endian, it is also good to define
123 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
124 *
125 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
126 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
127 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
128 * system-defined byte swap method. However, note
129 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
130 * this is fixed now. Often hton() and ntoh() will call the built-in
131 * __builtin_bswapXX()() function, so this size issue could affect
132 * USEFULBUF_CONFIG_HTON.
133 *
134 * Last, run the tests. They must all pass.
135 *
136 * These #define config options affect the inline implementation of
137 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
138 * also affect the 16-, 32-bit, float and double versions of these
139 * functions. Since they are inline, the size effect is not in the
140 * UsefulBuf object code, but in the calling code.
141 *
142 * Summary:
143 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
144 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
145 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
146 * handle big and little-endian with system option.
147 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
148 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200149 *
150 * It is possible to run this code in environments where using floating point is
151 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
152 * that is related to handling floating point types, along with related
153 * interfaces. This makes it possible to compile the code with the compile
154 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100155 */
156
157#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
158#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
159#endif
160
161
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700162#include <stdint.h> /* for uint8_t, uint16_t.... */
163#include <string.h> /* for strlen, memcpy, memmove, memset */
164#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100165
166
167#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700168#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100169#endif
170
171#ifdef __cplusplus
172extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700173#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700174} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700175#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100176#endif
177
178/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700179 * @file UsefulBuf.h
180 *
181 * The goal of this code is to make buffer and pointer manipulation
182 * easier and safer when working with binary data.
183 *
184 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
185 * structures are used to represent buffers rather than ad hoc
186 * pointers and lengths.
187 *
188 * With these it is possible to write code that does little or no
189 * direct pointer manipulation for copying and formatting data. For
190 * example, the QCBOR encoder was written using these and has less
191 * pointer manipulation.
192 *
193 * While it is true that object code using these functions will be a
194 * little larger and slower than a white-knuckle clever use of
195 * pointers might be, but not by that much or enough to have an effect
196 * for most use cases. For security-oriented code this is highly
197 * worthwhile. Clarity, simplicity, reviewability and are more
198 * important.
199 *
200 * There are some extra sanity and double checks in this code to help
201 * catch coding errors and simple memory corruption. They are helpful,
202 * but not a substitute for proper code review, input validation and
203 * such.
204 *
205 * This code consists of a lot of inline functions and a few that are
206 * not. It should not generate very much object code, especially with
207 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100208 */
209
210
211/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700212 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
213 * hold a pointer and length for binary data. In C99 this data
214 * structure can be passed on the stack making a lot of code cleaner
215 * than carrying around a pointer and length as two parameters.
216 *
217 * This is also conducive to secure coding practice as the length is
218 * always carried with the pointer and the convention for handling a
219 * pointer and a length is clear.
220 *
221 * While it might be possible to write buffer and pointer code more
222 * efficiently in some use cases, the thought is that unless there is
223 * an extreme need for performance (e.g., you are building a
224 * gigabit-per-second IP router), it is probably better to have
225 * cleaner code you can be most certain about the security of.
226 *
227 * The non-const @ref UsefulBuf is usually used to refer an empty
228 * buffer to be filled in. The length is the size of the buffer.
229 *
230 * The const @ref UsefulBufC is usually used to refer to some data
231 * that has been filled in. The length is amount of valid data pointed
232 * to.
233 *
234 * A common use mode is to pass a @ref UsefulBuf to a function, the
235 * function puts some data in it, then the function returns a @ref
236 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
237 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
238 * so the constness stays correct. There is no single "in,out"
239 * parameter (if there was, it would have to be non-const). Note that
240 * the pointer returned in the @ref UsefulBufC usually ends up being
241 * the same pointer passed in as a @ref UsefulBuf, though this is not
242 * striclty required.
243 *
244 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
245 * @c NULL.
246 *
247 * There are functions and macros for the following:
248 * - Initializing
249 * - Create initialized const @ref UsefulBufC from compiler literals
250 * - Create initialized const @ref UsefulBufC from NULL-terminated string
251 * - Make an empty @ref UsefulBuf on the stack
252 * - Checking whether a @ref UsefulBuf is null, empty or both
253 * - Copying, copying with offset, copying head or tail
254 * - Comparing and finding substrings
255 *
256 * See also @ref UsefulOutBuf. It is a richer structure that has both
257 * the size of the valid data and the size of the buffer.
258 *
259 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
260 * it can go on the stack and be a function parameter or return value.
261 *
262 * Another way to look at it is this. C has the NULL-terminated string
263 * as a means for handling text strings, but no means or convention
264 * for binary strings. Other languages do have such means, Rust, an
265 * efficient compiled language, for example.
266 *
267 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
268 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
269 * out like anything".
270 */
Michael Eckel5c531332020-03-02 01:35:30 +0100271typedef struct q_useful_buf_c {
272 const void *ptr;
273 size_t len;
274} UsefulBufC;
275
276
277/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700278 * This non-const @ref UsefulBuf is typically used for some allocated
279 * memory that is to be filled in. The @c len is the amount of memory,
280 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100281 */
282typedef struct q_useful_buf {
283 void *ptr;
284 size_t len;
285} UsefulBuf;
286
287
288/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700289 * A null @ref UsefulBufC is one that has no value in the same way a
290 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
291 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
292 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100293 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700294/*
295 * NULLUsefulBufC and few other macros have to be
296 * definied differently in C than C++ because there
297 * is no common construct for a literal structure.
298 *
299 * In C compound literals are used.
300 *
301 * In C++ list initalization is used. This only works
302 * in C++11 and later.
303 *
304 * Note that some popular C++ compilers can handle compound
305 * literals with on-by-default extensions, however
306 * this code aims for full correctness with strict
307 * compilers so they are not used.
308 */
309#ifdef __cplusplus
310#define NULLUsefulBufC {NULL, 0}
311#else
312#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
313#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100314
315/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700316 * A null @ref UsefulBuf is one that has no memory associated the same
317 * way @c NULL points to nothing. It does not matter what @c len is.
318 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700319#ifdef __cplusplus
320#define NULLUsefulBuf {NULL, 0}
321#else
322#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
323#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100324
325
326/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700327 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
328 *
329 * @param[in] UB The UsefulBuf to check.
330 *
331 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100332 */
333static inline int UsefulBuf_IsNULL(UsefulBuf UB);
334
335
336/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700337 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
338 *
339 * @param[in] UB The @ref UsefulBufC to check.
340 *
341 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100342 */
343static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
344
345
346/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700347 * @brief Check if a @ref UsefulBuf is empty or not.
348 *
349 * @param[in] UB The @ref UsefulBuf to check.
350 *
351 * @return 1 if it is empty, 0 if not.
352 *
353 * An "empty" @ref UsefulBuf is one that has a value and can be
354 * considered to be set, but that value is of zero length. It is
355 * empty when @c len is zero. It doesn't matter what the @c ptr is.
356 *
357 * Many uses will not need to clearly distinguish a @c NULL @ref
358 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
359 * @c len 0. However if a use of @ref UsefulBuf needs to make a
360 * distinction then @c ptr should not be @c NULL when the @ref
361 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100362 */
363static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
364
365
366/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700367 * @brief Check if a @ref UsefulBufC is empty or not.
368 *
369 * @param[in] UB The @ref UsefulBufC to check.
370 *
371 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100372 */
373static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
374
375
376/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700377 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
378 *
379 * @param[in] UB The @ref UsefulBuf to check.
380 *
381 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100382 */
383static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
384
385
386/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700387 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
388 *
389 * @param[in] UB The @ref UsefulBufC to check.
390 *
391 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100392 */
393static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
394
395
396/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700397 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
398 *
399 * @param[in] UB The @ref UsefulBuf to convert.
400 *
401 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100402 */
403static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
404
405
406/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700407 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
408 *
409 * @param[in] UBC The @ref UsefulBuf to convert.
410 *
411 * @return A non-const @ref UsefulBuf struct.
412 *
413 * Use of this is not necessary for the intended use mode of @ref
414 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
415 * created to describe a buffer that has not had any data put in
416 * it. Then the data is put in it. Then a @ref UsefulBufC is create
417 * to describe the part with the data in it. This goes from non-const
418 * to const, so this function is not needed.
419 *
420 * If the -Wcast-qual warning is enabled, this function can be used to
421 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100422 */
423static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
424
425
426/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700427 * Convert a literal string to a @ref UsefulBufC.
428 *
429 * @c szString must be a literal string that @c sizeof() works on.
430 * This is better for literal strings than UsefulBuf_FromSZ() because
431 * it generates less code. It will not work on non-literal strings.
432 *
433 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100434 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700435#ifdef __cplusplus
436#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
437#else
Michael Eckel5c531332020-03-02 01:35:30 +0100438#define UsefulBuf_FROM_SZ_LITERAL(szString) \
439 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700440#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100441
442
443/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700444 * Convert a literal byte array to a @ref UsefulBufC.
445 *
446 * @c pBytes must be a literal string that @c sizeof() works on. It
447 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100448 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700449#ifdef __cplusplus
450#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
451#else
Michael Eckel5c531332020-03-02 01:35:30 +0100452#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700453 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
454#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100455
456/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700457 * Make an automatic variable named @c name of type @ref UsefulBuf and
458 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100459 */
460#define UsefulBuf_MAKE_STACK_UB(name, size) \
461 uint8_t __pBuf##name[(size)];\
462 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
463
464
465/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700466 * Make a byte array in to a @ref UsefulBuf. This is usually used on
467 * stack variables or static variables. Also see @ref
468 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100469 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700470#ifdef __cplusplus
471#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
472#else
Michael Eckel5c531332020-03-02 01:35:30 +0100473#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700474 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
475#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100476
477
478/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700479 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
480 *
481 * @param[in] szString The string to convert.
482 *
483 * @return A @ref UsefulBufC struct.
484 *
485 * @c UsefulBufC.ptr points to the string so its lifetime must be
486 * maintained.
487 *
488 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100489 */
490static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
491
492
493/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700494 * @brief Copy one @ref UsefulBuf into another at an offset.
495 *
496 * @param[in] Dest Destination buffer to copy into.
497 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
498 * @param[in] Src The bytes to copy.
499 *
500 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
501 *
502 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
503 * size of @c Dest.
504 *
505 * This fails and returns @ref NULLUsefulBufC if the @c Src length
506 * plus @c uOffset is greater than the length of @c Dest.
507 *
508 * The results are undefined if @c Dest and @c Src overlap.
509 *
510 * This assumes that there is valid data in @c Dest up to @c
511 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
512 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100513 */
514UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
515
516
517/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700518 * @brief Copy one @ref UsefulBuf into another.
519 *
520 * @param[in] Dest The destination buffer to copy into.
521 * @param[out] Src The source to copy from.
522 *
523 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
524 * on failure.
525 *
526 * This fails if @c Src.len is greater than @c Dest.len.
527 *
528 * Note that like @c memcpy(), the pointers are not checked and this
529 * will crash rather than return @ref NULLUsefulBufC if they are @c
530 * NULL or invalid.
531 *
532 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100533 */
534static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
535
536
537/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700538 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
539 *
540 * @param[in] pDest The destination buffer to copy into.
541 * @param[in] value The value to set the bytes to.
542 *
543 * Note that like @c memset(), the pointer in @c pDest is not checked
544 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100545 */
546static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
547
548
549/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700550 * @brief Copy a pointer into a @ref UsefulBuf.
551 *
552 * @param[in,out] Dest The destination buffer to copy into.
553 * @param[in] ptr The source to copy from.
554 * @param[in] uLen Length of the source; amount to copy.
555 *
556 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
557 * on failure.
558 *
559 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
560 * than @c pDest->len.
561 *
562 * Note that like @c memcpy(), the pointers are not checked and this
563 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100564 */
565static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
566 const void *ptr,
567 size_t uLen);
568
569
570/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700571 * @brief Returns a truncation of a @ref UsefulBufC.
572 *
573 * @param[in] UB The buffer to get the head of.
574 * @param[in] uAmount The number of bytes in the head.
575 *
576 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100577 */
578static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
579
580
581/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700582 * @brief Returns bytes from the end of a @ref UsefulBufC.
583 *
584 * @param[in] UB The buffer to get the tail of.
585 * @param[in] uAmount The offset from the start where the tail is to begin.
586 *
587 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
588 * if @c uAmount is greater than the length of the @ref UsefulBufC.
589 *
590 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
591 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
592 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100593 */
594static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
595
596
597/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700598 * @brief Compare one @ref UsefulBufC to another.
599 *
600 * @param[in] UB1 The first buffer to compare.
601 * @param[in] UB2 The second buffer to compare.
602 *
603 * @return 0, positive or negative value.
604 *
605 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
606 * less than @c UB2 if it is shorter or the first byte that is not the
607 * same is less.
608 *
609 * Returns 0 if the inputs are the same.
610 *
611 * Returns a positive value if @c UB2 is less than @c UB1.
612 *
613 * All that is of significance is that the result is positive, negative
614 * or 0. (This doesn't return the difference between the first
615 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100616 */
617int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
618
619
620/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700621 * @brief Find first byte that is not a particular byte value.
622 *
623 * @param[in] UB The destination buffer for byte comparison.
624 * @param[in] uValue The byte value to compare to.
625 *
626 * @return Offset of first byte that isn't @c uValue or
627 * @c SIZE_MAX if all bytes are @c uValue.
628 *
629 * Note that unlike most comparison functions, 0
630 * does not indicate a successful comparison, so the
631 * test for match is:
632 *
633 * UsefulBuf_IsValue(...) == SIZE_MAX
634 *
635 * If @c UB is null or empty, there is no match
636 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100637 */
638size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
639
640
641/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700642 * @brief Find one @ref UsefulBufC in another.
643 *
644 * @param[in] BytesToSearch Buffer to search through.
645 * @param[in] BytesToFind Buffer with bytes to be found.
646 *
647 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100648 */
649size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
650
651
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700652/**
653 @brief Convert a pointer to an offset with bounds checking.
654
655 @param[in] UB Pointer to the UsefulInputBuf.
656 @param[in] p Pointer to convert to offset.
657
658 @return SIZE_MAX if @c p is out of range, the byte offset if not.
659*/
660static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
661
662
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800663#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100664/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700665#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100666
667/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
668#define MakeUsefulBufOnStack(name, size) \
669 uint8_t __pBuf##name[(size)];\
670 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
671
672/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
673#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700674 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100675
676/** Deprecated function; use UsefulBuf_Unconst() instead */
677static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
678{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700679 UsefulBuf UB;
680
Laurence Lundblade3eead482023-12-16 20:53:22 -0700681 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300682 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700683
684 UB.len = UBC.len;
685
686 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100687}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800688#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100689
690
691
692
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200693#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100694/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700695 * @brief Copy a @c float to a @c uint32_t.
696 *
697 * @param[in] f Float value to copy.
698 *
699 * @return A @c uint32_t with the float bits.
700 *
701 * Convenience function to avoid type punning, compiler warnings and
702 * such. The optimizer usually reduces this to a simple assignment. This
703 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100704 */
705static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
706
707
708/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700709 * @brief Copy a @c double to a @c uint64_t.
710 *
711 * @param[in] d Double value to copy.
712 *
713 * @return A @c uint64_t with the double bits.
714 *
715 * Convenience function to avoid type punning, compiler warnings and
716 * such. The optimizer usually reduces this to a simple assignment. This
717 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100718 */
719static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
720
721
722/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700723 * @brief Copy a @c uint32_t to a @c float.
724 *
725 * @param[in] u32 Integer value to copy.
726 *
727 * @return The value as a @c float.
728 *
729 * Convenience function to avoid type punning, compiler warnings and
730 * such. The optimizer usually reduces this to a simple assignment. This
731 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100732 */
733static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
734
735
736/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700737 * @brief Copy a @c uint64_t to a @c double.
738 *
739 * @param[in] u64 Integer value to copy.
740 *
741 * @return The value as a @c double.
742 *
743 * Convenience function to avoid type punning, compiler warnings and
744 * such. The optimizer usually reduces this to a simple assignment. This
745 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100746 */
747static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200748#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100749
750
751
752
753/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700754 * UsefulOutBuf is a structure and functions (an object) for
755 * serializing data into a buffer to encode for a network protocol or
756 * write data to a file.
757 *
758 * The main idea is that all the pointer manipulation is performed by
759 * @ref UsefulOutBuf functions so the caller doesn't have to do any
760 * pointer manipulation. The pointer manipulation is centralized.
761 * This code has been reviewed and written carefully so it
762 * spares the caller of much of this work and results in safer code
763 * with less effort.
764 *
765 * The @ref UsefulOutBuf methods that add data to the output buffer
766 * always check the length and will never write off the end of the
767 * output buffer. If an attempt to add data that will not fit is made,
768 * an internal error flag will be set and further attempts to add data
769 * will not do anything.
770 *
771 * There is no way to ever write off the end of that buffer when
772 * calling the @c UsefulOutBuf_AddXxx() and
773 * @c UsefulOutBuf_InsertXxx() functions.
774 *
775 * The functions to add data do not report success of failure. The
776 * caller only needs to check for an error in the final call, either
777 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
778 * result. This makes the calling code cleaner.
779 *
780 * There is a utility function to get the error status anytime along
781 * the way for a special circumstance. There are functions to see how
782 * much room is left and see if some data will fit too, but their use
783 * is generally unnecessary.
784 *
785 * The general call flow is:
786 *
787 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
788 * buffer given to it can be from the heap, stack or
789 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
790 * macro that makes a buffer on the stack and initializes it.
791 *
792 * - Call methods like UsefulOutBuf_InsertString(),
793 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
794 * to output data. The append calls add data to the end of the
795 * valid data. The insert calls take a position argument.
796 *
797 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
798 * there were no errors and to get the serialized output bytes.
799 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700800 * @ref UsefulOutBuf can be used in a mode to calculate the size of
801 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700802 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700803 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700804 *
805 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700806 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700807 *
808 * The possible errors are:
809 *
810 * - The @ref UsefulOutBuf was not initialized or was corrupted.
811 *
812 * - An attempt was made to add data that will not fit.
813 *
814 * - An attempt was made to insert data at a position beyond the end of
815 * the buffer.
816 *
817 * - An attempt was made to insert data at a position beyond the valid
818 * data in the buffer.
819 *
820 * Some inexpensive simple sanity checks are performed before every
821 * data addition to guard against use of an uninitialized or corrupted
822 * UsefulOutBuf.
823 *
824 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
825 * encoder has almost no pointer manipulation in it, is easier to
826 * read, and easier to review.
827 *
828 * A @ref UsefulOutBuf is small and can go on the stack:
829 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
830 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100831 */
832typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700833 /* PRIVATE DATA STRUCTURE */
834 UsefulBuf UB; /* Memory that is being output to */
835 size_t data_len; /* length of the valid data, the insertion point */
836 uint16_t magic; /* Used to detect corruption and lack
837 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100838 uint8_t err;
839} UsefulOutBuf;
840
841
842/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700843 * This is a @ref UsefulBuf value that can be passed to
844 * UsefulOutBuf_Init() to have it calculate the size of the output
845 * buffer needed. Pass this for @c Storage, call all the append and
846 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
847 * returned @ref UsefulBufC has the size.
848 *
849 * As one can see, this is just a NULL pointer and very large size.
850 * The NULL pointer tells UsefulOutputBuf to not copy any data.
851 */
852#ifdef __cplusplus
853#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
854#else
855#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
856#endif
857
858
859/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700860 * @brief Initialize and supply the output buffer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700861 *
862 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
863 * @param[in] Storage Buffer to output into.
864 *
865 * This initializes the @ref UsefulOutBuf with storage, sets the
866 * current position to the beginning of the buffer and clears the
867 * error state.
868 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700869 * See @ref SizeCalculateUsefulBuf for instructions on how to
870 * initialize a @ref UsefulOutBuf to calculate the size that would be
871 * output without actually outputting.
872 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700873 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100874 */
875void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
876
877
878/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700879 * Convenience macro to make a @ref UsefulOutBuf on the stack and
880 * initialize it with a stack buffer of the given size. The variable
881 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100882 */
883#define UsefulOutBuf_MakeOnStack(name, size) \
884 uint8_t __pBuf##name[(size)];\
885 UsefulOutBuf name;\
886 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
887
888
889/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700890 * @brief Reset a @ref UsefulOutBuf for re use.
891 *
892 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
893 *
894 * This sets the amount of data in the output buffer to none and
895 * clears the error state.
896 *
897 * The output buffer is still the same one and size as from the
898 * UsefulOutBuf_Init() call.
899 *
900 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100901 */
902static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
903
904
905/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700906 * @brief Returns position of end of data in the @ref UsefulOutBuf.
907 *
908 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
909 *
910 * @return position of end of data.
911 *
912 * On a freshly initialized @ref UsefulOutBuf with no data added, this
913 * will return 0. After 10 bytes have been added, it will return 10
914 * and so on.
915 *
916 * Generally, there is no need to call this for most uses of @ref
917 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100918 */
919static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
920
921
922/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700923 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
924 *
925 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
926 *
927 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100928 */
929static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
930
931
932/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700933 * @brief Inserts bytes into the @ref UsefulOutBuf.
934 *
935 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
936 * @param[in] NewData The bytes to insert.
937 * @param[in] uPos Index in output buffer at which to insert.
938 *
939 * @c NewData is the pointer and length for the bytes to be added to
940 * the output buffer. There must be room in the output buffer for all
941 * of @c NewData or an error will occur.
942 *
943 * The insertion point must be between 0 and the current valid
944 * data. If not, an error will occur. Appending data to the output
945 * buffer is achieved by inserting at the end of the valid data. This
946 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
947 *
948 * When insertion is performed, the bytes between the insertion point
949 * and the end of data previously added to the output buffer are slid
950 * to the right to make room for the new data.
951 *
952 * Overlapping buffers are OK. @c NewData can point to data in the
953 * output buffer.
954 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700955 * NewData.len may be 0 in which case nothing will be inserted.
956 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700957 * If an error occurs, an error state is set in the @ref
958 * UsefulOutBuf. No error is returned. All subsequent attempts to add
959 * data will do nothing.
960 *
961 * The intended use is that all additions are made without checking
962 * for an error. The error will be taken into account when
963 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
964 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100965 */
966void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
967 UsefulBufC NewData,
968 size_t uPos);
969
970
971/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700972 * @brief Insert a data buffer into the @ref UsefulOutBuf.
973 *
974 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
975 * @param[in] pBytes Pointer to the bytes to insert
976 * @param[in] uLen Length of the bytes to insert
977 * @param[in] uPos Index in output buffer at which to insert
978 *
979 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
980 * the difference being a pointer and length is passed in rather than an
981 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100982 */
983static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
984 const void *pBytes,
985 size_t uLen,
986 size_t uPos);
987
988
989/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700990 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
991 *
992 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
993 * @param[in] szString NULL-terminated string to insert.
994 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100995 */
996static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
997 const char *szString,
998 size_t uPos);
999
1000
1001/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001002 * @brief Insert a byte into the @ref UsefulOutBuf.
1003 *
1004 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1005 * @param[in] byte Bytes to insert.
1006 * @param[in] uPos Index in output buffer at which to insert.
1007 *
1008 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1009 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001010 */
1011static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1012 uint8_t byte,
1013 size_t uPos);
1014
1015
1016/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001017 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1018 *
1019 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1020 * @param[in] uInteger16 Integer to insert.
1021 * @param[in] uPos Index in output buffer at which to insert.
1022 *
1023 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1024 * with the difference being a two-byte integer is to be inserted.
1025 *
1026 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001027 */
1028static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1029 uint16_t uInteger16,
1030 size_t uPos);
1031
1032
1033/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001034 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1035 *
1036 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1037 * @param[in] uInteger32 Integer to insert.
1038 * @param[in] uPos Index in output buffer at which to insert.
1039 *
1040 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1041 * with the difference being a four-byte integer is to be inserted.
1042 *
1043 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001044 */
1045static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1046 uint32_t uInteger32,
1047 size_t uPos);
1048
1049
1050/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001051 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1052 *
1053 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1054 * @param[in] uInteger64 Integer to insert.
1055 * @param[in] uPos Index in output buffer at which to insert.
1056 *
1057 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1058 * with the difference being an eight-byte integer is to be inserted.
1059 *
1060 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001061 */
1062static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1063 uint64_t uInteger64,
1064 size_t uPos);
1065
1066
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001067#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001068/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001069 * @brief Insert a @c float into the @ref UsefulOutBuf.
1070 *
1071 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1072 * @param[in] f @c float to insert.
1073 * @param[in] uPos Index in output buffer at which to insert.
1074 *
1075 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1076 * with the difference being a @c float is to be inserted.
1077 *
1078 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001079 */
1080static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1081 float f,
1082 size_t uPos);
1083
1084
1085/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001086 * @brief Insert a @c double into the @ref UsefulOutBuf.
1087 *
1088 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1089 * @param[in] d @c double to insert.
1090 * @param[in] uPos Index in output buffer at which to insert.
1091 *
1092 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1093 * with the difference being a @c double is to be inserted.
1094 *
1095 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001096 */
1097static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1098 double d,
1099 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001100#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001101
1102
1103/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001104 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1105 *
1106 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1107 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1108 *
1109 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1110 * with the insertion point at the end of the valid data.
1111 */
Michael Eckel5c531332020-03-02 01:35:30 +01001112static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1113 UsefulBufC NewData);
1114
1115
1116/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001117 * @brief Append bytes to the @ref UsefulOutBuf.
1118 *
1119 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1120 * @param[in] pBytes Pointer to bytes to append.
1121 * @param[in] uLen Length of @c pBytes to append.
1122 *
1123 * See UsefulOutBuf_InsertData() for details. This does the same with
1124 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001125 */
1126static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1127 const void *pBytes,
1128 size_t uLen);
1129
1130
1131/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001132 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1133 *
1134 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1135 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001136 */
1137static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1138 const char *szString);
1139
1140
1141/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001142 * @brief Append a byte to the @ref UsefulOutBuf
1143 *
1144 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1145 * @param[in] byte Bytes to append.
1146 *
1147 * See UsefulOutBuf_InsertByte() for details. This does the same
1148 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001149 */
1150static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1151 uint8_t byte);
1152
1153
1154/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001155 * @brief Append an integer to the @ref UsefulOutBuf
1156 *
1157 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1158 * @param[in] uInteger16 Integer to append.
1159 *
1160 * See UsefulOutBuf_InsertUint16() for details. This does the same
1161 * with the insertion point at the end of the valid data.
1162 *
1163 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001164 */
1165static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1166 uint16_t uInteger16);
1167
1168
1169/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001170 * @brief Append an integer to the @ref UsefulOutBuf
1171 *
1172 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1173 * @param[in] uInteger32 Integer to append.
1174 *
1175 * See UsefulOutBuf_InsertUint32() for details. This does the same
1176 * with the insertion point at the end of the valid data.
1177 *
1178 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001179 */
1180static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1181 uint32_t uInteger32);
1182
1183
1184/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001185 * @brief Append an integer to the @ref UsefulOutBuf
1186 *
1187 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1188 * @param[in] uInteger64 Integer to append.
1189 *
1190 * See UsefulOutBuf_InsertUint64() for details. This does the same
1191 * with the insertion point at the end of the valid data.
1192 *
1193 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001194 */
1195static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1196 uint64_t uInteger64);
1197
1198
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001199#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001200/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001201 * @brief Append a @c float to the @ref UsefulOutBuf
1202 *
1203 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1204 * @param[in] f @c float to append.
1205 *
1206 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1207 * the insertion point at the end of the valid data.
1208 *
1209 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001210 */
1211static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1212 float f);
1213
1214
1215/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001216 * @brief Append a @c double to the @ref UsefulOutBuf
1217 *
1218 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1219 * @param[in] d @c double to append.
1220 *
1221 * See UsefulOutBuf_InsertDouble() for details. This does the same
1222 * with the insertion point at the end of the valid data.
1223 *
1224 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001225 */
1226static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1227 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001228#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001229
1230
1231/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001232 * @brief Returns the current error status.
1233 *
1234 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1235 *
1236 * @return 0 if all OK, 1 on error.
1237 *
1238 * This returns the error status since a call to either
1239 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1240 * goes into the error state, it will stay until one of those
1241 * functions is called.
1242 *
1243 * Possible error conditions are:
1244 * - bytes to be inserted will not fit
1245 * - insertion point is out of buffer or past valid data
1246 * - current position is off end of buffer (probably corrupted or uninitialized)
1247 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001248 */
1249static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1250
1251
1252/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001253 * @brief Returns number of bytes unused used in the output buffer.
1254 *
1255 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1256 *
1257 * @return Number of unused bytes or zero.
1258 *
1259 * Because of the error handling strategy and checks in
1260 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1261 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001262 */
1263static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1264
1265
1266/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001267 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1268 *
1269 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1270 * @param[in] uLen Number of bytes for which to check
1271 *
1272 * @return 1 if @c uLen bytes will fit, 0 if not.
1273 *
1274 * Because of the error handling strategy and checks in
1275 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1276 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001277 */
1278static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1279
1280
1281 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001282 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1283 *
1284 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1285 *
1286 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1287 *
1288 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1289 * just calculating the length of the encoded data.
1290 */
Michael Eckel5c531332020-03-02 01:35:30 +01001291static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1292
1293
1294/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001295 * @brief Returns pointer and length of the output buffer not yet used.
1296 *
1297 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1298 *
1299 * @return pointer and length of output buffer not used.
1300 *
1301 * This is an escape that allows the caller to write directly
1302 * to the output buffer without any checks. This doesn't
1303 * change the output buffer or state. It just returns a pointer
1304 * and length of the bytes remaining.
1305 *
1306 * This is useful to avoid having the bytes to be added all
1307 * in a contiguous buffer. Its use can save memory. A good
1308 * example is in the COSE encrypt implementation where
1309 * the output of the symmetric cipher can go directly
1310 * into the output buffer, rather than having to go into
1311 * an intermediate buffer.
1312 *
1313 * See UsefulOutBuf_Advance() which is used to tell
1314 * UsefulOutBuf how much was written.
1315 *
1316 * Warning: this bypasses the buffer safety provided by
1317 * UsefulOutBuf!
1318 */
1319static inline UsefulBuf
1320UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1321
1322
1323/**
1324 * @brief Advance the amount output assuming it was written by the caller.
1325 *
1326 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1327 * @param[in] uAmount The amount to advance.
1328 *
1329 * This advances the position in the output buffer
1330 * by \c uAmount. This assumes that the
1331 * caller has written \c uAmount to the pointer obtained
1332 * with UsefulOutBuf_GetOutPlace().
1333 *
1334 * Warning: this bypasses the buffer safety provided by
1335 * UsefulOutBuf!
1336 */
1337void
1338UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1339
1340
1341/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001342 * @brief Returns the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001343 *
1344 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1345 *
1346 * @return The valid data in @ref UsefulOutBuf or
1347 * @ref NULLUsefulBufC if there was an error adding data.
1348 *
1349 * The storage for the returned data is the @c Storage parameter
1350 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1351 *
1352 * This can be called anytime and many times to get intermediate
1353 * results. It doesn't change the data or reset the current position,
1354 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001355 */
1356UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1357
1358
1359/**
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001360 * @brief Copy out the data put into a UsefulOutBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001361 *
1362 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1363 * @param[out] Dest The destination buffer to copy into.
1364 *
1365 * @return Pointer and length of copied data or @c NULLUsefulBufC
1366 * if it will not fit in the @c Dest buffer or the error
1367 * state was entered.
1368 *
1369 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001370 * data to @c Dest rather than returning a pointer.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001371 */
Michael Eckel5c531332020-03-02 01:35:30 +01001372UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1373
1374
Laurence Lundbladed6e13022023-11-26 10:14:02 -07001375/**
1376 * @brief Returns data starting at an offset that was put into a UsefulOutBuf.
1377 *
1378 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1379 * @param[in] uOffset Offset to bytes to return.
1380 *
1381 * @return NULLUsefulBufC or the bytes at the offset.
1382 *
1383 * This is the same as UsefulOutBuf_OutUBuf() except a starting offset
1384 * maybe specified. It returns the bytes starting at @c uOffset to the
1385 * end of what was encoded so far. Calling this with @c uOffset 0 is
1386 * equivalent to UsefulOutBuf_OutUBuf().
1387 *
1388 * If there's nothing at @c uOffset or it is past the in the output
1389 * buffer, a \ref NULLUsefulBufC is returned.
1390 *
1391 * This is typically not needed in typical use. It is used by QCBOR
1392 * along with UsefulOutBuf_Compare() and UsefulOutBuf_Swap() for
1393 * sorting CBOR maps.
1394 */
1395UsefulBufC
1396UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pUOutBuf, size_t uOffset);
1397
1398
1399/**
1400 * @brief Compare bytes at offsets.
1401 *
1402 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1403 * @param[in] uStart1 Offset of first bytes to compare.
1404 * @param[in] uStart2 Offset of second bytes to compare.
1405 *
1406 * @return 0 for equality, positive if uStart1 is lexographically larger,
1407 * negative if uStart2 is lexographically larger.
1408 *
1409 * This looks into bytes that have been output at the offsets @c start1
1410 * and @c start2. It compares bytes at those two starting points until
1411 * they are not equal or the end of the output data is reached from
1412 * one of the starting points.
1413 *
1414 * This returns positive when @c uStart1 lexographically sorts ahead
1415 * of @c uStart2 and vice versa. Zero is returned if the strings
1416 * compare equally. This only happens when the end of the valid data
1417 * is reached from one of the starting points and the comparison up to
1418 * that point is equality.
1419 *
1420 * If either start is past the end of data in the output buffer, 0
1421 * will be returned. It is the caller's responsibility to make sure
1422 * the offsets are not off the end such that a comparison is actually
1423 * being made. No data will ever be read off the end of the buffer so
1424 * this safe no matter what offsets are passed.
1425 *
1426 * This is a relatively odd function in that it works on data in the
1427 * output buffer. It is employed by QCBOR to sort CBOR-encoded maps that
1428 * are in the output buffer.
1429 */
1430int UsefulOutBuf_Compare(UsefulOutBuf *pUOutBuf, size_t uStart1, size_t uStart2);
1431
1432
1433/**
1434 * @brief Swap two regions of output bytes.
1435 *
1436 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1437 * @param[in] uStartOffset Offset to start of bytes to be swapped.
1438 * @param[in] uPivotOffset Offset to pivot around which bytes are swapped.
1439 * @param[in] uEndOffset Offset to end of region to be swappe.
1440 *
1441 * This reaches into bytes that have been output and swaps two
1442 * adjacent regions.
1443 *
1444 * If any of the offsets are outside the range of valid data, no
1445 * swapping will be performed. If the start is not the smallest and
1446 * the pivot is not in the middle no swapping will be performed.
1447 *
1448 * The byte at @c uStartOffset will participate in the swapping. The
1449 * byte at @c uEndOffset will not participate in the swapping, only
1450 * the byte before it.
1451 *
1452 * This is a relatively odd function in that it works on data in the
1453 * output buffer. It is employed by QCBOR to bubble sort encoded CBOR
1454 * maps.
1455 */
1456void UsefulOutBuf_Swap(UsefulOutBuf *pUOutBuf,
1457 size_t uStartOffset,
1458 size_t uPivotOffset,
1459 size_t uEndOffset);
1460
1461
Michael Eckel5c531332020-03-02 01:35:30 +01001462
1463
1464/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001465 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1466 * for parsing data received. Initialize it with the data from the
1467 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1468 * get data chunks of various types. A position cursor is maintained
1469 * internally.
1470 *
1471 * As long as the functions here are used, there will never be any
1472 * reference off the end of the given buffer (except
1473 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1474 * called incorrectly, an attempt is made to seek off the end of the
1475 * buffer or such. This makes it easier to write safe and correct
1476 * code. For example, the QCBOR decoder implementation is safer and
1477 * easier to review through its use of @ref UsefulInputBuf.
1478 *
1479 * @ref UsefulInputBuf maintains an internal error state. The
1480 * intended use is fetching data chunks without any error checks until
1481 * the end. If there was any error, such as an attempt to fetch data
1482 * off the end, the error state is entered and no further data will be
1483 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1484 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1485 * null is not dereferenced, the error check can be put off until the
1486 * end, simplifying the calling code.
1487 *
1488 * The integer and float parsing expects network byte order (big
1489 * endian). Network byte order is what is used by TCP/IP, CBOR and
1490 * most internet protocols.
1491 *
1492 * Lots of inline functions are used to keep code size down. The
1493 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1494 * code size a lot. The only non-inline code is
1495 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1496 * @ref UsefulInputBuf doesn't add much code for all the messy
1497 * hard-to-get right issues with parsing binary protocols in C that it
1498 * solves.
1499 *
1500 * The parse context size is:
1501 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1502 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001503 */
1504typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001505 /* PRIVATE DATA STRUCTURE */
1506 UsefulBufC UB; /* Data being parsed */
1507 size_t cursor; /* Current offset in data being parse */
1508 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1509 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001510} UsefulInputBuf;
1511
1512#define UIB_MAGIC (0xB00F)
1513
1514
1515/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001516 * @brief Initialize the @ref UsefulInputBuf structure before use.
1517 *
1518 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1519 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001520 */
1521static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1522
1523
1524/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001525 * @brief Returns current position in input buffer.
1526 *
1527 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1528 *
1529 * @return Integer position of the cursor.
1530 *
1531 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001532 */
1533static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1534
1535
1536/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001537 * @brief Sets the current position in input buffer.
1538 *
1539 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1540 * @param[in] uPos Position to set to.
1541 *
1542 * If the position is off the end of the input buffer, the error state
1543 * is entered.
1544 *
1545 * Seeking to a valid position in the buffer will not reset the error
1546 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001547 */
1548static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1549
1550
1551/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001552 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1553 * the unconsumed bytes.
1554 *
1555 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1556 *
1557 * @return Number of bytes unconsumed or 0 on error.
1558 *
1559 * Returns 0 if the cursor is invalid or corruption of the
1560 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001561 */
1562static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1563
1564
1565/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001566 * @brief Check if there are unconsumed bytes.
1567 *
1568 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1569 * @param[in] uLen Number of bytes to check availability for.
1570 *
1571 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001572 */
1573static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1574
1575
1576/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001577 * @brief Convert a pointer to an offset with bounds checking.
1578 *
1579 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1580 * @param[in] p Pointer to convert to offset.
1581 *
1582 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1583 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001584static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1585
1586
1587/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001588 * @brief Get pointer to bytes out of the input buffer.
1589 *
1590 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1591 * @param[in] uNum Number of bytes to get.
1592 *
1593 * @return Pointer to bytes.
1594 *
1595 * This consumes @c uNum bytes from the input buffer. This returns a
1596 * pointer to the start of the @c uNum bytes.
1597 *
1598 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1599 * returned and the error state is entered.
1600 *
1601 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001602 */
1603const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1604
1605
1606/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001607 * @brief Get @ref UsefulBuf out of the input buffer.
1608 *
1609 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1610 * @param[in] uNum Number of bytes to get.
1611 *
1612 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1613 *
1614 * This consumes @c uNum bytes from the input buffer and returns the
1615 * pointer and length for them as a @ref UsefulBufC. The length
1616 * returned will always be @c uNum. The position cursor is advanced by
1617 * @c uNum bytes.
1618 *
1619 * If there are not @c uNum bytes in the input buffer, @ref
1620 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001621 */
1622static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1623
1624
1625/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001626 * @brief Get a byte out of the input buffer.
1627 *
1628 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1629 *
1630 * @return The byte.
1631 *
1632 * This consumes 1 byte from the input buffer, returns it and advances
1633 * the position cursor by 1.
1634 *
1635 * If there is not 1 byte in the buffer, 0 will be returned for the
1636 * byte and the error state is entered. To know if the 0 returned was
1637 * in error or the real value, the error state must be checked. If
1638 * possible, put this off until all values are retrieved to have
1639 * smaller and simpler code, but if not possible
1640 * UsefulInputBuf_GetError() can be called. Also, in the error state
1641 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1642 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001643 */
1644static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1645
1646
1647/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001648 * @brief Get a @c uint16_t out of the input buffer.
1649 *
1650 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1651 *
1652 * @return The @c uint16_t.
1653 *
1654 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1655 * a @c uint16_t and two bytes are consumed.
1656 *
1657 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001658 */
1659static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1660
1661
1662/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001663 * @brief Get a @c uint32_t out of the input buffer.
1664 *
1665 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1666 *
1667 * @return The @c uint32_t.
1668 *
1669 * See UsefulInputBuf_GetByte(). This works the same, except it
1670 * returns a @c uint32_t and four bytes are consumed.
1671 *
1672 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001673 */
1674static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1675
1676
1677/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001678 * @brief Get a @c uint64_t out of the input buffer.
1679 *
1680 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1681 *
1682 * @return The uint64_t.
1683 *
1684 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1685 * a @c uint64_t and eight bytes are consumed.
1686 *
1687 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001688 */
1689static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1690
1691
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001692#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001693/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001694 * @brief Get a float out of the input buffer.
1695 *
1696 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1697 *
1698 * @return The float.
1699 *
1700 * See UsefulInputBuf_GetByte(). This works the same, except it
1701 * returns a float and four bytes are consumed.
1702 *
1703 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001704 */
1705static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1706
1707
1708/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001709 * @brief Get a double out of the input buffer.
1710 *
1711 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1712 *
1713 * @return The double.
1714 *
1715 * See UsefulInputBuf_GetByte(). This works the same, except it
1716 * returns a double and eight bytes are consumed.
1717 *
1718 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001719 */
1720static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001721#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001722
1723
1724/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001725 * @brief Get the error status.
1726 *
1727 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1728 *
1729 * @return 0 if not in the error state, 1 if in the error state.
1730 *
1731 * This returns whether the @ref UsefulInputBuf is in the
1732 * error state or not.
1733 *
1734 * The error state is entered for one of these reasons:
1735 * - Attempt to fetch data past the end of the buffer
1736 * - Attempt to seek to a position past the end of the buffer
1737 * - Attempt to get data from an uninitialized or corrupt instance
1738 * of @ref UsefulInputBuf
1739 *
1740 * Once in the error state, it can only be cleared by calling
1741 * UsefulInputBuf_Init().
1742 *
1743 * For many use cases, it is possible to only call this once after all
1744 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1745 * possible if no reference to the data returned are needed before the
1746 * error state is checked.
1747 *
1748 * In some cases UsefulInputBuf_GetUsefulBuf() or
1749 * UsefulInputBuf_GetBytes() can stand in for this because they return
1750 * @c NULL if the error state has been entered. (The others can't stand
1751 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001752 */
1753static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1754
1755
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001756/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001757 * @brief Gets the input buffer length.
1758 *
1759 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1760 *
1761 * @return The length of the input buffer.
1762 *
1763 * This returns the length of the input buffer set by
1764 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001765 */
1766static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1767
1768
1769/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001770 * @brief Alters the input buffer length (use with caution).
1771 *
1772 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1773 * @param[in] uNewLen The new length of the input buffer.
1774 *
1775 * This alters the internal remembered length of the input buffer set
1776 * when UsefulInputBuf_Init() was called.
1777 *
1778 * The new length given here should always be equal to or less than
1779 * the length given when UsefulInputBuf_Init() was called. Making it
1780 * larger allows @ref UsefulInputBuf to run off the input buffer.
1781 *
1782 * The typical use is to set a length shorter than that when
1783 * initialized to constrain parsing. If
1784 * UsefulInputBuf_GetBufferLength() was called before this, then the
1785 * original length can be restored with another call to this.
1786 *
1787 * This should be used with caution. It is the only
1788 * @ref UsefulInputBuf method that can violate the safety of input
1789 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001790 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001791static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001792
1793
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001794
1795
Michael Eckel5c531332020-03-02 01:35:30 +01001796/*----------------------------------------------------------
1797 Inline implementations.
1798 */
1799static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1800{
1801 return !UB.ptr;
1802}
1803
1804
1805static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1806{
1807 return !UB.ptr;
1808}
1809
1810
1811static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1812{
1813 return !UB.len;
1814}
1815
1816
1817static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1818{
1819 return !UB.len;
1820}
1821
1822
1823static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1824{
1825 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1826}
1827
1828
1829static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1830{
1831 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1832}
1833
1834
1835static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1836{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001837 UsefulBufC UBC;
1838 UBC.ptr = UB.ptr;
1839 UBC.len = UB.len;
1840
1841 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001842}
1843
Michael Eckel5c531332020-03-02 01:35:30 +01001844static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1845{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001846 UsefulBuf UB;
1847
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001848 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001849 * the one place in UsefulBuf where it needs to be quieted.
1850 */
1851 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001852
1853 UB.len = UBC.len;
1854
1855 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001856}
1857
1858
1859static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1860{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001861 UsefulBufC UBC;
1862 UBC.ptr = szString;
1863 UBC.len = strlen(szString);
1864 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001865}
1866
1867
1868static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1869{
1870 return UsefulBuf_CopyOffset(Dest, 0, Src);
1871}
1872
1873
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001874static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001875{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001876 memset(Dest.ptr, value, Dest.len);
1877
1878 UsefulBufC UBC;
1879 UBC.ptr = Dest.ptr;
1880 UBC.len = Dest.len;
1881
1882 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001883}
1884
1885
1886static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1887{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001888 UsefulBufC UBC;
1889 UBC.ptr = ptr;
1890 UBC.len = len;
1891 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001892}
1893
1894
1895static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1896{
1897 if(uAmount > UB.len) {
1898 return NULLUsefulBufC;
1899 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001900 UsefulBufC UBC;
1901
1902 UBC.ptr = UB.ptr;
1903 UBC.len = uAmount;
1904
1905 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001906}
1907
1908
1909static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1910{
1911 UsefulBufC ReturnValue;
1912
1913 if(uAmount > UB.len) {
1914 ReturnValue = NULLUsefulBufC;
1915 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001916 ReturnValue.ptr = NULL;
1917 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001918 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001919 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1920 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001921 }
1922
1923 return ReturnValue;
1924}
1925
1926
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001927static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1928{
1929 if(UB.ptr == NULL) {
1930 return SIZE_MAX;
1931 }
1932
1933 if(p < UB.ptr) {
1934 /* given pointer is before start of buffer */
1935 return SIZE_MAX;
1936 }
1937
Laurence Lundblade3eead482023-12-16 20:53:22 -07001938 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001939 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001940
1941 if(uOffset >= UB.len) {
1942 /* given pointer is off the end of the buffer */
1943 return SIZE_MAX;
1944 }
1945
1946 return uOffset;
1947}
1948
Michael Eckel5c531332020-03-02 01:35:30 +01001949
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001950#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001951static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1952{
1953 uint32_t u32;
1954 memcpy(&u32, &f, sizeof(uint32_t));
1955 return u32;
1956}
1957
1958static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1959{
1960 uint64_t u64;
1961 memcpy(&u64, &d, sizeof(uint64_t));
1962 return u64;
1963}
1964
1965static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1966{
1967 double d;
1968 memcpy(&d, &u64, sizeof(uint64_t));
1969 return d;
1970}
1971
1972static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1973{
1974 float f;
1975 memcpy(&f, &u32, sizeof(uint32_t));
1976 return f;
1977}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001978#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001979
1980
1981
1982
1983static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1984{
1985 pMe->data_len = 0;
1986 pMe->err = 0;
1987}
1988
1989
1990static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1991{
1992 return pMe->data_len;
1993}
1994
1995
1996static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1997{
1998 return 0 == pMe->data_len;
1999}
2000
2001
2002static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
2003 const void *pBytes,
2004 size_t uLen,
2005 size_t uPos)
2006{
2007 UsefulBufC Data = {pBytes, uLen};
2008 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
2009}
2010
2011
2012static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
2013 const char *szString,
2014 size_t uPos)
2015{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002016 UsefulBufC UBC;
2017 UBC.ptr = szString;
2018 UBC.len = strlen(szString);
2019
2020 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01002021}
2022
2023
2024static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
2025 uint8_t byte,
2026 size_t uPos)
2027{
2028 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
2029}
2030
2031
2032static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
2033 uint16_t uInteger16,
2034 size_t uPos)
2035{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002036 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002037
2038 const void *pBytes;
2039
2040#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2041 pBytes = &uInteger16;
2042
2043#elif defined(USEFULBUF_CONFIG_HTON)
2044 uint16_t uTmp = htons(uInteger16);
2045 pBytes = &uTmp;
2046
2047#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2048 uint16_t uTmp = __builtin_bswap16(uInteger16);
2049 pBytes = &uTmp;
2050
2051#else
2052 uint8_t aTmp[2];
2053
2054 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
2055 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
2056
2057 pBytes = aTmp;
2058#endif
2059
2060 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
2061}
2062
2063
2064static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
2065 uint32_t uInteger32,
2066 size_t uPos)
2067{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002068 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002069
2070 const void *pBytes;
2071
2072#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2073 pBytes = &uInteger32;
2074
2075#elif defined(USEFULBUF_CONFIG_HTON)
2076 uint32_t uTmp = htonl(uInteger32);
2077 pBytes = &uTmp;
2078
2079#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2080 uint32_t uTmp = __builtin_bswap32(uInteger32);
2081
2082 pBytes = &uTmp;
2083
2084#else
2085 uint8_t aTmp[4];
2086
2087 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2088 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2089 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2090 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2091
2092 pBytes = aTmp;
2093#endif
2094
2095 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2096}
2097
2098static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002099 uint64_t uInteger64,
2100 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002101{
2102 const void *pBytes;
2103
2104#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002105 /* We have been told explicitly we are running on a big-endian
2106 * machine. Network byte order is big endian, so just copy. There
2107 * is no issue with alignment here because uInteger64 is always
2108 * aligned (and it doesn't matter if pBytes is aligned).
2109 */
Michael Eckel5c531332020-03-02 01:35:30 +01002110 pBytes = &uInteger64;
2111
2112#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002113 /* Use system function to handle big- and little-endian. This works
2114 * on both big- and little-endian machines, but hton() is not
2115 * always available or in a standard place so it is not used by
2116 * default. With some compilers and CPUs the code for this is very
2117 * compact through use of a special swap instruction and on
2118 * big-endian machines hton() will reduce to nothing.
2119 */
Michael Eckel5c531332020-03-02 01:35:30 +01002120 uint64_t uTmp = htonll(uInteger64);
2121
2122 pBytes = &uTmp;
2123
2124#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002125 /* Use built-in function for byte swapping. This usually compiles
2126 * to an efficient special byte swap instruction. Unlike hton() it
2127 * does not do this conditionally on the CPU endianness, so this
2128 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2129 */
Michael Eckel5c531332020-03-02 01:35:30 +01002130 uint64_t uTmp = __builtin_bswap64(uInteger64);
2131
2132 pBytes = &uTmp;
2133
2134#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002135 /* Default which works on every CPU with no dependency on anything
2136 * from the CPU, compiler, libraries or OS. This always works, but
2137 * it is usually a little larger and slower than hton().
2138 */
Michael Eckel5c531332020-03-02 01:35:30 +01002139 uint8_t aTmp[8];
2140
2141 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2142 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2143 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2144 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2145 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2146 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2147 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2148 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2149
2150 pBytes = aTmp;
2151#endif
2152
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002153 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002154 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2155}
2156
2157
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002158#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002159static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2160 float f,
2161 size_t uPos)
2162{
2163 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2164}
2165
2166
2167static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2168 double d,
2169 size_t uPos)
2170{
2171 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2172}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002173#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002174
2175
2176static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2177 UsefulBufC NewData)
2178{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002179 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002180 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2181}
2182
2183
2184static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2185 const void *pBytes,
2186 size_t uLen)
2187{
2188 UsefulBufC Data = {pBytes, uLen};
2189 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2190}
2191
2192
2193static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2194 const char *szString)
2195{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002196 UsefulBufC UBC;
2197 UBC.ptr = szString;
2198 UBC.len = strlen(szString);
2199
2200 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002201}
2202
2203
2204static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2205 uint8_t byte)
2206{
2207 UsefulOutBuf_AppendData(pMe, &byte, 1);
2208}
2209
2210
2211static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2212 uint16_t uInteger16)
2213{
2214 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2215}
2216
2217static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2218 uint32_t uInteger32)
2219{
2220 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2221}
2222
2223
2224static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2225 uint64_t uInteger64)
2226{
2227 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2228}
2229
2230
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002231#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002232static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2233 float f)
2234{
2235 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2236}
2237
2238
2239static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2240 double d)
2241{
2242 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2243}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002244#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002245
2246
2247static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2248{
2249 return pMe->err;
2250}
2251
2252
2253static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2254{
2255 return pMe->UB.len - pMe->data_len;
2256}
2257
2258
2259static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2260{
2261 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2262}
2263
2264
2265static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2266{
2267 return pMe->UB.ptr == NULL;
2268}
2269
2270
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002271static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2272{
2273 UsefulBuf R;
2274
2275 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002276 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002277 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2278 } else {
2279 R.ptr = NULL;
2280 }
2281
2282 return R;
2283}
2284
2285
2286
Michael Eckel5c531332020-03-02 01:35:30 +01002287
2288static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2289{
2290 pMe->cursor = 0;
2291 pMe->err = 0;
2292 pMe->magic = UIB_MAGIC;
2293 pMe->UB = UB;
2294}
2295
2296static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2297{
2298 return pMe->cursor;
2299}
2300
2301
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002302static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002303{
2304 return pMe->UB.len;
2305}
2306
2307
Michael Eckel5c531332020-03-02 01:35:30 +01002308static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2309{
2310 if(uPos > pMe->UB.len) {
2311 pMe->err = 1;
2312 } else {
2313 pMe->cursor = uPos;
2314 }
2315}
2316
2317
2318static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2319{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002320 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002321
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002322 /* Magic number is messed up. Either the structure got overwritten
2323 * or was never initialized.
2324 */
Michael Eckel5c531332020-03-02 01:35:30 +01002325 if(pMe->magic != UIB_MAGIC) {
2326 return 0;
2327 }
2328
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002329 /* The cursor is off the end of the input buffer given.
2330 * Presuming there are no bugs in this code, this should never happen.
2331 * If it so, the struct was corrupted. The check is retained as
2332 * as a defense in case there is a bug in this code or the struct is
2333 * corrupted.
2334 */
Michael Eckel5c531332020-03-02 01:35:30 +01002335 if(pMe->cursor > pMe->UB.len) {
2336 return 0;
2337 }
2338
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002339 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002340 return pMe->UB.len - pMe->cursor;
2341}
2342
2343
2344static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2345{
2346 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2347}
2348
2349
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002350static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2351{
2352 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2353}
2354
2355
Michael Eckel5c531332020-03-02 01:35:30 +01002356static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2357{
2358 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2359 if(!pResult) {
2360 return NULLUsefulBufC;
2361 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002362 UsefulBufC UBC;
2363 UBC.ptr = pResult;
2364 UBC.len = uNum;
2365 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002366 }
2367}
2368
2369
2370static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2371{
2372 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2373
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002374 /* The ternary operator is subject to integer promotion, because
2375 * the operands are smaller than int, so cast back to uint8_t is
2376 * needed to be completely explicit about types (for static
2377 * analyzers).
2378 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002379 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002380}
2381
2382static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2383{
2384 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2385
2386 if(!pResult) {
2387 return 0;
2388 }
2389
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002390 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002391#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2392 uint16_t uTmp;
2393 memcpy(&uTmp, pResult, sizeof(uint16_t));
2394
2395#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2396 return uTmp;
2397
2398#elif defined(USEFULBUF_CONFIG_HTON)
2399 return ntohs(uTmp);
2400
2401#else
2402 return __builtin_bswap16(uTmp);
2403
2404#endif
2405
2406#else
2407
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002408 /* The operations here are subject to integer promotion because the
2409 * operands are smaller than int. They will be promoted to unsigned
2410 * int for the shift and addition. The cast back to uint16_t is is
2411 * needed to be completely explicit about types (for static
2412 * analyzers).
2413 */
Michael Eckel5c531332020-03-02 01:35:30 +01002414 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2415
2416#endif
2417}
2418
2419
2420static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2421{
2422 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2423
2424 if(!pResult) {
2425 return 0;
2426 }
2427
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002428 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002429#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2430 uint32_t uTmp;
2431 memcpy(&uTmp, pResult, sizeof(uint32_t));
2432
2433#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2434 return uTmp;
2435
2436#elif defined(USEFULBUF_CONFIG_HTON)
2437 return ntohl(uTmp);
2438
2439#else
2440 return __builtin_bswap32(uTmp);
2441
2442#endif
2443
2444#else
2445 return ((uint32_t)pResult[0]<<24) +
2446 ((uint32_t)pResult[1]<<16) +
2447 ((uint32_t)pResult[2]<<8) +
2448 (uint32_t)pResult[3];
2449#endif
2450}
2451
2452
2453static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2454{
2455 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2456
2457 if(!pResult) {
2458 return 0;
2459 }
2460
2461#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002462 /* pResult will probably not be aligned. This memcpy() moves the
2463 * bytes into a temp variable safely for CPUs that can or can't do
2464 * unaligned memory access. Many compilers will optimize the
2465 * memcpy() into a simple move instruction.
2466 */
Michael Eckel5c531332020-03-02 01:35:30 +01002467 uint64_t uTmp;
2468 memcpy(&uTmp, pResult, sizeof(uint64_t));
2469
2470#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002471 /* We have been told expliclity this is a big-endian CPU. Since
2472 * network byte order is big-endian, there is nothing to do.
2473 */
Michael Eckel5c531332020-03-02 01:35:30 +01002474
2475 return uTmp;
2476
2477#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002478 /* We have been told to use ntoh(), the system function to handle
2479 * big- and little-endian. This works on both big- and
2480 * little-endian machines, but ntoh() is not always available or in
2481 * a standard place so it is not used by default. On some CPUs the
2482 * code for this is very compact through use of a special swap
2483 * instruction.
2484 */
Michael Eckel5c531332020-03-02 01:35:30 +01002485
2486 return ntohll(uTmp);
2487
2488#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002489 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2490 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2491 * __builtin_bswap64() and friends are not conditional on CPU
2492 * endianness so this must only be used on little-endian machines.
2493 */
Michael Eckel5c531332020-03-02 01:35:30 +01002494
2495 return __builtin_bswap64(uTmp);
2496
2497
2498#endif
2499
2500#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002501 /* This is the default code that works on every CPU and every
2502 * endianness with no dependency on ntoh(). This works on CPUs
2503 * that either allow or do not allow unaligned access. It will
2504 * always work, but usually is a little less efficient than ntoh().
2505 */
Michael Eckel5c531332020-03-02 01:35:30 +01002506
2507 return ((uint64_t)pResult[0]<<56) +
2508 ((uint64_t)pResult[1]<<48) +
2509 ((uint64_t)pResult[2]<<40) +
2510 ((uint64_t)pResult[3]<<32) +
2511 ((uint64_t)pResult[4]<<24) +
2512 ((uint64_t)pResult[5]<<16) +
2513 ((uint64_t)pResult[6]<<8) +
2514 (uint64_t)pResult[7];
2515#endif
2516}
2517
2518
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002519#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002520static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2521{
2522 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2523
2524 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2525}
2526
2527
2528static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2529{
2530 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2531
2532 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2533}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002534#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002535
2536
2537static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2538{
2539 return pMe->err;
2540}
2541
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002542
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002543static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002544{
2545 pMe->UB.len = uNewLen;
2546}
2547
2548
Michael Eckel5c531332020-03-02 01:35:30 +01002549#ifdef __cplusplus
2550}
2551#endif
2552
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002553#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002554
2555