blob: a965a22cb8f13b027523faa70d27b923632e4c9f [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06003 Copyright (c) 2018-2022, Laurence Lundblade.
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02004 Copyright (c) 2021, Arm Limited. All rights reserved.
Michael Eckel5c531332020-03-02 01:35:30 +01005
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =============================================================================*/
32
33/*============================================================================
34 FILE: UsefulBuf.h
35
36 DESCRIPTION: General purpose input and output buffers
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- --------------------------------------------------
Laurence Lundbladeb24faef2022-04-26 11:03:08 -060045 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf.
Laurence Lundblade8ece3732021-09-21 21:47:23 -070046 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070047 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070048 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080049 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070050 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010051 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
52 5/21/2019 llundblade #define configs for efficient endianness handling.
53 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
54 3/23/2019 llundblade Big documentation & style update. No interface
55 change.
56 3/6/2019 llundblade Add UsefulBuf_IsValue()
57 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
58 12/13/2018 llundblade Documentation improvements
59 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
60 UsefulBufC.
61 02/02/18 llundbla Full support for integers in and out; fix pointer
62 alignment bug. Incompatible change: integers
63 in/out are now in network byte order.
64 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
65 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
66 comparison for < or > for unequal length buffers.
67 Added UsefulBuf_Set() function.
68 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
69 11/13/16 llundbla Initial Version.
70
71 =============================================================================*/
72
73#ifndef _UsefulBuf_h
74#define _UsefulBuf_h
75
76
77/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070078 * Endianness Configuration
79 *
80 * This code is written so it will work correctly on big- and
81 * little-endian CPUs without configuration or any auto-detection of
82 * endianness. All code here will run correctly regardless of the
83 * endianness of the CPU it is running on.
84 *
85 * There are four C preprocessor macros that can be set with #define
86 * to explicitly configure endianness handling. Setting them can
87 * reduce code size a little and improve efficiency a little.
88 *
89 * Note that most of QCBOR is unaffected by this configuration. Its
90 * endianness handling is integrated with the code that handles
91 * alignment and preferred serialization. This configuration does
92 * affect QCBOR's (planned) implementation of integer arrays (tagged
93 * arrays) and use of the functions here to serialize or deserialize
94 * integers and floating-point values.
95 *
96 * Following is the recipe for configuring the endianness-related
97 * #defines.
98 *
99 * The first option is to not define anything. This will work fine
100 * with all CPUs, OS's and compilers. The code for encoding integers
101 * may be a little larger and slower.
102 *
103 * If your CPU is big-endian then define
104 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
105 * for big-endian CPUs. It will be small and efficient because there
106 * will be no byte swapping.
107 *
108 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
109 * OS's and compilers, but not all. On big-endian CPUs this should
110 * give the most efficient code, the same as
111 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
112 * call the system-defined byte swapping method which is presumably
113 * implemented efficiently. In some cases, this will be a dedicated
114 * byte swap instruction like Intel's bswap.
115 *
116 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
117 * little-endian, it is also good to define
118 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
119 *
120 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
121 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
122 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
123 * system-defined byte swap method. However, note
124 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
125 * this is fixed now. Often hton() and ntoh() will call the built-in
126 * __builtin_bswapXX()() function, so this size issue could affect
127 * USEFULBUF_CONFIG_HTON.
128 *
129 * Last, run the tests. They must all pass.
130 *
131 * These #define config options affect the inline implementation of
132 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
133 * also affect the 16-, 32-bit, float and double versions of these
134 * functions. Since they are inline, the size effect is not in the
135 * UsefulBuf object code, but in the calling code.
136 *
137 * Summary:
138 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
139 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
140 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
141 * handle big and little-endian with system option.
142 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
143 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200144 *
145 * It is possible to run this code in environments where using floating point is
146 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
147 * that is related to handling floating point types, along with related
148 * interfaces. This makes it possible to compile the code with the compile
149 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100150 */
151
152#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
153#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
154#endif
155
156
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700157#include <stdint.h> /* for uint8_t, uint16_t.... */
158#include <string.h> /* for strlen, memcpy, memmove, memset */
159#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100160
161
162#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700163#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100164#endif
165
166#ifdef __cplusplus
167extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700168#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700169} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700170#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100171#endif
172
173/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700174 * @file UsefulBuf.h
175 *
176 * The goal of this code is to make buffer and pointer manipulation
177 * easier and safer when working with binary data.
178 *
179 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
180 * structures are used to represent buffers rather than ad hoc
181 * pointers and lengths.
182 *
183 * With these it is possible to write code that does little or no
184 * direct pointer manipulation for copying and formatting data. For
185 * example, the QCBOR encoder was written using these and has less
186 * pointer manipulation.
187 *
188 * While it is true that object code using these functions will be a
189 * little larger and slower than a white-knuckle clever use of
190 * pointers might be, but not by that much or enough to have an effect
191 * for most use cases. For security-oriented code this is highly
192 * worthwhile. Clarity, simplicity, reviewability and are more
193 * important.
194 *
195 * There are some extra sanity and double checks in this code to help
196 * catch coding errors and simple memory corruption. They are helpful,
197 * but not a substitute for proper code review, input validation and
198 * such.
199 *
200 * This code consists of a lot of inline functions and a few that are
201 * not. It should not generate very much object code, especially with
202 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100203 */
204
205
206/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700207 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
208 * hold a pointer and length for binary data. In C99 this data
209 * structure can be passed on the stack making a lot of code cleaner
210 * than carrying around a pointer and length as two parameters.
211 *
212 * This is also conducive to secure coding practice as the length is
213 * always carried with the pointer and the convention for handling a
214 * pointer and a length is clear.
215 *
216 * While it might be possible to write buffer and pointer code more
217 * efficiently in some use cases, the thought is that unless there is
218 * an extreme need for performance (e.g., you are building a
219 * gigabit-per-second IP router), it is probably better to have
220 * cleaner code you can be most certain about the security of.
221 *
222 * The non-const @ref UsefulBuf is usually used to refer an empty
223 * buffer to be filled in. The length is the size of the buffer.
224 *
225 * The const @ref UsefulBufC is usually used to refer to some data
226 * that has been filled in. The length is amount of valid data pointed
227 * to.
228 *
229 * A common use mode is to pass a @ref UsefulBuf to a function, the
230 * function puts some data in it, then the function returns a @ref
231 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
232 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
233 * so the constness stays correct. There is no single "in,out"
234 * parameter (if there was, it would have to be non-const). Note that
235 * the pointer returned in the @ref UsefulBufC usually ends up being
236 * the same pointer passed in as a @ref UsefulBuf, though this is not
237 * striclty required.
238 *
239 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
240 * @c NULL.
241 *
242 * There are functions and macros for the following:
243 * - Initializing
244 * - Create initialized const @ref UsefulBufC from compiler literals
245 * - Create initialized const @ref UsefulBufC from NULL-terminated string
246 * - Make an empty @ref UsefulBuf on the stack
247 * - Checking whether a @ref UsefulBuf is null, empty or both
248 * - Copying, copying with offset, copying head or tail
249 * - Comparing and finding substrings
250 *
251 * See also @ref UsefulOutBuf. It is a richer structure that has both
252 * the size of the valid data and the size of the buffer.
253 *
254 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
255 * it can go on the stack and be a function parameter or return value.
256 *
257 * Another way to look at it is this. C has the NULL-terminated string
258 * as a means for handling text strings, but no means or convention
259 * for binary strings. Other languages do have such means, Rust, an
260 * efficient compiled language, for example.
261 *
262 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
263 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
264 * out like anything".
265 */
Michael Eckel5c531332020-03-02 01:35:30 +0100266typedef struct q_useful_buf_c {
267 const void *ptr;
268 size_t len;
269} UsefulBufC;
270
271
272/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700273 * This non-const @ref UsefulBuf is typically used for some allocated
274 * memory that is to be filled in. The @c len is the amount of memory,
275 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100276 */
277typedef struct q_useful_buf {
278 void *ptr;
279 size_t len;
280} UsefulBuf;
281
282
283/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700284 * A null @ref UsefulBufC is one that has no value in the same way a
285 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
286 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
287 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100288 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700289/*
290 * NULLUsefulBufC and few other macros have to be
291 * definied differently in C than C++ because there
292 * is no common construct for a literal structure.
293 *
294 * In C compound literals are used.
295 *
296 * In C++ list initalization is used. This only works
297 * in C++11 and later.
298 *
299 * Note that some popular C++ compilers can handle compound
300 * literals with on-by-default extensions, however
301 * this code aims for full correctness with strict
302 * compilers so they are not used.
303 */
304#ifdef __cplusplus
305#define NULLUsefulBufC {NULL, 0}
306#else
307#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
308#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100309
310/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700311 * A null @ref UsefulBuf is one that has no memory associated the same
312 * way @c NULL points to nothing. It does not matter what @c len is.
313 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700314#ifdef __cplusplus
315#define NULLUsefulBuf {NULL, 0}
316#else
317#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
318#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100319
320
321/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700322 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
323 *
324 * @param[in] UB The UsefulBuf to check.
325 *
326 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100327 */
328static inline int UsefulBuf_IsNULL(UsefulBuf UB);
329
330
331/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700332 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
333 *
334 * @param[in] UB The @ref UsefulBufC to check.
335 *
336 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100337 */
338static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
339
340
341/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700342 * @brief Check if a @ref UsefulBuf is empty or not.
343 *
344 * @param[in] UB The @ref UsefulBuf to check.
345 *
346 * @return 1 if it is empty, 0 if not.
347 *
348 * An "empty" @ref UsefulBuf is one that has a value and can be
349 * considered to be set, but that value is of zero length. It is
350 * empty when @c len is zero. It doesn't matter what the @c ptr is.
351 *
352 * Many uses will not need to clearly distinguish a @c NULL @ref
353 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
354 * @c len 0. However if a use of @ref UsefulBuf needs to make a
355 * distinction then @c ptr should not be @c NULL when the @ref
356 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100357 */
358static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
359
360
361/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700362 * @brief Check if a @ref UsefulBufC is empty or not.
363 *
364 * @param[in] UB The @ref UsefulBufC to check.
365 *
366 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100367 */
368static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
369
370
371/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700372 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
373 *
374 * @param[in] UB The @ref UsefulBuf to check.
375 *
376 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100377 */
378static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
379
380
381/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700382 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
383 *
384 * @param[in] UB The @ref UsefulBufC to check.
385 *
386 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100387 */
388static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
389
390
391/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700392 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
393 *
394 * @param[in] UB The @ref UsefulBuf to convert.
395 *
396 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100397 */
398static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
399
400
401/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700402 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
403 *
404 * @param[in] UBC The @ref UsefulBuf to convert.
405 *
406 * @return A non-const @ref UsefulBuf struct.
407 *
408 * Use of this is not necessary for the intended use mode of @ref
409 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
410 * created to describe a buffer that has not had any data put in
411 * it. Then the data is put in it. Then a @ref UsefulBufC is create
412 * to describe the part with the data in it. This goes from non-const
413 * to const, so this function is not needed.
414 *
415 * If the -Wcast-qual warning is enabled, this function can be used to
416 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100417 */
418static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
419
420
421/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700422 * Convert a literal string to a @ref UsefulBufC.
423 *
424 * @c szString must be a literal string that @c sizeof() works on.
425 * This is better for literal strings than UsefulBuf_FromSZ() because
426 * it generates less code. It will not work on non-literal strings.
427 *
428 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100429 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700430#ifdef __cplusplus
431#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
432#else
Michael Eckel5c531332020-03-02 01:35:30 +0100433#define UsefulBuf_FROM_SZ_LITERAL(szString) \
434 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700435#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100436
437
438/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700439 * Convert a literal byte array to a @ref UsefulBufC.
440 *
441 * @c pBytes must be a literal string that @c sizeof() works on. It
442 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100443 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700444#ifdef __cplusplus
445#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
446#else
Michael Eckel5c531332020-03-02 01:35:30 +0100447#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700448 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
449#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100450
451/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700452 * Make an automatic variable named @c name of type @ref UsefulBuf and
453 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100454 */
455#define UsefulBuf_MAKE_STACK_UB(name, size) \
456 uint8_t __pBuf##name[(size)];\
457 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
458
459
460/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700461 * Make a byte array in to a @ref UsefulBuf. This is usually used on
462 * stack variables or static variables. Also see @ref
463 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100464 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700465#ifdef __cplusplus
466#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
467#else
Michael Eckel5c531332020-03-02 01:35:30 +0100468#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700469 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
470#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100471
472
473/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700474 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
475 *
476 * @param[in] szString The string to convert.
477 *
478 * @return A @ref UsefulBufC struct.
479 *
480 * @c UsefulBufC.ptr points to the string so its lifetime must be
481 * maintained.
482 *
483 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100484 */
485static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
486
487
488/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700489 * @brief Copy one @ref UsefulBuf into another at an offset.
490 *
491 * @param[in] Dest Destination buffer to copy into.
492 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
493 * @param[in] Src The bytes to copy.
494 *
495 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
496 *
497 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
498 * size of @c Dest.
499 *
500 * This fails and returns @ref NULLUsefulBufC if the @c Src length
501 * plus @c uOffset is greater than the length of @c Dest.
502 *
503 * The results are undefined if @c Dest and @c Src overlap.
504 *
505 * This assumes that there is valid data in @c Dest up to @c
506 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
507 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100508 */
509UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
510
511
512/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700513 * @brief Copy one @ref UsefulBuf into another.
514 *
515 * @param[in] Dest The destination buffer to copy into.
516 * @param[out] Src The source to copy from.
517 *
518 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
519 * on failure.
520 *
521 * This fails if @c Src.len is greater than @c Dest.len.
522 *
523 * Note that like @c memcpy(), the pointers are not checked and this
524 * will crash rather than return @ref NULLUsefulBufC if they are @c
525 * NULL or invalid.
526 *
527 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100528 */
529static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
530
531
532/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700533 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
534 *
535 * @param[in] pDest The destination buffer to copy into.
536 * @param[in] value The value to set the bytes to.
537 *
538 * Note that like @c memset(), the pointer in @c pDest is not checked
539 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100540 */
541static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
542
543
544/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700545 * @brief Copy a pointer into a @ref UsefulBuf.
546 *
547 * @param[in,out] Dest The destination buffer to copy into.
548 * @param[in] ptr The source to copy from.
549 * @param[in] uLen Length of the source; amount to copy.
550 *
551 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
552 * on failure.
553 *
554 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
555 * than @c pDest->len.
556 *
557 * Note that like @c memcpy(), the pointers are not checked and this
558 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100559 */
560static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
561 const void *ptr,
562 size_t uLen);
563
564
565/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700566 * @brief Returns a truncation of a @ref UsefulBufC.
567 *
568 * @param[in] UB The buffer to get the head of.
569 * @param[in] uAmount The number of bytes in the head.
570 *
571 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100572 */
573static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
574
575
576/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700577 * @brief Returns bytes from the end of a @ref UsefulBufC.
578 *
579 * @param[in] UB The buffer to get the tail of.
580 * @param[in] uAmount The offset from the start where the tail is to begin.
581 *
582 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
583 * if @c uAmount is greater than the length of the @ref UsefulBufC.
584 *
585 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
586 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
587 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100588 */
589static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
590
591
592/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700593 * @brief Compare one @ref UsefulBufC to another.
594 *
595 * @param[in] UB1 The first buffer to compare.
596 * @param[in] UB2 The second buffer to compare.
597 *
598 * @return 0, positive or negative value.
599 *
600 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
601 * less than @c UB2 if it is shorter or the first byte that is not the
602 * same is less.
603 *
604 * Returns 0 if the inputs are the same.
605 *
606 * Returns a positive value if @c UB2 is less than @c UB1.
607 *
608 * All that is of significance is that the result is positive, negative
609 * or 0. (This doesn't return the difference between the first
610 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100611 */
612int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
613
614
615/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700616 * @brief Find first byte that is not a particular byte value.
617 *
618 * @param[in] UB The destination buffer for byte comparison.
619 * @param[in] uValue The byte value to compare to.
620 *
621 * @return Offset of first byte that isn't @c uValue or
622 * @c SIZE_MAX if all bytes are @c uValue.
623 *
624 * Note that unlike most comparison functions, 0
625 * does not indicate a successful comparison, so the
626 * test for match is:
627 *
628 * UsefulBuf_IsValue(...) == SIZE_MAX
629 *
630 * If @c UB is null or empty, there is no match
631 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100632 */
633size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
634
635
636/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700637 * @brief Find one @ref UsefulBufC in another.
638 *
639 * @param[in] BytesToSearch Buffer to search through.
640 * @param[in] BytesToFind Buffer with bytes to be found.
641 *
642 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100643 */
644size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
645
646
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700647/**
648 @brief Convert a pointer to an offset with bounds checking.
649
650 @param[in] UB Pointer to the UsefulInputBuf.
651 @param[in] p Pointer to convert to offset.
652
653 @return SIZE_MAX if @c p is out of range, the byte offset if not.
654*/
655static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
656
657
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800658#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100659/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700660#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100661
662/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
663#define MakeUsefulBufOnStack(name, size) \
664 uint8_t __pBuf##name[(size)];\
665 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
666
667/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
668#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700669 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100670
671/** Deprecated function; use UsefulBuf_Unconst() instead */
672static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
673{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700674 UsefulBuf UB;
675
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800676 // See UsefulBuf_Unconst() implementation for comment on pragmas
Dave Thaler93c01182022-08-06 15:08:35 -0400677#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800678#pragma GCC diagnostic push
679#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -0400680#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700681 UB.ptr = (void *)UBC.ptr;
Dave Thaler93c01182022-08-06 15:08:35 -0400682#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800683#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -0400684#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700685
686 UB.len = UBC.len;
687
688 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100689}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800690#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100691
692
693
694
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200695#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100696/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700697 * @brief Copy a @c float to a @c uint32_t.
698 *
699 * @param[in] f Float value to copy.
700 *
701 * @return A @c uint32_t with the float bits.
702 *
703 * Convenience function to avoid type punning, compiler warnings and
704 * such. The optimizer usually reduces this to a simple assignment. This
705 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100706 */
707static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
708
709
710/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700711 * @brief Copy a @c double to a @c uint64_t.
712 *
713 * @param[in] d Double value to copy.
714 *
715 * @return A @c uint64_t with the double bits.
716 *
717 * Convenience function to avoid type punning, compiler warnings and
718 * such. The optimizer usually reduces this to a simple assignment. This
719 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100720 */
721static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
722
723
724/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700725 * @brief Copy a @c uint32_t to a @c float.
726 *
727 * @param[in] u32 Integer value to copy.
728 *
729 * @return The value as a @c float.
730 *
731 * Convenience function to avoid type punning, compiler warnings and
732 * such. The optimizer usually reduces this to a simple assignment. This
733 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100734 */
735static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
736
737
738/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700739 * @brief Copy a @c uint64_t to a @c double.
740 *
741 * @param[in] u64 Integer value to copy.
742 *
743 * @return The value as a @c double.
744 *
745 * Convenience function to avoid type punning, compiler warnings and
746 * such. The optimizer usually reduces this to a simple assignment. This
747 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100748 */
749static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200750#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100751
752
753
754
755/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700756 * UsefulOutBuf is a structure and functions (an object) for
757 * serializing data into a buffer to encode for a network protocol or
758 * write data to a file.
759 *
760 * The main idea is that all the pointer manipulation is performed by
761 * @ref UsefulOutBuf functions so the caller doesn't have to do any
762 * pointer manipulation. The pointer manipulation is centralized.
763 * This code has been reviewed and written carefully so it
764 * spares the caller of much of this work and results in safer code
765 * with less effort.
766 *
767 * The @ref UsefulOutBuf methods that add data to the output buffer
768 * always check the length and will never write off the end of the
769 * output buffer. If an attempt to add data that will not fit is made,
770 * an internal error flag will be set and further attempts to add data
771 * will not do anything.
772 *
773 * There is no way to ever write off the end of that buffer when
774 * calling the @c UsefulOutBuf_AddXxx() and
775 * @c UsefulOutBuf_InsertXxx() functions.
776 *
777 * The functions to add data do not report success of failure. The
778 * caller only needs to check for an error in the final call, either
779 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
780 * result. This makes the calling code cleaner.
781 *
782 * There is a utility function to get the error status anytime along
783 * the way for a special circumstance. There are functions to see how
784 * much room is left and see if some data will fit too, but their use
785 * is generally unnecessary.
786 *
787 * The general call flow is:
788 *
789 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
790 * buffer given to it can be from the heap, stack or
791 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
792 * macro that makes a buffer on the stack and initializes it.
793 *
794 * - Call methods like UsefulOutBuf_InsertString(),
795 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
796 * to output data. The append calls add data to the end of the
797 * valid data. The insert calls take a position argument.
798 *
799 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
800 * there were no errors and to get the serialized output bytes.
801 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700802 * @ref UsefulOutBuf can be used in a mode to calculate the size of
803 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700804 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700805 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700806 *
807 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700808 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700809 *
810 * The possible errors are:
811 *
812 * - The @ref UsefulOutBuf was not initialized or was corrupted.
813 *
814 * - An attempt was made to add data that will not fit.
815 *
816 * - An attempt was made to insert data at a position beyond the end of
817 * the buffer.
818 *
819 * - An attempt was made to insert data at a position beyond the valid
820 * data in the buffer.
821 *
822 * Some inexpensive simple sanity checks are performed before every
823 * data addition to guard against use of an uninitialized or corrupted
824 * UsefulOutBuf.
825 *
826 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
827 * encoder has almost no pointer manipulation in it, is easier to
828 * read, and easier to review.
829 *
830 * A @ref UsefulOutBuf is small and can go on the stack:
831 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
832 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100833 */
834typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700835 /* PRIVATE DATA STRUCTURE */
836 UsefulBuf UB; /* Memory that is being output to */
837 size_t data_len; /* length of the valid data, the insertion point */
838 uint16_t magic; /* Used to detect corruption and lack
839 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100840 uint8_t err;
841} UsefulOutBuf;
842
843
844/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700845 * This is a @ref UsefulBuf value that can be passed to
846 * UsefulOutBuf_Init() to have it calculate the size of the output
847 * buffer needed. Pass this for @c Storage, call all the append and
848 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
849 * returned @ref UsefulBufC has the size.
850 *
851 * As one can see, this is just a NULL pointer and very large size.
852 * The NULL pointer tells UsefulOutputBuf to not copy any data.
853 */
854#ifdef __cplusplus
855#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
856#else
857#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
858#endif
859
860
861/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700862 * @brief Initialize and supply the actual output buffer.
863 *
864 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
865 * @param[in] Storage Buffer to output into.
866 *
867 * This initializes the @ref UsefulOutBuf with storage, sets the
868 * current position to the beginning of the buffer and clears the
869 * error state.
870 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700871 * See @ref SizeCalculateUsefulBuf for instructions on how to
872 * initialize a @ref UsefulOutBuf to calculate the size that would be
873 * output without actually outputting.
874 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700875 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100876 */
877void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
878
879
880/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700881 * Convenience macro to make a @ref UsefulOutBuf on the stack and
882 * initialize it with a stack buffer of the given size. The variable
883 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100884 */
885#define UsefulOutBuf_MakeOnStack(name, size) \
886 uint8_t __pBuf##name[(size)];\
887 UsefulOutBuf name;\
888 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
889
890
891/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700892 * @brief Reset a @ref UsefulOutBuf for re use.
893 *
894 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
895 *
896 * This sets the amount of data in the output buffer to none and
897 * clears the error state.
898 *
899 * The output buffer is still the same one and size as from the
900 * UsefulOutBuf_Init() call.
901 *
902 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100903 */
904static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
905
906
907/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700908 * @brief Returns position of end of data in the @ref UsefulOutBuf.
909 *
910 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
911 *
912 * @return position of end of data.
913 *
914 * On a freshly initialized @ref UsefulOutBuf with no data added, this
915 * will return 0. After 10 bytes have been added, it will return 10
916 * and so on.
917 *
918 * Generally, there is no need to call this for most uses of @ref
919 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100920 */
921static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
922
923
924/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700925 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
926 *
927 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
928 *
929 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100930 */
931static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
932
933
934/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700935 * @brief Inserts bytes into the @ref UsefulOutBuf.
936 *
937 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
938 * @param[in] NewData The bytes to insert.
939 * @param[in] uPos Index in output buffer at which to insert.
940 *
941 * @c NewData is the pointer and length for the bytes to be added to
942 * the output buffer. There must be room in the output buffer for all
943 * of @c NewData or an error will occur.
944 *
945 * The insertion point must be between 0 and the current valid
946 * data. If not, an error will occur. Appending data to the output
947 * buffer is achieved by inserting at the end of the valid data. This
948 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
949 *
950 * When insertion is performed, the bytes between the insertion point
951 * and the end of data previously added to the output buffer are slid
952 * to the right to make room for the new data.
953 *
954 * Overlapping buffers are OK. @c NewData can point to data in the
955 * output buffer.
956 *
Laurence Lundblade54618d52022-12-19 21:41:55 -0700957 * NewData.len may be 0 in which case nothing will be inserted.
958 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700959 * If an error occurs, an error state is set in the @ref
960 * UsefulOutBuf. No error is returned. All subsequent attempts to add
961 * data will do nothing.
962 *
963 * The intended use is that all additions are made without checking
964 * for an error. The error will be taken into account when
965 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
966 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100967 */
968void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
969 UsefulBufC NewData,
970 size_t uPos);
971
972
973/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700974 * @brief Insert a data buffer into the @ref UsefulOutBuf.
975 *
976 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
977 * @param[in] pBytes Pointer to the bytes to insert
978 * @param[in] uLen Length of the bytes to insert
979 * @param[in] uPos Index in output buffer at which to insert
980 *
981 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
982 * the difference being a pointer and length is passed in rather than an
983 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100984 */
985static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
986 const void *pBytes,
987 size_t uLen,
988 size_t uPos);
989
990
991/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700992 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
993 *
994 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
995 * @param[in] szString NULL-terminated string to insert.
996 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100997 */
998static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
999 const char *szString,
1000 size_t uPos);
1001
1002
1003/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001004 * @brief Insert a byte into the @ref UsefulOutBuf.
1005 *
1006 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1007 * @param[in] byte Bytes to insert.
1008 * @param[in] uPos Index in output buffer at which to insert.
1009 *
1010 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1011 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001012 */
1013static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1014 uint8_t byte,
1015 size_t uPos);
1016
1017
1018/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001019 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1020 *
1021 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1022 * @param[in] uInteger16 Integer to insert.
1023 * @param[in] uPos Index in output buffer at which to insert.
1024 *
1025 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1026 * with the difference being a two-byte integer is to be inserted.
1027 *
1028 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001029 */
1030static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1031 uint16_t uInteger16,
1032 size_t uPos);
1033
1034
1035/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001036 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1037 *
1038 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1039 * @param[in] uInteger32 Integer to insert.
1040 * @param[in] uPos Index in output buffer at which to insert.
1041 *
1042 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1043 * with the difference being a four-byte integer is to be inserted.
1044 *
1045 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001046 */
1047static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1048 uint32_t uInteger32,
1049 size_t uPos);
1050
1051
1052/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001053 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1054 *
1055 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1056 * @param[in] uInteger64 Integer to insert.
1057 * @param[in] uPos Index in output buffer at which to insert.
1058 *
1059 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1060 * with the difference being an eight-byte integer is to be inserted.
1061 *
1062 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001063 */
1064static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1065 uint64_t uInteger64,
1066 size_t uPos);
1067
1068
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001069#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001070/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001071 * @brief Insert a @c float into the @ref UsefulOutBuf.
1072 *
1073 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1074 * @param[in] f @c float to insert.
1075 * @param[in] uPos Index in output buffer at which to insert.
1076 *
1077 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1078 * with the difference being a @c float is to be inserted.
1079 *
1080 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001081 */
1082static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1083 float f,
1084 size_t uPos);
1085
1086
1087/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001088 * @brief Insert a @c double into the @ref UsefulOutBuf.
1089 *
1090 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1091 * @param[in] d @c double to insert.
1092 * @param[in] uPos Index in output buffer at which to insert.
1093 *
1094 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1095 * with the difference being a @c double is to be inserted.
1096 *
1097 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001098 */
1099static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1100 double d,
1101 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001102#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001103
1104
1105/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001106 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1107 *
1108 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1109 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1110 *
1111 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1112 * with the insertion point at the end of the valid data.
1113 */
Michael Eckel5c531332020-03-02 01:35:30 +01001114static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1115 UsefulBufC NewData);
1116
1117
1118/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001119 * @brief Append bytes to the @ref UsefulOutBuf.
1120 *
1121 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1122 * @param[in] pBytes Pointer to bytes to append.
1123 * @param[in] uLen Length of @c pBytes to append.
1124 *
1125 * See UsefulOutBuf_InsertData() for details. This does the same with
1126 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001127 */
1128static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1129 const void *pBytes,
1130 size_t uLen);
1131
1132
1133/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001134 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1135 *
1136 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1137 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001138 */
1139static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1140 const char *szString);
1141
1142
1143/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001144 * @brief Append a byte to the @ref UsefulOutBuf
1145 *
1146 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1147 * @param[in] byte Bytes to append.
1148 *
1149 * See UsefulOutBuf_InsertByte() for details. This does the same
1150 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001151 */
1152static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1153 uint8_t byte);
1154
1155
1156/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001157 * @brief Append an integer to the @ref UsefulOutBuf
1158 *
1159 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1160 * @param[in] uInteger16 Integer to append.
1161 *
1162 * See UsefulOutBuf_InsertUint16() for details. This does the same
1163 * with the insertion point at the end of the valid data.
1164 *
1165 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001166 */
1167static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1168 uint16_t uInteger16);
1169
1170
1171/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001172 * @brief Append an integer to the @ref UsefulOutBuf
1173 *
1174 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1175 * @param[in] uInteger32 Integer to append.
1176 *
1177 * See UsefulOutBuf_InsertUint32() for details. This does the same
1178 * with the insertion point at the end of the valid data.
1179 *
1180 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001181 */
1182static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1183 uint32_t uInteger32);
1184
1185
1186/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001187 * @brief Append an integer to the @ref UsefulOutBuf
1188 *
1189 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1190 * @param[in] uInteger64 Integer to append.
1191 *
1192 * See UsefulOutBuf_InsertUint64() for details. This does the same
1193 * with the insertion point at the end of the valid data.
1194 *
1195 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001196 */
1197static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1198 uint64_t uInteger64);
1199
1200
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001201#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001202/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001203 * @brief Append a @c float to the @ref UsefulOutBuf
1204 *
1205 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1206 * @param[in] f @c float to append.
1207 *
1208 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1209 * the insertion point at the end of the valid data.
1210 *
1211 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001212 */
1213static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1214 float f);
1215
1216
1217/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001218 * @brief Append a @c double to the @ref UsefulOutBuf
1219 *
1220 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1221 * @param[in] d @c double to append.
1222 *
1223 * See UsefulOutBuf_InsertDouble() for details. This does the same
1224 * with the insertion point at the end of the valid data.
1225 *
1226 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001227 */
1228static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1229 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001230#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001231
1232
1233/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001234 * @brief Returns the current error status.
1235 *
1236 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1237 *
1238 * @return 0 if all OK, 1 on error.
1239 *
1240 * This returns the error status since a call to either
1241 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1242 * goes into the error state, it will stay until one of those
1243 * functions is called.
1244 *
1245 * Possible error conditions are:
1246 * - bytes to be inserted will not fit
1247 * - insertion point is out of buffer or past valid data
1248 * - current position is off end of buffer (probably corrupted or uninitialized)
1249 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001250 */
1251static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1252
1253
1254/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001255 * @brief Returns number of bytes unused used in the output buffer.
1256 *
1257 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1258 *
1259 * @return Number of unused bytes or zero.
1260 *
1261 * Because of the error handling strategy and checks in
1262 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1263 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001264 */
1265static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1266
1267
1268/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001269 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1270 *
1271 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1272 * @param[in] uLen Number of bytes for which to check
1273 *
1274 * @return 1 if @c uLen bytes will fit, 0 if not.
1275 *
1276 * Because of the error handling strategy and checks in
1277 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1278 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001279 */
1280static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1281
1282
1283 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001284 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1285 *
1286 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1287 *
1288 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1289 *
1290 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1291 * just calculating the length of the encoded data.
1292 */
Michael Eckel5c531332020-03-02 01:35:30 +01001293static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1294
1295
1296/**
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06001297 * @brief Returns pointer and length of the output buffer not yet used.
1298 *
1299 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1300 *
1301 * @return pointer and length of output buffer not used.
1302 *
1303 * This is an escape that allows the caller to write directly
1304 * to the output buffer without any checks. This doesn't
1305 * change the output buffer or state. It just returns a pointer
1306 * and length of the bytes remaining.
1307 *
1308 * This is useful to avoid having the bytes to be added all
1309 * in a contiguous buffer. Its use can save memory. A good
1310 * example is in the COSE encrypt implementation where
1311 * the output of the symmetric cipher can go directly
1312 * into the output buffer, rather than having to go into
1313 * an intermediate buffer.
1314 *
1315 * See UsefulOutBuf_Advance() which is used to tell
1316 * UsefulOutBuf how much was written.
1317 *
1318 * Warning: this bypasses the buffer safety provided by
1319 * UsefulOutBuf!
1320 */
1321static inline UsefulBuf
1322UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
1323
1324
1325/**
1326 * @brief Advance the amount output assuming it was written by the caller.
1327 *
1328 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1329 * @param[in] uAmount The amount to advance.
1330 *
1331 * This advances the position in the output buffer
1332 * by \c uAmount. This assumes that the
1333 * caller has written \c uAmount to the pointer obtained
1334 * with UsefulOutBuf_GetOutPlace().
1335 *
1336 * Warning: this bypasses the buffer safety provided by
1337 * UsefulOutBuf!
1338 */
1339void
1340UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
1341
1342
1343/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001344 * @brief Returns the resulting valid data in a UsefulOutBuf
1345 *
1346 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1347 *
1348 * @return The valid data in @ref UsefulOutBuf or
1349 * @ref NULLUsefulBufC if there was an error adding data.
1350 *
1351 * The storage for the returned data is the @c Storage parameter
1352 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1353 *
1354 * This can be called anytime and many times to get intermediate
1355 * results. It doesn't change the data or reset the current position,
1356 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001357 */
1358UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1359
1360
1361/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001362 * @brief Copies the valid data into a supplied buffer
1363 *
1364 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1365 * @param[out] Dest The destination buffer to copy into.
1366 *
1367 * @return Pointer and length of copied data or @c NULLUsefulBufC
1368 * if it will not fit in the @c Dest buffer or the error
1369 * state was entered.
1370 *
1371 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1372 * data to @c Dest.
1373 */
Michael Eckel5c531332020-03-02 01:35:30 +01001374UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1375
1376
1377
1378
1379/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001380 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1381 * for parsing data received. Initialize it with the data from the
1382 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1383 * get data chunks of various types. A position cursor is maintained
1384 * internally.
1385 *
1386 * As long as the functions here are used, there will never be any
1387 * reference off the end of the given buffer (except
1388 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1389 * called incorrectly, an attempt is made to seek off the end of the
1390 * buffer or such. This makes it easier to write safe and correct
1391 * code. For example, the QCBOR decoder implementation is safer and
1392 * easier to review through its use of @ref UsefulInputBuf.
1393 *
1394 * @ref UsefulInputBuf maintains an internal error state. The
1395 * intended use is fetching data chunks without any error checks until
1396 * the end. If there was any error, such as an attempt to fetch data
1397 * off the end, the error state is entered and no further data will be
1398 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1399 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1400 * null is not dereferenced, the error check can be put off until the
1401 * end, simplifying the calling code.
1402 *
1403 * The integer and float parsing expects network byte order (big
1404 * endian). Network byte order is what is used by TCP/IP, CBOR and
1405 * most internet protocols.
1406 *
1407 * Lots of inline functions are used to keep code size down. The
1408 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1409 * code size a lot. The only non-inline code is
1410 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1411 * @ref UsefulInputBuf doesn't add much code for all the messy
1412 * hard-to-get right issues with parsing binary protocols in C that it
1413 * solves.
1414 *
1415 * The parse context size is:
1416 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1417 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001418 */
1419typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001420 /* PRIVATE DATA STRUCTURE */
1421 UsefulBufC UB; /* Data being parsed */
1422 size_t cursor; /* Current offset in data being parse */
1423 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1424 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001425} UsefulInputBuf;
1426
1427#define UIB_MAGIC (0xB00F)
1428
1429
1430/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001431 * @brief Initialize the @ref UsefulInputBuf structure before use.
1432 *
1433 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1434 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001435 */
1436static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1437
1438
1439/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001440 * @brief Returns current position in input buffer.
1441 *
1442 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1443 *
1444 * @return Integer position of the cursor.
1445 *
1446 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001447 */
1448static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1449
1450
1451/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001452 * @brief Sets the current position in input buffer.
1453 *
1454 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1455 * @param[in] uPos Position to set to.
1456 *
1457 * If the position is off the end of the input buffer, the error state
1458 * is entered.
1459 *
1460 * Seeking to a valid position in the buffer will not reset the error
1461 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001462 */
1463static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1464
1465
1466/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001467 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1468 * the unconsumed bytes.
1469 *
1470 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1471 *
1472 * @return Number of bytes unconsumed or 0 on error.
1473 *
1474 * Returns 0 if the cursor is invalid or corruption of the
1475 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001476 */
1477static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1478
1479
1480/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001481 * @brief Check if there are unconsumed bytes.
1482 *
1483 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1484 * @param[in] uLen Number of bytes to check availability for.
1485 *
1486 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001487 */
1488static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1489
1490
1491/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001492 * @brief Convert a pointer to an offset with bounds checking.
1493 *
1494 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1495 * @param[in] p Pointer to convert to offset.
1496 *
1497 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1498 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001499static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1500
1501
1502/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001503 * @brief Get pointer to bytes out of the input buffer.
1504 *
1505 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1506 * @param[in] uNum Number of bytes to get.
1507 *
1508 * @return Pointer to bytes.
1509 *
1510 * This consumes @c uNum bytes from the input buffer. This returns a
1511 * pointer to the start of the @c uNum bytes.
1512 *
1513 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1514 * returned and the error state is entered.
1515 *
1516 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001517 */
1518const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1519
1520
1521/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001522 * @brief Get @ref UsefulBuf out of the input buffer.
1523 *
1524 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1525 * @param[in] uNum Number of bytes to get.
1526 *
1527 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1528 *
1529 * This consumes @c uNum bytes from the input buffer and returns the
1530 * pointer and length for them as a @ref UsefulBufC. The length
1531 * returned will always be @c uNum. The position cursor is advanced by
1532 * @c uNum bytes.
1533 *
1534 * If there are not @c uNum bytes in the input buffer, @ref
1535 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001536 */
1537static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1538
1539
1540/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001541 * @brief Get a byte out of the input buffer.
1542 *
1543 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1544 *
1545 * @return The byte.
1546 *
1547 * This consumes 1 byte from the input buffer, returns it and advances
1548 * the position cursor by 1.
1549 *
1550 * If there is not 1 byte in the buffer, 0 will be returned for the
1551 * byte and the error state is entered. To know if the 0 returned was
1552 * in error or the real value, the error state must be checked. If
1553 * possible, put this off until all values are retrieved to have
1554 * smaller and simpler code, but if not possible
1555 * UsefulInputBuf_GetError() can be called. Also, in the error state
1556 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1557 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001558 */
1559static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1560
1561
1562/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001563 * @brief Get a @c uint16_t out of the input buffer.
1564 *
1565 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1566 *
1567 * @return The @c uint16_t.
1568 *
1569 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1570 * a @c uint16_t and two bytes are consumed.
1571 *
1572 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001573 */
1574static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1575
1576
1577/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001578 * @brief Get a @c uint32_t out of the input buffer.
1579 *
1580 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1581 *
1582 * @return The @c uint32_t.
1583 *
1584 * See UsefulInputBuf_GetByte(). This works the same, except it
1585 * returns a @c uint32_t and four bytes are consumed.
1586 *
1587 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001588 */
1589static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1590
1591
1592/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001593 * @brief Get a @c uint64_t out of the input buffer.
1594 *
1595 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1596 *
1597 * @return The uint64_t.
1598 *
1599 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1600 * a @c uint64_t and eight bytes are consumed.
1601 *
1602 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001603 */
1604static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1605
1606
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001607#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001608/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001609 * @brief Get a float out of the input buffer.
1610 *
1611 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1612 *
1613 * @return The float.
1614 *
1615 * See UsefulInputBuf_GetByte(). This works the same, except it
1616 * returns a float and four bytes are consumed.
1617 *
1618 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001619 */
1620static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1621
1622
1623/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001624 * @brief Get a double out of the input buffer.
1625 *
1626 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1627 *
1628 * @return The double.
1629 *
1630 * See UsefulInputBuf_GetByte(). This works the same, except it
1631 * returns a double and eight bytes are consumed.
1632 *
1633 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001634 */
1635static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001636#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001637
1638
1639/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001640 * @brief Get the error status.
1641 *
1642 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1643 *
1644 * @return 0 if not in the error state, 1 if in the error state.
1645 *
1646 * This returns whether the @ref UsefulInputBuf is in the
1647 * error state or not.
1648 *
1649 * The error state is entered for one of these reasons:
1650 * - Attempt to fetch data past the end of the buffer
1651 * - Attempt to seek to a position past the end of the buffer
1652 * - Attempt to get data from an uninitialized or corrupt instance
1653 * of @ref UsefulInputBuf
1654 *
1655 * Once in the error state, it can only be cleared by calling
1656 * UsefulInputBuf_Init().
1657 *
1658 * For many use cases, it is possible to only call this once after all
1659 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1660 * possible if no reference to the data returned are needed before the
1661 * error state is checked.
1662 *
1663 * In some cases UsefulInputBuf_GetUsefulBuf() or
1664 * UsefulInputBuf_GetBytes() can stand in for this because they return
1665 * @c NULL if the error state has been entered. (The others can't stand
1666 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001667 */
1668static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1669
1670
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001671/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001672 * @brief Gets the input buffer length.
1673 *
1674 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1675 *
1676 * @return The length of the input buffer.
1677 *
1678 * This returns the length of the input buffer set by
1679 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001680 */
1681static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1682
1683
1684/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001685 * @brief Alters the input buffer length (use with caution).
1686 *
1687 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1688 * @param[in] uNewLen The new length of the input buffer.
1689 *
1690 * This alters the internal remembered length of the input buffer set
1691 * when UsefulInputBuf_Init() was called.
1692 *
1693 * The new length given here should always be equal to or less than
1694 * the length given when UsefulInputBuf_Init() was called. Making it
1695 * larger allows @ref UsefulInputBuf to run off the input buffer.
1696 *
1697 * The typical use is to set a length shorter than that when
1698 * initialized to constrain parsing. If
1699 * UsefulInputBuf_GetBufferLength() was called before this, then the
1700 * original length can be restored with another call to this.
1701 *
1702 * This should be used with caution. It is the only
1703 * @ref UsefulInputBuf method that can violate the safety of input
1704 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001705 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001706static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001707
1708
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001709
1710
Michael Eckel5c531332020-03-02 01:35:30 +01001711/*----------------------------------------------------------
1712 Inline implementations.
1713 */
1714static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1715{
1716 return !UB.ptr;
1717}
1718
1719
1720static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1721{
1722 return !UB.ptr;
1723}
1724
1725
1726static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1727{
1728 return !UB.len;
1729}
1730
1731
1732static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1733{
1734 return !UB.len;
1735}
1736
1737
1738static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1739{
1740 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1741}
1742
1743
1744static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1745{
1746 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1747}
1748
1749
1750static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1751{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001752 UsefulBufC UBC;
1753 UBC.ptr = UB.ptr;
1754 UBC.len = UB.len;
1755
1756 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001757}
1758
Michael Eckel5c531332020-03-02 01:35:30 +01001759static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1760{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001761 UsefulBuf UB;
1762
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001763 /* -Wcast-qual is a good warning flag to use in general. This is
1764 * the one place in UsefulBuf where it needs to be quieted. Since
1765 * clang supports GCC pragmas, this works for clang too. */
Dave Thaler93c01182022-08-06 15:08:35 -04001766#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001767#pragma GCC diagnostic push
1768#pragma GCC diagnostic ignored "-Wcast-qual"
Dave Thaler93c01182022-08-06 15:08:35 -04001769#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001770 UB.ptr = (void *)UBC.ptr;
Dave Thaler93c01182022-08-06 15:08:35 -04001771#ifndef _MSC_VER
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001772#pragma GCC diagnostic pop
Dave Thaler93c01182022-08-06 15:08:35 -04001773#endif
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001774
1775 UB.len = UBC.len;
1776
1777 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001778}
1779
1780
1781static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1782{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001783 UsefulBufC UBC;
1784 UBC.ptr = szString;
1785 UBC.len = strlen(szString);
1786 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001787}
1788
1789
1790static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1791{
1792 return UsefulBuf_CopyOffset(Dest, 0, Src);
1793}
1794
1795
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001796static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001797{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001798 memset(Dest.ptr, value, Dest.len);
1799
1800 UsefulBufC UBC;
1801 UBC.ptr = Dest.ptr;
1802 UBC.len = Dest.len;
1803
1804 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001805}
1806
1807
1808static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1809{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001810 UsefulBufC UBC;
1811 UBC.ptr = ptr;
1812 UBC.len = len;
1813 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001814}
1815
1816
1817static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1818{
1819 if(uAmount > UB.len) {
1820 return NULLUsefulBufC;
1821 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001822 UsefulBufC UBC;
1823
1824 UBC.ptr = UB.ptr;
1825 UBC.len = uAmount;
1826
1827 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001828}
1829
1830
1831static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1832{
1833 UsefulBufC ReturnValue;
1834
1835 if(uAmount > UB.len) {
1836 ReturnValue = NULLUsefulBufC;
1837 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001838 ReturnValue.ptr = NULL;
1839 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001840 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001841 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1842 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001843 }
1844
1845 return ReturnValue;
1846}
1847
1848
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001849static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1850{
1851 if(UB.ptr == NULL) {
1852 return SIZE_MAX;
1853 }
1854
1855 if(p < UB.ptr) {
1856 /* given pointer is before start of buffer */
1857 return SIZE_MAX;
1858 }
1859
1860 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001861 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001862
1863 if(uOffset >= UB.len) {
1864 /* given pointer is off the end of the buffer */
1865 return SIZE_MAX;
1866 }
1867
1868 return uOffset;
1869}
1870
Michael Eckel5c531332020-03-02 01:35:30 +01001871
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001872#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001873static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1874{
1875 uint32_t u32;
1876 memcpy(&u32, &f, sizeof(uint32_t));
1877 return u32;
1878}
1879
1880static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1881{
1882 uint64_t u64;
1883 memcpy(&u64, &d, sizeof(uint64_t));
1884 return u64;
1885}
1886
1887static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1888{
1889 double d;
1890 memcpy(&d, &u64, sizeof(uint64_t));
1891 return d;
1892}
1893
1894static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1895{
1896 float f;
1897 memcpy(&f, &u32, sizeof(uint32_t));
1898 return f;
1899}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001900#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001901
1902
1903
1904
1905static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1906{
1907 pMe->data_len = 0;
1908 pMe->err = 0;
1909}
1910
1911
1912static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1913{
1914 return pMe->data_len;
1915}
1916
1917
1918static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1919{
1920 return 0 == pMe->data_len;
1921}
1922
1923
1924static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1925 const void *pBytes,
1926 size_t uLen,
1927 size_t uPos)
1928{
1929 UsefulBufC Data = {pBytes, uLen};
1930 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1931}
1932
1933
1934static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1935 const char *szString,
1936 size_t uPos)
1937{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001938 UsefulBufC UBC;
1939 UBC.ptr = szString;
1940 UBC.len = strlen(szString);
1941
1942 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001943}
1944
1945
1946static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1947 uint8_t byte,
1948 size_t uPos)
1949{
1950 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1951}
1952
1953
1954static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1955 uint16_t uInteger16,
1956 size_t uPos)
1957{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001958 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001959
1960 const void *pBytes;
1961
1962#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1963 pBytes = &uInteger16;
1964
1965#elif defined(USEFULBUF_CONFIG_HTON)
1966 uint16_t uTmp = htons(uInteger16);
1967 pBytes = &uTmp;
1968
1969#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1970 uint16_t uTmp = __builtin_bswap16(uInteger16);
1971 pBytes = &uTmp;
1972
1973#else
1974 uint8_t aTmp[2];
1975
1976 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1977 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1978
1979 pBytes = aTmp;
1980#endif
1981
1982 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1983}
1984
1985
1986static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1987 uint32_t uInteger32,
1988 size_t uPos)
1989{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001990 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001991
1992 const void *pBytes;
1993
1994#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1995 pBytes = &uInteger32;
1996
1997#elif defined(USEFULBUF_CONFIG_HTON)
1998 uint32_t uTmp = htonl(uInteger32);
1999 pBytes = &uTmp;
2000
2001#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
2002 uint32_t uTmp = __builtin_bswap32(uInteger32);
2003
2004 pBytes = &uTmp;
2005
2006#else
2007 uint8_t aTmp[4];
2008
2009 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
2010 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
2011 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
2012 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
2013
2014 pBytes = aTmp;
2015#endif
2016
2017 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
2018}
2019
2020static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002021 uint64_t uInteger64,
2022 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01002023{
2024 const void *pBytes;
2025
2026#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002027 /* We have been told explicitly we are running on a big-endian
2028 * machine. Network byte order is big endian, so just copy. There
2029 * is no issue with alignment here because uInteger64 is always
2030 * aligned (and it doesn't matter if pBytes is aligned).
2031 */
Michael Eckel5c531332020-03-02 01:35:30 +01002032 pBytes = &uInteger64;
2033
2034#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002035 /* Use system function to handle big- and little-endian. This works
2036 * on both big- and little-endian machines, but hton() is not
2037 * always available or in a standard place so it is not used by
2038 * default. With some compilers and CPUs the code for this is very
2039 * compact through use of a special swap instruction and on
2040 * big-endian machines hton() will reduce to nothing.
2041 */
Michael Eckel5c531332020-03-02 01:35:30 +01002042 uint64_t uTmp = htonll(uInteger64);
2043
2044 pBytes = &uTmp;
2045
2046#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002047 /* Use built-in function for byte swapping. This usually compiles
2048 * to an efficient special byte swap instruction. Unlike hton() it
2049 * does not do this conditionally on the CPU endianness, so this
2050 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
2051 */
Michael Eckel5c531332020-03-02 01:35:30 +01002052 uint64_t uTmp = __builtin_bswap64(uInteger64);
2053
2054 pBytes = &uTmp;
2055
2056#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002057 /* Default which works on every CPU with no dependency on anything
2058 * from the CPU, compiler, libraries or OS. This always works, but
2059 * it is usually a little larger and slower than hton().
2060 */
Michael Eckel5c531332020-03-02 01:35:30 +01002061 uint8_t aTmp[8];
2062
2063 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2064 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2065 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2066 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2067 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2068 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2069 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2070 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2071
2072 pBytes = aTmp;
2073#endif
2074
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002075 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002076 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2077}
2078
2079
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002080#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002081static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2082 float f,
2083 size_t uPos)
2084{
2085 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2086}
2087
2088
2089static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2090 double d,
2091 size_t uPos)
2092{
2093 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2094}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002095#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002096
2097
2098static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2099 UsefulBufC NewData)
2100{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002101 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002102 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2103}
2104
2105
2106static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2107 const void *pBytes,
2108 size_t uLen)
2109{
2110 UsefulBufC Data = {pBytes, uLen};
2111 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2112}
2113
2114
2115static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2116 const char *szString)
2117{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002118 UsefulBufC UBC;
2119 UBC.ptr = szString;
2120 UBC.len = strlen(szString);
2121
2122 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002123}
2124
2125
2126static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2127 uint8_t byte)
2128{
2129 UsefulOutBuf_AppendData(pMe, &byte, 1);
2130}
2131
2132
2133static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2134 uint16_t uInteger16)
2135{
2136 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2137}
2138
2139static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2140 uint32_t uInteger32)
2141{
2142 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2143}
2144
2145
2146static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2147 uint64_t uInteger64)
2148{
2149 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2150}
2151
2152
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002153#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002154static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2155 float f)
2156{
2157 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2158}
2159
2160
2161static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2162 double d)
2163{
2164 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2165}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002166#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002167
2168
2169static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2170{
2171 return pMe->err;
2172}
2173
2174
2175static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2176{
2177 return pMe->UB.len - pMe->data_len;
2178}
2179
2180
2181static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2182{
2183 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2184}
2185
2186
2187static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2188{
2189 return pMe->UB.ptr == NULL;
2190}
2191
2192
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002193static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
2194{
2195 UsefulBuf R;
2196
2197 R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
Paul Liétarc6cfa332022-07-26 19:24:01 +01002198 if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
Laurence Lundbladeb24faef2022-04-26 11:03:08 -06002199 R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
2200 } else {
2201 R.ptr = NULL;
2202 }
2203
2204 return R;
2205}
2206
2207
2208
Michael Eckel5c531332020-03-02 01:35:30 +01002209
2210static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2211{
2212 pMe->cursor = 0;
2213 pMe->err = 0;
2214 pMe->magic = UIB_MAGIC;
2215 pMe->UB = UB;
2216}
2217
2218static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2219{
2220 return pMe->cursor;
2221}
2222
2223
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002224static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002225{
2226 return pMe->UB.len;
2227}
2228
2229
Michael Eckel5c531332020-03-02 01:35:30 +01002230static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2231{
2232 if(uPos > pMe->UB.len) {
2233 pMe->err = 1;
2234 } else {
2235 pMe->cursor = uPos;
2236 }
2237}
2238
2239
2240static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2241{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002242 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002243
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002244 /* Magic number is messed up. Either the structure got overwritten
2245 * or was never initialized.
2246 */
Michael Eckel5c531332020-03-02 01:35:30 +01002247 if(pMe->magic != UIB_MAGIC) {
2248 return 0;
2249 }
2250
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002251 /* The cursor is off the end of the input buffer given.
2252 * Presuming there are no bugs in this code, this should never happen.
2253 * If it so, the struct was corrupted. The check is retained as
2254 * as a defense in case there is a bug in this code or the struct is
2255 * corrupted.
2256 */
Michael Eckel5c531332020-03-02 01:35:30 +01002257 if(pMe->cursor > pMe->UB.len) {
2258 return 0;
2259 }
2260
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002261 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002262 return pMe->UB.len - pMe->cursor;
2263}
2264
2265
2266static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2267{
2268 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2269}
2270
2271
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002272static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2273{
2274 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2275}
2276
2277
Michael Eckel5c531332020-03-02 01:35:30 +01002278static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2279{
2280 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2281 if(!pResult) {
2282 return NULLUsefulBufC;
2283 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002284 UsefulBufC UBC;
2285 UBC.ptr = pResult;
2286 UBC.len = uNum;
2287 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002288 }
2289}
2290
2291
2292static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2293{
2294 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2295
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002296 /* The ternary operator is subject to integer promotion, because
2297 * the operands are smaller than int, so cast back to uint8_t is
2298 * needed to be completely explicit about types (for static
2299 * analyzers).
2300 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002301 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002302}
2303
2304static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2305{
2306 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2307
2308 if(!pResult) {
2309 return 0;
2310 }
2311
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002312 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002313#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2314 uint16_t uTmp;
2315 memcpy(&uTmp, pResult, sizeof(uint16_t));
2316
2317#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2318 return uTmp;
2319
2320#elif defined(USEFULBUF_CONFIG_HTON)
2321 return ntohs(uTmp);
2322
2323#else
2324 return __builtin_bswap16(uTmp);
2325
2326#endif
2327
2328#else
2329
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002330 /* The operations here are subject to integer promotion because the
2331 * operands are smaller than int. They will be promoted to unsigned
2332 * int for the shift and addition. The cast back to uint16_t is is
2333 * needed to be completely explicit about types (for static
2334 * analyzers).
2335 */
Michael Eckel5c531332020-03-02 01:35:30 +01002336 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2337
2338#endif
2339}
2340
2341
2342static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2343{
2344 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2345
2346 if(!pResult) {
2347 return 0;
2348 }
2349
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002350 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002351#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2352 uint32_t uTmp;
2353 memcpy(&uTmp, pResult, sizeof(uint32_t));
2354
2355#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2356 return uTmp;
2357
2358#elif defined(USEFULBUF_CONFIG_HTON)
2359 return ntohl(uTmp);
2360
2361#else
2362 return __builtin_bswap32(uTmp);
2363
2364#endif
2365
2366#else
2367 return ((uint32_t)pResult[0]<<24) +
2368 ((uint32_t)pResult[1]<<16) +
2369 ((uint32_t)pResult[2]<<8) +
2370 (uint32_t)pResult[3];
2371#endif
2372}
2373
2374
2375static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2376{
2377 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2378
2379 if(!pResult) {
2380 return 0;
2381 }
2382
2383#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002384 /* pResult will probably not be aligned. This memcpy() moves the
2385 * bytes into a temp variable safely for CPUs that can or can't do
2386 * unaligned memory access. Many compilers will optimize the
2387 * memcpy() into a simple move instruction.
2388 */
Michael Eckel5c531332020-03-02 01:35:30 +01002389 uint64_t uTmp;
2390 memcpy(&uTmp, pResult, sizeof(uint64_t));
2391
2392#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002393 /* We have been told expliclity this is a big-endian CPU. Since
2394 * network byte order is big-endian, there is nothing to do.
2395 */
Michael Eckel5c531332020-03-02 01:35:30 +01002396
2397 return uTmp;
2398
2399#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002400 /* We have been told to use ntoh(), the system function to handle
2401 * big- and little-endian. This works on both big- and
2402 * little-endian machines, but ntoh() is not always available or in
2403 * a standard place so it is not used by default. On some CPUs the
2404 * code for this is very compact through use of a special swap
2405 * instruction.
2406 */
Michael Eckel5c531332020-03-02 01:35:30 +01002407
2408 return ntohll(uTmp);
2409
2410#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002411 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2412 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2413 * __builtin_bswap64() and friends are not conditional on CPU
2414 * endianness so this must only be used on little-endian machines.
2415 */
Michael Eckel5c531332020-03-02 01:35:30 +01002416
2417 return __builtin_bswap64(uTmp);
2418
2419
2420#endif
2421
2422#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002423 /* This is the default code that works on every CPU and every
2424 * endianness with no dependency on ntoh(). This works on CPUs
2425 * that either allow or do not allow unaligned access. It will
2426 * always work, but usually is a little less efficient than ntoh().
2427 */
Michael Eckel5c531332020-03-02 01:35:30 +01002428
2429 return ((uint64_t)pResult[0]<<56) +
2430 ((uint64_t)pResult[1]<<48) +
2431 ((uint64_t)pResult[2]<<40) +
2432 ((uint64_t)pResult[3]<<32) +
2433 ((uint64_t)pResult[4]<<24) +
2434 ((uint64_t)pResult[5]<<16) +
2435 ((uint64_t)pResult[6]<<8) +
2436 (uint64_t)pResult[7];
2437#endif
2438}
2439
2440
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002441#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002442static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2443{
2444 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2445
2446 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2447}
2448
2449
2450static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2451{
2452 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2453
2454 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2455}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002456#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002457
2458
2459static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2460{
2461 return pMe->err;
2462}
2463
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002464
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002465static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002466{
2467 pMe->UB.len = uNewLen;
2468}
2469
2470
Michael Eckel5c531332020-03-02 01:35:30 +01002471#ifdef __cplusplus
2472}
2473#endif
2474
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002475#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002476
2477