blob: fb3c12be795e0f4c58251744494fce85381177df [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 Lundblade48d8ace2021-08-19 22:00:26 -070045 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070046 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080047 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070048 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010049 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
50 5/21/2019 llundblade #define configs for efficient endianness handling.
51 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
52 3/23/2019 llundblade Big documentation & style update. No interface
53 change.
54 3/6/2019 llundblade Add UsefulBuf_IsValue()
55 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
56 12/13/2018 llundblade Documentation improvements
57 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
58 UsefulBufC.
59 02/02/18 llundbla Full support for integers in and out; fix pointer
60 alignment bug. Incompatible change: integers
61 in/out are now in network byte order.
62 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
63 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
64 comparison for < or > for unequal length buffers.
65 Added UsefulBuf_Set() function.
66 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
67 11/13/16 llundbla Initial Version.
68
69 =============================================================================*/
70
71#ifndef _UsefulBuf_h
72#define _UsefulBuf_h
73
74
75/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070076 * Endianness Configuration
77 *
78 * This code is written so it will work correctly on big- and
79 * little-endian CPUs without configuration or any auto-detection of
80 * endianness. All code here will run correctly regardless of the
81 * endianness of the CPU it is running on.
82 *
83 * There are four C preprocessor macros that can be set with #define
84 * to explicitly configure endianness handling. Setting them can
85 * reduce code size a little and improve efficiency a little.
86 *
87 * Note that most of QCBOR is unaffected by this configuration. Its
88 * endianness handling is integrated with the code that handles
89 * alignment and preferred serialization. This configuration does
90 * affect QCBOR's (planned) implementation of integer arrays (tagged
91 * arrays) and use of the functions here to serialize or deserialize
92 * integers and floating-point values.
93 *
94 * Following is the recipe for configuring the endianness-related
95 * #defines.
96 *
97 * The first option is to not define anything. This will work fine
98 * with all CPUs, OS's and compilers. The code for encoding integers
99 * may be a little larger and slower.
100 *
101 * If your CPU is big-endian then define
102 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
103 * for big-endian CPUs. It will be small and efficient because there
104 * will be no byte swapping.
105 *
106 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
107 * OS's and compilers, but not all. On big-endian CPUs this should
108 * give the most efficient code, the same as
109 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
110 * call the system-defined byte swapping method which is presumably
111 * implemented efficiently. In some cases, this will be a dedicated
112 * byte swap instruction like Intel's bswap.
113 *
114 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
115 * little-endian, it is also good to define
116 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
117 *
118 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
119 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
120 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
121 * system-defined byte swap method. However, note
122 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
123 * this is fixed now. Often hton() and ntoh() will call the built-in
124 * __builtin_bswapXX()() function, so this size issue could affect
125 * USEFULBUF_CONFIG_HTON.
126 *
127 * Last, run the tests. They must all pass.
128 *
129 * These #define config options affect the inline implementation of
130 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
131 * also affect the 16-, 32-bit, float and double versions of these
132 * functions. Since they are inline, the size effect is not in the
133 * UsefulBuf object code, but in the calling code.
134 *
135 * Summary:
136 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
137 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
138 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
139 * handle big and little-endian with system option.
140 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
141 * use __builtin_bswapXX().
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200142 *
143 * It is possible to run this code in environments where using floating point is
144 * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
145 * that is related to handling floating point types, along with related
146 * interfaces. This makes it possible to compile the code with the compile
147 * option -mgeneral-regs-only.
Michael Eckel5c531332020-03-02 01:35:30 +0100148 */
149
150#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
151#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
152#endif
153
154
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700155#include <stdint.h> /* for uint8_t, uint16_t.... */
156#include <string.h> /* for strlen, memcpy, memmove, memset */
157#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100158
159
160#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700161#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100162#endif
163
164#ifdef __cplusplus
165extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700166#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700167} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700168#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100169#endif
170
171/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700172 * @file UsefulBuf.h
173 *
174 * The goal of this code is to make buffer and pointer manipulation
175 * easier and safer when working with binary data.
176 *
177 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
178 * structures are used to represent buffers rather than ad hoc
179 * pointers and lengths.
180 *
181 * With these it is possible to write code that does little or no
182 * direct pointer manipulation for copying and formatting data. For
183 * example, the QCBOR encoder was written using these and has less
184 * pointer manipulation.
185 *
186 * While it is true that object code using these functions will be a
187 * little larger and slower than a white-knuckle clever use of
188 * pointers might be, but not by that much or enough to have an effect
189 * for most use cases. For security-oriented code this is highly
190 * worthwhile. Clarity, simplicity, reviewability and are more
191 * important.
192 *
193 * There are some extra sanity and double checks in this code to help
194 * catch coding errors and simple memory corruption. They are helpful,
195 * but not a substitute for proper code review, input validation and
196 * such.
197 *
198 * This code consists of a lot of inline functions and a few that are
199 * not. It should not generate very much object code, especially with
200 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100201 */
202
203
204/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700205 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
206 * hold a pointer and length for binary data. In C99 this data
207 * structure can be passed on the stack making a lot of code cleaner
208 * than carrying around a pointer and length as two parameters.
209 *
210 * This is also conducive to secure coding practice as the length is
211 * always carried with the pointer and the convention for handling a
212 * pointer and a length is clear.
213 *
214 * While it might be possible to write buffer and pointer code more
215 * efficiently in some use cases, the thought is that unless there is
216 * an extreme need for performance (e.g., you are building a
217 * gigabit-per-second IP router), it is probably better to have
218 * cleaner code you can be most certain about the security of.
219 *
220 * The non-const @ref UsefulBuf is usually used to refer an empty
221 * buffer to be filled in. The length is the size of the buffer.
222 *
223 * The const @ref UsefulBufC is usually used to refer to some data
224 * that has been filled in. The length is amount of valid data pointed
225 * to.
226 *
227 * A common use mode is to pass a @ref UsefulBuf to a function, the
228 * function puts some data in it, then the function returns a @ref
229 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
230 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
231 * so the constness stays correct. There is no single "in,out"
232 * parameter (if there was, it would have to be non-const). Note that
233 * the pointer returned in the @ref UsefulBufC usually ends up being
234 * the same pointer passed in as a @ref UsefulBuf, though this is not
235 * striclty required.
236 *
237 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
238 * @c NULL.
239 *
240 * There are functions and macros for the following:
241 * - Initializing
242 * - Create initialized const @ref UsefulBufC from compiler literals
243 * - Create initialized const @ref UsefulBufC from NULL-terminated string
244 * - Make an empty @ref UsefulBuf on the stack
245 * - Checking whether a @ref UsefulBuf is null, empty or both
246 * - Copying, copying with offset, copying head or tail
247 * - Comparing and finding substrings
248 *
249 * See also @ref UsefulOutBuf. It is a richer structure that has both
250 * the size of the valid data and the size of the buffer.
251 *
252 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
253 * it can go on the stack and be a function parameter or return value.
254 *
255 * Another way to look at it is this. C has the NULL-terminated string
256 * as a means for handling text strings, but no means or convention
257 * for binary strings. Other languages do have such means, Rust, an
258 * efficient compiled language, for example.
259 *
260 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
261 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
262 * out like anything".
263 */
Michael Eckel5c531332020-03-02 01:35:30 +0100264typedef struct q_useful_buf_c {
265 const void *ptr;
266 size_t len;
267} UsefulBufC;
268
269
270/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700271 * This non-const @ref UsefulBuf is typically used for some allocated
272 * memory that is to be filled in. The @c len is the amount of memory,
273 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100274 */
275typedef struct q_useful_buf {
276 void *ptr;
277 size_t len;
278} UsefulBuf;
279
280
281/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700282 * A null @ref UsefulBufC is one that has no value in the same way a
283 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
284 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
285 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100286 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700287/*
288 * NULLUsefulBufC and few other macros have to be
289 * definied differently in C than C++ because there
290 * is no common construct for a literal structure.
291 *
292 * In C compound literals are used.
293 *
294 * In C++ list initalization is used. This only works
295 * in C++11 and later.
296 *
297 * Note that some popular C++ compilers can handle compound
298 * literals with on-by-default extensions, however
299 * this code aims for full correctness with strict
300 * compilers so they are not used.
301 */
302#ifdef __cplusplus
303#define NULLUsefulBufC {NULL, 0}
304#else
305#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
306#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100307
308/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700309 * A null @ref UsefulBuf is one that has no memory associated the same
310 * way @c NULL points to nothing. It does not matter what @c len is.
311 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700312#ifdef __cplusplus
313#define NULLUsefulBuf {NULL, 0}
314#else
315#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
316#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100317
318
319/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700320 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
321 *
322 * @param[in] UB The UsefulBuf to check.
323 *
324 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100325 */
326static inline int UsefulBuf_IsNULL(UsefulBuf UB);
327
328
329/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700330 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
331 *
332 * @param[in] UB The @ref UsefulBufC to check.
333 *
334 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100335 */
336static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
337
338
339/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700340 * @brief Check if a @ref UsefulBuf is empty or not.
341 *
342 * @param[in] UB The @ref UsefulBuf to check.
343 *
344 * @return 1 if it is empty, 0 if not.
345 *
346 * An "empty" @ref UsefulBuf is one that has a value and can be
347 * considered to be set, but that value is of zero length. It is
348 * empty when @c len is zero. It doesn't matter what the @c ptr is.
349 *
350 * Many uses will not need to clearly distinguish a @c NULL @ref
351 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
352 * @c len 0. However if a use of @ref UsefulBuf needs to make a
353 * distinction then @c ptr should not be @c NULL when the @ref
354 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100355 */
356static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
357
358
359/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700360 * @brief Check if a @ref UsefulBufC is empty or not.
361 *
362 * @param[in] UB The @ref UsefulBufC to check.
363 *
364 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100365 */
366static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
367
368
369/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700370 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
371 *
372 * @param[in] UB The @ref UsefulBuf to check.
373 *
374 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100375 */
376static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
377
378
379/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700380 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
381 *
382 * @param[in] UB The @ref UsefulBufC to check.
383 *
384 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100385 */
386static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
387
388
389/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700390 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
391 *
392 * @param[in] UB The @ref UsefulBuf to convert.
393 *
394 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100395 */
396static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
397
398
399/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700400 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
401 *
402 * @param[in] UBC The @ref UsefulBuf to convert.
403 *
404 * @return A non-const @ref UsefulBuf struct.
405 *
406 * Use of this is not necessary for the intended use mode of @ref
407 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
408 * created to describe a buffer that has not had any data put in
409 * it. Then the data is put in it. Then a @ref UsefulBufC is create
410 * to describe the part with the data in it. This goes from non-const
411 * to const, so this function is not needed.
412 *
413 * If the -Wcast-qual warning is enabled, this function can be used to
414 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100415 */
416static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
417
418
419/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700420 * Convert a literal string to a @ref UsefulBufC.
421 *
422 * @c szString must be a literal string that @c sizeof() works on.
423 * This is better for literal strings than UsefulBuf_FromSZ() because
424 * it generates less code. It will not work on non-literal strings.
425 *
426 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100427 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700428#ifdef __cplusplus
429#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
430#else
Michael Eckel5c531332020-03-02 01:35:30 +0100431#define UsefulBuf_FROM_SZ_LITERAL(szString) \
432 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700433#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100434
435
436/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700437 * Convert a literal byte array to a @ref UsefulBufC.
438 *
439 * @c pBytes must be a literal string that @c sizeof() works on. It
440 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100441 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700442#ifdef __cplusplus
443#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
444#else
Michael Eckel5c531332020-03-02 01:35:30 +0100445#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700446 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
447#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100448
449/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700450 * Make an automatic variable named @c name of type @ref UsefulBuf and
451 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100452 */
453#define UsefulBuf_MAKE_STACK_UB(name, size) \
454 uint8_t __pBuf##name[(size)];\
455 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
456
457
458/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700459 * Make a byte array in to a @ref UsefulBuf. This is usually used on
460 * stack variables or static variables. Also see @ref
461 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100462 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700463#ifdef __cplusplus
464#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
465#else
Michael Eckel5c531332020-03-02 01:35:30 +0100466#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700467 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
468#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100469
470
471/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700472 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
473 *
474 * @param[in] szString The string to convert.
475 *
476 * @return A @ref UsefulBufC struct.
477 *
478 * @c UsefulBufC.ptr points to the string so its lifetime must be
479 * maintained.
480 *
481 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100482 */
483static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
484
485
486/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700487 * @brief Copy one @ref UsefulBuf into another at an offset.
488 *
489 * @param[in] Dest Destination buffer to copy into.
490 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
491 * @param[in] Src The bytes to copy.
492 *
493 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
494 *
495 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
496 * size of @c Dest.
497 *
498 * This fails and returns @ref NULLUsefulBufC if the @c Src length
499 * plus @c uOffset is greater than the length of @c Dest.
500 *
501 * The results are undefined if @c Dest and @c Src overlap.
502 *
503 * This assumes that there is valid data in @c Dest up to @c
504 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
505 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100506 */
507UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
508
509
510/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700511 * @brief Copy one @ref UsefulBuf into another.
512 *
513 * @param[in] Dest The destination buffer to copy into.
514 * @param[out] Src The source to copy from.
515 *
516 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
517 * on failure.
518 *
519 * This fails if @c Src.len is greater than @c Dest.len.
520 *
521 * Note that like @c memcpy(), the pointers are not checked and this
522 * will crash rather than return @ref NULLUsefulBufC if they are @c
523 * NULL or invalid.
524 *
525 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100526 */
527static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
528
529
530/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700531 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
532 *
533 * @param[in] pDest The destination buffer to copy into.
534 * @param[in] value The value to set the bytes to.
535 *
536 * Note that like @c memset(), the pointer in @c pDest is not checked
537 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100538 */
539static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
540
541
542/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700543 * @brief Copy a pointer into a @ref UsefulBuf.
544 *
545 * @param[in,out] Dest The destination buffer to copy into.
546 * @param[in] ptr The source to copy from.
547 * @param[in] uLen Length of the source; amount to copy.
548 *
549 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
550 * on failure.
551 *
552 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
553 * than @c pDest->len.
554 *
555 * Note that like @c memcpy(), the pointers are not checked and this
556 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100557 */
558static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
559 const void *ptr,
560 size_t uLen);
561
562
563/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700564 * @brief Returns a truncation of a @ref UsefulBufC.
565 *
566 * @param[in] UB The buffer to get the head of.
567 * @param[in] uAmount The number of bytes in the head.
568 *
569 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100570 */
571static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
572
573
574/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700575 * @brief Returns bytes from the end of a @ref UsefulBufC.
576 *
577 * @param[in] UB The buffer to get the tail of.
578 * @param[in] uAmount The offset from the start where the tail is to begin.
579 *
580 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
581 * if @c uAmount is greater than the length of the @ref UsefulBufC.
582 *
583 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
584 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
585 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100586 */
587static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
588
589
590/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700591 * @brief Compare one @ref UsefulBufC to another.
592 *
593 * @param[in] UB1 The first buffer to compare.
594 * @param[in] UB2 The second buffer to compare.
595 *
596 * @return 0, positive or negative value.
597 *
598 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
599 * less than @c UB2 if it is shorter or the first byte that is not the
600 * same is less.
601 *
602 * Returns 0 if the inputs are the same.
603 *
604 * Returns a positive value if @c UB2 is less than @c UB1.
605 *
606 * All that is of significance is that the result is positive, negative
607 * or 0. (This doesn't return the difference between the first
608 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100609 */
610int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
611
612
613/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700614 * @brief Find first byte that is not a particular byte value.
615 *
616 * @param[in] UB The destination buffer for byte comparison.
617 * @param[in] uValue The byte value to compare to.
618 *
619 * @return Offset of first byte that isn't @c uValue or
620 * @c SIZE_MAX if all bytes are @c uValue.
621 *
622 * Note that unlike most comparison functions, 0
623 * does not indicate a successful comparison, so the
624 * test for match is:
625 *
626 * UsefulBuf_IsValue(...) == SIZE_MAX
627 *
628 * If @c UB is null or empty, there is no match
629 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100630 */
631size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
632
633
634/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700635 * @brief Find one @ref UsefulBufC in another.
636 *
637 * @param[in] BytesToSearch Buffer to search through.
638 * @param[in] BytesToFind Buffer with bytes to be found.
639 *
640 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100641 */
642size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
643
644
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700645/**
646 @brief Convert a pointer to an offset with bounds checking.
647
648 @param[in] UB Pointer to the UsefulInputBuf.
649 @param[in] p Pointer to convert to offset.
650
651 @return SIZE_MAX if @c p is out of range, the byte offset if not.
652*/
653static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
654
655
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800656#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100657/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700658#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100659
660/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
661#define MakeUsefulBufOnStack(name, size) \
662 uint8_t __pBuf##name[(size)];\
663 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
664
665/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
666#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700667 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100668
669/** Deprecated function; use UsefulBuf_Unconst() instead */
670static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
671{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700672 UsefulBuf UB;
673
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800674 // See UsefulBuf_Unconst() implementation for comment on pragmas
675#pragma GCC diagnostic push
676#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700677 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800678#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700679
680 UB.len = UBC.len;
681
682 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100683}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800684#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100685
686
687
688
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200689#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +0100690/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700691 * @brief Copy a @c float to a @c uint32_t.
692 *
693 * @param[in] f Float value to copy.
694 *
695 * @return A @c uint32_t with the float bits.
696 *
697 * Convenience function to avoid type punning, compiler warnings and
698 * such. The optimizer usually reduces this to a simple assignment. This
699 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100700 */
701static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
702
703
704/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700705 * @brief Copy a @c double to a @c uint64_t.
706 *
707 * @param[in] d Double value to copy.
708 *
709 * @return A @c uint64_t with the double bits.
710 *
711 * Convenience function to avoid type punning, compiler warnings and
712 * such. The optimizer usually reduces this to a simple assignment. This
713 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100714 */
715static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
716
717
718/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700719 * @brief Copy a @c uint32_t to a @c float.
720 *
721 * @param[in] u32 Integer value to copy.
722 *
723 * @return The value as a @c float.
724 *
725 * Convenience function to avoid type punning, compiler warnings and
726 * such. The optimizer usually reduces this to a simple assignment. This
727 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100728 */
729static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
730
731
732/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700733 * @brief Copy a @c uint64_t to a @c double.
734 *
735 * @param[in] u64 Integer value to copy.
736 *
737 * @return The value as a @c double.
738 *
739 * Convenience function to avoid type punning, compiler warnings and
740 * such. The optimizer usually reduces this to a simple assignment. This
741 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100742 */
743static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +0200744#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +0100745
746
747
748
749/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700750 * UsefulOutBuf is a structure and functions (an object) for
751 * serializing data into a buffer to encode for a network protocol or
752 * write data to a file.
753 *
754 * The main idea is that all the pointer manipulation is performed by
755 * @ref UsefulOutBuf functions so the caller doesn't have to do any
756 * pointer manipulation. The pointer manipulation is centralized.
757 * This code has been reviewed and written carefully so it
758 * spares the caller of much of this work and results in safer code
759 * with less effort.
760 *
761 * The @ref UsefulOutBuf methods that add data to the output buffer
762 * always check the length and will never write off the end of the
763 * output buffer. If an attempt to add data that will not fit is made,
764 * an internal error flag will be set and further attempts to add data
765 * will not do anything.
766 *
767 * There is no way to ever write off the end of that buffer when
768 * calling the @c UsefulOutBuf_AddXxx() and
769 * @c UsefulOutBuf_InsertXxx() functions.
770 *
771 * The functions to add data do not report success of failure. The
772 * caller only needs to check for an error in the final call, either
773 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
774 * result. This makes the calling code cleaner.
775 *
776 * There is a utility function to get the error status anytime along
777 * the way for a special circumstance. There are functions to see how
778 * much room is left and see if some data will fit too, but their use
779 * is generally unnecessary.
780 *
781 * The general call flow is:
782 *
783 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
784 * buffer given to it can be from the heap, stack or
785 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
786 * macro that makes a buffer on the stack and initializes it.
787 *
788 * - Call methods like UsefulOutBuf_InsertString(),
789 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
790 * to output data. The append calls add data to the end of the
791 * valid data. The insert calls take a position argument.
792 *
793 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
794 * there were no errors and to get the serialized output bytes.
795 *
796 * @ref UsefulOutBuf can be used in a size calculation mode to
797 * calculate the size of output that would be generated. This is
798 * useful to calculate the size of a buffer that is to be allocated to
799 * hold the output. To use @ref UsefulOutBuf in this mode, call
800 * UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
801 * @c (UsefulBuf){NULL, MAX_UINT32}. Then call all the Insert and Add
802 * functions. No attempt will be made to actually copy data, so only
803 * the lengths have to be valid for inputs to these calls.
804 *
805 * Methods like UsefulOutBuf_InsertUint64() always output in network
806 * bytes order (big endian).
807 *
808 * The possible errors are:
809 *
810 * - The @ref UsefulOutBuf was not initialized or was corrupted.
811 *
812 * - An attempt was made to add data that will not fit.
813 *
814 * - An attempt was made to insert data at a position beyond the end of
815 * the buffer.
816 *
817 * - An attempt was made to insert data at a position beyond the valid
818 * data in the buffer.
819 *
820 * Some inexpensive simple sanity checks are performed before every
821 * data addition to guard against use of an uninitialized or corrupted
822 * UsefulOutBuf.
823 *
824 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
825 * encoder has almost no pointer manipulation in it, is easier to
826 * read, and easier to review.
827 *
828 * A @ref UsefulOutBuf is small and can go on the stack:
829 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
830 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100831 */
832typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700833 /* PRIVATE DATA STRUCTURE */
834 UsefulBuf UB; /* Memory that is being output to */
835 size_t data_len; /* length of the valid data, the insertion point */
836 uint16_t magic; /* Used to detect corruption and lack
837 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100838 uint8_t err;
839} UsefulOutBuf;
840
841
842/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700843 * @brief Initialize and supply the actual output buffer.
844 *
845 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
846 * @param[in] Storage Buffer to output into.
847 *
848 * This initializes the @ref UsefulOutBuf with storage, sets the
849 * current position to the beginning of the buffer and clears the
850 * error state.
851 *
852 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100853 */
854void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
855
856
857/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700858 * Convenience macro to make a @ref UsefulOutBuf on the stack and
859 * initialize it with a stack buffer of the given size. The variable
860 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100861 */
862#define UsefulOutBuf_MakeOnStack(name, size) \
863 uint8_t __pBuf##name[(size)];\
864 UsefulOutBuf name;\
865 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
866
867
868/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700869 * @brief Reset a @ref UsefulOutBuf for re use.
870 *
871 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
872 *
873 * This sets the amount of data in the output buffer to none and
874 * clears the error state.
875 *
876 * The output buffer is still the same one and size as from the
877 * UsefulOutBuf_Init() call.
878 *
879 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100880 */
881static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
882
883
884/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700885 * @brief Returns position of end of data in the @ref UsefulOutBuf.
886 *
887 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
888 *
889 * @return position of end of data.
890 *
891 * On a freshly initialized @ref UsefulOutBuf with no data added, this
892 * will return 0. After 10 bytes have been added, it will return 10
893 * and so on.
894 *
895 * Generally, there is no need to call this for most uses of @ref
896 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100897 */
898static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
899
900
901/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700902 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
903 *
904 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
905 *
906 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100907 */
908static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
909
910
911/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700912 * @brief Inserts bytes into the @ref UsefulOutBuf.
913 *
914 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
915 * @param[in] NewData The bytes to insert.
916 * @param[in] uPos Index in output buffer at which to insert.
917 *
918 * @c NewData is the pointer and length for the bytes to be added to
919 * the output buffer. There must be room in the output buffer for all
920 * of @c NewData or an error will occur.
921 *
922 * The insertion point must be between 0 and the current valid
923 * data. If not, an error will occur. Appending data to the output
924 * buffer is achieved by inserting at the end of the valid data. This
925 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
926 *
927 * When insertion is performed, the bytes between the insertion point
928 * and the end of data previously added to the output buffer are slid
929 * to the right to make room for the new data.
930 *
931 * Overlapping buffers are OK. @c NewData can point to data in the
932 * output buffer.
933 *
934 * If an error occurs, an error state is set in the @ref
935 * UsefulOutBuf. No error is returned. All subsequent attempts to add
936 * data will do nothing.
937 *
938 * The intended use is that all additions are made without checking
939 * for an error. The error will be taken into account when
940 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
941 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100942 */
943void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
944 UsefulBufC NewData,
945 size_t uPos);
946
947
948/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700949 * @brief Insert a data buffer into the @ref UsefulOutBuf.
950 *
951 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
952 * @param[in] pBytes Pointer to the bytes to insert
953 * @param[in] uLen Length of the bytes to insert
954 * @param[in] uPos Index in output buffer at which to insert
955 *
956 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
957 * the difference being a pointer and length is passed in rather than an
958 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100959 */
960static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
961 const void *pBytes,
962 size_t uLen,
963 size_t uPos);
964
965
966/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700967 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
968 *
969 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
970 * @param[in] szString NULL-terminated string to insert.
971 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100972 */
973static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
974 const char *szString,
975 size_t uPos);
976
977
978/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700979 * @brief Insert a byte into the @ref UsefulOutBuf.
980 *
981 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
982 * @param[in] byte Bytes to insert.
983 * @param[in] uPos Index in output buffer at which to insert.
984 *
985 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
986 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +0100987 */
988static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
989 uint8_t byte,
990 size_t uPos);
991
992
993/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700994 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
995 *
996 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
997 * @param[in] uInteger16 Integer to insert.
998 * @param[in] uPos Index in output buffer at which to insert.
999 *
1000 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1001 * with the difference being a two-byte integer is to be inserted.
1002 *
1003 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001004 */
1005static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
1006 uint16_t uInteger16,
1007 size_t uPos);
1008
1009
1010/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001011 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1012 *
1013 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1014 * @param[in] uInteger32 Integer to insert.
1015 * @param[in] uPos Index in output buffer at which to insert.
1016 *
1017 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1018 * with the difference being a four-byte integer is to be inserted.
1019 *
1020 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001021 */
1022static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1023 uint32_t uInteger32,
1024 size_t uPos);
1025
1026
1027/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001028 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1029 *
1030 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1031 * @param[in] uInteger64 Integer to insert.
1032 * @param[in] uPos Index in output buffer at which to insert.
1033 *
1034 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1035 * with the difference being an eight-byte integer is to be inserted.
1036 *
1037 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001038 */
1039static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1040 uint64_t uInteger64,
1041 size_t uPos);
1042
1043
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001044#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001045/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001046 * @brief Insert a @c float into the @ref UsefulOutBuf.
1047 *
1048 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1049 * @param[in] f @c float 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 a @c float is to be inserted.
1054 *
1055 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001056 */
1057static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1058 float f,
1059 size_t uPos);
1060
1061
1062/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001063 * @brief Insert a @c double into the @ref UsefulOutBuf.
1064 *
1065 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1066 * @param[in] d @c double to insert.
1067 * @param[in] uPos Index in output buffer at which to insert.
1068 *
1069 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1070 * with the difference being a @c double is to be inserted.
1071 *
1072 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001073 */
1074static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1075 double d,
1076 size_t uPos);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001077#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001078
1079
1080/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001081 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1082 *
1083 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1084 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1085 *
1086 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1087 * with the insertion point at the end of the valid data.
1088 */
Michael Eckel5c531332020-03-02 01:35:30 +01001089static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1090 UsefulBufC NewData);
1091
1092
1093/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001094 * @brief Append bytes to the @ref UsefulOutBuf.
1095 *
1096 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1097 * @param[in] pBytes Pointer to bytes to append.
1098 * @param[in] uLen Length of @c pBytes to append.
1099 *
1100 * See UsefulOutBuf_InsertData() for details. This does the same with
1101 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001102 */
1103static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1104 const void *pBytes,
1105 size_t uLen);
1106
1107
1108/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001109 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1110 *
1111 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1112 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001113 */
1114static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1115 const char *szString);
1116
1117
1118/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001119 * @brief Append a byte to the @ref UsefulOutBuf
1120 *
1121 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1122 * @param[in] byte Bytes to append.
1123 *
1124 * See UsefulOutBuf_InsertByte() for details. This does the same
1125 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001126 */
1127static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1128 uint8_t byte);
1129
1130
1131/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001132 * @brief Append an integer to the @ref UsefulOutBuf
1133 *
1134 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1135 * @param[in] uInteger16 Integer to append.
1136 *
1137 * See UsefulOutBuf_InsertUint16() for details. This does the same
1138 * with the insertion point at the end of the valid data.
1139 *
1140 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001141 */
1142static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1143 uint16_t uInteger16);
1144
1145
1146/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001147 * @brief Append an integer to the @ref UsefulOutBuf
1148 *
1149 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1150 * @param[in] uInteger32 Integer to append.
1151 *
1152 * See UsefulOutBuf_InsertUint32() for details. This does the same
1153 * with the insertion point at the end of the valid data.
1154 *
1155 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001156 */
1157static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1158 uint32_t uInteger32);
1159
1160
1161/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001162 * @brief Append an integer to the @ref UsefulOutBuf
1163 *
1164 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1165 * @param[in] uInteger64 Integer to append.
1166 *
1167 * See UsefulOutBuf_InsertUint64() for details. This does the same
1168 * with the insertion point at the end of the valid data.
1169 *
1170 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001171 */
1172static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1173 uint64_t uInteger64);
1174
1175
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001176#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001177/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001178 * @brief Append a @c float to the @ref UsefulOutBuf
1179 *
1180 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1181 * @param[in] f @c float to append.
1182 *
1183 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1184 * the insertion point at the end of the valid data.
1185 *
1186 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001187 */
1188static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1189 float f);
1190
1191
1192/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001193 * @brief Append a @c double to the @ref UsefulOutBuf
1194 *
1195 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1196 * @param[in] d @c double to append.
1197 *
1198 * See UsefulOutBuf_InsertDouble() for details. This does the same
1199 * with the insertion point at the end of the valid data.
1200 *
1201 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001202 */
1203static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1204 double d);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001205#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001206
1207
1208/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001209 * @brief Returns the current error status.
1210 *
1211 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1212 *
1213 * @return 0 if all OK, 1 on error.
1214 *
1215 * This returns the error status since a call to either
1216 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1217 * goes into the error state, it will stay until one of those
1218 * functions is called.
1219 *
1220 * Possible error conditions are:
1221 * - bytes to be inserted will not fit
1222 * - insertion point is out of buffer or past valid data
1223 * - current position is off end of buffer (probably corrupted or uninitialized)
1224 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001225 */
1226static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1227
1228
1229/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001230 * @brief Returns number of bytes unused used in the output buffer.
1231 *
1232 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1233 *
1234 * @return Number of unused bytes or zero.
1235 *
1236 * Because of the error handling strategy and checks in
1237 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1238 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001239 */
1240static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1241
1242
1243/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001244 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1245 *
1246 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1247 * @param[in] uLen Number of bytes for which to check
1248 *
1249 * @return 1 if @c uLen bytes will fit, 0 if not.
1250 *
1251 * Because of the error handling strategy and checks in
1252 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1253 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001254 */
1255static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1256
1257
1258 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001259 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1260 *
1261 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1262 *
1263 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1264 *
1265 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1266 * just calculating the length of the encoded data.
1267 */
Michael Eckel5c531332020-03-02 01:35:30 +01001268static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1269
1270
1271/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001272 * @brief Returns the resulting valid data in a UsefulOutBuf
1273 *
1274 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1275 *
1276 * @return The valid data in @ref UsefulOutBuf or
1277 * @ref NULLUsefulBufC if there was an error adding data.
1278 *
1279 * The storage for the returned data is the @c Storage parameter
1280 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1281 *
1282 * This can be called anytime and many times to get intermediate
1283 * results. It doesn't change the data or reset the current position,
1284 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001285 */
1286UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1287
1288
1289/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001290 * @brief Copies the valid data into a supplied buffer
1291 *
1292 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1293 * @param[out] Dest The destination buffer to copy into.
1294 *
1295 * @return Pointer and length of copied data or @c NULLUsefulBufC
1296 * if it will not fit in the @c Dest buffer or the error
1297 * state was entered.
1298 *
1299 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1300 * data to @c Dest.
1301 */
Michael Eckel5c531332020-03-02 01:35:30 +01001302UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1303
1304
1305
1306
1307/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001308 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1309 * for parsing data received. Initialize it with the data from the
1310 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1311 * get data chunks of various types. A position cursor is maintained
1312 * internally.
1313 *
1314 * As long as the functions here are used, there will never be any
1315 * reference off the end of the given buffer (except
1316 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1317 * called incorrectly, an attempt is made to seek off the end of the
1318 * buffer or such. This makes it easier to write safe and correct
1319 * code. For example, the QCBOR decoder implementation is safer and
1320 * easier to review through its use of @ref UsefulInputBuf.
1321 *
1322 * @ref UsefulInputBuf maintains an internal error state. The
1323 * intended use is fetching data chunks without any error checks until
1324 * the end. If there was any error, such as an attempt to fetch data
1325 * off the end, the error state is entered and no further data will be
1326 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1327 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1328 * null is not dereferenced, the error check can be put off until the
1329 * end, simplifying the calling code.
1330 *
1331 * The integer and float parsing expects network byte order (big
1332 * endian). Network byte order is what is used by TCP/IP, CBOR and
1333 * most internet protocols.
1334 *
1335 * Lots of inline functions are used to keep code size down. The
1336 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1337 * code size a lot. The only non-inline code is
1338 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1339 * @ref UsefulInputBuf doesn't add much code for all the messy
1340 * hard-to-get right issues with parsing binary protocols in C that it
1341 * solves.
1342 *
1343 * The parse context size is:
1344 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1345 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001346 */
1347typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001348 /* PRIVATE DATA STRUCTURE */
1349 UsefulBufC UB; /* Data being parsed */
1350 size_t cursor; /* Current offset in data being parse */
1351 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1352 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001353} UsefulInputBuf;
1354
1355#define UIB_MAGIC (0xB00F)
1356
1357
1358/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001359 * @brief Initialize the @ref UsefulInputBuf structure before use.
1360 *
1361 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1362 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001363 */
1364static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1365
1366
1367/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001368 * @brief Returns current position in input buffer.
1369 *
1370 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1371 *
1372 * @return Integer position of the cursor.
1373 *
1374 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001375 */
1376static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1377
1378
1379/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001380 * @brief Sets the current position in input buffer.
1381 *
1382 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1383 * @param[in] uPos Position to set to.
1384 *
1385 * If the position is off the end of the input buffer, the error state
1386 * is entered.
1387 *
1388 * Seeking to a valid position in the buffer will not reset the error
1389 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001390 */
1391static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1392
1393
1394/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001395 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1396 * the unconsumed bytes.
1397 *
1398 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1399 *
1400 * @return Number of bytes unconsumed or 0 on error.
1401 *
1402 * Returns 0 if the cursor is invalid or corruption of the
1403 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001404 */
1405static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1406
1407
1408/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001409 * @brief Check if there are unconsumed bytes.
1410 *
1411 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1412 * @param[in] uLen Number of bytes to check availability for.
1413 *
1414 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001415 */
1416static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1417
1418
1419/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001420 * @brief Convert a pointer to an offset with bounds checking.
1421 *
1422 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1423 * @param[in] p Pointer to convert to offset.
1424 *
1425 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1426 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001427static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1428
1429
1430/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001431 * @brief Get pointer to bytes out of the input buffer.
1432 *
1433 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1434 * @param[in] uNum Number of bytes to get.
1435 *
1436 * @return Pointer to bytes.
1437 *
1438 * This consumes @c uNum bytes from the input buffer. This returns a
1439 * pointer to the start of the @c uNum bytes.
1440 *
1441 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1442 * returned and the error state is entered.
1443 *
1444 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001445 */
1446const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1447
1448
1449/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001450 * @brief Get @ref UsefulBuf out of the input buffer.
1451 *
1452 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1453 * @param[in] uNum Number of bytes to get.
1454 *
1455 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1456 *
1457 * This consumes @c uNum bytes from the input buffer and returns the
1458 * pointer and length for them as a @ref UsefulBufC. The length
1459 * returned will always be @c uNum. The position cursor is advanced by
1460 * @c uNum bytes.
1461 *
1462 * If there are not @c uNum bytes in the input buffer, @ref
1463 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001464 */
1465static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1466
1467
1468/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001469 * @brief Get a byte out of the input buffer.
1470 *
1471 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1472 *
1473 * @return The byte.
1474 *
1475 * This consumes 1 byte from the input buffer, returns it and advances
1476 * the position cursor by 1.
1477 *
1478 * If there is not 1 byte in the buffer, 0 will be returned for the
1479 * byte and the error state is entered. To know if the 0 returned was
1480 * in error or the real value, the error state must be checked. If
1481 * possible, put this off until all values are retrieved to have
1482 * smaller and simpler code, but if not possible
1483 * UsefulInputBuf_GetError() can be called. Also, in the error state
1484 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1485 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001486 */
1487static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1488
1489
1490/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001491 * @brief Get a @c uint16_t out of the input buffer.
1492 *
1493 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1494 *
1495 * @return The @c uint16_t.
1496 *
1497 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1498 * a @c uint16_t and two bytes are consumed.
1499 *
1500 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001501 */
1502static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1503
1504
1505/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001506 * @brief Get a @c uint32_t out of the input buffer.
1507 *
1508 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1509 *
1510 * @return The @c uint32_t.
1511 *
1512 * See UsefulInputBuf_GetByte(). This works the same, except it
1513 * returns a @c uint32_t and four bytes are consumed.
1514 *
1515 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001516 */
1517static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1518
1519
1520/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001521 * @brief Get a @c uint64_t out of the input buffer.
1522 *
1523 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1524 *
1525 * @return The uint64_t.
1526 *
1527 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1528 * a @c uint64_t and eight bytes are consumed.
1529 *
1530 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001531 */
1532static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1533
1534
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001535#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001536/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001537 * @brief Get a float out of the input buffer.
1538 *
1539 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1540 *
1541 * @return The float.
1542 *
1543 * See UsefulInputBuf_GetByte(). This works the same, except it
1544 * returns a float and four bytes are consumed.
1545 *
1546 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001547 */
1548static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1549
1550
1551/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001552 * @brief Get a double out of the input buffer.
1553 *
1554 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1555 *
1556 * @return The double.
1557 *
1558 * See UsefulInputBuf_GetByte(). This works the same, except it
1559 * returns a double and eight bytes are consumed.
1560 *
1561 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001562 */
1563static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001564#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001565
1566
1567/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001568 * @brief Get the error status.
1569 *
1570 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1571 *
1572 * @return 0 if not in the error state, 1 if in the error state.
1573 *
1574 * This returns whether the @ref UsefulInputBuf is in the
1575 * error state or not.
1576 *
1577 * The error state is entered for one of these reasons:
1578 * - Attempt to fetch data past the end of the buffer
1579 * - Attempt to seek to a position past the end of the buffer
1580 * - Attempt to get data from an uninitialized or corrupt instance
1581 * of @ref UsefulInputBuf
1582 *
1583 * Once in the error state, it can only be cleared by calling
1584 * UsefulInputBuf_Init().
1585 *
1586 * For many use cases, it is possible to only call this once after all
1587 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1588 * possible if no reference to the data returned are needed before the
1589 * error state is checked.
1590 *
1591 * In some cases UsefulInputBuf_GetUsefulBuf() or
1592 * UsefulInputBuf_GetBytes() can stand in for this because they return
1593 * @c NULL if the error state has been entered. (The others can't stand
1594 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001595 */
1596static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1597
1598
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001599/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001600 * @brief Gets the input buffer length.
1601 *
1602 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1603 *
1604 * @return The length of the input buffer.
1605 *
1606 * This returns the length of the input buffer set by
1607 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001608 */
1609static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1610
1611
1612/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001613 * @brief Alters the input buffer length (use with caution).
1614 *
1615 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1616 * @param[in] uNewLen The new length of the input buffer.
1617 *
1618 * This alters the internal remembered length of the input buffer set
1619 * when UsefulInputBuf_Init() was called.
1620 *
1621 * The new length given here should always be equal to or less than
1622 * the length given when UsefulInputBuf_Init() was called. Making it
1623 * larger allows @ref UsefulInputBuf to run off the input buffer.
1624 *
1625 * The typical use is to set a length shorter than that when
1626 * initialized to constrain parsing. If
1627 * UsefulInputBuf_GetBufferLength() was called before this, then the
1628 * original length can be restored with another call to this.
1629 *
1630 * This should be used with caution. It is the only
1631 * @ref UsefulInputBuf method that can violate the safety of input
1632 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001633 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001634static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001635
1636
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001637
1638
Michael Eckel5c531332020-03-02 01:35:30 +01001639/*----------------------------------------------------------
1640 Inline implementations.
1641 */
1642static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1643{
1644 return !UB.ptr;
1645}
1646
1647
1648static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1649{
1650 return !UB.ptr;
1651}
1652
1653
1654static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1655{
1656 return !UB.len;
1657}
1658
1659
1660static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1661{
1662 return !UB.len;
1663}
1664
1665
1666static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1667{
1668 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1669}
1670
1671
1672static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1673{
1674 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1675}
1676
1677
1678static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1679{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001680 UsefulBufC UBC;
1681 UBC.ptr = UB.ptr;
1682 UBC.len = UB.len;
1683
1684 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001685}
1686
Michael Eckel5c531332020-03-02 01:35:30 +01001687static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1688{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001689 UsefulBuf UB;
1690
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001691 /* -Wcast-qual is a good warning flag to use in general. This is
1692 * the one place in UsefulBuf where it needs to be quieted. Since
1693 * clang supports GCC pragmas, this works for clang too. */
1694#pragma GCC diagnostic push
1695#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001696 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001697#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001698
1699 UB.len = UBC.len;
1700
1701 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001702}
1703
1704
1705static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1706{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001707 UsefulBufC UBC;
1708 UBC.ptr = szString;
1709 UBC.len = strlen(szString);
1710 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001711}
1712
1713
1714static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1715{
1716 return UsefulBuf_CopyOffset(Dest, 0, Src);
1717}
1718
1719
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001720static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001721{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001722 memset(Dest.ptr, value, Dest.len);
1723
1724 UsefulBufC UBC;
1725 UBC.ptr = Dest.ptr;
1726 UBC.len = Dest.len;
1727
1728 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001729}
1730
1731
1732static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1733{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001734 UsefulBufC UBC;
1735 UBC.ptr = ptr;
1736 UBC.len = len;
1737 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001738}
1739
1740
1741static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1742{
1743 if(uAmount > UB.len) {
1744 return NULLUsefulBufC;
1745 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001746 UsefulBufC UBC;
1747
1748 UBC.ptr = UB.ptr;
1749 UBC.len = uAmount;
1750
1751 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001752}
1753
1754
1755static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1756{
1757 UsefulBufC ReturnValue;
1758
1759 if(uAmount > UB.len) {
1760 ReturnValue = NULLUsefulBufC;
1761 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001762 ReturnValue.ptr = NULL;
1763 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001764 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001765 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1766 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001767 }
1768
1769 return ReturnValue;
1770}
1771
1772
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001773static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1774{
1775 if(UB.ptr == NULL) {
1776 return SIZE_MAX;
1777 }
1778
1779 if(p < UB.ptr) {
1780 /* given pointer is before start of buffer */
1781 return SIZE_MAX;
1782 }
1783
1784 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001785 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001786
1787 if(uOffset >= UB.len) {
1788 /* given pointer is off the end of the buffer */
1789 return SIZE_MAX;
1790 }
1791
1792 return uOffset;
1793}
1794
Michael Eckel5c531332020-03-02 01:35:30 +01001795
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001796#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01001797static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1798{
1799 uint32_t u32;
1800 memcpy(&u32, &f, sizeof(uint32_t));
1801 return u32;
1802}
1803
1804static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1805{
1806 uint64_t u64;
1807 memcpy(&u64, &d, sizeof(uint64_t));
1808 return u64;
1809}
1810
1811static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1812{
1813 double d;
1814 memcpy(&d, &u64, sizeof(uint64_t));
1815 return d;
1816}
1817
1818static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1819{
1820 float f;
1821 memcpy(&f, &u32, sizeof(uint32_t));
1822 return f;
1823}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02001824#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01001825
1826
1827
1828
1829static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1830{
1831 pMe->data_len = 0;
1832 pMe->err = 0;
1833}
1834
1835
1836static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1837{
1838 return pMe->data_len;
1839}
1840
1841
1842static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1843{
1844 return 0 == pMe->data_len;
1845}
1846
1847
1848static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1849 const void *pBytes,
1850 size_t uLen,
1851 size_t uPos)
1852{
1853 UsefulBufC Data = {pBytes, uLen};
1854 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1855}
1856
1857
1858static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1859 const char *szString,
1860 size_t uPos)
1861{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001862 UsefulBufC UBC;
1863 UBC.ptr = szString;
1864 UBC.len = strlen(szString);
1865
1866 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001867}
1868
1869
1870static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1871 uint8_t byte,
1872 size_t uPos)
1873{
1874 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1875}
1876
1877
1878static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1879 uint16_t uInteger16,
1880 size_t uPos)
1881{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001882 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001883
1884 const void *pBytes;
1885
1886#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1887 pBytes = &uInteger16;
1888
1889#elif defined(USEFULBUF_CONFIG_HTON)
1890 uint16_t uTmp = htons(uInteger16);
1891 pBytes = &uTmp;
1892
1893#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1894 uint16_t uTmp = __builtin_bswap16(uInteger16);
1895 pBytes = &uTmp;
1896
1897#else
1898 uint8_t aTmp[2];
1899
1900 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1901 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1902
1903 pBytes = aTmp;
1904#endif
1905
1906 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1907}
1908
1909
1910static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1911 uint32_t uInteger32,
1912 size_t uPos)
1913{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001914 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001915
1916 const void *pBytes;
1917
1918#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1919 pBytes = &uInteger32;
1920
1921#elif defined(USEFULBUF_CONFIG_HTON)
1922 uint32_t uTmp = htonl(uInteger32);
1923 pBytes = &uTmp;
1924
1925#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1926 uint32_t uTmp = __builtin_bswap32(uInteger32);
1927
1928 pBytes = &uTmp;
1929
1930#else
1931 uint8_t aTmp[4];
1932
1933 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1934 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1935 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1936 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1937
1938 pBytes = aTmp;
1939#endif
1940
1941 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1942}
1943
1944static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001945 uint64_t uInteger64,
1946 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01001947{
1948 const void *pBytes;
1949
1950#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001951 /* We have been told explicitly we are running on a big-endian
1952 * machine. Network byte order is big endian, so just copy. There
1953 * is no issue with alignment here because uInteger64 is always
1954 * aligned (and it doesn't matter if pBytes is aligned).
1955 */
Michael Eckel5c531332020-03-02 01:35:30 +01001956 pBytes = &uInteger64;
1957
1958#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001959 /* Use system function to handle big- and little-endian. This works
1960 * on both big- and little-endian machines, but hton() is not
1961 * always available or in a standard place so it is not used by
1962 * default. With some compilers and CPUs the code for this is very
1963 * compact through use of a special swap instruction and on
1964 * big-endian machines hton() will reduce to nothing.
1965 */
Michael Eckel5c531332020-03-02 01:35:30 +01001966 uint64_t uTmp = htonll(uInteger64);
1967
1968 pBytes = &uTmp;
1969
1970#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001971 /* Use built-in function for byte swapping. This usually compiles
1972 * to an efficient special byte swap instruction. Unlike hton() it
1973 * does not do this conditionally on the CPU endianness, so this
1974 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1975 */
Michael Eckel5c531332020-03-02 01:35:30 +01001976 uint64_t uTmp = __builtin_bswap64(uInteger64);
1977
1978 pBytes = &uTmp;
1979
1980#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001981 /* Default which works on every CPU with no dependency on anything
1982 * from the CPU, compiler, libraries or OS. This always works, but
1983 * it is usually a little larger and slower than hton().
1984 */
Michael Eckel5c531332020-03-02 01:35:30 +01001985 uint8_t aTmp[8];
1986
1987 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1988 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1989 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1990 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1991 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1992 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1993 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1994 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
1995
1996 pBytes = aTmp;
1997#endif
1998
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001999 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01002000 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
2001}
2002
2003
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002004#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002005static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
2006 float f,
2007 size_t uPos)
2008{
2009 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
2010}
2011
2012
2013static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
2014 double d,
2015 size_t uPos)
2016{
2017 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2018}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002019#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002020
2021
2022static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2023 UsefulBufC NewData)
2024{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002025 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002026 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2027}
2028
2029
2030static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2031 const void *pBytes,
2032 size_t uLen)
2033{
2034 UsefulBufC Data = {pBytes, uLen};
2035 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2036}
2037
2038
2039static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2040 const char *szString)
2041{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002042 UsefulBufC UBC;
2043 UBC.ptr = szString;
2044 UBC.len = strlen(szString);
2045
2046 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002047}
2048
2049
2050static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2051 uint8_t byte)
2052{
2053 UsefulOutBuf_AppendData(pMe, &byte, 1);
2054}
2055
2056
2057static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2058 uint16_t uInteger16)
2059{
2060 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2061}
2062
2063static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2064 uint32_t uInteger32)
2065{
2066 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2067}
2068
2069
2070static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2071 uint64_t uInteger64)
2072{
2073 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2074}
2075
2076
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002077#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002078static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2079 float f)
2080{
2081 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2082}
2083
2084
2085static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2086 double d)
2087{
2088 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2089}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002090#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002091
2092
2093static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2094{
2095 return pMe->err;
2096}
2097
2098
2099static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2100{
2101 return pMe->UB.len - pMe->data_len;
2102}
2103
2104
2105static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2106{
2107 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2108}
2109
2110
2111static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2112{
2113 return pMe->UB.ptr == NULL;
2114}
2115
2116
2117
2118static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2119{
2120 pMe->cursor = 0;
2121 pMe->err = 0;
2122 pMe->magic = UIB_MAGIC;
2123 pMe->UB = UB;
2124}
2125
2126static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2127{
2128 return pMe->cursor;
2129}
2130
2131
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002132static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002133{
2134 return pMe->UB.len;
2135}
2136
2137
Michael Eckel5c531332020-03-02 01:35:30 +01002138static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2139{
2140 if(uPos > pMe->UB.len) {
2141 pMe->err = 1;
2142 } else {
2143 pMe->cursor = uPos;
2144 }
2145}
2146
2147
2148static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2149{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002150 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002151
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002152 /* Magic number is messed up. Either the structure got overwritten
2153 * or was never initialized.
2154 */
Michael Eckel5c531332020-03-02 01:35:30 +01002155 if(pMe->magic != UIB_MAGIC) {
2156 return 0;
2157 }
2158
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002159 /* The cursor is off the end of the input buffer given.
2160 * Presuming there are no bugs in this code, this should never happen.
2161 * If it so, the struct was corrupted. The check is retained as
2162 * as a defense in case there is a bug in this code or the struct is
2163 * corrupted.
2164 */
Michael Eckel5c531332020-03-02 01:35:30 +01002165 if(pMe->cursor > pMe->UB.len) {
2166 return 0;
2167 }
2168
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002169 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002170 return pMe->UB.len - pMe->cursor;
2171}
2172
2173
2174static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2175{
2176 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2177}
2178
2179
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002180static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2181{
2182 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2183}
2184
2185
Michael Eckel5c531332020-03-02 01:35:30 +01002186static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2187{
2188 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2189 if(!pResult) {
2190 return NULLUsefulBufC;
2191 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002192 UsefulBufC UBC;
2193 UBC.ptr = pResult;
2194 UBC.len = uNum;
2195 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002196 }
2197}
2198
2199
2200static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2201{
2202 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2203
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002204 /* The ternary operator is subject to integer promotion, because
2205 * the operands are smaller than int, so cast back to uint8_t is
2206 * needed to be completely explicit about types (for static
2207 * analyzers).
2208 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002209 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002210}
2211
2212static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2213{
2214 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2215
2216 if(!pResult) {
2217 return 0;
2218 }
2219
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002220 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002221#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2222 uint16_t uTmp;
2223 memcpy(&uTmp, pResult, sizeof(uint16_t));
2224
2225#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2226 return uTmp;
2227
2228#elif defined(USEFULBUF_CONFIG_HTON)
2229 return ntohs(uTmp);
2230
2231#else
2232 return __builtin_bswap16(uTmp);
2233
2234#endif
2235
2236#else
2237
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002238 /* The operations here are subject to integer promotion because the
2239 * operands are smaller than int. They will be promoted to unsigned
2240 * int for the shift and addition. The cast back to uint16_t is is
2241 * needed to be completely explicit about types (for static
2242 * analyzers).
2243 */
Michael Eckel5c531332020-03-02 01:35:30 +01002244 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2245
2246#endif
2247}
2248
2249
2250static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2251{
2252 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2253
2254 if(!pResult) {
2255 return 0;
2256 }
2257
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002258 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002259#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2260 uint32_t uTmp;
2261 memcpy(&uTmp, pResult, sizeof(uint32_t));
2262
2263#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2264 return uTmp;
2265
2266#elif defined(USEFULBUF_CONFIG_HTON)
2267 return ntohl(uTmp);
2268
2269#else
2270 return __builtin_bswap32(uTmp);
2271
2272#endif
2273
2274#else
2275 return ((uint32_t)pResult[0]<<24) +
2276 ((uint32_t)pResult[1]<<16) +
2277 ((uint32_t)pResult[2]<<8) +
2278 (uint32_t)pResult[3];
2279#endif
2280}
2281
2282
2283static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2284{
2285 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2286
2287 if(!pResult) {
2288 return 0;
2289 }
2290
2291#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002292 /* pResult will probably not be aligned. This memcpy() moves the
2293 * bytes into a temp variable safely for CPUs that can or can't do
2294 * unaligned memory access. Many compilers will optimize the
2295 * memcpy() into a simple move instruction.
2296 */
Michael Eckel5c531332020-03-02 01:35:30 +01002297 uint64_t uTmp;
2298 memcpy(&uTmp, pResult, sizeof(uint64_t));
2299
2300#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002301 /* We have been told expliclity this is a big-endian CPU. Since
2302 * network byte order is big-endian, there is nothing to do.
2303 */
Michael Eckel5c531332020-03-02 01:35:30 +01002304
2305 return uTmp;
2306
2307#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002308 /* We have been told to use ntoh(), the system function to handle
2309 * big- and little-endian. This works on both big- and
2310 * little-endian machines, but ntoh() is not always available or in
2311 * a standard place so it is not used by default. On some CPUs the
2312 * code for this is very compact through use of a special swap
2313 * instruction.
2314 */
Michael Eckel5c531332020-03-02 01:35:30 +01002315
2316 return ntohll(uTmp);
2317
2318#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002319 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2320 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2321 * __builtin_bswap64() and friends are not conditional on CPU
2322 * endianness so this must only be used on little-endian machines.
2323 */
Michael Eckel5c531332020-03-02 01:35:30 +01002324
2325 return __builtin_bswap64(uTmp);
2326
2327
2328#endif
2329
2330#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002331 /* This is the default code that works on every CPU and every
2332 * endianness with no dependency on ntoh(). This works on CPUs
2333 * that either allow or do not allow unaligned access. It will
2334 * always work, but usually is a little less efficient than ntoh().
2335 */
Michael Eckel5c531332020-03-02 01:35:30 +01002336
2337 return ((uint64_t)pResult[0]<<56) +
2338 ((uint64_t)pResult[1]<<48) +
2339 ((uint64_t)pResult[2]<<40) +
2340 ((uint64_t)pResult[3]<<32) +
2341 ((uint64_t)pResult[4]<<24) +
2342 ((uint64_t)pResult[5]<<16) +
2343 ((uint64_t)pResult[6]<<8) +
2344 (uint64_t)pResult[7];
2345#endif
2346}
2347
2348
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002349#ifndef USEFULBUF_DISABLE_ALL_FLOAT
Michael Eckel5c531332020-03-02 01:35:30 +01002350static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2351{
2352 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2353
2354 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2355}
2356
2357
2358static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2359{
2360 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2361
2362 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2363}
Máté Tóth-Pálef5f07a2021-09-17 19:31:37 +02002364#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
Michael Eckel5c531332020-03-02 01:35:30 +01002365
2366
2367static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2368{
2369 return pMe->err;
2370}
2371
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002372
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002373static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002374{
2375 pMe->UB.len = uNewLen;
2376}
2377
2378
Michael Eckel5c531332020-03-02 01:35:30 +01002379#ifdef __cplusplus
2380}
2381#endif
2382
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002383#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002384
2385