blob: 5f530445a1177d087292c1b67447b260a92f1caa [file] [log] [blame]
Laurence Lundblade3eead482023-12-16 20:53:22 -07001/* =========================================================================
2 * Copyright (c) 2016-2018, The Linux Foundation.
3 * Copyright (c) 2018-2022, Laurence Lundblade.
4 * Copyright (c) 2021, Arm Limited. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of The Linux Foundation nor the names of its
17 * contributors, nor the name "Laurence Lundblade" may be used to
18 * endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ========================================================================= */
Michael Eckel5c531332020-03-02 01:35:30 +010033
34/*============================================================================
35 FILE: UsefulBuf.h
36
37 DESCRIPTION: General purpose input and output buffers
38
39 EDIT HISTORY FOR FILE:
40
41 This section contains comments describing changes made to the module.
42 Notice that changes are listed in reverse chronological order.
43
44 when who what, where, why
45 -------- ---- --------------------------------------------------
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070046 19/12/2022 llundblade Document that adding empty data is allowed.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060047 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070048 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070049 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070050 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080051 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070052 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010053 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
54 5/21/2019 llundblade #define configs for efficient endianness handling.
55 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
56 3/23/2019 llundblade Big documentation & style update. No interface
57 change.
58 3/6/2019 llundblade Add UsefulBuf_IsValue()
59 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
60 12/13/2018 llundblade Documentation improvements
61 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
62 UsefulBufC.
63 02/02/18 llundbla Full support for integers in and out; fix pointer
64 alignment bug. Incompatible change: integers
65 in/out are now in network byte order.
66 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
67 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
68 comparison for < or > for unequal length buffers.
69 Added UsefulBuf_Set() function.
70 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
71 11/13/16 llundbla Initial Version.
72
73 =============================================================================*/
74
75#ifndef _UsefulBuf_h
76#define _UsefulBuf_h
77
78
79/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070080 * Endianness Configuration
81 *
82 * This code is written so it will work correctly on big- and
83 * little-endian CPUs without configuration or any auto-detection of
84 * endianness. All code here will run correctly regardless of the
85 * endianness of the CPU it is running on.
86 *
87 * There are four C preprocessor macros that can be set with #define
88 * to explicitly configure endianness handling. Setting them can
89 * reduce code size a little and improve efficiency a little.
90 *
91 * Note that most of QCBOR is unaffected by this configuration. Its
92 * endianness handling is integrated with the code that handles
93 * alignment and preferred serialization. This configuration does
94 * affect QCBOR's (planned) implementation of integer arrays (tagged
95 * arrays) and use of the functions here to serialize or deserialize
96 * integers and floating-point values.
97 *
98 * Following is the recipe for configuring the endianness-related
99 * #defines.
100 *
101 * The first option is to not define anything. This will work fine
102 * with all CPUs, OS's and compilers. The code for encoding integers
103 * may be a little larger and slower.
104 *
105 * If your CPU is big-endian then define
106 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
107 * for big-endian CPUs. It will be small and efficient because there
108 * will be no byte swapping.
109 *
110 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
111 * OS's and compilers, but not all. On big-endian CPUs this should
112 * give the most efficient code, the same as
113 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
114 * call the system-defined byte swapping method which is presumably
115 * implemented efficiently. In some cases, this will be a dedicated
116 * byte swap instruction like Intel's bswap.
117 *
118 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
119 * little-endian, it is also good to define
120 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
121 *
122 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
123 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
124 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
125 * system-defined byte swap method. However, note
126 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
127 * this is fixed now. Often hton() and ntoh() will call the built-in
128 * __builtin_bswapXX()() function, so this size issue could affect
129 * USEFULBUF_CONFIG_HTON.
130 *
131 * Last, run the tests. They must all pass.
132 *
133 * These #define config options affect the inline implementation of
134 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
135 * also affect the 16-, 32-bit, float and double versions of these
136 * functions. Since they are inline, the size effect is not in the
137 * UsefulBuf object code, but in the calling code.
138 *
139 * Summary:
140 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
141 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
142 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
143 * handle big and little-endian with system option.
144 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
145 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200146 *
147 * It is possible to run this code in environments where using floating point is
148 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
149 * that is related to handling floating point types, along with related
150 * interfaces. This makes it possible to compile the code with the compile
151 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100152 */
153
154#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
155#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
156#endif
157
158
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700159#include <stdint.h> /* for uint8_t, uint16_t.... */
160#include <string.h> /* for strlen, memcpy, memmove, memset */
161#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100162
163
164#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700165#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100166#endif
167
168#ifdef __cplusplus
169extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700170#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700171} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700172#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100173#endif
174
175/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700176 * @file UsefulBuf.h
177 *
178 * The goal of this code is to make buffer and pointer manipulation
179 * easier and safer when working with binary data.
180 *
181 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
182 * structures are used to represent buffers rather than ad hoc
183 * pointers and lengths.
184 *
185 * With these it is possible to write code that does little or no
186 * direct pointer manipulation for copying and formatting data. For
187 * example, the QCBOR encoder was written using these and has less
188 * pointer manipulation.
189 *
190 * While it is true that object code using these functions will be a
191 * little larger and slower than a white-knuckle clever use of
192 * pointers might be, but not by that much or enough to have an effect
193 * for most use cases. For security-oriented code this is highly
194 * worthwhile. Clarity, simplicity, reviewability and are more
195 * important.
196 *
197 * There are some extra sanity and double checks in this code to help
198 * catch coding errors and simple memory corruption. They are helpful,
199 * but not a substitute for proper code review, input validation and
200 * such.
201 *
202 * This code consists of a lot of inline functions and a few that are
203 * not. It should not generate very much object code, especially with
204 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100205 */
206
207
208/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700209 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
210 * hold a pointer and length for binary data. In C99 this data
211 * structure can be passed on the stack making a lot of code cleaner
212 * than carrying around a pointer and length as two parameters.
213 *
214 * This is also conducive to secure coding practice as the length is
215 * always carried with the pointer and the convention for handling a
216 * pointer and a length is clear.
217 *
218 * While it might be possible to write buffer and pointer code more
219 * efficiently in some use cases, the thought is that unless there is
220 * an extreme need for performance (e.g., you are building a
221 * gigabit-per-second IP router), it is probably better to have
222 * cleaner code you can be most certain about the security of.
223 *
224 * The non-const @ref UsefulBuf is usually used to refer an empty
225 * buffer to be filled in. The length is the size of the buffer.
226 *
227 * The const @ref UsefulBufC is usually used to refer to some data
228 * that has been filled in. The length is amount of valid data pointed
229 * to.
230 *
231 * A common use mode is to pass a @ref UsefulBuf to a function, the
232 * function puts some data in it, then the function returns a @ref
233 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
234 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
235 * so the constness stays correct. There is no single "in,out"
236 * parameter (if there was, it would have to be non-const). Note that
237 * the pointer returned in the @ref UsefulBufC usually ends up being
238 * the same pointer passed in as a @ref UsefulBuf, though this is not
239 * striclty required.
240 *
241 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
242 * @c NULL.
243 *
244 * There are functions and macros for the following:
245 * - Initializing
246 * - Create initialized const @ref UsefulBufC from compiler literals
247 * - Create initialized const @ref UsefulBufC from NULL-terminated string
248 * - Make an empty @ref UsefulBuf on the stack
249 * - Checking whether a @ref UsefulBuf is null, empty or both
250 * - Copying, copying with offset, copying head or tail
251 * - Comparing and finding substrings
252 *
253 * See also @ref UsefulOutBuf. It is a richer structure that has both
254 * the size of the valid data and the size of the buffer.
255 *
256 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
257 * it can go on the stack and be a function parameter or return value.
258 *
259 * Another way to look at it is this. C has the NULL-terminated string
260 * as a means for handling text strings, but no means or convention
261 * for binary strings. Other languages do have such means, Rust, an
262 * efficient compiled language, for example.
263 *
264 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
265 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
266 * out like anything".
267 */
Michael Eckel5c531332020-03-02 01:35:30 +0100268typedef struct q_useful_buf_c {
269 const void *ptr;
270 size_t len;
271} UsefulBufC;
272
273
274/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700275 * This non-const @ref UsefulBuf is typically used for some allocated
276 * memory that is to be filled in. The @c len is the amount of memory,
277 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100278 */
279typedef struct q_useful_buf {
280 void *ptr;
281 size_t len;
282} UsefulBuf;
283
284
285/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700286 * A null @ref UsefulBufC is one that has no value in the same way a
287 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
288 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
289 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100290 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700291/*
292 * NULLUsefulBufC and few other macros have to be
293 * definied differently in C than C++ because there
294 * is no common construct for a literal structure.
295 *
296 * In C compound literals are used.
297 *
298 * In C++ list initalization is used. This only works
299 * in C++11 and later.
300 *
301 * Note that some popular C++ compilers can handle compound
302 * literals with on-by-default extensions, however
303 * this code aims for full correctness with strict
304 * compilers so they are not used.
305 */
306#ifdef __cplusplus
307#define NULLUsefulBufC {NULL, 0}
308#else
309#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
310#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100311
312/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700313 * A null @ref UsefulBuf is one that has no memory associated the same
314 * way @c NULL points to nothing. It does not matter what @c len is.
315 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700316#ifdef __cplusplus
317#define NULLUsefulBuf {NULL, 0}
318#else
319#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
320#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100321
322
323/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700324 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
325 *
326 * @param[in] UB The UsefulBuf to check.
327 *
328 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100329 */
330static inline int UsefulBuf_IsNULL(UsefulBuf UB);
331
332
333/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700334 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
335 *
336 * @param[in] UB The @ref UsefulBufC to check.
337 *
338 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100339 */
340static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
341
342
343/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700344 * @brief Check if a @ref UsefulBuf is empty or not.
345 *
346 * @param[in] UB The @ref UsefulBuf to check.
347 *
348 * @return 1 if it is empty, 0 if not.
349 *
350 * An "empty" @ref UsefulBuf is one that has a value and can be
351 * considered to be set, but that value is of zero length. It is
352 * empty when @c len is zero. It doesn't matter what the @c ptr is.
353 *
354 * Many uses will not need to clearly distinguish a @c NULL @ref
355 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
356 * @c len 0. However if a use of @ref UsefulBuf needs to make a
357 * distinction then @c ptr should not be @c NULL when the @ref
358 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100359 */
360static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
361
362
363/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700364 * @brief Check if a @ref UsefulBufC is empty or not.
365 *
366 * @param[in] UB The @ref UsefulBufC to check.
367 *
368 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100369 */
370static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
371
372
373/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700374 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
375 *
376 * @param[in] UB The @ref UsefulBuf to check.
377 *
378 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100379 */
380static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
381
382
383/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700384 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
385 *
386 * @param[in] UB The @ref UsefulBufC to check.
387 *
388 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100389 */
390static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
391
392
393/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700394 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
395 *
396 * @param[in] UB The @ref UsefulBuf to convert.
397 *
398 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100399 */
400static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
401
402
403/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700404 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
405 *
406 * @param[in] UBC The @ref UsefulBuf to convert.
407 *
408 * @return A non-const @ref UsefulBuf struct.
409 *
410 * Use of this is not necessary for the intended use mode of @ref
411 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
412 * created to describe a buffer that has not had any data put in
413 * it. Then the data is put in it. Then a @ref UsefulBufC is create
414 * to describe the part with the data in it. This goes from non-const
415 * to const, so this function is not needed.
416 *
417 * If the -Wcast-qual warning is enabled, this function can be used to
418 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100419 */
420static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
421
422
423/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700424 * Convert a literal string to a @ref UsefulBufC.
425 *
426 * @c szString must be a literal string that @c sizeof() works on.
427 * This is better for literal strings than UsefulBuf_FromSZ() because
428 * it generates less code. It will not work on non-literal strings.
429 *
430 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100431 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700432#ifdef __cplusplus
433#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
434#else
Michael Eckel5c531332020-03-02 01:35:30 +0100435#define UsefulBuf_FROM_SZ_LITERAL(szString) \
436 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700437#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100438
439
440/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700441 * Convert a literal byte array to a @ref UsefulBufC.
442 *
443 * @c pBytes must be a literal string that @c sizeof() works on. It
444 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100445 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700446#ifdef __cplusplus
447#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
448#else
Michael Eckel5c531332020-03-02 01:35:30 +0100449#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700450 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
451#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100452
453/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700454 * Make an automatic variable named @c name of type @ref UsefulBuf and
455 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100456 */
457#define UsefulBuf_MAKE_STACK_UB(name, size) \
458 uint8_t __pBuf##name[(size)];\
459 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
460
461
462/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700463 * Make a byte array in to a @ref UsefulBuf. This is usually used on
464 * stack variables or static variables. Also see @ref
465 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100466 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700467#ifdef __cplusplus
468#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
469#else
Michael Eckel5c531332020-03-02 01:35:30 +0100470#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700471 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
472#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100473
474
475/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700476 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
477 *
478 * @param[in] szString The string to convert.
479 *
480 * @return A @ref UsefulBufC struct.
481 *
482 * @c UsefulBufC.ptr points to the string so its lifetime must be
483 * maintained.
484 *
485 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100486 */
487static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
488
489
490/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700491 * @brief Copy one @ref UsefulBuf into another at an offset.
492 *
493 * @param[in] Dest Destination buffer to copy into.
494 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
495 * @param[in] Src The bytes to copy.
496 *
497 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
498 *
499 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
500 * size of @c Dest.
501 *
502 * This fails and returns @ref NULLUsefulBufC if the @c Src length
503 * plus @c uOffset is greater than the length of @c Dest.
504 *
505 * The results are undefined if @c Dest and @c Src overlap.
506 *
507 * This assumes that there is valid data in @c Dest up to @c
508 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
509 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100510 */
511UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
512
513
514/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700515 * @brief Copy one @ref UsefulBuf into another.
516 *
517 * @param[in] Dest The destination buffer to copy into.
518 * @param[out] Src The source to copy from.
519 *
520 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
521 * on failure.
522 *
523 * This fails if @c Src.len is greater than @c Dest.len.
524 *
525 * Note that like @c memcpy(), the pointers are not checked and this
526 * will crash rather than return @ref NULLUsefulBufC if they are @c
527 * NULL or invalid.
528 *
529 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100530 */
531static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
532
533
534/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700535 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
536 *
537 * @param[in] pDest The destination buffer to copy into.
538 * @param[in] value The value to set the bytes to.
539 *
540 * Note that like @c memset(), the pointer in @c pDest is not checked
541 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100542 */
543static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
544
545
546/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700547 * @brief Copy a pointer into a @ref UsefulBuf.
548 *
549 * @param[in,out] Dest The destination buffer to copy into.
550 * @param[in] ptr The source to copy from.
551 * @param[in] uLen Length of the source; amount to copy.
552 *
553 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
554 * on failure.
555 *
556 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
557 * than @c pDest->len.
558 *
559 * Note that like @c memcpy(), the pointers are not checked and this
560 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100561 */
562static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
563 const void *ptr,
564 size_t uLen);
565
566
567/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700568 * @brief Returns a truncation of a @ref UsefulBufC.
569 *
570 * @param[in] UB The buffer to get the head of.
571 * @param[in] uAmount The number of bytes in the head.
572 *
573 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100574 */
575static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
576
577
578/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700579 * @brief Returns bytes from the end of a @ref UsefulBufC.
580 *
581 * @param[in] UB The buffer to get the tail of.
582 * @param[in] uAmount The offset from the start where the tail is to begin.
583 *
584 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
585 * if @c uAmount is greater than the length of the @ref UsefulBufC.
586 *
587 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
588 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
589 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100590 */
591static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
592
593
594/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700595 * @brief Compare one @ref UsefulBufC to another.
596 *
597 * @param[in] UB1 The first buffer to compare.
598 * @param[in] UB2 The second buffer to compare.
599 *
600 * @return 0, positive or negative value.
601 *
602 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
603 * less than @c UB2 if it is shorter or the first byte that is not the
604 * same is less.
605 *
606 * Returns 0 if the inputs are the same.
607 *
608 * Returns a positive value if @c UB2 is less than @c UB1.
609 *
610 * All that is of significance is that the result is positive, negative
611 * or 0. (This doesn't return the difference between the first
612 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100613 */
614int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
615
616
617/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700618 * @brief Find first byte that is not a particular byte value.
619 *
620 * @param[in] UB The destination buffer for byte comparison.
621 * @param[in] uValue The byte value to compare to.
622 *
623 * @return Offset of first byte that isn't @c uValue or
624 * @c SIZE_MAX if all bytes are @c uValue.
625 *
626 * Note that unlike most comparison functions, 0
627 * does not indicate a successful comparison, so the
628 * test for match is:
629 *
630 * UsefulBuf_IsValue(...) == SIZE_MAX
631 *
632 * If @c UB is null or empty, there is no match
633 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100634 */
635size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
636
637
638/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700639 * @brief Find one @ref UsefulBufC in another.
640 *
641 * @param[in] BytesToSearch Buffer to search through.
642 * @param[in] BytesToFind Buffer with bytes to be found.
643 *
644 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100645 */
646size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
647
648
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700649/**
650 @brief Convert a pointer to an offset with bounds checking.
651
652 @param[in] UB Pointer to the UsefulInputBuf.
653 @param[in] p Pointer to convert to offset.
654
655 @return SIZE_MAX if @c p is out of range, the byte offset if not.
656*/
657static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
658
659
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800660#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100661/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700662#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100663
664/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
665#define MakeUsefulBufOnStack(name, size) \
666 uint8_t __pBuf##name[(size)];\
667 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
668
669/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
670#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700671 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100672
673/** Deprecated function; use UsefulBuf_Unconst() instead */
674static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
675{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700676 UsefulBuf UB;
677
Laurence Lundblade3eead482023-12-16 20:53:22 -0700678 /* See UsefulBuf_Unconst() implementation for comment */
Maxim Zhukovd538f0a2022-12-20 20:40:38 +0300679 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700680
681 UB.len = UBC.len;
682
683 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100684}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800685#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100686
687
688
689
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200690#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100691/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700692 * @brief Copy a @c float to a @c uint32_t.
693 *
694 * @param[in] f Float value to copy.
695 *
696 * @return A @c uint32_t with the float bits.
697 *
698 * Convenience function to avoid type punning, compiler warnings and
699 * such. The optimizer usually reduces this to a simple assignment. This
700 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100701 */
702static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
703
704
705/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700706 * @brief Copy a @c double to a @c uint64_t.
707 *
708 * @param[in] d Double value to copy.
709 *
710 * @return A @c uint64_t with the double bits.
711 *
712 * Convenience function to avoid type punning, compiler warnings and
713 * such. The optimizer usually reduces this to a simple assignment. This
714 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100715 */
716static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
717
718
719/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700720 * @brief Copy a @c uint32_t to a @c float.
721 *
722 * @param[in] u32 Integer value to copy.
723 *
724 * @return The value as a @c float.
725 *
726 * Convenience function to avoid type punning, compiler warnings and
727 * such. The optimizer usually reduces this to a simple assignment. This
728 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100729 */
730static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
731
732
733/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700734 * @brief Copy a @c uint64_t to a @c double.
735 *
736 * @param[in] u64 Integer value to copy.
737 *
738 * @return The value as a @c double.
739 *
740 * Convenience function to avoid type punning, compiler warnings and
741 * such. The optimizer usually reduces this to a simple assignment. This
742 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100743 */
744static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200745#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100746
747
748
749
750/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700751 * UsefulOutBuf is a structure and functions (an object) for
752 * serializing data into a buffer to encode for a network protocol or
753 * write data to a file.
754 *
755 * The main idea is that all the pointer manipulation is performed by
756 * @ref UsefulOutBuf functions so the caller doesn't have to do any
757 * pointer manipulation. The pointer manipulation is centralized.
758 * This code has been reviewed and written carefully so it
759 * spares the caller of much of this work and results in safer code
760 * with less effort.
761 *
762 * The @ref UsefulOutBuf methods that add data to the output buffer
763 * always check the length and will never write off the end of the
764 * output buffer. If an attempt to add data that will not fit is made,
765 * an internal error flag will be set and further attempts to add data
766 * will not do anything.
767 *
768 * There is no way to ever write off the end of that buffer when
769 * calling the @c UsefulOutBuf_AddXxx() and
770 * @c UsefulOutBuf_InsertXxx() functions.
771 *
772 * The functions to add data do not report success of failure. The
773 * caller only needs to check for an error in the final call, either
774 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
775 * result. This makes the calling code cleaner.
776 *
777 * There is a utility function to get the error status anytime along
778 * the way for a special circumstance. There are functions to see how
779 * much room is left and see if some data will fit too, but their use
780 * is generally unnecessary.
781 *
782 * The general call flow is:
783 *
784 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
785 * buffer given to it can be from the heap, stack or
786 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
787 * macro that makes a buffer on the stack and initializes it.
788 *
789 * - Call methods like UsefulOutBuf_InsertString(),
790 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
791 * to output data. The append calls add data to the end of the
792 * valid data. The insert calls take a position argument.
793 *
794 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
795 * there were no errors and to get the serialized output bytes.
796 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700797 * @ref UsefulOutBuf can be used in a mode to calculate the size of
798 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700799 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700800 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700801 *
802 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700803 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700804 *
805 * The possible errors are:
806 *
807 * - The @ref UsefulOutBuf was not initialized or was corrupted.
808 *
809 * - An attempt was made to add data that will not fit.
810 *
811 * - An attempt was made to insert data at a position beyond the end of
812 * the buffer.
813 *
814 * - An attempt was made to insert data at a position beyond the valid
815 * data in the buffer.
816 *
817 * Some inexpensive simple sanity checks are performed before every
818 * data addition to guard against use of an uninitialized or corrupted
819 * UsefulOutBuf.
820 *
821 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
822 * encoder has almost no pointer manipulation in it, is easier to
823 * read, and easier to review.
824 *
825 * A @ref UsefulOutBuf is small and can go on the stack:
826 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
827 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100828 */
829typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700830 /* PRIVATE DATA STRUCTURE */
831 UsefulBuf UB; /* Memory that is being output to */
832 size_t data_len; /* length of the valid data, the insertion point */
833 uint16_t magic; /* Used to detect corruption and lack
834 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100835 uint8_t err;
836} UsefulOutBuf;
837
838
839/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700840 * This is a @ref UsefulBuf value that can be passed to
841 * UsefulOutBuf_Init() to have it calculate the size of the output
842 * buffer needed. Pass this for @c Storage, call all the append and
843 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
844 * returned @ref UsefulBufC has the size.
845 *
846 * As one can see, this is just a NULL pointer and very large size.
847 * The NULL pointer tells UsefulOutputBuf to not copy any data.
848 */
849#ifdef __cplusplus
850#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
851#else
852#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
853#endif
854
855
856/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700857 * @brief Initialize and supply the actual output buffer.
858 *
859 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
860 * @param[in] Storage Buffer to output into.
861 *
862 * This initializes the @ref UsefulOutBuf with storage, sets the
863 * current position to the beginning of the buffer and clears the
864 * error state.
865 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700866 * See @ref SizeCalculateUsefulBuf for instructions on how to
867 * initialize a @ref UsefulOutBuf to calculate the size that would be
868 * output without actually outputting.
869 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700870 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100871 */
872void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
873
874
875/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700876 * Convenience macro to make a @ref UsefulOutBuf on the stack and
877 * initialize it with a stack buffer of the given size. The variable
878 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100879 */
880#define UsefulOutBuf_MakeOnStack(name, size) \
881 uint8_t __pBuf##name[(size)];\
882 UsefulOutBuf name;\
883 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
884
885
886/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700887 * @brief Reset a @ref UsefulOutBuf for re use.
888 *
889 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
890 *
891 * This sets the amount of data in the output buffer to none and
892 * clears the error state.
893 *
894 * The output buffer is still the same one and size as from the
895 * UsefulOutBuf_Init() call.
896 *
897 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100898 */
899static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
900
901
902/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700903 * @brief Returns position of end of data in the @ref UsefulOutBuf.
904 *
905 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
906 *
907 * @return position of end of data.
908 *
909 * On a freshly initialized @ref UsefulOutBuf with no data added, this
910 * will return 0. After 10 bytes have been added, it will return 10
911 * and so on.
912 *
913 * Generally, there is no need to call this for most uses of @ref
914 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100915 */
916static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
917
918
919/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700920 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
921 *
922 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
923 *
924 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100925 */
926static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
927
928
929/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700930 * @brief Inserts bytes into the @ref UsefulOutBuf.
931 *
932 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
933 * @param[in] NewData The bytes to insert.
934 * @param[in] uPos Index in output buffer at which to insert.
935 *
936 * @c NewData is the pointer and length for the bytes to be added to
937 * the output buffer. There must be room in the output buffer for all
938 * of @c NewData or an error will occur.
939 *
940 * The insertion point must be between 0 and the current valid
941 * data. If not, an error will occur. Appending data to the output
942 * buffer is achieved by inserting at the end of the valid data. This
943 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
944 *
945 * When insertion is performed, the bytes between the insertion point
946 * and the end of data previously added to the output buffer are slid
947 * to the right to make room for the new data.
948 *
949 * Overlapping buffers are OK. @c NewData can point to data in the
950 * output buffer.
951 *
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700952 * NewData.len may be 0 in which case nothing will be inserted.
953 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700954 * If an error occurs, an error state is set in the @ref
955 * UsefulOutBuf. No error is returned. All subsequent attempts to add
956 * data will do nothing.
957 *
958 * The intended use is that all additions are made without checking
959 * for an error. The error will be taken into account when
960 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
961 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100962 */
963void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
964 UsefulBufC NewData,
965 size_t uPos);
966
967
968/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700969 * @brief Insert a data buffer into the @ref UsefulOutBuf.
970 *
971 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
972 * @param[in] pBytes Pointer to the bytes to insert
973 * @param[in] uLen Length of the bytes to insert
974 * @param[in] uPos Index in output buffer at which to insert
975 *
976 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
977 * the difference being a pointer and length is passed in rather than an
978 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100979 */
980static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
981 const void *pBytes,
982 size_t uLen,
983 size_t uPos);
984
985
986/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700987 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
988 *
989 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
990 * @param[in] szString NULL-terminated string to insert.
991 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100992 */
993static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
994 const char *szString,
995 size_t uPos);
996
997
998/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700999 * @brief Insert a byte into the @ref UsefulOutBuf.
1000 *
1001 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1002 * @param[in] byte Bytes to insert.
1003 * @param[in] uPos Index in output buffer at which to insert.
1004 *
1005 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1006 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001007 */
1008static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1009 uint8_t byte,
1010 size_t uPos);
1011
1012
1013/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001014 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1015 *
1016 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1017 * @param[in] uInteger16 Integer to insert.
1018 * @param[in] uPos Index in output buffer at which to insert.
1019 *
1020 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1021 * with the difference being a two-byte integer is to be inserted.
1022 *
1023 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001024 */
1025static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1026 uint16_t uInteger16,
1027 size_t uPos);
1028
1029
1030/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001031 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1032 *
1033 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1034 * @param[in] uInteger32 Integer to insert.
1035 * @param[in] uPos Index in output buffer at which to insert.
1036 *
1037 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1038 * with the difference being a four-byte integer is to be inserted.
1039 *
1040 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001041 */
1042static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1043 uint32_t uInteger32,
1044 size_t uPos);
1045
1046
1047/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001048 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1049 *
1050 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1051 * @param[in] uInteger64 Integer to insert.
1052 * @param[in] uPos Index in output buffer at which to insert.
1053 *
1054 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1055 * with the difference being an eight-byte integer is to be inserted.
1056 *
1057 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001058 */
1059static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1060 uint64_t uInteger64,
1061 size_t uPos);
1062
1063
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001064#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001065/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001066 * @brief Insert a @c float into the @ref UsefulOutBuf.
1067 *
1068 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1069 * @param[in] f @c float to insert.
1070 * @param[in] uPos Index in output buffer at which to insert.
1071 *
1072 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1073 * with the difference being a @c float is to be inserted.
1074 *
1075 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001076 */
1077static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1078 float f,
1079 size_t uPos);
1080
1081
1082/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001083 * @brief Insert a @c double into the @ref UsefulOutBuf.
1084 *
1085 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1086 * @param[in] d @c double to insert.
1087 * @param[in] uPos Index in output buffer at which to insert.
1088 *
1089 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1090 * with the difference being a @c double is to be inserted.
1091 *
1092 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001093 */
1094static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1095 double d,
1096 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001097#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001098
1099
1100/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001101 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1102 *
1103 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1104 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1105 *
1106 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1107 * with the insertion point at the end of the valid data.
1108 */
Michael Eckel5c531332020-03-02 01:35:30 +01001109static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1110 UsefulBufC NewData);
1111
1112
1113/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001114 * @brief Append bytes to the @ref UsefulOutBuf.
1115 *
1116 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1117 * @param[in] pBytes Pointer to bytes to append.
1118 * @param[in] uLen Length of @c pBytes to append.
1119 *
1120 * See UsefulOutBuf_InsertData() for details. This does the same with
1121 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001122 */
1123static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1124 const void *pBytes,
1125 size_t uLen);
1126
1127
1128/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001129 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1130 *
1131 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1132 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001133 */
1134static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1135 const char *szString);
1136
1137
1138/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001139 * @brief Append a byte to the @ref UsefulOutBuf
1140 *
1141 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1142 * @param[in] byte Bytes to append.
1143 *
1144 * See UsefulOutBuf_InsertByte() for details. This does the same
1145 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001146 */
1147static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1148 uint8_t byte);
1149
1150
1151/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001152 * @brief Append an integer to the @ref UsefulOutBuf
1153 *
1154 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1155 * @param[in] uInteger16 Integer to append.
1156 *
1157 * See UsefulOutBuf_InsertUint16() for details. This does the same
1158 * with the insertion point at the end of the valid data.
1159 *
1160 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001161 */
1162static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1163 uint16_t uInteger16);
1164
1165
1166/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001167 * @brief Append an integer to the @ref UsefulOutBuf
1168 *
1169 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1170 * @param[in] uInteger32 Integer to append.
1171 *
1172 * See UsefulOutBuf_InsertUint32() for details. This does the same
1173 * with the insertion point at the end of the valid data.
1174 *
1175 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001176 */
1177static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1178 uint32_t uInteger32);
1179
1180
1181/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001182 * @brief Append an integer to the @ref UsefulOutBuf
1183 *
1184 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1185 * @param[in] uInteger64 Integer to append.
1186 *
1187 * See UsefulOutBuf_InsertUint64() for details. This does the same
1188 * with the insertion point at the end of the valid data.
1189 *
1190 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001191 */
1192static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1193 uint64_t uInteger64);
1194
1195
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001196#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001197/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001198 * @brief Append a @c float to the @ref UsefulOutBuf
1199 *
1200 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1201 * @param[in] f @c float to append.
1202 *
1203 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1204 * the insertion point at the end of the valid data.
1205 *
1206 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001207 */
1208static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1209 float f);
1210
1211
1212/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001213 * @brief Append a @c double to the @ref UsefulOutBuf
1214 *
1215 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1216 * @param[in] d @c double to append.
1217 *
1218 * See UsefulOutBuf_InsertDouble() for details. This does the same
1219 * with the insertion point at the end of the valid data.
1220 *
1221 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001222 */
1223static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1224 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001225#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001226
1227
1228/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001229 * @brief Returns the current error status.
1230 *
1231 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1232 *
1233 * @return 0 if all OK, 1 on error.
1234 *
1235 * This returns the error status since a call to either
1236 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1237 * goes into the error state, it will stay until one of those
1238 * functions is called.
1239 *
1240 * Possible error conditions are:
1241 * - bytes to be inserted will not fit
1242 * - insertion point is out of buffer or past valid data
1243 * - current position is off end of buffer (probably corrupted or uninitialized)
1244 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001245 */
1246static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1247
1248
1249/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001250 * @brief Returns number of bytes unused used in the output buffer.
1251 *
1252 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1253 *
1254 * @return Number of unused bytes or zero.
1255 *
1256 * Because of the error handling strategy and checks in
1257 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1258 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001259 */
1260static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1261
1262
1263/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001264 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1265 *
1266 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1267 * @param[in] uLen Number of bytes for which to check
1268 *
1269 * @return 1 if @c uLen bytes will fit, 0 if not.
1270 *
1271 * Because of the error handling strategy and checks in
1272 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1273 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001274 */
1275static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1276
1277
1278 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001279 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1280 *
1281 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1282 *
1283 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1284 *
1285 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1286 * just calculating the length of the encoded data.
1287 */
Michael Eckel5c531332020-03-02 01:35:30 +01001288static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1289
1290
1291/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001292 * @brief Returns pointer and length of the output buffer not yet used.
1293 *
1294 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1295 *
1296 * @return pointer and length of output buffer not used.
1297 *
1298 * This is an escape that allows the caller to write directly
1299 * to the output buffer without any checks. This doesn't
1300 * change the output buffer or state. It just returns a pointer
1301 * and length of the bytes remaining.
1302 *
1303 * This is useful to avoid having the bytes to be added all
1304 * in a contiguous buffer. Its use can save memory. A good
1305 * example is in the COSE encrypt implementation where
1306 * the output of the symmetric cipher can go directly
1307 * into the output buffer, rather than having to go into
1308 * an intermediate buffer.
1309 *
1310 * See UsefulOutBuf_Advance() which is used to tell
1311 * UsefulOutBuf how much was written.
1312 *
1313 * Warning: this bypasses the buffer safety provided by
1314 * UsefulOutBuf!
1315 */
1316static inline UsefulBuf
1317UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1318
1319
1320/**
1321 * @brief Advance the amount output assuming it was written by the caller.
1322 *
1323 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1324 * @param[in] uAmount The amount to advance.
1325 *
1326 * This advances the position in the output buffer
1327 * by \c uAmount. This assumes that the
1328 * caller has written \c uAmount to the pointer obtained
1329 * with UsefulOutBuf_GetOutPlace().
1330 *
1331 * Warning: this bypasses the buffer safety provided by
1332 * UsefulOutBuf!
1333 */
1334void
1335UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1336
1337
1338/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001339 * @brief Returns the resulting valid data in a UsefulOutBuf
1340 *
1341 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1342 *
1343 * @return The valid data in @ref UsefulOutBuf or
1344 * @ref NULLUsefulBufC if there was an error adding data.
1345 *
1346 * The storage for the returned data is the @c Storage parameter
1347 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1348 *
1349 * This can be called anytime and many times to get intermediate
1350 * results. It doesn't change the data or reset the current position,
1351 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001352 */
1353UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1354
1355
1356/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001357 * @brief Copies the valid data into a supplied buffer
1358 *
1359 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1360 * @param[out] Dest The destination buffer to copy into.
1361 *
1362 * @return Pointer and length of copied data or @c NULLUsefulBufC
1363 * if it will not fit in the @c Dest buffer or the error
1364 * state was entered.
1365 *
1366 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1367 * data to @c Dest.
1368 */
Michael Eckel5c531332020-03-02 01:35:30 +01001369UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1370
1371
1372
1373
1374/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001375 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1376 * for parsing data received. Initialize it with the data from the
1377 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1378 * get data chunks of various types. A position cursor is maintained
1379 * internally.
1380 *
1381 * As long as the functions here are used, there will never be any
1382 * reference off the end of the given buffer (except
1383 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1384 * called incorrectly, an attempt is made to seek off the end of the
1385 * buffer or such. This makes it easier to write safe and correct
1386 * code. For example, the QCBOR decoder implementation is safer and
1387 * easier to review through its use of @ref UsefulInputBuf.
1388 *
1389 * @ref UsefulInputBuf maintains an internal error state. The
1390 * intended use is fetching data chunks without any error checks until
1391 * the end. If there was any error, such as an attempt to fetch data
1392 * off the end, the error state is entered and no further data will be
1393 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1394 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1395 * null is not dereferenced, the error check can be put off until the
1396 * end, simplifying the calling code.
1397 *
1398 * The integer and float parsing expects network byte order (big
1399 * endian). Network byte order is what is used by TCP/IP, CBOR and
1400 * most internet protocols.
1401 *
1402 * Lots of inline functions are used to keep code size down. The
1403 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1404 * code size a lot. The only non-inline code is
1405 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1406 * @ref UsefulInputBuf doesn't add much code for all the messy
1407 * hard-to-get right issues with parsing binary protocols in C that it
1408 * solves.
1409 *
1410 * The parse context size is:
1411 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1412 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001413 */
1414typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001415 /* PRIVATE DATA STRUCTURE */
1416 UsefulBufC UB; /* Data being parsed */
1417 size_t cursor; /* Current offset in data being parse */
1418 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1419 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001420} UsefulInputBuf;
1421
1422#define UIB_MAGIC (0xB00F)
1423
1424
1425/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001426 * @brief Initialize the @ref UsefulInputBuf structure before use.
1427 *
1428 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1429 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001430 */
1431static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1432
1433
1434/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001435 * @brief Returns current position in input buffer.
1436 *
1437 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1438 *
1439 * @return Integer position of the cursor.
1440 *
1441 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001442 */
1443static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1444
1445
1446/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001447 * @brief Sets the current position in input buffer.
1448 *
1449 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1450 * @param[in] uPos Position to set to.
1451 *
1452 * If the position is off the end of the input buffer, the error state
1453 * is entered.
1454 *
1455 * Seeking to a valid position in the buffer will not reset the error
1456 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001457 */
1458static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1459
1460
1461/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001462 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1463 * the unconsumed bytes.
1464 *
1465 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1466 *
1467 * @return Number of bytes unconsumed or 0 on error.
1468 *
1469 * Returns 0 if the cursor is invalid or corruption of the
1470 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001471 */
1472static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1473
1474
1475/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001476 * @brief Check if there are unconsumed bytes.
1477 *
1478 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1479 * @param[in] uLen Number of bytes to check availability for.
1480 *
1481 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001482 */
1483static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1484
1485
1486/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001487 * @brief Convert a pointer to an offset with bounds checking.
1488 *
1489 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1490 * @param[in] p Pointer to convert to offset.
1491 *
1492 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1493 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001494static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1495
1496
1497/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001498 * @brief Get pointer to bytes out of the input buffer.
1499 *
1500 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1501 * @param[in] uNum Number of bytes to get.
1502 *
1503 * @return Pointer to bytes.
1504 *
1505 * This consumes @c uNum bytes from the input buffer. This returns a
1506 * pointer to the start of the @c uNum bytes.
1507 *
1508 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1509 * returned and the error state is entered.
1510 *
1511 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001512 */
1513const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1514
1515
1516/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001517 * @brief Get @ref UsefulBuf out of the input buffer.
1518 *
1519 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1520 * @param[in] uNum Number of bytes to get.
1521 *
1522 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1523 *
1524 * This consumes @c uNum bytes from the input buffer and returns the
1525 * pointer and length for them as a @ref UsefulBufC. The length
1526 * returned will always be @c uNum. The position cursor is advanced by
1527 * @c uNum bytes.
1528 *
1529 * If there are not @c uNum bytes in the input buffer, @ref
1530 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001531 */
1532static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1533
1534
1535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001536 * @brief Get a byte out of the input buffer.
1537 *
1538 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1539 *
1540 * @return The byte.
1541 *
1542 * This consumes 1 byte from the input buffer, returns it and advances
1543 * the position cursor by 1.
1544 *
1545 * If there is not 1 byte in the buffer, 0 will be returned for the
1546 * byte and the error state is entered. To know if the 0 returned was
1547 * in error or the real value, the error state must be checked. If
1548 * possible, put this off until all values are retrieved to have
1549 * smaller and simpler code, but if not possible
1550 * UsefulInputBuf_GetError() can be called. Also, in the error state
1551 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1552 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001553 */
1554static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1555
1556
1557/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001558 * @brief Get a @c uint16_t out of the input buffer.
1559 *
1560 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1561 *
1562 * @return The @c uint16_t.
1563 *
1564 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1565 * a @c uint16_t and two bytes are consumed.
1566 *
1567 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001568 */
1569static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1570
1571
1572/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001573 * @brief Get a @c uint32_t out of the input buffer.
1574 *
1575 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1576 *
1577 * @return The @c uint32_t.
1578 *
1579 * See UsefulInputBuf_GetByte(). This works the same, except it
1580 * returns a @c uint32_t and four bytes are consumed.
1581 *
1582 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001583 */
1584static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1585
1586
1587/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001588 * @brief Get a @c uint64_t out of the input buffer.
1589 *
1590 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1591 *
1592 * @return The uint64_t.
1593 *
1594 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1595 * a @c uint64_t and eight bytes are consumed.
1596 *
1597 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001598 */
1599static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1600
1601
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001602#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001603/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001604 * @brief Get a float out of the input buffer.
1605 *
1606 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1607 *
1608 * @return The float.
1609 *
1610 * See UsefulInputBuf_GetByte(). This works the same, except it
1611 * returns a float and four bytes are consumed.
1612 *
1613 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001614 */
1615static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1616
1617
1618/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001619 * @brief Get a double out of the input buffer.
1620 *
1621 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1622 *
1623 * @return The double.
1624 *
1625 * See UsefulInputBuf_GetByte(). This works the same, except it
1626 * returns a double and eight bytes are consumed.
1627 *
1628 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001629 */
1630static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001631#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001632
1633
1634/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001635 * @brief Get the error status.
1636 *
1637 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1638 *
1639 * @return 0 if not in the error state, 1 if in the error state.
1640 *
1641 * This returns whether the @ref UsefulInputBuf is in the
1642 * error state or not.
1643 *
1644 * The error state is entered for one of these reasons:
1645 * - Attempt to fetch data past the end of the buffer
1646 * - Attempt to seek to a position past the end of the buffer
1647 * - Attempt to get data from an uninitialized or corrupt instance
1648 * of @ref UsefulInputBuf
1649 *
1650 * Once in the error state, it can only be cleared by calling
1651 * UsefulInputBuf_Init().
1652 *
1653 * For many use cases, it is possible to only call this once after all
1654 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1655 * possible if no reference to the data returned are needed before the
1656 * error state is checked.
1657 *
1658 * In some cases UsefulInputBuf_GetUsefulBuf() or
1659 * UsefulInputBuf_GetBytes() can stand in for this because they return
1660 * @c NULL if the error state has been entered. (The others can't stand
1661 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001662 */
1663static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1664
1665
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001666/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001667 * @brief Gets the input buffer length.
1668 *
1669 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1670 *
1671 * @return The length of the input buffer.
1672 *
1673 * This returns the length of the input buffer set by
1674 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001675 */
1676static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1677
1678
1679/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001680 * @brief Alters the input buffer length (use with caution).
1681 *
1682 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1683 * @param[in] uNewLen The new length of the input buffer.
1684 *
1685 * This alters the internal remembered length of the input buffer set
1686 * when UsefulInputBuf_Init() was called.
1687 *
1688 * The new length given here should always be equal to or less than
1689 * the length given when UsefulInputBuf_Init() was called. Making it
1690 * larger allows @ref UsefulInputBuf to run off the input buffer.
1691 *
1692 * The typical use is to set a length shorter than that when
1693 * initialized to constrain parsing. If
1694 * UsefulInputBuf_GetBufferLength() was called before this, then the
1695 * original length can be restored with another call to this.
1696 *
1697 * This should be used with caution. It is the only
1698 * @ref UsefulInputBuf method that can violate the safety of input
1699 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001700 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001701static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001702
1703
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001704
1705
Michael Eckel5c531332020-03-02 01:35:30 +01001706/*----------------------------------------------------------
1707 Inline implementations.
1708 */
1709static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1710{
1711 return !UB.ptr;
1712}
1713
1714
1715static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1716{
1717 return !UB.ptr;
1718}
1719
1720
1721static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1722{
1723 return !UB.len;
1724}
1725
1726
1727static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1728{
1729 return !UB.len;
1730}
1731
1732
1733static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1734{
1735 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1736}
1737
1738
1739static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1740{
1741 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1742}
1743
1744
1745static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1746{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001747 UsefulBufC UBC;
1748 UBC.ptr = UB.ptr;
1749 UBC.len = UB.len;
1750
1751 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001752}
1753
Michael Eckel5c531332020-03-02 01:35:30 +01001754static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1755{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001756 UsefulBuf UB;
1757
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001758 /* -Wcast-qual is a good warning flag to use in general. This is
Maxim Zhukovd538f0a2022-12-20 20:40:38 +03001759 * the one place in UsefulBuf where it needs to be quieted.
1760 */
1761 UB.ptr = (void *)(uintptr_t)UBC.ptr;
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001762
1763 UB.len = UBC.len;
1764
1765 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001766}
1767
1768
1769static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1770{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001771 UsefulBufC UBC;
1772 UBC.ptr = szString;
1773 UBC.len = strlen(szString);
1774 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001775}
1776
1777
1778static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1779{
1780 return UsefulBuf_CopyOffset(Dest, 0, Src);
1781}
1782
1783
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001784static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001785{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001786 memset(Dest.ptr, value, Dest.len);
1787
1788 UsefulBufC UBC;
1789 UBC.ptr = Dest.ptr;
1790 UBC.len = Dest.len;
1791
1792 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001793}
1794
1795
1796static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1797{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001798 UsefulBufC UBC;
1799 UBC.ptr = ptr;
1800 UBC.len = len;
1801 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001802}
1803
1804
1805static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1806{
1807 if(uAmount > UB.len) {
1808 return NULLUsefulBufC;
1809 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001810 UsefulBufC UBC;
1811
1812 UBC.ptr = UB.ptr;
1813 UBC.len = uAmount;
1814
1815 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001816}
1817
1818
1819static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1820{
1821 UsefulBufC ReturnValue;
1822
1823 if(uAmount > UB.len) {
1824 ReturnValue = NULLUsefulBufC;
1825 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001826 ReturnValue.ptr = NULL;
1827 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001828 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001829 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1830 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001831 }
1832
1833 return ReturnValue;
1834}
1835
1836
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001837static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1838{
1839 if(UB.ptr == NULL) {
1840 return SIZE_MAX;
1841 }
1842
1843 if(p < UB.ptr) {
1844 /* given pointer is before start of buffer */
1845 return SIZE_MAX;
1846 }
1847
Laurence Lundblade3eead482023-12-16 20:53:22 -07001848 /* Cast to size_t (from ptrdiff_t) is OK because of check above */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001849 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001850
1851 if(uOffset >= UB.len) {
1852 /* given pointer is off the end of the buffer */
1853 return SIZE_MAX;
1854 }
1855
1856 return uOffset;
1857}
1858
Michael Eckel5c531332020-03-02 01:35:30 +01001859
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001860#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001861static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1862{
1863 uint32_t u32;
1864 memcpy(&u32, &f, sizeof(uint32_t));
1865 return u32;
1866}
1867
1868static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1869{
1870 uint64_t u64;
1871 memcpy(&u64, &d, sizeof(uint64_t));
1872 return u64;
1873}
1874
1875static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1876{
1877 double d;
1878 memcpy(&d, &u64, sizeof(uint64_t));
1879 return d;
1880}
1881
1882static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1883{
1884 float f;
1885 memcpy(&f, &u32, sizeof(uint32_t));
1886 return f;
1887}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001888#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001889
1890
1891
1892
1893static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1894{
1895 pMe->data_len = 0;
1896 pMe->err = 0;
1897}
1898
1899
1900static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1901{
1902 return pMe->data_len;
1903}
1904
1905
1906static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1907{
1908 return 0 == pMe->data_len;
1909}
1910
1911
1912static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1913 const void *pBytes,
1914 size_t uLen,
1915 size_t uPos)
1916{
1917 UsefulBufC Data = {pBytes, uLen};
1918 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1919}
1920
1921
1922static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1923 const char *szString,
1924 size_t uPos)
1925{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001926 UsefulBufC UBC;
1927 UBC.ptr = szString;
1928 UBC.len = strlen(szString);
1929
1930 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001931}
1932
1933
1934static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1935 uint8_t byte,
1936 size_t uPos)
1937{
1938 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1939}
1940
1941
1942static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1943 uint16_t uInteger16,
1944 size_t uPos)
1945{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001946 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001947
1948 const void *pBytes;
1949
1950#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1951 pBytes = &uInteger16;
1952
1953#elif defined(USEFULBUF_CONFIG_HTON)
1954 uint16_t uTmp = htons(uInteger16);
1955 pBytes = &uTmp;
1956
1957#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1958 uint16_t uTmp = __builtin_bswap16(uInteger16);
1959 pBytes = &uTmp;
1960
1961#else
1962 uint8_t aTmp[2];
1963
1964 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1965 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1966
1967 pBytes = aTmp;
1968#endif
1969
1970 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1971}
1972
1973
1974static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1975 uint32_t uInteger32,
1976 size_t uPos)
1977{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001978 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001979
1980 const void *pBytes;
1981
1982#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1983 pBytes = &uInteger32;
1984
1985#elif defined(USEFULBUF_CONFIG_HTON)
1986 uint32_t uTmp = htonl(uInteger32);
1987 pBytes = &uTmp;
1988
1989#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1990 uint32_t uTmp = __builtin_bswap32(uInteger32);
1991
1992 pBytes = &uTmp;
1993
1994#else
1995 uint8_t aTmp[4];
1996
1997 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1998 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1999 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2000 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2001
2002 pBytes = aTmp;
2003#endif
2004
2005 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2006}
2007
2008static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002009 uint64_t uInteger64,
2010 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002011{
2012 const void *pBytes;
2013
2014#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002015 /* We have been told explicitly we are running on a big-endian
2016 * machine. Network byte order is big endian, so just copy. There
2017 * is no issue with alignment here because uInteger64 is always
2018 * aligned (and it doesn't matter if pBytes is aligned).
2019 */
Michael Eckel5c531332020-03-02 01:35:30 +01002020 pBytes = &uInteger64;
2021
2022#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002023 /* Use system function to handle big- and little-endian. This works
2024 * on both big- and little-endian machines, but hton() is not
2025 * always available or in a standard place so it is not used by
2026 * default. With some compilers and CPUs the code for this is very
2027 * compact through use of a special swap instruction and on
2028 * big-endian machines hton() will reduce to nothing.
2029 */
Michael Eckel5c531332020-03-02 01:35:30 +01002030 uint64_t uTmp = htonll(uInteger64);
2031
2032 pBytes = &uTmp;
2033
2034#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002035 /* Use built-in function for byte swapping. This usually compiles
2036 * to an efficient special byte swap instruction. Unlike hton() it
2037 * does not do this conditionally on the CPU endianness, so this
2038 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2039 */
Michael Eckel5c531332020-03-02 01:35:30 +01002040 uint64_t uTmp = __builtin_bswap64(uInteger64);
2041
2042 pBytes = &uTmp;
2043
2044#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002045 /* Default which works on every CPU with no dependency on anything
2046 * from the CPU, compiler, libraries or OS. This always works, but
2047 * it is usually a little larger and slower than hton().
2048 */
Michael Eckel5c531332020-03-02 01:35:30 +01002049 uint8_t aTmp[8];
2050
2051 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2052 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2053 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2054 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2055 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2056 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2057 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2058 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2059
2060 pBytes = aTmp;
2061#endif
2062
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002063 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002064 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2065}
2066
2067
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002068#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002069static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2070 float f,
2071 size_t uPos)
2072{
2073 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2074}
2075
2076
2077static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2078 double d,
2079 size_t uPos)
2080{
2081 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2082}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002083#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002084
2085
2086static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2087 UsefulBufC NewData)
2088{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002089 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002090 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2091}
2092
2093
2094static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2095 const void *pBytes,
2096 size_t uLen)
2097{
2098 UsefulBufC Data = {pBytes, uLen};
2099 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2100}
2101
2102
2103static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2104 const char *szString)
2105{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002106 UsefulBufC UBC;
2107 UBC.ptr = szString;
2108 UBC.len = strlen(szString);
2109
2110 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002111}
2112
2113
2114static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2115 uint8_t byte)
2116{
2117 UsefulOutBuf_AppendData(pMe, &byte, 1);
2118}
2119
2120
2121static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2122 uint16_t uInteger16)
2123{
2124 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2125}
2126
2127static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2128 uint32_t uInteger32)
2129{
2130 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2131}
2132
2133
2134static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2135 uint64_t uInteger64)
2136{
2137 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2138}
2139
2140
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002141#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002142static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2143 float f)
2144{
2145 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2146}
2147
2148
2149static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2150 double d)
2151{
2152 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2153}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002154#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002155
2156
2157static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2158{
2159 return pMe->err;
2160}
2161
2162
2163static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2164{
2165 return pMe->UB.len - pMe->data_len;
2166}
2167
2168
2169static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2170{
2171 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2172}
2173
2174
2175static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2176{
2177 return pMe->UB.ptr == NULL;
2178}
2179
2180
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002181static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2182{
2183 UsefulBuf R;
2184
2185 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002186 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002187 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2188 } else {
2189 R.ptr = NULL;
2190 }
2191
2192 return R;
2193}
2194
2195
2196
Michael Eckel5c531332020-03-02 01:35:30 +01002197
2198static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2199{
2200 pMe->cursor = 0;
2201 pMe->err = 0;
2202 pMe->magic = UIB_MAGIC;
2203 pMe->UB = UB;
2204}
2205
2206static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2207{
2208 return pMe->cursor;
2209}
2210
2211
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002212static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002213{
2214 return pMe->UB.len;
2215}
2216
2217
Michael Eckel5c531332020-03-02 01:35:30 +01002218static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2219{
2220 if(uPos > pMe->UB.len) {
2221 pMe->err = 1;
2222 } else {
2223 pMe->cursor = uPos;
2224 }
2225}
2226
2227
2228static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2229{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002230 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002231
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002232 /* Magic number is messed up. Either the structure got overwritten
2233 * or was never initialized.
2234 */
Michael Eckel5c531332020-03-02 01:35:30 +01002235 if(pMe->magic != UIB_MAGIC) {
2236 return 0;
2237 }
2238
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002239 /* The cursor is off the end of the input buffer given.
2240 * Presuming there are no bugs in this code, this should never happen.
2241 * If it so, the struct was corrupted. The check is retained as
2242 * as a defense in case there is a bug in this code or the struct is
2243 * corrupted.
2244 */
Michael Eckel5c531332020-03-02 01:35:30 +01002245 if(pMe->cursor > pMe->UB.len) {
2246 return 0;
2247 }
2248
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002249 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002250 return pMe->UB.len - pMe->cursor;
2251}
2252
2253
2254static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2255{
2256 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2257}
2258
2259
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002260static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2261{
2262 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2263}
2264
2265
Michael Eckel5c531332020-03-02 01:35:30 +01002266static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2267{
2268 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2269 if(!pResult) {
2270 return NULLUsefulBufC;
2271 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002272 UsefulBufC UBC;
2273 UBC.ptr = pResult;
2274 UBC.len = uNum;
2275 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002276 }
2277}
2278
2279
2280static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2281{
2282 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2283
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002284 /* The ternary operator is subject to integer promotion, because
2285 * the operands are smaller than int, so cast back to uint8_t is
2286 * needed to be completely explicit about types (for static
2287 * analyzers).
2288 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002289 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002290}
2291
2292static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2293{
2294 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2295
2296 if(!pResult) {
2297 return 0;
2298 }
2299
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002300 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002301#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2302 uint16_t uTmp;
2303 memcpy(&uTmp, pResult, sizeof(uint16_t));
2304
2305#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2306 return uTmp;
2307
2308#elif defined(USEFULBUF_CONFIG_HTON)
2309 return ntohs(uTmp);
2310
2311#else
2312 return __builtin_bswap16(uTmp);
2313
2314#endif
2315
2316#else
2317
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002318 /* The operations here are subject to integer promotion because the
2319 * operands are smaller than int. They will be promoted to unsigned
2320 * int for the shift and addition. The cast back to uint16_t is is
2321 * needed to be completely explicit about types (for static
2322 * analyzers).
2323 */
Michael Eckel5c531332020-03-02 01:35:30 +01002324 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2325
2326#endif
2327}
2328
2329
2330static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2331{
2332 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2333
2334 if(!pResult) {
2335 return 0;
2336 }
2337
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002338 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002339#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2340 uint32_t uTmp;
2341 memcpy(&uTmp, pResult, sizeof(uint32_t));
2342
2343#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2344 return uTmp;
2345
2346#elif defined(USEFULBUF_CONFIG_HTON)
2347 return ntohl(uTmp);
2348
2349#else
2350 return __builtin_bswap32(uTmp);
2351
2352#endif
2353
2354#else
2355 return ((uint32_t)pResult[0]<<24) +
2356 ((uint32_t)pResult[1]<<16) +
2357 ((uint32_t)pResult[2]<<8) +
2358 (uint32_t)pResult[3];
2359#endif
2360}
2361
2362
2363static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2364{
2365 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2366
2367 if(!pResult) {
2368 return 0;
2369 }
2370
2371#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002372 /* pResult will probably not be aligned. This memcpy() moves the
2373 * bytes into a temp variable safely for CPUs that can or can't do
2374 * unaligned memory access. Many compilers will optimize the
2375 * memcpy() into a simple move instruction.
2376 */
Michael Eckel5c531332020-03-02 01:35:30 +01002377 uint64_t uTmp;
2378 memcpy(&uTmp, pResult, sizeof(uint64_t));
2379
2380#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002381 /* We have been told expliclity this is a big-endian CPU. Since
2382 * network byte order is big-endian, there is nothing to do.
2383 */
Michael Eckel5c531332020-03-02 01:35:30 +01002384
2385 return uTmp;
2386
2387#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002388 /* We have been told to use ntoh(), the system function to handle
2389 * big- and little-endian. This works on both big- and
2390 * little-endian machines, but ntoh() is not always available or in
2391 * a standard place so it is not used by default. On some CPUs the
2392 * code for this is very compact through use of a special swap
2393 * instruction.
2394 */
Michael Eckel5c531332020-03-02 01:35:30 +01002395
2396 return ntohll(uTmp);
2397
2398#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002399 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2400 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2401 * __builtin_bswap64() and friends are not conditional on CPU
2402 * endianness so this must only be used on little-endian machines.
2403 */
Michael Eckel5c531332020-03-02 01:35:30 +01002404
2405 return __builtin_bswap64(uTmp);
2406
2407
2408#endif
2409
2410#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002411 /* This is the default code that works on every CPU and every
2412 * endianness with no dependency on ntoh(). This works on CPUs
2413 * that either allow or do not allow unaligned access. It will
2414 * always work, but usually is a little less efficient than ntoh().
2415 */
Michael Eckel5c531332020-03-02 01:35:30 +01002416
2417 return ((uint64_t)pResult[0]<<56) +
2418 ((uint64_t)pResult[1]<<48) +
2419 ((uint64_t)pResult[2]<<40) +
2420 ((uint64_t)pResult[3]<<32) +
2421 ((uint64_t)pResult[4]<<24) +
2422 ((uint64_t)pResult[5]<<16) +
2423 ((uint64_t)pResult[6]<<8) +
2424 (uint64_t)pResult[7];
2425#endif
2426}
2427
2428
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002429#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002430static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2431{
2432 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2433
2434 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2435}
2436
2437
2438static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2439{
2440 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2441
2442 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2443}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002444#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002445
2446
2447static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2448{
2449 return pMe->err;
2450}
2451
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002452
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002453static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002454{
2455 pMe->UB.len = uNewLen;
2456}
2457
2458
Michael Eckel5c531332020-03-02 01:35:30 +01002459#ifdef __cplusplus
2460}
2461#endif
2462
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002463#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002464
2465