blob: 186bd44d9ee77bcf24f25c56c1e9905450294823 [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06003 Copyright (c) 2018-2022, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited. All rights reserved.
Michael Eckel5c531332020-03-02 01:35:30 +01005
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =============================================================================*/
32
33/*============================================================================
34 FILE: UsefulBuf.h
35
36 DESCRIPTION: General purpose input and output buffers
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- --------------------------------------------------
Laurence Lundblade8f310dd2022-10-08 14:43:38 -070045 9/8/2022 llundblade Add comment about preference for use of const.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060046 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070047 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070048 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070049 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080050 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070051 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010052 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
53 5/21/2019 llundblade #define configs for efficient endianness handling.
54 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
55 3/23/2019 llundblade Big documentation & style update. No interface
56 change.
57 3/6/2019 llundblade Add UsefulBuf_IsValue()
58 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
59 12/13/2018 llundblade Documentation improvements
60 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
61 UsefulBufC.
62 02/02/18 llundbla Full support for integers in and out; fix pointer
63 alignment bug. Incompatible change: integers
64 in/out are now in network byte order.
65 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
66 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
67 comparison for < or > for unequal length buffers.
68 Added UsefulBuf_Set() function.
69 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
70 11/13/16 llundbla Initial Version.
71
72 =============================================================================*/
73
74#ifndef _UsefulBuf_h
75#define _UsefulBuf_h
76
77
78/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070079 * Endianness Configuration
80 *
81 * This code is written so it will work correctly on big- and
82 * little-endian CPUs without configuration or any auto-detection of
83 * endianness. All code here will run correctly regardless of the
84 * endianness of the CPU it is running on.
85 *
86 * There are four C preprocessor macros that can be set with #define
87 * to explicitly configure endianness handling. Setting them can
88 * reduce code size a little and improve efficiency a little.
89 *
90 * Note that most of QCBOR is unaffected by this configuration. Its
91 * endianness handling is integrated with the code that handles
92 * alignment and preferred serialization. This configuration does
93 * affect QCBOR's (planned) implementation of integer arrays (tagged
94 * arrays) and use of the functions here to serialize or deserialize
95 * integers and floating-point values.
96 *
97 * Following is the recipe for configuring the endianness-related
98 * #defines.
99 *
100 * The first option is to not define anything. This will work fine
101 * with all CPUs, OS's and compilers. The code for encoding integers
102 * may be a little larger and slower.
103 *
104 * If your CPU is big-endian then define
105 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
106 * for big-endian CPUs. It will be small and efficient because there
107 * will be no byte swapping.
108 *
109 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
110 * OS's and compilers, but not all. On big-endian CPUs this should
111 * give the most efficient code, the same as
112 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
113 * call the system-defined byte swapping method which is presumably
114 * implemented efficiently. In some cases, this will be a dedicated
115 * byte swap instruction like Intel's bswap.
116 *
117 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
118 * little-endian, it is also good to define
119 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
120 *
121 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
122 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
123 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
124 * system-defined byte swap method. However, note
125 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
126 * this is fixed now. Often hton() and ntoh() will call the built-in
127 * __builtin_bswapXX()() function, so this size issue could affect
128 * USEFULBUF_CONFIG_HTON.
129 *
130 * Last, run the tests. They must all pass.
131 *
132 * These #define config options affect the inline implementation of
133 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
134 * also affect the 16-, 32-bit, float and double versions of these
135 * functions. Since they are inline, the size effect is not in the
136 * UsefulBuf object code, but in the calling code.
137 *
138 * Summary:
139 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
140 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
141 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
142 * handle big and little-endian with system option.
143 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
144 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200145 *
146 * It is possible to run this code in environments where using floating point is
147 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
148 * that is related to handling floating point types, along with related
149 * interfaces. This makes it possible to compile the code with the compile
150 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100151 */
152
153#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
154#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
155#endif
156
157
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700158#include <stdint.h> /* for uint8_t, uint16_t.... */
159#include <string.h> /* for strlen, memcpy, memmove, memset */
160#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100161
162
163#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700164#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100165#endif
166
167#ifdef __cplusplus
168extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700169#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700170} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700171#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100172#endif
173
174/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700175 * @file UsefulBuf.h
176 *
177 * The goal of this code is to make buffer and pointer manipulation
178 * easier and safer when working with binary data.
179 *
180 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
181 * structures are used to represent buffers rather than ad hoc
182 * pointers and lengths.
183 *
184 * With these it is possible to write code that does little or no
185 * direct pointer manipulation for copying and formatting data. For
186 * example, the QCBOR encoder was written using these and has less
187 * pointer manipulation.
188 *
189 * While it is true that object code using these functions will be a
190 * little larger and slower than a white-knuckle clever use of
191 * pointers might be, but not by that much or enough to have an effect
192 * for most use cases. For security-oriented code this is highly
193 * worthwhile. Clarity, simplicity, reviewability and are more
194 * important.
195 *
196 * There are some extra sanity and double checks in this code to help
197 * catch coding errors and simple memory corruption. They are helpful,
198 * but not a substitute for proper code review, input validation and
199 * such.
200 *
201 * This code consists of a lot of inline functions and a few that are
202 * not. It should not generate very much object code, especially with
203 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100204 */
205
206
207/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700208 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
209 * hold a pointer and length for binary data. In C99 this data
210 * structure can be passed on the stack making a lot of code cleaner
211 * than carrying around a pointer and length as two parameters.
212 *
213 * This is also conducive to secure coding practice as the length is
214 * always carried with the pointer and the convention for handling a
215 * pointer and a length is clear.
216 *
217 * While it might be possible to write buffer and pointer code more
218 * efficiently in some use cases, the thought is that unless there is
219 * an extreme need for performance (e.g., you are building a
220 * gigabit-per-second IP router), it is probably better to have
221 * cleaner code you can be most certain about the security of.
222 *
Laurence Lundblade8f310dd2022-10-08 14:43:38 -0700223 * This aims to make maximum use of constness as as a good and
224 * thorough coding practice. It tell someone reading the code
225 * a lot about the assumptions in the code and how it should work.
226 * Some good information is here https://matt.sh/sytycc and
227 * https://stackoverflow.com/questions/117293/use-of-const-for-function-parameters
228 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700229 * The non-const @ref UsefulBuf is usually used to refer an empty
230 * buffer to be filled in. The length is the size of the buffer.
231 *
232 * The const @ref UsefulBufC is usually used to refer to some data
233 * that has been filled in. The length is amount of valid data pointed
234 * to.
235 *
236 * A common use mode is to pass a @ref UsefulBuf to a function, the
237 * function puts some data in it, then the function returns a @ref
238 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
239 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
240 * so the constness stays correct. There is no single "in,out"
241 * parameter (if there was, it would have to be non-const). Note that
242 * the pointer returned in the @ref UsefulBufC usually ends up being
243 * the same pointer passed in as a @ref UsefulBuf, though this is not
244 * striclty required.
245 *
246 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
247 * @c NULL.
248 *
249 * There are functions and macros for the following:
250 * - Initializing
251 * - Create initialized const @ref UsefulBufC from compiler literals
252 * - Create initialized const @ref UsefulBufC from NULL-terminated string
253 * - Make an empty @ref UsefulBuf on the stack
254 * - Checking whether a @ref UsefulBuf is null, empty or both
255 * - Copying, copying with offset, copying head or tail
256 * - Comparing and finding substrings
257 *
258 * See also @ref UsefulOutBuf. It is a richer structure that has both
259 * the size of the valid data and the size of the buffer.
260 *
261 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
262 * it can go on the stack and be a function parameter or return value.
263 *
264 * Another way to look at it is this. C has the NULL-terminated string
265 * as a means for handling text strings, but no means or convention
266 * for binary strings. Other languages do have such means, Rust, an
267 * efficient compiled language, for example.
268 *
269 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
270 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
271 * out like anything".
272 */
Michael Eckel5c531332020-03-02 01:35:30 +0100273typedef struct q_useful_buf_c {
274 const void *ptr;
275 size_t len;
276} UsefulBufC;
277
278
279/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700280 * This non-const @ref UsefulBuf is typically used for some allocated
281 * memory that is to be filled in. The @c len is the amount of memory,
282 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100283 */
284typedef struct q_useful_buf {
285 void *ptr;
286 size_t len;
287} UsefulBuf;
288
289
290/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700291 * A null @ref UsefulBufC is one that has no value in the same way a
292 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
293 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
294 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100295 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700296/*
297 * NULLUsefulBufC and few other macros have to be
298 * definied differently in C than C++ because there
299 * is no common construct for a literal structure.
300 *
301 * In C compound literals are used.
302 *
303 * In C++ list initalization is used. This only works
304 * in C++11 and later.
305 *
306 * Note that some popular C++ compilers can handle compound
307 * literals with on-by-default extensions, however
308 * this code aims for full correctness with strict
309 * compilers so they are not used.
310 */
311#ifdef __cplusplus
312#define NULLUsefulBufC {NULL, 0}
313#else
314#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
315#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100316
317/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700318 * A null @ref UsefulBuf is one that has no memory associated the same
319 * way @c NULL points to nothing. It does not matter what @c len is.
320 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700321#ifdef __cplusplus
322#define NULLUsefulBuf {NULL, 0}
323#else
324#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
325#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100326
327
328/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700329 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
330 *
331 * @param[in] UB The UsefulBuf to check.
332 *
333 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100334 */
335static inline int UsefulBuf_IsNULL(UsefulBuf UB);
336
337
338/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700339 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
340 *
341 * @param[in] UB The @ref UsefulBufC to check.
342 *
343 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100344 */
345static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
346
347
348/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700349 * @brief Check if a @ref UsefulBuf is empty or not.
350 *
351 * @param[in] UB The @ref UsefulBuf to check.
352 *
353 * @return 1 if it is empty, 0 if not.
354 *
355 * An "empty" @ref UsefulBuf is one that has a value and can be
356 * considered to be set, but that value is of zero length. It is
357 * empty when @c len is zero. It doesn't matter what the @c ptr is.
358 *
359 * Many uses will not need to clearly distinguish a @c NULL @ref
360 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
361 * @c len 0. However if a use of @ref UsefulBuf needs to make a
362 * distinction then @c ptr should not be @c NULL when the @ref
363 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100364 */
365static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
366
367
368/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700369 * @brief Check if a @ref UsefulBufC is empty or not.
370 *
371 * @param[in] UB The @ref UsefulBufC to check.
372 *
373 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100374 */
375static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
376
377
378/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700379 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
380 *
381 * @param[in] UB The @ref UsefulBuf to check.
382 *
383 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100384 */
385static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
386
387
388/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700389 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
390 *
391 * @param[in] UB The @ref UsefulBufC to check.
392 *
393 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100394 */
395static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
396
397
398/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700399 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
400 *
401 * @param[in] UB The @ref UsefulBuf to convert.
402 *
403 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100404 */
405static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
406
407
408/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700409 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
410 *
411 * @param[in] UBC The @ref UsefulBuf to convert.
412 *
413 * @return A non-const @ref UsefulBuf struct.
414 *
415 * Use of this is not necessary for the intended use mode of @ref
416 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
417 * created to describe a buffer that has not had any data put in
418 * it. Then the data is put in it. Then a @ref UsefulBufC is create
419 * to describe the part with the data in it. This goes from non-const
420 * to const, so this function is not needed.
421 *
422 * If the -Wcast-qual warning is enabled, this function can be used to
423 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100424 */
425static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
426
427
428/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700429 * Convert a literal string to a @ref UsefulBufC.
430 *
431 * @c szString must be a literal string that @c sizeof() works on.
432 * This is better for literal strings than UsefulBuf_FromSZ() because
433 * it generates less code. It will not work on non-literal strings.
434 *
435 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100436 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700437#ifdef __cplusplus
438#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
439#else
Michael Eckel5c531332020-03-02 01:35:30 +0100440#define UsefulBuf_FROM_SZ_LITERAL(szString) \
441 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700442#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100443
444
445/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700446 * Convert a literal byte array to a @ref UsefulBufC.
447 *
448 * @c pBytes must be a literal string that @c sizeof() works on. It
449 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100450 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700451#ifdef __cplusplus
452#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
453#else
Michael Eckel5c531332020-03-02 01:35:30 +0100454#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700455 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
456#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100457
458/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700459 * Make an automatic variable named @c name of type @ref UsefulBuf and
460 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100461 */
462#define UsefulBuf_MAKE_STACK_UB(name, size) \
463 uint8_t __pBuf##name[(size)];\
464 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
465
466
467/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700468 * Make a byte array in to a @ref UsefulBuf. This is usually used on
469 * stack variables or static variables. Also see @ref
470 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100471 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700472#ifdef __cplusplus
473#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
474#else
Michael Eckel5c531332020-03-02 01:35:30 +0100475#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700476 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
477#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100478
479
480/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700481 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
482 *
483 * @param[in] szString The string to convert.
484 *
485 * @return A @ref UsefulBufC struct.
486 *
487 * @c UsefulBufC.ptr points to the string so its lifetime must be
488 * maintained.
489 *
490 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100491 */
492static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
493
494
495/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700496 * @brief Copy one @ref UsefulBuf into another at an offset.
497 *
498 * @param[in] Dest Destination buffer to copy into.
499 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
500 * @param[in] Src The bytes to copy.
501 *
502 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
503 *
504 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
505 * size of @c Dest.
506 *
507 * This fails and returns @ref NULLUsefulBufC if the @c Src length
508 * plus @c uOffset is greater than the length of @c Dest.
509 *
510 * The results are undefined if @c Dest and @c Src overlap.
511 *
512 * This assumes that there is valid data in @c Dest up to @c
513 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
514 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100515 */
516UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
517
518
519/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700520 * @brief Copy one @ref UsefulBuf into another.
521 *
522 * @param[in] Dest The destination buffer to copy into.
523 * @param[out] Src The source to copy from.
524 *
525 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
526 * on failure.
527 *
528 * This fails if @c Src.len is greater than @c Dest.len.
529 *
530 * Note that like @c memcpy(), the pointers are not checked and this
531 * will crash rather than return @ref NULLUsefulBufC if they are @c
532 * NULL or invalid.
533 *
534 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100535 */
536static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
537
538
539/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700540 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
541 *
542 * @param[in] pDest The destination buffer to copy into.
543 * @param[in] value The value to set the bytes to.
544 *
545 * Note that like @c memset(), the pointer in @c pDest is not checked
546 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100547 */
548static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
549
550
551/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700552 * @brief Copy a pointer into a @ref UsefulBuf.
553 *
554 * @param[in,out] Dest The destination buffer to copy into.
555 * @param[in] ptr The source to copy from.
556 * @param[in] uLen Length of the source; amount to copy.
557 *
558 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
559 * on failure.
560 *
561 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
562 * than @c pDest->len.
563 *
564 * Note that like @c memcpy(), the pointers are not checked and this
565 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100566 */
567static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
568 const void *ptr,
569 size_t uLen);
570
571
572/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700573 * @brief Returns a truncation of a @ref UsefulBufC.
574 *
575 * @param[in] UB The buffer to get the head of.
576 * @param[in] uAmount The number of bytes in the head.
577 *
578 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100579 */
580static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
581
582
583/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700584 * @brief Returns bytes from the end of a @ref UsefulBufC.
585 *
586 * @param[in] UB The buffer to get the tail of.
587 * @param[in] uAmount The offset from the start where the tail is to begin.
588 *
589 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
590 * if @c uAmount is greater than the length of the @ref UsefulBufC.
591 *
592 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
593 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
594 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100595 */
596static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
597
598
599/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700600 * @brief Compare one @ref UsefulBufC to another.
601 *
602 * @param[in] UB1 The first buffer to compare.
603 * @param[in] UB2 The second buffer to compare.
604 *
605 * @return 0, positive or negative value.
606 *
607 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
608 * less than @c UB2 if it is shorter or the first byte that is not the
609 * same is less.
610 *
611 * Returns 0 if the inputs are the same.
612 *
613 * Returns a positive value if @c UB2 is less than @c UB1.
614 *
615 * All that is of significance is that the result is positive, negative
616 * or 0. (This doesn't return the difference between the first
617 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100618 */
619int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
620
621
622/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700623 * @brief Find first byte that is not a particular byte value.
624 *
625 * @param[in] UB The destination buffer for byte comparison.
626 * @param[in] uValue The byte value to compare to.
627 *
628 * @return Offset of first byte that isn't @c uValue or
629 * @c SIZE_MAX if all bytes are @c uValue.
630 *
631 * Note that unlike most comparison functions, 0
632 * does not indicate a successful comparison, so the
633 * test for match is:
634 *
635 * UsefulBuf_IsValue(...) == SIZE_MAX
636 *
637 * If @c UB is null or empty, there is no match
638 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100639 */
640size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
641
642
643/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700644 * @brief Find one @ref UsefulBufC in another.
645 *
646 * @param[in] BytesToSearch Buffer to search through.
647 * @param[in] BytesToFind Buffer with bytes to be found.
648 *
649 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100650 */
651size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
652
653
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700654/**
655 @brief Convert a pointer to an offset with bounds checking.
656
657 @param[in] UB Pointer to the UsefulInputBuf.
658 @param[in] p Pointer to convert to offset.
659
660 @return SIZE_MAX if @c p is out of range, the byte offset if not.
661*/
662static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
663
664
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800665#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100666/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700667#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100668
669/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
670#define MakeUsefulBufOnStack(name, size) \
671 uint8_t __pBuf##name[(size)];\
672 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
673
674/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
675#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700676 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100677
678/** Deprecated function; use UsefulBuf_Unconst() instead */
679static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
680{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700681 UsefulBuf UB;
682
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800683 // See UsefulBuf_Unconst() implementation for comment on pragmas
Dave Thaler93c01182022-08-06 15:08:35 -0400684#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800685#pragma GCC diagnostic push
686#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400687#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700688 UB.ptr = (void *)UBC.ptr;
Dave Thaler93c01182022-08-06 15:08:35 -0400689#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800690#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400691#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700692
693 UB.len = UBC.len;
694
695 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100696}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800697#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100698
699
700
701
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200702#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100703/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700704 * @brief Copy a @c float to a @c uint32_t.
705 *
706 * @param[in] f Float value to copy.
707 *
708 * @return A @c uint32_t with the float bits.
709 *
710 * Convenience function to avoid type punning, compiler warnings and
711 * such. The optimizer usually reduces this to a simple assignment. This
712 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100713 */
714static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
715
716
717/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700718 * @brief Copy a @c double to a @c uint64_t.
719 *
720 * @param[in] d Double value to copy.
721 *
722 * @return A @c uint64_t with the double bits.
723 *
724 * Convenience function to avoid type punning, compiler warnings and
725 * such. The optimizer usually reduces this to a simple assignment. This
726 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100727 */
728static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
729
730
731/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700732 * @brief Copy a @c uint32_t to a @c float.
733 *
734 * @param[in] u32 Integer value to copy.
735 *
736 * @return The value as a @c float.
737 *
738 * Convenience function to avoid type punning, compiler warnings and
739 * such. The optimizer usually reduces this to a simple assignment. This
740 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100741 */
742static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
743
744
745/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700746 * @brief Copy a @c uint64_t to a @c double.
747 *
748 * @param[in] u64 Integer value to copy.
749 *
750 * @return The value as a @c double.
751 *
752 * Convenience function to avoid type punning, compiler warnings and
753 * such. The optimizer usually reduces this to a simple assignment. This
754 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100755 */
756static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200757#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100758
759
760
761
762/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700763 * UsefulOutBuf is a structure and functions (an object) for
764 * serializing data into a buffer to encode for a network protocol or
765 * write data to a file.
766 *
767 * The main idea is that all the pointer manipulation is performed by
768 * @ref UsefulOutBuf functions so the caller doesn't have to do any
769 * pointer manipulation. The pointer manipulation is centralized.
770 * This code has been reviewed and written carefully so it
771 * spares the caller of much of this work and results in safer code
772 * with less effort.
773 *
774 * The @ref UsefulOutBuf methods that add data to the output buffer
775 * always check the length and will never write off the end of the
776 * output buffer. If an attempt to add data that will not fit is made,
777 * an internal error flag will be set and further attempts to add data
778 * will not do anything.
779 *
780 * There is no way to ever write off the end of that buffer when
781 * calling the @c UsefulOutBuf_AddXxx() and
782 * @c UsefulOutBuf_InsertXxx() functions.
783 *
784 * The functions to add data do not report success of failure. The
785 * caller only needs to check for an error in the final call, either
786 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
787 * result. This makes the calling code cleaner.
788 *
789 * There is a utility function to get the error status anytime along
790 * the way for a special circumstance. There are functions to see how
791 * much room is left and see if some data will fit too, but their use
792 * is generally unnecessary.
793 *
794 * The general call flow is:
795 *
796 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
797 * buffer given to it can be from the heap, stack or
798 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
799 * macro that makes a buffer on the stack and initializes it.
800 *
801 * - Call methods like UsefulOutBuf_InsertString(),
802 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
803 * to output data. The append calls add data to the end of the
804 * valid data. The insert calls take a position argument.
805 *
806 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
807 * there were no errors and to get the serialized output bytes.
808 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700809 * @ref UsefulOutBuf can be used in a mode to calculate the size of
810 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700811 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700812 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700813 *
814 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700815 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700816 *
817 * The possible errors are:
818 *
819 * - The @ref UsefulOutBuf was not initialized or was corrupted.
820 *
821 * - An attempt was made to add data that will not fit.
822 *
823 * - An attempt was made to insert data at a position beyond the end of
824 * the buffer.
825 *
826 * - An attempt was made to insert data at a position beyond the valid
827 * data in the buffer.
828 *
829 * Some inexpensive simple sanity checks are performed before every
830 * data addition to guard against use of an uninitialized or corrupted
831 * UsefulOutBuf.
832 *
833 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
834 * encoder has almost no pointer manipulation in it, is easier to
835 * read, and easier to review.
836 *
837 * A @ref UsefulOutBuf is small and can go on the stack:
838 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
839 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100840 */
841typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700842 /* PRIVATE DATA STRUCTURE */
843 UsefulBuf UB; /* Memory that is being output to */
844 size_t data_len; /* length of the valid data, the insertion point */
845 uint16_t magic; /* Used to detect corruption and lack
846 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100847 uint8_t err;
848} UsefulOutBuf;
849
850
851/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700852 * This is a @ref UsefulBuf value that can be passed to
853 * UsefulOutBuf_Init() to have it calculate the size of the output
854 * buffer needed. Pass this for @c Storage, call all the append and
855 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
856 * returned @ref UsefulBufC has the size.
857 *
858 * As one can see, this is just a NULL pointer and very large size.
859 * The NULL pointer tells UsefulOutputBuf to not copy any data.
860 */
861#ifdef __cplusplus
862#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
863#else
864#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
865#endif
866
867
868/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700869 * @brief Initialize and supply the actual output buffer.
870 *
871 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
872 * @param[in] Storage Buffer to output into.
873 *
874 * This initializes the @ref UsefulOutBuf with storage, sets the
875 * current position to the beginning of the buffer and clears the
876 * error state.
877 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700878 * See @ref SizeCalculateUsefulBuf for instructions on how to
879 * initialize a @ref UsefulOutBuf to calculate the size that would be
880 * output without actually outputting.
881 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700882 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100883 */
884void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
885
886
887/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700888 * Convenience macro to make a @ref UsefulOutBuf on the stack and
889 * initialize it with a stack buffer of the given size. The variable
890 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100891 */
892#define UsefulOutBuf_MakeOnStack(name, size) \
893 uint8_t __pBuf##name[(size)];\
894 UsefulOutBuf name;\
895 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
896
897
898/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700899 * @brief Reset a @ref UsefulOutBuf for re use.
900 *
901 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
902 *
903 * This sets the amount of data in the output buffer to none and
904 * clears the error state.
905 *
906 * The output buffer is still the same one and size as from the
907 * UsefulOutBuf_Init() call.
908 *
909 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100910 */
911static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
912
913
914/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700915 * @brief Returns position of end of data in the @ref UsefulOutBuf.
916 *
917 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
918 *
919 * @return position of end of data.
920 *
921 * On a freshly initialized @ref UsefulOutBuf with no data added, this
922 * will return 0. After 10 bytes have been added, it will return 10
923 * and so on.
924 *
925 * Generally, there is no need to call this for most uses of @ref
926 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100927 */
928static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
929
930
931/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700932 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
933 *
934 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
935 *
936 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100937 */
938static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
939
940
941/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700942 * @brief Inserts bytes into the @ref UsefulOutBuf.
943 *
944 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
945 * @param[in] NewData The bytes to insert.
946 * @param[in] uPos Index in output buffer at which to insert.
947 *
948 * @c NewData is the pointer and length for the bytes to be added to
949 * the output buffer. There must be room in the output buffer for all
950 * of @c NewData or an error will occur.
951 *
952 * The insertion point must be between 0 and the current valid
953 * data. If not, an error will occur. Appending data to the output
954 * buffer is achieved by inserting at the end of the valid data. This
955 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
956 *
957 * When insertion is performed, the bytes between the insertion point
958 * and the end of data previously added to the output buffer are slid
959 * to the right to make room for the new data.
960 *
961 * Overlapping buffers are OK. @c NewData can point to data in the
962 * output buffer.
963 *
964 * If an error occurs, an error state is set in the @ref
965 * UsefulOutBuf. No error is returned. All subsequent attempts to add
966 * data will do nothing.
967 *
968 * The intended use is that all additions are made without checking
969 * for an error. The error will be taken into account when
970 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
971 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100972 */
973void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
974 UsefulBufC NewData,
975 size_t uPos);
976
977
978/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700979 * @brief Insert a data buffer into the @ref UsefulOutBuf.
980 *
981 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
982 * @param[in] pBytes Pointer to the bytes to insert
983 * @param[in] uLen Length of the bytes to insert
984 * @param[in] uPos Index in output buffer at which to insert
985 *
986 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
987 * the difference being a pointer and length is passed in rather than an
988 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100989 */
990static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
991 const void *pBytes,
992 size_t uLen,
993 size_t uPos);
994
995
996/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700997 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
998 *
999 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1000 * @param[in] szString NULL-terminated string to insert.
1001 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +01001002 */
1003static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
1004 const char *szString,
1005 size_t uPos);
1006
1007
1008/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001009 * @brief Insert a byte into the @ref UsefulOutBuf.
1010 *
1011 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1012 * @param[in] byte Bytes to insert.
1013 * @param[in] uPos Index in output buffer at which to insert.
1014 *
1015 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1016 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001017 */
1018static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1019 uint8_t byte,
1020 size_t uPos);
1021
1022
1023/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001024 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1025 *
1026 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1027 * @param[in] uInteger16 Integer to insert.
1028 * @param[in] uPos Index in output buffer at which to insert.
1029 *
1030 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1031 * with the difference being a two-byte integer is to be inserted.
1032 *
1033 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001034 */
1035static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1036 uint16_t uInteger16,
1037 size_t uPos);
1038
1039
1040/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001041 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1042 *
1043 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1044 * @param[in] uInteger32 Integer to insert.
1045 * @param[in] uPos Index in output buffer at which to insert.
1046 *
1047 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1048 * with the difference being a four-byte integer is to be inserted.
1049 *
1050 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001051 */
1052static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1053 uint32_t uInteger32,
1054 size_t uPos);
1055
1056
1057/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001058 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1059 *
1060 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1061 * @param[in] uInteger64 Integer to insert.
1062 * @param[in] uPos Index in output buffer at which to insert.
1063 *
1064 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1065 * with the difference being an eight-byte integer is to be inserted.
1066 *
1067 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001068 */
1069static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1070 uint64_t uInteger64,
1071 size_t uPos);
1072
1073
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001074#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001075/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001076 * @brief Insert a @c float into the @ref UsefulOutBuf.
1077 *
1078 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1079 * @param[in] f @c float to insert.
1080 * @param[in] uPos Index in output buffer at which to insert.
1081 *
1082 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1083 * with the difference being a @c float is to be inserted.
1084 *
1085 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001086 */
1087static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1088 float f,
1089 size_t uPos);
1090
1091
1092/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001093 * @brief Insert a @c double into the @ref UsefulOutBuf.
1094 *
1095 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1096 * @param[in] d @c double to insert.
1097 * @param[in] uPos Index in output buffer at which to insert.
1098 *
1099 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1100 * with the difference being a @c double is to be inserted.
1101 *
1102 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001103 */
1104static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1105 double d,
1106 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001107#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001108
1109
1110/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001111 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1112 *
1113 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1114 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1115 *
1116 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1117 * with the insertion point at the end of the valid data.
1118 */
Michael Eckel5c531332020-03-02 01:35:30 +01001119static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1120 UsefulBufC NewData);
1121
1122
1123/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001124 * @brief Append bytes to the @ref UsefulOutBuf.
1125 *
1126 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1127 * @param[in] pBytes Pointer to bytes to append.
1128 * @param[in] uLen Length of @c pBytes to append.
1129 *
1130 * See UsefulOutBuf_InsertData() for details. This does the same with
1131 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001132 */
1133static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1134 const void *pBytes,
1135 size_t uLen);
1136
1137
1138/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001139 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1140 *
1141 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1142 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001143 */
1144static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1145 const char *szString);
1146
1147
1148/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001149 * @brief Append a byte to the @ref UsefulOutBuf
1150 *
1151 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1152 * @param[in] byte Bytes to append.
1153 *
1154 * See UsefulOutBuf_InsertByte() for details. This does the same
1155 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001156 */
1157static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1158 uint8_t byte);
1159
1160
1161/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001162 * @brief Append an integer to the @ref UsefulOutBuf
1163 *
1164 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1165 * @param[in] uInteger16 Integer to append.
1166 *
1167 * See UsefulOutBuf_InsertUint16() for details. This does the same
1168 * with the insertion point at the end of the valid data.
1169 *
1170 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001171 */
1172static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1173 uint16_t uInteger16);
1174
1175
1176/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001177 * @brief Append an integer to the @ref UsefulOutBuf
1178 *
1179 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1180 * @param[in] uInteger32 Integer to append.
1181 *
1182 * See UsefulOutBuf_InsertUint32() for details. This does the same
1183 * with the insertion point at the end of the valid data.
1184 *
1185 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001186 */
1187static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1188 uint32_t uInteger32);
1189
1190
1191/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001192 * @brief Append an integer to the @ref UsefulOutBuf
1193 *
1194 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1195 * @param[in] uInteger64 Integer to append.
1196 *
1197 * See UsefulOutBuf_InsertUint64() for details. This does the same
1198 * with the insertion point at the end of the valid data.
1199 *
1200 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001201 */
1202static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1203 uint64_t uInteger64);
1204
1205
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001206#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001207/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001208 * @brief Append a @c float to the @ref UsefulOutBuf
1209 *
1210 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1211 * @param[in] f @c float to append.
1212 *
1213 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1214 * the insertion point at the end of the valid data.
1215 *
1216 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001217 */
1218static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1219 float f);
1220
1221
1222/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001223 * @brief Append a @c double to the @ref UsefulOutBuf
1224 *
1225 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1226 * @param[in] d @c double to append.
1227 *
1228 * See UsefulOutBuf_InsertDouble() for details. This does the same
1229 * with the insertion point at the end of the valid data.
1230 *
1231 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001232 */
1233static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1234 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001235#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001236
1237
1238/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001239 * @brief Returns the current error status.
1240 *
1241 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1242 *
1243 * @return 0 if all OK, 1 on error.
1244 *
1245 * This returns the error status since a call to either
1246 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1247 * goes into the error state, it will stay until one of those
1248 * functions is called.
1249 *
1250 * Possible error conditions are:
1251 * - bytes to be inserted will not fit
1252 * - insertion point is out of buffer or past valid data
1253 * - current position is off end of buffer (probably corrupted or uninitialized)
1254 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001255 */
1256static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1257
1258
1259/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001260 * @brief Returns number of bytes unused used in the output buffer.
1261 *
1262 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1263 *
1264 * @return Number of unused bytes or zero.
1265 *
1266 * Because of the error handling strategy and checks in
1267 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1268 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001269 */
1270static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1271
1272
1273/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001274 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1275 *
1276 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1277 * @param[in] uLen Number of bytes for which to check
1278 *
1279 * @return 1 if @c uLen bytes will fit, 0 if not.
1280 *
1281 * Because of the error handling strategy and checks in
1282 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1283 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001284 */
1285static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1286
1287
1288 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001289 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1290 *
1291 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1292 *
1293 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1294 *
1295 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1296 * just calculating the length of the encoded data.
1297 */
Michael Eckel5c531332020-03-02 01:35:30 +01001298static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1299
1300
1301/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001302 * @brief Returns pointer and length of the output buffer not yet used.
1303 *
1304 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1305 *
1306 * @return pointer and length of output buffer not used.
1307 *
1308 * This is an escape that allows the caller to write directly
1309 * to the output buffer without any checks. This doesn't
1310 * change the output buffer or state. It just returns a pointer
1311 * and length of the bytes remaining.
1312 *
1313 * This is useful to avoid having the bytes to be added all
1314 * in a contiguous buffer. Its use can save memory. A good
1315 * example is in the COSE encrypt implementation where
1316 * the output of the symmetric cipher can go directly
1317 * into the output buffer, rather than having to go into
1318 * an intermediate buffer.
1319 *
1320 * See UsefulOutBuf_Advance() which is used to tell
1321 * UsefulOutBuf how much was written.
1322 *
1323 * Warning: this bypasses the buffer safety provided by
1324 * UsefulOutBuf!
1325 */
1326static inline UsefulBuf
1327UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1328
1329
1330/**
1331 * @brief Advance the amount output assuming it was written by the caller.
1332 *
1333 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1334 * @param[in] uAmount The amount to advance.
1335 *
1336 * This advances the position in the output buffer
1337 * by \c uAmount. This assumes that the
1338 * caller has written \c uAmount to the pointer obtained
1339 * with UsefulOutBuf_GetOutPlace().
1340 *
1341 * Warning: this bypasses the buffer safety provided by
1342 * UsefulOutBuf!
1343 */
1344void
1345UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1346
1347
1348/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001349 * @brief Returns the resulting valid data in a UsefulOutBuf
1350 *
1351 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1352 *
1353 * @return The valid data in @ref UsefulOutBuf or
1354 * @ref NULLUsefulBufC if there was an error adding data.
1355 *
1356 * The storage for the returned data is the @c Storage parameter
1357 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1358 *
1359 * This can be called anytime and many times to get intermediate
1360 * results. It doesn't change the data or reset the current position,
1361 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001362 */
1363UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1364
1365
1366/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001367 * @brief Copies the valid data into a supplied buffer
1368 *
1369 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1370 * @param[out] Dest The destination buffer to copy into.
1371 *
1372 * @return Pointer and length of copied data or @c NULLUsefulBufC
1373 * if it will not fit in the @c Dest buffer or the error
1374 * state was entered.
1375 *
1376 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1377 * data to @c Dest.
1378 */
Michael Eckel5c531332020-03-02 01:35:30 +01001379UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1380
1381
1382
1383
1384/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001385 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1386 * for parsing data received. Initialize it with the data from the
1387 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1388 * get data chunks of various types. A position cursor is maintained
1389 * internally.
1390 *
1391 * As long as the functions here are used, there will never be any
1392 * reference off the end of the given buffer (except
1393 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1394 * called incorrectly, an attempt is made to seek off the end of the
1395 * buffer or such. This makes it easier to write safe and correct
1396 * code. For example, the QCBOR decoder implementation is safer and
1397 * easier to review through its use of @ref UsefulInputBuf.
1398 *
1399 * @ref UsefulInputBuf maintains an internal error state. The
1400 * intended use is fetching data chunks without any error checks until
1401 * the end. If there was any error, such as an attempt to fetch data
1402 * off the end, the error state is entered and no further data will be
1403 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1404 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1405 * null is not dereferenced, the error check can be put off until the
1406 * end, simplifying the calling code.
1407 *
1408 * The integer and float parsing expects network byte order (big
1409 * endian). Network byte order is what is used by TCP/IP, CBOR and
1410 * most internet protocols.
1411 *
1412 * Lots of inline functions are used to keep code size down. The
1413 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1414 * code size a lot. The only non-inline code is
1415 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1416 * @ref UsefulInputBuf doesn't add much code for all the messy
1417 * hard-to-get right issues with parsing binary protocols in C that it
1418 * solves.
1419 *
1420 * The parse context size is:
1421 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1422 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001423 */
1424typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001425 /* PRIVATE DATA STRUCTURE */
1426 UsefulBufC UB; /* Data being parsed */
1427 size_t cursor; /* Current offset in data being parse */
1428 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1429 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001430} UsefulInputBuf;
1431
1432#define UIB_MAGIC (0xB00F)
1433
1434
1435/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001436 * @brief Initialize the @ref UsefulInputBuf structure before use.
1437 *
1438 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1439 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001440 */
1441static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1442
1443
1444/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001445 * @brief Returns current position in input buffer.
1446 *
1447 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1448 *
1449 * @return Integer position of the cursor.
1450 *
1451 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001452 */
1453static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1454
1455
1456/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001457 * @brief Sets the current position in input buffer.
1458 *
1459 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1460 * @param[in] uPos Position to set to.
1461 *
1462 * If the position is off the end of the input buffer, the error state
1463 * is entered.
1464 *
1465 * Seeking to a valid position in the buffer will not reset the error
1466 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001467 */
1468static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1469
1470
1471/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001472 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1473 * the unconsumed bytes.
1474 *
1475 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1476 *
1477 * @return Number of bytes unconsumed or 0 on error.
1478 *
1479 * Returns 0 if the cursor is invalid or corruption of the
1480 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001481 */
1482static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1483
1484
1485/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001486 * @brief Check if there are unconsumed bytes.
1487 *
1488 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1489 * @param[in] uLen Number of bytes to check availability for.
1490 *
1491 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001492 */
1493static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1494
1495
1496/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001497 * @brief Convert a pointer to an offset with bounds checking.
1498 *
1499 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1500 * @param[in] p Pointer to convert to offset.
1501 *
1502 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1503 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001504static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1505
1506
1507/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001508 * @brief Get pointer to bytes out of the input buffer.
1509 *
1510 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1511 * @param[in] uNum Number of bytes to get.
1512 *
1513 * @return Pointer to bytes.
1514 *
1515 * This consumes @c uNum bytes from the input buffer. This returns a
1516 * pointer to the start of the @c uNum bytes.
1517 *
1518 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1519 * returned and the error state is entered.
1520 *
1521 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001522 */
1523const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1524
1525
1526/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001527 * @brief Get @ref UsefulBuf out of the input buffer.
1528 *
1529 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1530 * @param[in] uNum Number of bytes to get.
1531 *
1532 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1533 *
1534 * This consumes @c uNum bytes from the input buffer and returns the
1535 * pointer and length for them as a @ref UsefulBufC. The length
1536 * returned will always be @c uNum. The position cursor is advanced by
1537 * @c uNum bytes.
1538 *
1539 * If there are not @c uNum bytes in the input buffer, @ref
1540 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001541 */
1542static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1543
1544
1545/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001546 * @brief Get a byte out of the input buffer.
1547 *
1548 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1549 *
1550 * @return The byte.
1551 *
1552 * This consumes 1 byte from the input buffer, returns it and advances
1553 * the position cursor by 1.
1554 *
1555 * If there is not 1 byte in the buffer, 0 will be returned for the
1556 * byte and the error state is entered. To know if the 0 returned was
1557 * in error or the real value, the error state must be checked. If
1558 * possible, put this off until all values are retrieved to have
1559 * smaller and simpler code, but if not possible
1560 * UsefulInputBuf_GetError() can be called. Also, in the error state
1561 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1562 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001563 */
1564static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1565
1566
1567/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001568 * @brief Get a @c uint16_t out of the input buffer.
1569 *
1570 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1571 *
1572 * @return The @c uint16_t.
1573 *
1574 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1575 * a @c uint16_t and two bytes are consumed.
1576 *
1577 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001578 */
1579static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1580
1581
1582/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001583 * @brief Get a @c uint32_t out of the input buffer.
1584 *
1585 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1586 *
1587 * @return The @c uint32_t.
1588 *
1589 * See UsefulInputBuf_GetByte(). This works the same, except it
1590 * returns a @c uint32_t and four bytes are consumed.
1591 *
1592 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001593 */
1594static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1595
1596
1597/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001598 * @brief Get a @c uint64_t out of the input buffer.
1599 *
1600 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1601 *
1602 * @return The uint64_t.
1603 *
1604 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1605 * a @c uint64_t and eight bytes are consumed.
1606 *
1607 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001608 */
1609static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1610
1611
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001612#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001613/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001614 * @brief Get a float out of the input buffer.
1615 *
1616 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1617 *
1618 * @return The float.
1619 *
1620 * See UsefulInputBuf_GetByte(). This works the same, except it
1621 * returns a float and four bytes are consumed.
1622 *
1623 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001624 */
1625static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1626
1627
1628/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001629 * @brief Get a double out of the input buffer.
1630 *
1631 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1632 *
1633 * @return The double.
1634 *
1635 * See UsefulInputBuf_GetByte(). This works the same, except it
1636 * returns a double and eight bytes are consumed.
1637 *
1638 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001639 */
1640static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001641#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001642
1643
1644/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001645 * @brief Get the error status.
1646 *
1647 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1648 *
1649 * @return 0 if not in the error state, 1 if in the error state.
1650 *
1651 * This returns whether the @ref UsefulInputBuf is in the
1652 * error state or not.
1653 *
1654 * The error state is entered for one of these reasons:
1655 * - Attempt to fetch data past the end of the buffer
1656 * - Attempt to seek to a position past the end of the buffer
1657 * - Attempt to get data from an uninitialized or corrupt instance
1658 * of @ref UsefulInputBuf
1659 *
1660 * Once in the error state, it can only be cleared by calling
1661 * UsefulInputBuf_Init().
1662 *
1663 * For many use cases, it is possible to only call this once after all
1664 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1665 * possible if no reference to the data returned are needed before the
1666 * error state is checked.
1667 *
1668 * In some cases UsefulInputBuf_GetUsefulBuf() or
1669 * UsefulInputBuf_GetBytes() can stand in for this because they return
1670 * @c NULL if the error state has been entered. (The others can't stand
1671 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001672 */
1673static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1674
1675
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001676/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001677 * @brief Gets the input buffer length.
1678 *
1679 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1680 *
1681 * @return The length of the input buffer.
1682 *
1683 * This returns the length of the input buffer set by
1684 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001685 */
1686static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1687
1688
1689/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001690 * @brief Alters the input buffer length (use with caution).
1691 *
1692 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1693 * @param[in] uNewLen The new length of the input buffer.
1694 *
1695 * This alters the internal remembered length of the input buffer set
1696 * when UsefulInputBuf_Init() was called.
1697 *
1698 * The new length given here should always be equal to or less than
1699 * the length given when UsefulInputBuf_Init() was called. Making it
1700 * larger allows @ref UsefulInputBuf to run off the input buffer.
1701 *
1702 * The typical use is to set a length shorter than that when
1703 * initialized to constrain parsing. If
1704 * UsefulInputBuf_GetBufferLength() was called before this, then the
1705 * original length can be restored with another call to this.
1706 *
1707 * This should be used with caution. It is the only
1708 * @ref UsefulInputBuf method that can violate the safety of input
1709 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001710 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001711static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001712
1713
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001714
1715
Michael Eckel5c531332020-03-02 01:35:30 +01001716/*----------------------------------------------------------
1717 Inline implementations.
1718 */
1719static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1720{
1721 return !UB.ptr;
1722}
1723
1724
1725static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1726{
1727 return !UB.ptr;
1728}
1729
1730
1731static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1732{
1733 return !UB.len;
1734}
1735
1736
1737static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1738{
1739 return !UB.len;
1740}
1741
1742
1743static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1744{
1745 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1746}
1747
1748
1749static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1750{
1751 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1752}
1753
1754
1755static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1756{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001757 UsefulBufC UBC;
1758 UBC.ptr = UB.ptr;
1759 UBC.len = UB.len;
1760
1761 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001762}
1763
Michael Eckel5c531332020-03-02 01:35:30 +01001764static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1765{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001766 UsefulBuf UB;
1767
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001768 /* -Wcast-qual is a good warning flag to use in general. This is
1769 * the one place in UsefulBuf where it needs to be quieted. Since
1770 * clang supports GCC pragmas, this works for clang too. */
Dave Thaler93c01182022-08-06 15:08:35 -04001771#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001772#pragma GCC diagnostic push
1773#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -04001774#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001775 UB.ptr = (void *)UBC.ptr;
Dave Thaler93c01182022-08-06 15:08:35 -04001776#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001777#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -04001778#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001779
1780 UB.len = UBC.len;
1781
1782 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001783}
1784
1785
1786static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1787{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001788 UsefulBufC UBC;
1789 UBC.ptr = szString;
1790 UBC.len = strlen(szString);
1791 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001792}
1793
1794
1795static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1796{
1797 return UsefulBuf_CopyOffset(Dest, 0, Src);
1798}
1799
1800
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001801static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001802{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001803 memset(Dest.ptr, value, Dest.len);
1804
1805 UsefulBufC UBC;
1806 UBC.ptr = Dest.ptr;
1807 UBC.len = Dest.len;
1808
1809 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001810}
1811
1812
1813static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1814{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001815 UsefulBufC UBC;
1816 UBC.ptr = ptr;
1817 UBC.len = len;
1818 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001819}
1820
1821
1822static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1823{
1824 if(uAmount > UB.len) {
1825 return NULLUsefulBufC;
1826 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001827 UsefulBufC UBC;
1828
1829 UBC.ptr = UB.ptr;
1830 UBC.len = uAmount;
1831
1832 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001833}
1834
1835
1836static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1837{
1838 UsefulBufC ReturnValue;
1839
1840 if(uAmount > UB.len) {
1841 ReturnValue = NULLUsefulBufC;
1842 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001843 ReturnValue.ptr = NULL;
1844 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001845 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001846 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1847 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001848 }
1849
1850 return ReturnValue;
1851}
1852
1853
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001854static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1855{
1856 if(UB.ptr == NULL) {
1857 return SIZE_MAX;
1858 }
1859
1860 if(p < UB.ptr) {
1861 /* given pointer is before start of buffer */
1862 return SIZE_MAX;
1863 }
1864
1865 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001866 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001867
1868 if(uOffset >= UB.len) {
1869 /* given pointer is off the end of the buffer */
1870 return SIZE_MAX;
1871 }
1872
1873 return uOffset;
1874}
1875
Michael Eckel5c531332020-03-02 01:35:30 +01001876
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001877#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001878static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1879{
1880 uint32_t u32;
1881 memcpy(&u32, &f, sizeof(uint32_t));
1882 return u32;
1883}
1884
1885static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1886{
1887 uint64_t u64;
1888 memcpy(&u64, &d, sizeof(uint64_t));
1889 return u64;
1890}
1891
1892static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1893{
1894 double d;
1895 memcpy(&d, &u64, sizeof(uint64_t));
1896 return d;
1897}
1898
1899static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1900{
1901 float f;
1902 memcpy(&f, &u32, sizeof(uint32_t));
1903 return f;
1904}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001905#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001906
1907
1908
1909
1910static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1911{
1912 pMe->data_len = 0;
1913 pMe->err = 0;
1914}
1915
1916
1917static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1918{
1919 return pMe->data_len;
1920}
1921
1922
1923static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1924{
1925 return 0 == pMe->data_len;
1926}
1927
1928
1929static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1930 const void *pBytes,
1931 size_t uLen,
1932 size_t uPos)
1933{
1934 UsefulBufC Data = {pBytes, uLen};
1935 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1936}
1937
1938
1939static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1940 const char *szString,
1941 size_t uPos)
1942{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001943 UsefulBufC UBC;
1944 UBC.ptr = szString;
1945 UBC.len = strlen(szString);
1946
1947 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001948}
1949
1950
1951static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1952 uint8_t byte,
1953 size_t uPos)
1954{
1955 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1956}
1957
1958
1959static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1960 uint16_t uInteger16,
1961 size_t uPos)
1962{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001963 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001964
1965 const void *pBytes;
1966
1967#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1968 pBytes = &uInteger16;
1969
1970#elif defined(USEFULBUF_CONFIG_HTON)
1971 uint16_t uTmp = htons(uInteger16);
1972 pBytes = &uTmp;
1973
1974#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1975 uint16_t uTmp = __builtin_bswap16(uInteger16);
1976 pBytes = &uTmp;
1977
1978#else
1979 uint8_t aTmp[2];
1980
1981 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1982 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1983
1984 pBytes = aTmp;
1985#endif
1986
1987 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1988}
1989
1990
1991static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1992 uint32_t uInteger32,
1993 size_t uPos)
1994{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001995 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001996
1997 const void *pBytes;
1998
1999#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2000 pBytes = &uInteger32;
2001
2002#elif defined(USEFULBUF_CONFIG_HTON)
2003 uint32_t uTmp = htonl(uInteger32);
2004 pBytes = &uTmp;
2005
2006#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2007 uint32_t uTmp = __builtin_bswap32(uInteger32);
2008
2009 pBytes = &uTmp;
2010
2011#else
2012 uint8_t aTmp[4];
2013
2014 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2015 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2016 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2017 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2018
2019 pBytes = aTmp;
2020#endif
2021
2022 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2023}
2024
2025static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002026 uint64_t uInteger64,
2027 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002028{
2029 const void *pBytes;
2030
2031#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002032 /* We have been told explicitly we are running on a big-endian
2033 * machine. Network byte order is big endian, so just copy. There
2034 * is no issue with alignment here because uInteger64 is always
2035 * aligned (and it doesn't matter if pBytes is aligned).
2036 */
Michael Eckel5c531332020-03-02 01:35:30 +01002037 pBytes = &uInteger64;
2038
2039#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002040 /* Use system function to handle big- and little-endian. This works
2041 * on both big- and little-endian machines, but hton() is not
2042 * always available or in a standard place so it is not used by
2043 * default. With some compilers and CPUs the code for this is very
2044 * compact through use of a special swap instruction and on
2045 * big-endian machines hton() will reduce to nothing.
2046 */
Michael Eckel5c531332020-03-02 01:35:30 +01002047 uint64_t uTmp = htonll(uInteger64);
2048
2049 pBytes = &uTmp;
2050
2051#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002052 /* Use built-in function for byte swapping. This usually compiles
2053 * to an efficient special byte swap instruction. Unlike hton() it
2054 * does not do this conditionally on the CPU endianness, so this
2055 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2056 */
Michael Eckel5c531332020-03-02 01:35:30 +01002057 uint64_t uTmp = __builtin_bswap64(uInteger64);
2058
2059 pBytes = &uTmp;
2060
2061#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002062 /* Default which works on every CPU with no dependency on anything
2063 * from the CPU, compiler, libraries or OS. This always works, but
2064 * it is usually a little larger and slower than hton().
2065 */
Michael Eckel5c531332020-03-02 01:35:30 +01002066 uint8_t aTmp[8];
2067
2068 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2069 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2070 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2071 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2072 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2073 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2074 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2075 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2076
2077 pBytes = aTmp;
2078#endif
2079
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002080 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002081 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2082}
2083
2084
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002085#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002086static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2087 float f,
2088 size_t uPos)
2089{
2090 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2091}
2092
2093
2094static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2095 double d,
2096 size_t uPos)
2097{
2098 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2099}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002100#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002101
2102
2103static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2104 UsefulBufC NewData)
2105{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002106 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002107 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2108}
2109
2110
2111static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2112 const void *pBytes,
2113 size_t uLen)
2114{
2115 UsefulBufC Data = {pBytes, uLen};
2116 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2117}
2118
2119
2120static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2121 const char *szString)
2122{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002123 UsefulBufC UBC;
2124 UBC.ptr = szString;
2125 UBC.len = strlen(szString);
2126
2127 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002128}
2129
2130
2131static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2132 uint8_t byte)
2133{
2134 UsefulOutBuf_AppendData(pMe, &byte, 1);
2135}
2136
2137
2138static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2139 uint16_t uInteger16)
2140{
2141 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2142}
2143
2144static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2145 uint32_t uInteger32)
2146{
2147 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2148}
2149
2150
2151static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2152 uint64_t uInteger64)
2153{
2154 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
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_AppendFloat(UsefulOutBuf *pMe,
2160 float f)
2161{
2162 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2163}
2164
2165
2166static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2167 double d)
2168{
2169 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2170}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002171#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002172
2173
2174static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2175{
2176 return pMe->err;
2177}
2178
2179
2180static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2181{
2182 return pMe->UB.len - pMe->data_len;
2183}
2184
2185
2186static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2187{
2188 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2189}
2190
2191
2192static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2193{
2194 return pMe->UB.ptr == NULL;
2195}
2196
2197
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002198static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2199{
2200 UsefulBuf R;
2201
2202 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002203 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002204 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2205 } else {
2206 R.ptr = NULL;
2207 }
2208
2209 return R;
2210}
2211
2212
2213
Michael Eckel5c531332020-03-02 01:35:30 +01002214
2215static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2216{
2217 pMe->cursor = 0;
2218 pMe->err = 0;
2219 pMe->magic = UIB_MAGIC;
2220 pMe->UB = UB;
2221}
2222
2223static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2224{
2225 return pMe->cursor;
2226}
2227
2228
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002229static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002230{
2231 return pMe->UB.len;
2232}
2233
2234
Michael Eckel5c531332020-03-02 01:35:30 +01002235static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2236{
2237 if(uPos > pMe->UB.len) {
2238 pMe->err = 1;
2239 } else {
2240 pMe->cursor = uPos;
2241 }
2242}
2243
2244
2245static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2246{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002247 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002248
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002249 /* Magic number is messed up. Either the structure got overwritten
2250 * or was never initialized.
2251 */
Michael Eckel5c531332020-03-02 01:35:30 +01002252 if(pMe->magic != UIB_MAGIC) {
2253 return 0;
2254 }
2255
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002256 /* The cursor is off the end of the input buffer given.
2257 * Presuming there are no bugs in this code, this should never happen.
2258 * If it so, the struct was corrupted. The check is retained as
2259 * as a defense in case there is a bug in this code or the struct is
2260 * corrupted.
2261 */
Michael Eckel5c531332020-03-02 01:35:30 +01002262 if(pMe->cursor > pMe->UB.len) {
2263 return 0;
2264 }
2265
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002266 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002267 return pMe->UB.len - pMe->cursor;
2268}
2269
2270
2271static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2272{
2273 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2274}
2275
2276
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002277static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2278{
2279 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2280}
2281
2282
Michael Eckel5c531332020-03-02 01:35:30 +01002283static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2284{
2285 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2286 if(!pResult) {
2287 return NULLUsefulBufC;
2288 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002289 UsefulBufC UBC;
2290 UBC.ptr = pResult;
2291 UBC.len = uNum;
2292 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002293 }
2294}
2295
2296
2297static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2298{
2299 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2300
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002301 /* The ternary operator is subject to integer promotion, because
2302 * the operands are smaller than int, so cast back to uint8_t is
2303 * needed to be completely explicit about types (for static
2304 * analyzers).
2305 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002306 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002307}
2308
2309static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2310{
2311 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2312
2313 if(!pResult) {
2314 return 0;
2315 }
2316
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002317 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002318#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2319 uint16_t uTmp;
2320 memcpy(&uTmp, pResult, sizeof(uint16_t));
2321
2322#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2323 return uTmp;
2324
2325#elif defined(USEFULBUF_CONFIG_HTON)
2326 return ntohs(uTmp);
2327
2328#else
2329 return __builtin_bswap16(uTmp);
2330
2331#endif
2332
2333#else
2334
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002335 /* The operations here are subject to integer promotion because the
2336 * operands are smaller than int. They will be promoted to unsigned
2337 * int for the shift and addition. The cast back to uint16_t is is
2338 * needed to be completely explicit about types (for static
2339 * analyzers).
2340 */
Michael Eckel5c531332020-03-02 01:35:30 +01002341 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2342
2343#endif
2344}
2345
2346
2347static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2348{
2349 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2350
2351 if(!pResult) {
2352 return 0;
2353 }
2354
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002355 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002356#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2357 uint32_t uTmp;
2358 memcpy(&uTmp, pResult, sizeof(uint32_t));
2359
2360#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2361 return uTmp;
2362
2363#elif defined(USEFULBUF_CONFIG_HTON)
2364 return ntohl(uTmp);
2365
2366#else
2367 return __builtin_bswap32(uTmp);
2368
2369#endif
2370
2371#else
2372 return ((uint32_t)pResult[0]<<24) +
2373 ((uint32_t)pResult[1]<<16) +
2374 ((uint32_t)pResult[2]<<8) +
2375 (uint32_t)pResult[3];
2376#endif
2377}
2378
2379
2380static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2381{
2382 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2383
2384 if(!pResult) {
2385 return 0;
2386 }
2387
2388#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002389 /* pResult will probably not be aligned. This memcpy() moves the
2390 * bytes into a temp variable safely for CPUs that can or can't do
2391 * unaligned memory access. Many compilers will optimize the
2392 * memcpy() into a simple move instruction.
2393 */
Michael Eckel5c531332020-03-02 01:35:30 +01002394 uint64_t uTmp;
2395 memcpy(&uTmp, pResult, sizeof(uint64_t));
2396
2397#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002398 /* We have been told expliclity this is a big-endian CPU. Since
2399 * network byte order is big-endian, there is nothing to do.
2400 */
Michael Eckel5c531332020-03-02 01:35:30 +01002401
2402 return uTmp;
2403
2404#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002405 /* We have been told to use ntoh(), the system function to handle
2406 * big- and little-endian. This works on both big- and
2407 * little-endian machines, but ntoh() is not always available or in
2408 * a standard place so it is not used by default. On some CPUs the
2409 * code for this is very compact through use of a special swap
2410 * instruction.
2411 */
Michael Eckel5c531332020-03-02 01:35:30 +01002412
2413 return ntohll(uTmp);
2414
2415#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002416 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2417 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2418 * __builtin_bswap64() and friends are not conditional on CPU
2419 * endianness so this must only be used on little-endian machines.
2420 */
Michael Eckel5c531332020-03-02 01:35:30 +01002421
2422 return __builtin_bswap64(uTmp);
2423
2424
2425#endif
2426
2427#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002428 /* This is the default code that works on every CPU and every
2429 * endianness with no dependency on ntoh(). This works on CPUs
2430 * that either allow or do not allow unaligned access. It will
2431 * always work, but usually is a little less efficient than ntoh().
2432 */
Michael Eckel5c531332020-03-02 01:35:30 +01002433
2434 return ((uint64_t)pResult[0]<<56) +
2435 ((uint64_t)pResult[1]<<48) +
2436 ((uint64_t)pResult[2]<<40) +
2437 ((uint64_t)pResult[3]<<32) +
2438 ((uint64_t)pResult[4]<<24) +
2439 ((uint64_t)pResult[5]<<16) +
2440 ((uint64_t)pResult[6]<<8) +
2441 (uint64_t)pResult[7];
2442#endif
2443}
2444
2445
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002446#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002447static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2448{
2449 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2450
2451 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2452}
2453
2454
2455static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2456{
2457 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2458
2459 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2460}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002461#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002462
2463
2464static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2465{
2466 return pMe->err;
2467}
2468
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002469
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002470static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002471{
2472 pMe->UB.len = uNewLen;
2473}
2474
2475
Michael Eckel5c531332020-03-02 01:35:30 +01002476#ifdef __cplusplus
2477}
2478#endif
2479
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002480#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002481
2482