blob: 1662fccdfa5f5274c67ec305dc991e1ef9331426 [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladecf41c522021-02-20 10:19:07 -07003 Copyright (c) 2018-2021, 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 Lundblade8ece3732021-09-21 21:47:23 -070045 9/21/2021 llundbla Clarify UsefulOutBuf size calculation mode
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070046 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070047 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080048 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070049 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010050 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
51 5/21/2019 llundblade #define configs for efficient endianness handling.
52 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
53 3/23/2019 llundblade Big documentation & style update. No interface
54 change.
55 3/6/2019 llundblade Add UsefulBuf_IsValue()
56 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
57 12/13/2018 llundblade Documentation improvements
58 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
59 UsefulBufC.
60 02/02/18 llundbla Full support for integers in and out; fix pointer
61 alignment bug. Incompatible change: integers
62 in/out are now in network byte order.
63 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
64 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
65 comparison for < or > for unequal length buffers.
66 Added UsefulBuf_Set() function.
67 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
68 11/13/16 llundbla Initial Version.
69
70 =============================================================================*/
71
72#ifndef _UsefulBuf_h
73#define _UsefulBuf_h
74
75
76/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070077 * Endianness Configuration
78 *
79 * This code is written so it will work correctly on big- and
80 * little-endian CPUs without configuration or any auto-detection of
81 * endianness. All code here will run correctly regardless of the
82 * endianness of the CPU it is running on.
83 *
84 * There are four C preprocessor macros that can be set with #define
85 * to explicitly configure endianness handling. Setting them can
86 * reduce code size a little and improve efficiency a little.
87 *
88 * Note that most of QCBOR is unaffected by this configuration. Its
89 * endianness handling is integrated with the code that handles
90 * alignment and preferred serialization. This configuration does
91 * affect QCBOR's (planned) implementation of integer arrays (tagged
92 * arrays) and use of the functions here to serialize or deserialize
93 * integers and floating-point values.
94 *
95 * Following is the recipe for configuring the endianness-related
96 * #defines.
97 *
98 * The first option is to not define anything. This will work fine
99 * with all CPUs, OS's and compilers. The code for encoding integers
100 * may be a little larger and slower.
101 *
102 * If your CPU is big-endian then define
103 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
104 * for big-endian CPUs. It will be small and efficient because there
105 * will be no byte swapping.
106 *
107 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
108 * OS's and compilers, but not all. On big-endian CPUs this should
109 * give the most efficient code, the same as
110 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
111 * call the system-defined byte swapping method which is presumably
112 * implemented efficiently. In some cases, this will be a dedicated
113 * byte swap instruction like Intel's bswap.
114 *
115 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
116 * little-endian, it is also good to define
117 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
118 *
119 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
120 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
121 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
122 * system-defined byte swap method. However, note
123 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
124 * this is fixed now. Often hton() and ntoh() will call the built-in
125 * __builtin_bswapXX()() function, so this size issue could affect
126 * USEFULBUF_CONFIG_HTON.
127 *
128 * Last, run the tests. They must all pass.
129 *
130 * These #define config options affect the inline implementation of
131 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
132 * also affect the 16-, 32-bit, float and double versions of these
133 * functions. Since they are inline, the size effect is not in the
134 * UsefulBuf object code, but in the calling code.
135 *
136 * Summary:
137 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
138 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
139 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
140 * handle big and little-endian with system option.
141 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
142 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200143 *
144 * It is possible to run this code in environments where using floating point is
145 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
146 * that is related to handling floating point types, along with related
147 * interfaces. This makes it possible to compile the code with the compile
148 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100149 */
150
151#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
152#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
153#endif
154
155
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700156#include <stdint.h> /* for uint8_t, uint16_t.... */
157#include <string.h> /* for strlen, memcpy, memmove, memset */
158#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100159
160
161#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700162#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100163#endif
164
165#ifdef __cplusplus
166extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700167#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700168} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700169#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100170#endif
171
172/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700173 * @file UsefulBuf.h
174 *
175 * The goal of this code is to make buffer and pointer manipulation
176 * easier and safer when working with binary data.
177 *
178 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
179 * structures are used to represent buffers rather than ad hoc
180 * pointers and lengths.
181 *
182 * With these it is possible to write code that does little or no
183 * direct pointer manipulation for copying and formatting data. For
184 * example, the QCBOR encoder was written using these and has less
185 * pointer manipulation.
186 *
187 * While it is true that object code using these functions will be a
188 * little larger and slower than a white-knuckle clever use of
189 * pointers might be, but not by that much or enough to have an effect
190 * for most use cases. For security-oriented code this is highly
191 * worthwhile. Clarity, simplicity, reviewability and are more
192 * important.
193 *
194 * There are some extra sanity and double checks in this code to help
195 * catch coding errors and simple memory corruption. They are helpful,
196 * but not a substitute for proper code review, input validation and
197 * such.
198 *
199 * This code consists of a lot of inline functions and a few that are
200 * not. It should not generate very much object code, especially with
201 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100202 */
203
204
205/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700206 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
207 * hold a pointer and length for binary data. In C99 this data
208 * structure can be passed on the stack making a lot of code cleaner
209 * than carrying around a pointer and length as two parameters.
210 *
211 * This is also conducive to secure coding practice as the length is
212 * always carried with the pointer and the convention for handling a
213 * pointer and a length is clear.
214 *
215 * While it might be possible to write buffer and pointer code more
216 * efficiently in some use cases, the thought is that unless there is
217 * an extreme need for performance (e.g., you are building a
218 * gigabit-per-second IP router), it is probably better to have
219 * cleaner code you can be most certain about the security of.
220 *
221 * The non-const @ref UsefulBuf is usually used to refer an empty
222 * buffer to be filled in. The length is the size of the buffer.
223 *
224 * The const @ref UsefulBufC is usually used to refer to some data
225 * that has been filled in. The length is amount of valid data pointed
226 * to.
227 *
228 * A common use mode is to pass a @ref UsefulBuf to a function, the
229 * function puts some data in it, then the function returns a @ref
230 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
231 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
232 * so the constness stays correct. There is no single "in,out"
233 * parameter (if there was, it would have to be non-const). Note that
234 * the pointer returned in the @ref UsefulBufC usually ends up being
235 * the same pointer passed in as a @ref UsefulBuf, though this is not
236 * striclty required.
237 *
238 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
239 * @c NULL.
240 *
241 * There are functions and macros for the following:
242 * - Initializing
243 * - Create initialized const @ref UsefulBufC from compiler literals
244 * - Create initialized const @ref UsefulBufC from NULL-terminated string
245 * - Make an empty @ref UsefulBuf on the stack
246 * - Checking whether a @ref UsefulBuf is null, empty or both
247 * - Copying, copying with offset, copying head or tail
248 * - Comparing and finding substrings
249 *
250 * See also @ref UsefulOutBuf. It is a richer structure that has both
251 * the size of the valid data and the size of the buffer.
252 *
253 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
254 * it can go on the stack and be a function parameter or return value.
255 *
256 * Another way to look at it is this. C has the NULL-terminated string
257 * as a means for handling text strings, but no means or convention
258 * for binary strings. Other languages do have such means, Rust, an
259 * efficient compiled language, for example.
260 *
261 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
262 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
263 * out like anything".
264 */
Michael Eckel5c531332020-03-02 01:35:30 +0100265typedef struct q_useful_buf_c {
266 const void *ptr;
267 size_t len;
268} UsefulBufC;
269
270
271/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700272 * This non-const @ref UsefulBuf is typically used for some allocated
273 * memory that is to be filled in. The @c len is the amount of memory,
274 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100275 */
276typedef struct q_useful_buf {
277 void *ptr;
278 size_t len;
279} UsefulBuf;
280
281
282/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700283 * A null @ref UsefulBufC is one that has no value in the same way a
284 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
285 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
286 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100287 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700288/*
289 * NULLUsefulBufC and few other macros have to be
290 * definied differently in C than C++ because there
291 * is no common construct for a literal structure.
292 *
293 * In C compound literals are used.
294 *
295 * In C++ list initalization is used. This only works
296 * in C++11 and later.
297 *
298 * Note that some popular C++ compilers can handle compound
299 * literals with on-by-default extensions, however
300 * this code aims for full correctness with strict
301 * compilers so they are not used.
302 */
303#ifdef __cplusplus
304#define NULLUsefulBufC {NULL, 0}
305#else
306#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
307#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100308
309/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700310 * A null @ref UsefulBuf is one that has no memory associated the same
311 * way @c NULL points to nothing. It does not matter what @c len is.
312 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700313#ifdef __cplusplus
314#define NULLUsefulBuf {NULL, 0}
315#else
316#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
317#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100318
319
320/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700321 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
322 *
323 * @param[in] UB The UsefulBuf to check.
324 *
325 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100326 */
327static inline int UsefulBuf_IsNULL(UsefulBuf UB);
328
329
330/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700331 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
332 *
333 * @param[in] UB The @ref UsefulBufC to check.
334 *
335 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100336 */
337static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
338
339
340/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700341 * @brief Check if a @ref UsefulBuf is empty or not.
342 *
343 * @param[in] UB The @ref UsefulBuf to check.
344 *
345 * @return 1 if it is empty, 0 if not.
346 *
347 * An "empty" @ref UsefulBuf is one that has a value and can be
348 * considered to be set, but that value is of zero length. It is
349 * empty when @c len is zero. It doesn't matter what the @c ptr is.
350 *
351 * Many uses will not need to clearly distinguish a @c NULL @ref
352 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
353 * @c len 0. However if a use of @ref UsefulBuf needs to make a
354 * distinction then @c ptr should not be @c NULL when the @ref
355 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100356 */
357static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
358
359
360/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700361 * @brief Check if a @ref UsefulBufC is empty or not.
362 *
363 * @param[in] UB The @ref UsefulBufC to check.
364 *
365 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100366 */
367static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
368
369
370/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700371 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
372 *
373 * @param[in] UB The @ref UsefulBuf to check.
374 *
375 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100376 */
377static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
378
379
380/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700381 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
382 *
383 * @param[in] UB The @ref UsefulBufC to check.
384 *
385 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100386 */
387static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
388
389
390/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700391 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
392 *
393 * @param[in] UB The @ref UsefulBuf to convert.
394 *
395 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100396 */
397static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
398
399
400/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700401 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
402 *
403 * @param[in] UBC The @ref UsefulBuf to convert.
404 *
405 * @return A non-const @ref UsefulBuf struct.
406 *
407 * Use of this is not necessary for the intended use mode of @ref
408 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
409 * created to describe a buffer that has not had any data put in
410 * it. Then the data is put in it. Then a @ref UsefulBufC is create
411 * to describe the part with the data in it. This goes from non-const
412 * to const, so this function is not needed.
413 *
414 * If the -Wcast-qual warning is enabled, this function can be used to
415 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100416 */
417static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
418
419
420/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700421 * Convert a literal string to a @ref UsefulBufC.
422 *
423 * @c szString must be a literal string that @c sizeof() works on.
424 * This is better for literal strings than UsefulBuf_FromSZ() because
425 * it generates less code. It will not work on non-literal strings.
426 *
427 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100428 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700429#ifdef __cplusplus
430#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
431#else
Michael Eckel5c531332020-03-02 01:35:30 +0100432#define UsefulBuf_FROM_SZ_LITERAL(szString) \
433 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700434#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100435
436
437/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700438 * Convert a literal byte array to a @ref UsefulBufC.
439 *
440 * @c pBytes must be a literal string that @c sizeof() works on. It
441 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100442 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700443#ifdef __cplusplus
444#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
445#else
Michael Eckel5c531332020-03-02 01:35:30 +0100446#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700447 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
448#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100449
450/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700451 * Make an automatic variable named @c name of type @ref UsefulBuf and
452 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100453 */
454#define UsefulBuf_MAKE_STACK_UB(name, size) \
455 uint8_t __pBuf##name[(size)];\
456 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
457
458
459/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700460 * Make a byte array in to a @ref UsefulBuf. This is usually used on
461 * stack variables or static variables. Also see @ref
462 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100463 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700464#ifdef __cplusplus
465#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
466#else
Michael Eckel5c531332020-03-02 01:35:30 +0100467#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700468 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
469#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100470
471
472/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700473 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
474 *
475 * @param[in] szString The string to convert.
476 *
477 * @return A @ref UsefulBufC struct.
478 *
479 * @c UsefulBufC.ptr points to the string so its lifetime must be
480 * maintained.
481 *
482 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100483 */
484static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
485
486
487/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700488 * @brief Copy one @ref UsefulBuf into another at an offset.
489 *
490 * @param[in] Dest Destination buffer to copy into.
491 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
492 * @param[in] Src The bytes to copy.
493 *
494 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
495 *
496 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
497 * size of @c Dest.
498 *
499 * This fails and returns @ref NULLUsefulBufC if the @c Src length
500 * plus @c uOffset is greater than the length of @c Dest.
501 *
502 * The results are undefined if @c Dest and @c Src overlap.
503 *
504 * This assumes that there is valid data in @c Dest up to @c
505 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
506 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100507 */
508UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
509
510
511/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700512 * @brief Copy one @ref UsefulBuf into another.
513 *
514 * @param[in] Dest The destination buffer to copy into.
515 * @param[out] Src The source to copy from.
516 *
517 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
518 * on failure.
519 *
520 * This fails if @c Src.len is greater than @c Dest.len.
521 *
522 * Note that like @c memcpy(), the pointers are not checked and this
523 * will crash rather than return @ref NULLUsefulBufC if they are @c
524 * NULL or invalid.
525 *
526 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100527 */
528static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
529
530
531/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700532 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
533 *
534 * @param[in] pDest The destination buffer to copy into.
535 * @param[in] value The value to set the bytes to.
536 *
537 * Note that like @c memset(), the pointer in @c pDest is not checked
538 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100539 */
540static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
541
542
543/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700544 * @brief Copy a pointer into a @ref UsefulBuf.
545 *
546 * @param[in,out] Dest The destination buffer to copy into.
547 * @param[in] ptr The source to copy from.
548 * @param[in] uLen Length of the source; amount to copy.
549 *
550 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
551 * on failure.
552 *
553 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
554 * than @c pDest->len.
555 *
556 * Note that like @c memcpy(), the pointers are not checked and this
557 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100558 */
559static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
560 const void *ptr,
561 size_t uLen);
562
563
564/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700565 * @brief Returns a truncation of a @ref UsefulBufC.
566 *
567 * @param[in] UB The buffer to get the head of.
568 * @param[in] uAmount The number of bytes in the head.
569 *
570 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100571 */
572static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
573
574
575/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700576 * @brief Returns bytes from the end of a @ref UsefulBufC.
577 *
578 * @param[in] UB The buffer to get the tail of.
579 * @param[in] uAmount The offset from the start where the tail is to begin.
580 *
581 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
582 * if @c uAmount is greater than the length of the @ref UsefulBufC.
583 *
584 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
585 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
586 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100587 */
588static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
589
590
591/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700592 * @brief Compare one @ref UsefulBufC to another.
593 *
594 * @param[in] UB1 The first buffer to compare.
595 * @param[in] UB2 The second buffer to compare.
596 *
597 * @return 0, positive or negative value.
598 *
599 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
600 * less than @c UB2 if it is shorter or the first byte that is not the
601 * same is less.
602 *
603 * Returns 0 if the inputs are the same.
604 *
605 * Returns a positive value if @c UB2 is less than @c UB1.
606 *
607 * All that is of significance is that the result is positive, negative
608 * or 0. (This doesn't return the difference between the first
609 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100610 */
611int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
612
613
614/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700615 * @brief Find first byte that is not a particular byte value.
616 *
617 * @param[in] UB The destination buffer for byte comparison.
618 * @param[in] uValue The byte value to compare to.
619 *
620 * @return Offset of first byte that isn't @c uValue or
621 * @c SIZE_MAX if all bytes are @c uValue.
622 *
623 * Note that unlike most comparison functions, 0
624 * does not indicate a successful comparison, so the
625 * test for match is:
626 *
627 * UsefulBuf_IsValue(...) == SIZE_MAX
628 *
629 * If @c UB is null or empty, there is no match
630 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100631 */
632size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
633
634
635/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700636 * @brief Find one @ref UsefulBufC in another.
637 *
638 * @param[in] BytesToSearch Buffer to search through.
639 * @param[in] BytesToFind Buffer with bytes to be found.
640 *
641 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100642 */
643size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
644
645
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700646/**
647 @brief Convert a pointer to an offset with bounds checking.
648
649 @param[in] UB Pointer to the UsefulInputBuf.
650 @param[in] p Pointer to convert to offset.
651
652 @return SIZE_MAX if @c p is out of range, the byte offset if not.
653*/
654static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
655
656
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800657#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100658/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700659#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100660
661/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
662#define MakeUsefulBufOnStack(name, size) \
663 uint8_t __pBuf##name[(size)];\
664 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
665
666/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
667#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700668 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100669
670/** Deprecated function; use UsefulBuf_Unconst() instead */
671static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
672{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700673 UsefulBuf UB;
674
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800675 // See UsefulBuf_Unconst() implementation for comment on pragmas
676#pragma GCC diagnostic push
677#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700678 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800679#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700680
681 UB.len = UBC.len;
682
683 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100684}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800685#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100686
687
688
689
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200690#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100691/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700692 * @brief Copy a @c float to a @c uint32_t.
693 *
694 * @param[in] f Float value to copy.
695 *
696 * @return A @c uint32_t with the float bits.
697 *
698 * Convenience function to avoid type punning, compiler warnings and
699 * such. The optimizer usually reduces this to a simple assignment. This
700 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100701 */
702static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
703
704
705/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700706 * @brief Copy a @c double to a @c uint64_t.
707 *
708 * @param[in] d Double value to copy.
709 *
710 * @return A @c uint64_t with the double bits.
711 *
712 * Convenience function to avoid type punning, compiler warnings and
713 * such. The optimizer usually reduces this to a simple assignment. This
714 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100715 */
716static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
717
718
719/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700720 * @brief Copy a @c uint32_t to a @c float.
721 *
722 * @param[in] u32 Integer value to copy.
723 *
724 * @return The value as a @c float.
725 *
726 * Convenience function to avoid type punning, compiler warnings and
727 * such. The optimizer usually reduces this to a simple assignment. This
728 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100729 */
730static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
731
732
733/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700734 * @brief Copy a @c uint64_t to a @c double.
735 *
736 * @param[in] u64 Integer value to copy.
737 *
738 * @return The value as a @c double.
739 *
740 * Convenience function to avoid type punning, compiler warnings and
741 * such. The optimizer usually reduces this to a simple assignment. This
742 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100743 */
744static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200745#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100746
747
748
749
750/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700751 * UsefulOutBuf is a structure and functions (an object) for
752 * serializing data into a buffer to encode for a network protocol or
753 * write data to a file.
754 *
755 * The main idea is that all the pointer manipulation is performed by
756 * @ref UsefulOutBuf functions so the caller doesn't have to do any
757 * pointer manipulation. The pointer manipulation is centralized.
758 * This code has been reviewed and written carefully so it
759 * spares the caller of much of this work and results in safer code
760 * with less effort.
761 *
762 * The @ref UsefulOutBuf methods that add data to the output buffer
763 * always check the length and will never write off the end of the
764 * output buffer. If an attempt to add data that will not fit is made,
765 * an internal error flag will be set and further attempts to add data
766 * will not do anything.
767 *
768 * There is no way to ever write off the end of that buffer when
769 * calling the @c UsefulOutBuf_AddXxx() and
770 * @c UsefulOutBuf_InsertXxx() functions.
771 *
772 * The functions to add data do not report success of failure. The
773 * caller only needs to check for an error in the final call, either
774 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
775 * result. This makes the calling code cleaner.
776 *
777 * There is a utility function to get the error status anytime along
778 * the way for a special circumstance. There are functions to see how
779 * much room is left and see if some data will fit too, but their use
780 * is generally unnecessary.
781 *
782 * The general call flow is:
783 *
784 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
785 * buffer given to it can be from the heap, stack or
786 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
787 * macro that makes a buffer on the stack and initializes it.
788 *
789 * - Call methods like UsefulOutBuf_InsertString(),
790 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
791 * to output data. The append calls add data to the end of the
792 * valid data. The insert calls take a position argument.
793 *
794 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
795 * there were no errors and to get the serialized output bytes.
796 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700797 * @ref UsefulOutBuf can be used in a mode to calculate the size of
798 * what would be output without actually outputting anything. This is
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700799 * useful to calculate the size of a buffer that is to be allocated to
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700800 * hold the output. See @ref SizeCalculateUsefulBuf.
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700801 *
802 * Methods like UsefulOutBuf_InsertUint64() always output in network
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700803 * byte order (big endian).
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700804 *
805 * The possible errors are:
806 *
807 * - The @ref UsefulOutBuf was not initialized or was corrupted.
808 *
809 * - An attempt was made to add data that will not fit.
810 *
811 * - An attempt was made to insert data at a position beyond the end of
812 * the buffer.
813 *
814 * - An attempt was made to insert data at a position beyond the valid
815 * data in the buffer.
816 *
817 * Some inexpensive simple sanity checks are performed before every
818 * data addition to guard against use of an uninitialized or corrupted
819 * UsefulOutBuf.
820 *
821 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
822 * encoder has almost no pointer manipulation in it, is easier to
823 * read, and easier to review.
824 *
825 * A @ref UsefulOutBuf is small and can go on the stack:
826 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
827 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100828 */
829typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700830 /* PRIVATE DATA STRUCTURE */
831 UsefulBuf UB; /* Memory that is being output to */
832 size_t data_len; /* length of the valid data, the insertion point */
833 uint16_t magic; /* Used to detect corruption and lack
834 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100835 uint8_t err;
836} UsefulOutBuf;
837
838
839/**
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700840 * This is a @ref UsefulBuf value that can be passed to
841 * UsefulOutBuf_Init() to have it calculate the size of the output
842 * buffer needed. Pass this for @c Storage, call all the append and
843 * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
844 * returned @ref UsefulBufC has the size.
845 *
846 * As one can see, this is just a NULL pointer and very large size.
847 * The NULL pointer tells UsefulOutputBuf to not copy any data.
848 */
849#ifdef __cplusplus
850#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
851#else
852#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
853#endif
854
855
856/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700857 * @brief Initialize and supply the actual output buffer.
858 *
859 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
860 * @param[in] Storage Buffer to output into.
861 *
862 * This initializes the @ref UsefulOutBuf with storage, sets the
863 * current position to the beginning of the buffer and clears the
864 * error state.
865 *
Laurence Lundblade8ece3732021-09-21 21:47:23 -0700866 * See @ref SizeCalculateUsefulBuf for instructions on how to
867 * initialize a @ref UsefulOutBuf to calculate the size that would be
868 * output without actually outputting.
869 *
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700870 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100871 */
872void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
873
874
875/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700876 * Convenience macro to make a @ref UsefulOutBuf on the stack and
877 * initialize it with a stack buffer of the given size. The variable
878 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100879 */
880#define UsefulOutBuf_MakeOnStack(name, size) \
881 uint8_t __pBuf##name[(size)];\
882 UsefulOutBuf name;\
883 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
884
885
886/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700887 * @brief Reset a @ref UsefulOutBuf for re use.
888 *
889 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
890 *
891 * This sets the amount of data in the output buffer to none and
892 * clears the error state.
893 *
894 * The output buffer is still the same one and size as from the
895 * UsefulOutBuf_Init() call.
896 *
897 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100898 */
899static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
900
901
902/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700903 * @brief Returns position of end of data in the @ref UsefulOutBuf.
904 *
905 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
906 *
907 * @return position of end of data.
908 *
909 * On a freshly initialized @ref UsefulOutBuf with no data added, this
910 * will return 0. After 10 bytes have been added, it will return 10
911 * and so on.
912 *
913 * Generally, there is no need to call this for most uses of @ref
914 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100915 */
916static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
917
918
919/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700920 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
921 *
922 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
923 *
924 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100925 */
926static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
927
928
929/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700930 * @brief Inserts bytes into the @ref UsefulOutBuf.
931 *
932 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
933 * @param[in] NewData The bytes to insert.
934 * @param[in] uPos Index in output buffer at which to insert.
935 *
936 * @c NewData is the pointer and length for the bytes to be added to
937 * the output buffer. There must be room in the output buffer for all
938 * of @c NewData or an error will occur.
939 *
940 * The insertion point must be between 0 and the current valid
941 * data. If not, an error will occur. Appending data to the output
942 * buffer is achieved by inserting at the end of the valid data. This
943 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
944 *
945 * When insertion is performed, the bytes between the insertion point
946 * and the end of data previously added to the output buffer are slid
947 * to the right to make room for the new data.
948 *
949 * Overlapping buffers are OK. @c NewData can point to data in the
950 * output buffer.
951 *
952 * If an error occurs, an error state is set in the @ref
953 * UsefulOutBuf. No error is returned. All subsequent attempts to add
954 * data will do nothing.
955 *
956 * The intended use is that all additions are made without checking
957 * for an error. The error will be taken into account when
958 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
959 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100960 */
961void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
962 UsefulBufC NewData,
963 size_t uPos);
964
965
966/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700967 * @brief Insert a data buffer into the @ref UsefulOutBuf.
968 *
969 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
970 * @param[in] pBytes Pointer to the bytes to insert
971 * @param[in] uLen Length of the bytes to insert
972 * @param[in] uPos Index in output buffer at which to insert
973 *
974 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
975 * the difference being a pointer and length is passed in rather than an
976 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100977 */
978static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
979 const void *pBytes,
980 size_t uLen,
981 size_t uPos);
982
983
984/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700985 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
986 *
987 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
988 * @param[in] szString NULL-terminated string to insert.
989 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100990 */
991static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
992 const char *szString,
993 size_t uPos);
994
995
996/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700997 * @brief Insert a byte into the @ref UsefulOutBuf.
998 *
999 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
1000 * @param[in] byte Bytes to insert.
1001 * @param[in] uPos Index in output buffer at which to insert.
1002 *
1003 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1004 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +01001005 */
1006static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
1007 uint8_t byte,
1008 size_t uPos);
1009
1010
1011/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001012 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
1013 *
1014 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1015 * @param[in] uInteger16 Integer to insert.
1016 * @param[in] uPos Index in output buffer at which to insert.
1017 *
1018 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1019 * with the difference being a two-byte integer is to be inserted.
1020 *
1021 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001022 */
1023static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1024 uint16_t uInteger16,
1025 size_t uPos);
1026
1027
1028/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001029 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1030 *
1031 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1032 * @param[in] uInteger32 Integer to insert.
1033 * @param[in] uPos Index in output buffer at which to insert.
1034 *
1035 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1036 * with the difference being a four-byte integer is to be inserted.
1037 *
1038 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001039 */
1040static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1041 uint32_t uInteger32,
1042 size_t uPos);
1043
1044
1045/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001046 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1047 *
1048 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1049 * @param[in] uInteger64 Integer to insert.
1050 * @param[in] uPos Index in output buffer at which to insert.
1051 *
1052 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1053 * with the difference being an eight-byte integer is to be inserted.
1054 *
1055 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001056 */
1057static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1058 uint64_t uInteger64,
1059 size_t uPos);
1060
1061
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001062#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001063/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001064 * @brief Insert a @c float into the @ref UsefulOutBuf.
1065 *
1066 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1067 * @param[in] f @c float to insert.
1068 * @param[in] uPos Index in output buffer at which to insert.
1069 *
1070 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1071 * with the difference being a @c float is to be inserted.
1072 *
1073 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001074 */
1075static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1076 float f,
1077 size_t uPos);
1078
1079
1080/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001081 * @brief Insert a @c double into the @ref UsefulOutBuf.
1082 *
1083 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1084 * @param[in] d @c double to insert.
1085 * @param[in] uPos Index in output buffer at which to insert.
1086 *
1087 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1088 * with the difference being a @c double is to be inserted.
1089 *
1090 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001091 */
1092static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1093 double d,
1094 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001095#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001096
1097
1098/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001099 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1100 *
1101 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1102 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1103 *
1104 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1105 * with the insertion point at the end of the valid data.
1106 */
Michael Eckel5c531332020-03-02 01:35:30 +01001107static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1108 UsefulBufC NewData);
1109
1110
1111/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001112 * @brief Append bytes to the @ref UsefulOutBuf.
1113 *
1114 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1115 * @param[in] pBytes Pointer to bytes to append.
1116 * @param[in] uLen Length of @c pBytes to append.
1117 *
1118 * See UsefulOutBuf_InsertData() for details. This does the same with
1119 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001120 */
1121static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1122 const void *pBytes,
1123 size_t uLen);
1124
1125
1126/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001127 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1128 *
1129 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1130 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001131 */
1132static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1133 const char *szString);
1134
1135
1136/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001137 * @brief Append a byte to the @ref UsefulOutBuf
1138 *
1139 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1140 * @param[in] byte Bytes to append.
1141 *
1142 * See UsefulOutBuf_InsertByte() for details. This does the same
1143 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001144 */
1145static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1146 uint8_t byte);
1147
1148
1149/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001150 * @brief Append an integer to the @ref UsefulOutBuf
1151 *
1152 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1153 * @param[in] uInteger16 Integer to append.
1154 *
1155 * See UsefulOutBuf_InsertUint16() for details. This does the same
1156 * with the insertion point at the end of the valid data.
1157 *
1158 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001159 */
1160static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1161 uint16_t uInteger16);
1162
1163
1164/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001165 * @brief Append an integer to the @ref UsefulOutBuf
1166 *
1167 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1168 * @param[in] uInteger32 Integer to append.
1169 *
1170 * See UsefulOutBuf_InsertUint32() for details. This does the same
1171 * with the insertion point at the end of the valid data.
1172 *
1173 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001174 */
1175static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1176 uint32_t uInteger32);
1177
1178
1179/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001180 * @brief Append an integer to the @ref UsefulOutBuf
1181 *
1182 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1183 * @param[in] uInteger64 Integer to append.
1184 *
1185 * See UsefulOutBuf_InsertUint64() for details. This does the same
1186 * with the insertion point at the end of the valid data.
1187 *
1188 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001189 */
1190static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1191 uint64_t uInteger64);
1192
1193
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001194#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001195/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001196 * @brief Append a @c float to the @ref UsefulOutBuf
1197 *
1198 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1199 * @param[in] f @c float to append.
1200 *
1201 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1202 * the insertion point at the end of the valid data.
1203 *
1204 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001205 */
1206static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1207 float f);
1208
1209
1210/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001211 * @brief Append a @c double to the @ref UsefulOutBuf
1212 *
1213 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1214 * @param[in] d @c double to append.
1215 *
1216 * See UsefulOutBuf_InsertDouble() for details. This does the same
1217 * with the insertion point at the end of the valid data.
1218 *
1219 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001220 */
1221static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1222 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001223#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001224
1225
1226/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001227 * @brief Returns the current error status.
1228 *
1229 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1230 *
1231 * @return 0 if all OK, 1 on error.
1232 *
1233 * This returns the error status since a call to either
1234 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1235 * goes into the error state, it will stay until one of those
1236 * functions is called.
1237 *
1238 * Possible error conditions are:
1239 * - bytes to be inserted will not fit
1240 * - insertion point is out of buffer or past valid data
1241 * - current position is off end of buffer (probably corrupted or uninitialized)
1242 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001243 */
1244static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1245
1246
1247/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001248 * @brief Returns number of bytes unused used in the output buffer.
1249 *
1250 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1251 *
1252 * @return Number of unused bytes or zero.
1253 *
1254 * Because of the error handling strategy and checks in
1255 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1256 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001257 */
1258static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1259
1260
1261/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001262 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1263 *
1264 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1265 * @param[in] uLen Number of bytes for which to check
1266 *
1267 * @return 1 if @c uLen bytes will fit, 0 if not.
1268 *
1269 * Because of the error handling strategy and checks in
1270 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1271 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001272 */
1273static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1274
1275
1276 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001277 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1278 *
1279 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1280 *
1281 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1282 *
1283 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1284 * just calculating the length of the encoded data.
1285 */
Michael Eckel5c531332020-03-02 01:35:30 +01001286static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1287
1288
1289/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001290 * @brief Returns the resulting valid data in a UsefulOutBuf
1291 *
1292 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1293 *
1294 * @return The valid data in @ref UsefulOutBuf or
1295 * @ref NULLUsefulBufC if there was an error adding data.
1296 *
1297 * The storage for the returned data is the @c Storage parameter
1298 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1299 *
1300 * This can be called anytime and many times to get intermediate
1301 * results. It doesn't change the data or reset the current position,
1302 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001303 */
1304UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1305
1306
1307/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001308 * @brief Copies the valid data into a supplied buffer
1309 *
1310 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1311 * @param[out] Dest The destination buffer to copy into.
1312 *
1313 * @return Pointer and length of copied data or @c NULLUsefulBufC
1314 * if it will not fit in the @c Dest buffer or the error
1315 * state was entered.
1316 *
1317 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1318 * data to @c Dest.
1319 */
Michael Eckel5c531332020-03-02 01:35:30 +01001320UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1321
1322
1323
1324
1325/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001326 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1327 * for parsing data received. Initialize it with the data from the
1328 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1329 * get data chunks of various types. A position cursor is maintained
1330 * internally.
1331 *
1332 * As long as the functions here are used, there will never be any
1333 * reference off the end of the given buffer (except
1334 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1335 * called incorrectly, an attempt is made to seek off the end of the
1336 * buffer or such. This makes it easier to write safe and correct
1337 * code. For example, the QCBOR decoder implementation is safer and
1338 * easier to review through its use of @ref UsefulInputBuf.
1339 *
1340 * @ref UsefulInputBuf maintains an internal error state. The
1341 * intended use is fetching data chunks without any error checks until
1342 * the end. If there was any error, such as an attempt to fetch data
1343 * off the end, the error state is entered and no further data will be
1344 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1345 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1346 * null is not dereferenced, the error check can be put off until the
1347 * end, simplifying the calling code.
1348 *
1349 * The integer and float parsing expects network byte order (big
1350 * endian). Network byte order is what is used by TCP/IP, CBOR and
1351 * most internet protocols.
1352 *
1353 * Lots of inline functions are used to keep code size down. The
1354 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1355 * code size a lot. The only non-inline code is
1356 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1357 * @ref UsefulInputBuf doesn't add much code for all the messy
1358 * hard-to-get right issues with parsing binary protocols in C that it
1359 * solves.
1360 *
1361 * The parse context size is:
1362 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1363 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001364 */
1365typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001366 /* PRIVATE DATA STRUCTURE */
1367 UsefulBufC UB; /* Data being parsed */
1368 size_t cursor; /* Current offset in data being parse */
1369 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1370 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001371} UsefulInputBuf;
1372
1373#define UIB_MAGIC (0xB00F)
1374
1375
1376/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001377 * @brief Initialize the @ref UsefulInputBuf structure before use.
1378 *
1379 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1380 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001381 */
1382static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1383
1384
1385/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001386 * @brief Returns current position in input buffer.
1387 *
1388 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1389 *
1390 * @return Integer position of the cursor.
1391 *
1392 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001393 */
1394static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1395
1396
1397/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001398 * @brief Sets the current position in input buffer.
1399 *
1400 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1401 * @param[in] uPos Position to set to.
1402 *
1403 * If the position is off the end of the input buffer, the error state
1404 * is entered.
1405 *
1406 * Seeking to a valid position in the buffer will not reset the error
1407 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001408 */
1409static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1410
1411
1412/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001413 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1414 * the unconsumed bytes.
1415 *
1416 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1417 *
1418 * @return Number of bytes unconsumed or 0 on error.
1419 *
1420 * Returns 0 if the cursor is invalid or corruption of the
1421 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001422 */
1423static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1424
1425
1426/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001427 * @brief Check if there are unconsumed bytes.
1428 *
1429 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1430 * @param[in] uLen Number of bytes to check availability for.
1431 *
1432 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001433 */
1434static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1435
1436
1437/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001438 * @brief Convert a pointer to an offset with bounds checking.
1439 *
1440 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1441 * @param[in] p Pointer to convert to offset.
1442 *
1443 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1444 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001445static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1446
1447
1448/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001449 * @brief Get pointer to bytes out of the input buffer.
1450 *
1451 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1452 * @param[in] uNum Number of bytes to get.
1453 *
1454 * @return Pointer to bytes.
1455 *
1456 * This consumes @c uNum bytes from the input buffer. This returns a
1457 * pointer to the start of the @c uNum bytes.
1458 *
1459 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1460 * returned and the error state is entered.
1461 *
1462 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001463 */
1464const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1465
1466
1467/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001468 * @brief Get @ref UsefulBuf out of the input buffer.
1469 *
1470 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1471 * @param[in] uNum Number of bytes to get.
1472 *
1473 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1474 *
1475 * This consumes @c uNum bytes from the input buffer and returns the
1476 * pointer and length for them as a @ref UsefulBufC. The length
1477 * returned will always be @c uNum. The position cursor is advanced by
1478 * @c uNum bytes.
1479 *
1480 * If there are not @c uNum bytes in the input buffer, @ref
1481 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001482 */
1483static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1484
1485
1486/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001487 * @brief Get a byte out of the input buffer.
1488 *
1489 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1490 *
1491 * @return The byte.
1492 *
1493 * This consumes 1 byte from the input buffer, returns it and advances
1494 * the position cursor by 1.
1495 *
1496 * If there is not 1 byte in the buffer, 0 will be returned for the
1497 * byte and the error state is entered. To know if the 0 returned was
1498 * in error or the real value, the error state must be checked. If
1499 * possible, put this off until all values are retrieved to have
1500 * smaller and simpler code, but if not possible
1501 * UsefulInputBuf_GetError() can be called. Also, in the error state
1502 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1503 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001504 */
1505static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1506
1507
1508/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001509 * @brief Get a @c uint16_t out of the input buffer.
1510 *
1511 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1512 *
1513 * @return The @c uint16_t.
1514 *
1515 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1516 * a @c uint16_t and two bytes are consumed.
1517 *
1518 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001519 */
1520static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1521
1522
1523/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001524 * @brief Get a @c uint32_t out of the input buffer.
1525 *
1526 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1527 *
1528 * @return The @c uint32_t.
1529 *
1530 * See UsefulInputBuf_GetByte(). This works the same, except it
1531 * returns a @c uint32_t and four bytes are consumed.
1532 *
1533 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001534 */
1535static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1536
1537
1538/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001539 * @brief Get a @c uint64_t out of the input buffer.
1540 *
1541 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1542 *
1543 * @return The uint64_t.
1544 *
1545 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1546 * a @c uint64_t and eight bytes are consumed.
1547 *
1548 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001549 */
1550static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1551
1552
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001553#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001554/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001555 * @brief Get a float out of the input buffer.
1556 *
1557 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1558 *
1559 * @return The float.
1560 *
1561 * See UsefulInputBuf_GetByte(). This works the same, except it
1562 * returns a float and four bytes are consumed.
1563 *
1564 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001565 */
1566static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1567
1568
1569/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001570 * @brief Get a double out of the input buffer.
1571 *
1572 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1573 *
1574 * @return The double.
1575 *
1576 * See UsefulInputBuf_GetByte(). This works the same, except it
1577 * returns a double and eight bytes are consumed.
1578 *
1579 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001580 */
1581static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001582#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001583
1584
1585/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001586 * @brief Get the error status.
1587 *
1588 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1589 *
1590 * @return 0 if not in the error state, 1 if in the error state.
1591 *
1592 * This returns whether the @ref UsefulInputBuf is in the
1593 * error state or not.
1594 *
1595 * The error state is entered for one of these reasons:
1596 * - Attempt to fetch data past the end of the buffer
1597 * - Attempt to seek to a position past the end of the buffer
1598 * - Attempt to get data from an uninitialized or corrupt instance
1599 * of @ref UsefulInputBuf
1600 *
1601 * Once in the error state, it can only be cleared by calling
1602 * UsefulInputBuf_Init().
1603 *
1604 * For many use cases, it is possible to only call this once after all
1605 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1606 * possible if no reference to the data returned are needed before the
1607 * error state is checked.
1608 *
1609 * In some cases UsefulInputBuf_GetUsefulBuf() or
1610 * UsefulInputBuf_GetBytes() can stand in for this because they return
1611 * @c NULL if the error state has been entered. (The others can't stand
1612 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001613 */
1614static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1615
1616
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001617/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001618 * @brief Gets the input buffer length.
1619 *
1620 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1621 *
1622 * @return The length of the input buffer.
1623 *
1624 * This returns the length of the input buffer set by
1625 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001626 */
1627static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1628
1629
1630/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001631 * @brief Alters the input buffer length (use with caution).
1632 *
1633 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1634 * @param[in] uNewLen The new length of the input buffer.
1635 *
1636 * This alters the internal remembered length of the input buffer set
1637 * when UsefulInputBuf_Init() was called.
1638 *
1639 * The new length given here should always be equal to or less than
1640 * the length given when UsefulInputBuf_Init() was called. Making it
1641 * larger allows @ref UsefulInputBuf to run off the input buffer.
1642 *
1643 * The typical use is to set a length shorter than that when
1644 * initialized to constrain parsing. If
1645 * UsefulInputBuf_GetBufferLength() was called before this, then the
1646 * original length can be restored with another call to this.
1647 *
1648 * This should be used with caution. It is the only
1649 * @ref UsefulInputBuf method that can violate the safety of input
1650 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001651 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001652static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001653
1654
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001655
1656
Michael Eckel5c531332020-03-02 01:35:30 +01001657/*----------------------------------------------------------
1658 Inline implementations.
1659 */
1660static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1661{
1662 return !UB.ptr;
1663}
1664
1665
1666static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1667{
1668 return !UB.ptr;
1669}
1670
1671
1672static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1673{
1674 return !UB.len;
1675}
1676
1677
1678static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1679{
1680 return !UB.len;
1681}
1682
1683
1684static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1685{
1686 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1687}
1688
1689
1690static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1691{
1692 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1693}
1694
1695
1696static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1697{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001698 UsefulBufC UBC;
1699 UBC.ptr = UB.ptr;
1700 UBC.len = UB.len;
1701
1702 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001703}
1704
Michael Eckel5c531332020-03-02 01:35:30 +01001705static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1706{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001707 UsefulBuf UB;
1708
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001709 /* -Wcast-qual is a good warning flag to use in general. This is
1710 * the one place in UsefulBuf where it needs to be quieted. Since
1711 * clang supports GCC pragmas, this works for clang too. */
1712#pragma GCC diagnostic push
1713#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001714 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001715#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001716
1717 UB.len = UBC.len;
1718
1719 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001720}
1721
1722
1723static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1724{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001725 UsefulBufC UBC;
1726 UBC.ptr = szString;
1727 UBC.len = strlen(szString);
1728 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001729}
1730
1731
1732static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1733{
1734 return UsefulBuf_CopyOffset(Dest, 0, Src);
1735}
1736
1737
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001738static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001739{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001740 memset(Dest.ptr, value, Dest.len);
1741
1742 UsefulBufC UBC;
1743 UBC.ptr = Dest.ptr;
1744 UBC.len = Dest.len;
1745
1746 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001747}
1748
1749
1750static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1751{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001752 UsefulBufC UBC;
1753 UBC.ptr = ptr;
1754 UBC.len = len;
1755 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001756}
1757
1758
1759static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1760{
1761 if(uAmount > UB.len) {
1762 return NULLUsefulBufC;
1763 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001764 UsefulBufC UBC;
1765
1766 UBC.ptr = UB.ptr;
1767 UBC.len = uAmount;
1768
1769 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001770}
1771
1772
1773static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1774{
1775 UsefulBufC ReturnValue;
1776
1777 if(uAmount > UB.len) {
1778 ReturnValue = NULLUsefulBufC;
1779 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001780 ReturnValue.ptr = NULL;
1781 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001782 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001783 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1784 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001785 }
1786
1787 return ReturnValue;
1788}
1789
1790
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001791static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1792{
1793 if(UB.ptr == NULL) {
1794 return SIZE_MAX;
1795 }
1796
1797 if(p < UB.ptr) {
1798 /* given pointer is before start of buffer */
1799 return SIZE_MAX;
1800 }
1801
1802 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001803 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001804
1805 if(uOffset >= UB.len) {
1806 /* given pointer is off the end of the buffer */
1807 return SIZE_MAX;
1808 }
1809
1810 return uOffset;
1811}
1812
Michael Eckel5c531332020-03-02 01:35:30 +01001813
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001814#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001815static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1816{
1817 uint32_t u32;
1818 memcpy(&u32, &f, sizeof(uint32_t));
1819 return u32;
1820}
1821
1822static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1823{
1824 uint64_t u64;
1825 memcpy(&u64, &d, sizeof(uint64_t));
1826 return u64;
1827}
1828
1829static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1830{
1831 double d;
1832 memcpy(&d, &u64, sizeof(uint64_t));
1833 return d;
1834}
1835
1836static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1837{
1838 float f;
1839 memcpy(&f, &u32, sizeof(uint32_t));
1840 return f;
1841}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001842#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001843
1844
1845
1846
1847static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1848{
1849 pMe->data_len = 0;
1850 pMe->err = 0;
1851}
1852
1853
1854static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1855{
1856 return pMe->data_len;
1857}
1858
1859
1860static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1861{
1862 return 0 == pMe->data_len;
1863}
1864
1865
1866static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1867 const void *pBytes,
1868 size_t uLen,
1869 size_t uPos)
1870{
1871 UsefulBufC Data = {pBytes, uLen};
1872 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1873}
1874
1875
1876static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1877 const char *szString,
1878 size_t uPos)
1879{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001880 UsefulBufC UBC;
1881 UBC.ptr = szString;
1882 UBC.len = strlen(szString);
1883
1884 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001885}
1886
1887
1888static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1889 uint8_t byte,
1890 size_t uPos)
1891{
1892 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1893}
1894
1895
1896static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1897 uint16_t uInteger16,
1898 size_t uPos)
1899{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001900 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001901
1902 const void *pBytes;
1903
1904#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1905 pBytes = &uInteger16;
1906
1907#elif defined(USEFULBUF_CONFIG_HTON)
1908 uint16_t uTmp = htons(uInteger16);
1909 pBytes = &uTmp;
1910
1911#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1912 uint16_t uTmp = __builtin_bswap16(uInteger16);
1913 pBytes = &uTmp;
1914
1915#else
1916 uint8_t aTmp[2];
1917
1918 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1919 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1920
1921 pBytes = aTmp;
1922#endif
1923
1924 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1925}
1926
1927
1928static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1929 uint32_t uInteger32,
1930 size_t uPos)
1931{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001932 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001933
1934 const void *pBytes;
1935
1936#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1937 pBytes = &uInteger32;
1938
1939#elif defined(USEFULBUF_CONFIG_HTON)
1940 uint32_t uTmp = htonl(uInteger32);
1941 pBytes = &uTmp;
1942
1943#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1944 uint32_t uTmp = __builtin_bswap32(uInteger32);
1945
1946 pBytes = &uTmp;
1947
1948#else
1949 uint8_t aTmp[4];
1950
1951 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1952 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1953 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1954 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1955
1956 pBytes = aTmp;
1957#endif
1958
1959 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1960}
1961
1962static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001963 uint64_t uInteger64,
1964 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01001965{
1966 const void *pBytes;
1967
1968#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001969 /* We have been told explicitly we are running on a big-endian
1970 * machine. Network byte order is big endian, so just copy. There
1971 * is no issue with alignment here because uInteger64 is always
1972 * aligned (and it doesn't matter if pBytes is aligned).
1973 */
Michael Eckel5c531332020-03-02 01:35:30 +01001974 pBytes = &uInteger64;
1975
1976#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001977 /* Use system function to handle big- and little-endian. This works
1978 * on both big- and little-endian machines, but hton() is not
1979 * always available or in a standard place so it is not used by
1980 * default. With some compilers and CPUs the code for this is very
1981 * compact through use of a special swap instruction and on
1982 * big-endian machines hton() will reduce to nothing.
1983 */
Michael Eckel5c531332020-03-02 01:35:30 +01001984 uint64_t uTmp = htonll(uInteger64);
1985
1986 pBytes = &uTmp;
1987
1988#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001989 /* Use built-in function for byte swapping. This usually compiles
1990 * to an efficient special byte swap instruction. Unlike hton() it
1991 * does not do this conditionally on the CPU endianness, so this
1992 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1993 */
Michael Eckel5c531332020-03-02 01:35:30 +01001994 uint64_t uTmp = __builtin_bswap64(uInteger64);
1995
1996 pBytes = &uTmp;
1997
1998#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001999 /* Default which works on every CPU with no dependency on anything
2000 * from the CPU, compiler, libraries or OS. This always works, but
2001 * it is usually a little larger and slower than hton().
2002 */
Michael Eckel5c531332020-03-02 01:35:30 +01002003 uint8_t aTmp[8];
2004
2005 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
2006 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
2007 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
2008 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
2009 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
2010 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
2011 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
2012 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
2013
2014 pBytes = aTmp;
2015#endif
2016
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002017 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002018 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2019}
2020
2021
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002022#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002023static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2024 float f,
2025 size_t uPos)
2026{
2027 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2028}
2029
2030
2031static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2032 double d,
2033 size_t uPos)
2034{
2035 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2036}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002037#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002038
2039
2040static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2041 UsefulBufC NewData)
2042{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002043 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002044 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2045}
2046
2047
2048static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2049 const void *pBytes,
2050 size_t uLen)
2051{
2052 UsefulBufC Data = {pBytes, uLen};
2053 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2054}
2055
2056
2057static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2058 const char *szString)
2059{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002060 UsefulBufC UBC;
2061 UBC.ptr = szString;
2062 UBC.len = strlen(szString);
2063
2064 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002065}
2066
2067
2068static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2069 uint8_t byte)
2070{
2071 UsefulOutBuf_AppendData(pMe, &byte, 1);
2072}
2073
2074
2075static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2076 uint16_t uInteger16)
2077{
2078 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2079}
2080
2081static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2082 uint32_t uInteger32)
2083{
2084 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2085}
2086
2087
2088static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2089 uint64_t uInteger64)
2090{
2091 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2092}
2093
2094
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002095#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002096static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2097 float f)
2098{
2099 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2100}
2101
2102
2103static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2104 double d)
2105{
2106 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2107}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002108#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002109
2110
2111static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2112{
2113 return pMe->err;
2114}
2115
2116
2117static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2118{
2119 return pMe->UB.len - pMe->data_len;
2120}
2121
2122
2123static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2124{
2125 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2126}
2127
2128
2129static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2130{
2131 return pMe->UB.ptr == NULL;
2132}
2133
2134
2135
2136static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2137{
2138 pMe->cursor = 0;
2139 pMe->err = 0;
2140 pMe->magic = UIB_MAGIC;
2141 pMe->UB = UB;
2142}
2143
2144static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2145{
2146 return pMe->cursor;
2147}
2148
2149
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002150static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002151{
2152 return pMe->UB.len;
2153}
2154
2155
Michael Eckel5c531332020-03-02 01:35:30 +01002156static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2157{
2158 if(uPos > pMe->UB.len) {
2159 pMe->err = 1;
2160 } else {
2161 pMe->cursor = uPos;
2162 }
2163}
2164
2165
2166static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2167{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002168 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002169
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002170 /* Magic number is messed up. Either the structure got overwritten
2171 * or was never initialized.
2172 */
Michael Eckel5c531332020-03-02 01:35:30 +01002173 if(pMe->magic != UIB_MAGIC) {
2174 return 0;
2175 }
2176
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002177 /* The cursor is off the end of the input buffer given.
2178 * Presuming there are no bugs in this code, this should never happen.
2179 * If it so, the struct was corrupted. The check is retained as
2180 * as a defense in case there is a bug in this code or the struct is
2181 * corrupted.
2182 */
Michael Eckel5c531332020-03-02 01:35:30 +01002183 if(pMe->cursor > pMe->UB.len) {
2184 return 0;
2185 }
2186
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002187 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002188 return pMe->UB.len - pMe->cursor;
2189}
2190
2191
2192static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2193{
2194 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2195}
2196
2197
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002198static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2199{
2200 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2201}
2202
2203
Michael Eckel5c531332020-03-02 01:35:30 +01002204static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2205{
2206 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2207 if(!pResult) {
2208 return NULLUsefulBufC;
2209 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002210 UsefulBufC UBC;
2211 UBC.ptr = pResult;
2212 UBC.len = uNum;
2213 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002214 }
2215}
2216
2217
2218static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2219{
2220 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2221
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002222 /* The ternary operator is subject to integer promotion, because
2223 * the operands are smaller than int, so cast back to uint8_t is
2224 * needed to be completely explicit about types (for static
2225 * analyzers).
2226 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002227 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002228}
2229
2230static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2231{
2232 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2233
2234 if(!pResult) {
2235 return 0;
2236 }
2237
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002238 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002239#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2240 uint16_t uTmp;
2241 memcpy(&uTmp, pResult, sizeof(uint16_t));
2242
2243#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2244 return uTmp;
2245
2246#elif defined(USEFULBUF_CONFIG_HTON)
2247 return ntohs(uTmp);
2248
2249#else
2250 return __builtin_bswap16(uTmp);
2251
2252#endif
2253
2254#else
2255
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002256 /* The operations here are subject to integer promotion because the
2257 * operands are smaller than int. They will be promoted to unsigned
2258 * int for the shift and addition. The cast back to uint16_t is is
2259 * needed to be completely explicit about types (for static
2260 * analyzers).
2261 */
Michael Eckel5c531332020-03-02 01:35:30 +01002262 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2263
2264#endif
2265}
2266
2267
2268static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2269{
2270 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2271
2272 if(!pResult) {
2273 return 0;
2274 }
2275
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002276 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002277#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2278 uint32_t uTmp;
2279 memcpy(&uTmp, pResult, sizeof(uint32_t));
2280
2281#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2282 return uTmp;
2283
2284#elif defined(USEFULBUF_CONFIG_HTON)
2285 return ntohl(uTmp);
2286
2287#else
2288 return __builtin_bswap32(uTmp);
2289
2290#endif
2291
2292#else
2293 return ((uint32_t)pResult[0]<<24) +
2294 ((uint32_t)pResult[1]<<16) +
2295 ((uint32_t)pResult[2]<<8) +
2296 (uint32_t)pResult[3];
2297#endif
2298}
2299
2300
2301static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2302{
2303 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2304
2305 if(!pResult) {
2306 return 0;
2307 }
2308
2309#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002310 /* pResult will probably not be aligned. This memcpy() moves the
2311 * bytes into a temp variable safely for CPUs that can or can't do
2312 * unaligned memory access. Many compilers will optimize the
2313 * memcpy() into a simple move instruction.
2314 */
Michael Eckel5c531332020-03-02 01:35:30 +01002315 uint64_t uTmp;
2316 memcpy(&uTmp, pResult, sizeof(uint64_t));
2317
2318#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002319 /* We have been told expliclity this is a big-endian CPU. Since
2320 * network byte order is big-endian, there is nothing to do.
2321 */
Michael Eckel5c531332020-03-02 01:35:30 +01002322
2323 return uTmp;
2324
2325#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002326 /* We have been told to use ntoh(), the system function to handle
2327 * big- and little-endian. This works on both big- and
2328 * little-endian machines, but ntoh() is not always available or in
2329 * a standard place so it is not used by default. On some CPUs the
2330 * code for this is very compact through use of a special swap
2331 * instruction.
2332 */
Michael Eckel5c531332020-03-02 01:35:30 +01002333
2334 return ntohll(uTmp);
2335
2336#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002337 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2338 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2339 * __builtin_bswap64() and friends are not conditional on CPU
2340 * endianness so this must only be used on little-endian machines.
2341 */
Michael Eckel5c531332020-03-02 01:35:30 +01002342
2343 return __builtin_bswap64(uTmp);
2344
2345
2346#endif
2347
2348#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002349 /* This is the default code that works on every CPU and every
2350 * endianness with no dependency on ntoh(). This works on CPUs
2351 * that either allow or do not allow unaligned access. It will
2352 * always work, but usually is a little less efficient than ntoh().
2353 */
Michael Eckel5c531332020-03-02 01:35:30 +01002354
2355 return ((uint64_t)pResult[0]<<56) +
2356 ((uint64_t)pResult[1]<<48) +
2357 ((uint64_t)pResult[2]<<40) +
2358 ((uint64_t)pResult[3]<<32) +
2359 ((uint64_t)pResult[4]<<24) +
2360 ((uint64_t)pResult[5]<<16) +
2361 ((uint64_t)pResult[6]<<8) +
2362 (uint64_t)pResult[7];
2363#endif
2364}
2365
2366
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002367#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002368static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2369{
2370 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2371
2372 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2373}
2374
2375
2376static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2377{
2378 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2379
2380 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2381}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002382#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002383
2384
2385static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2386{
2387 return pMe->err;
2388}
2389
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002390
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002391static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002392{
2393 pMe->UB.len = uNewLen;
2394}
2395
2396
Michael Eckel5c531332020-03-02 01:35:30 +01002397#ifdef __cplusplus
2398}
2399#endif
2400
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002401#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002402
2403