blob: c271a31116e5f8a6a3411519276402cd5519142f [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.
Michael Eckel5c531332020-03-02 01:35:30 +01004
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above
11 copyright notice, this list of conditions and the following
12 disclaimer in the documentation and/or other materials provided
13 with the distribution.
14 * Neither the name of The Linux Foundation nor the names of its
15 contributors, nor the name "Laurence Lundblade" may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 =============================================================================*/
31
32/*============================================================================
33 FILE: UsefulBuf.h
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42 when who what, where, why
43 -------- ---- --------------------------------------------------
Laurence Lundblade48d8ace2021-08-19 22:00:26 -070044 8/8/2021 dthaler/llundbla Work with C++ without compiler extensions
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070045 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080046 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070047 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010048 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
49 5/21/2019 llundblade #define configs for efficient endianness handling.
50 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
51 3/23/2019 llundblade Big documentation & style update. No interface
52 change.
53 3/6/2019 llundblade Add UsefulBuf_IsValue()
54 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
55 12/13/2018 llundblade Documentation improvements
56 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
57 UsefulBufC.
58 02/02/18 llundbla Full support for integers in and out; fix pointer
59 alignment bug. Incompatible change: integers
60 in/out are now in network byte order.
61 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
62 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
63 comparison for < or > for unequal length buffers.
64 Added UsefulBuf_Set() function.
65 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
66 11/13/16 llundbla Initial Version.
67
68 =============================================================================*/
69
70#ifndef _UsefulBuf_h
71#define _UsefulBuf_h
72
73
74/*
Laurence Lundbladedabaffe2021-05-11 10:47:46 -070075 * Endianness Configuration
76 *
77 * This code is written so it will work correctly on big- and
78 * little-endian CPUs without configuration or any auto-detection of
79 * endianness. All code here will run correctly regardless of the
80 * endianness of the CPU it is running on.
81 *
82 * There are four C preprocessor macros that can be set with #define
83 * to explicitly configure endianness handling. Setting them can
84 * reduce code size a little and improve efficiency a little.
85 *
86 * Note that most of QCBOR is unaffected by this configuration. Its
87 * endianness handling is integrated with the code that handles
88 * alignment and preferred serialization. This configuration does
89 * affect QCBOR's (planned) implementation of integer arrays (tagged
90 * arrays) and use of the functions here to serialize or deserialize
91 * integers and floating-point values.
92 *
93 * Following is the recipe for configuring the endianness-related
94 * #defines.
95 *
96 * The first option is to not define anything. This will work fine
97 * with all CPUs, OS's and compilers. The code for encoding integers
98 * may be a little larger and slower.
99 *
100 * If your CPU is big-endian then define
101 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
102 * for big-endian CPUs. It will be small and efficient because there
103 * will be no byte swapping.
104 *
105 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
106 * OS's and compilers, but not all. On big-endian CPUs this should
107 * give the most efficient code, the same as
108 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
109 * call the system-defined byte swapping method which is presumably
110 * implemented efficiently. In some cases, this will be a dedicated
111 * byte swap instruction like Intel's bswap.
112 *
113 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
114 * little-endian, it is also good to define
115 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
116 *
117 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
118 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
119 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
120 * system-defined byte swap method. However, note
121 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
122 * this is fixed now. Often hton() and ntoh() will call the built-in
123 * __builtin_bswapXX()() function, so this size issue could affect
124 * USEFULBUF_CONFIG_HTON.
125 *
126 * Last, run the tests. They must all pass.
127 *
128 * These #define config options affect the inline implementation of
129 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
130 * also affect the 16-, 32-bit, float and double versions of these
131 * functions. Since they are inline, the size effect is not in the
132 * UsefulBuf object code, but in the calling code.
133 *
134 * Summary:
135 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
136 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
137 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
138 * handle big and little-endian with system option.
139 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
140 * use __builtin_bswapXX().
Michael Eckel5c531332020-03-02 01:35:30 +0100141 */
142
143#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
144#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
145#endif
146
147
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700148#include <stdint.h> /* for uint8_t, uint16_t.... */
149#include <string.h> /* for strlen, memcpy, memmove, memset */
150#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100151
152
153#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700154#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100155#endif
156
157#ifdef __cplusplus
158extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700159#if 0
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700160} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700161#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100162#endif
163
164/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700165 * @file UsefulBuf.h
166 *
167 * The goal of this code is to make buffer and pointer manipulation
168 * easier and safer when working with binary data.
169 *
170 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
171 * structures are used to represent buffers rather than ad hoc
172 * pointers and lengths.
173 *
174 * With these it is possible to write code that does little or no
175 * direct pointer manipulation for copying and formatting data. For
176 * example, the QCBOR encoder was written using these and has less
177 * pointer manipulation.
178 *
179 * While it is true that object code using these functions will be a
180 * little larger and slower than a white-knuckle clever use of
181 * pointers might be, but not by that much or enough to have an effect
182 * for most use cases. For security-oriented code this is highly
183 * worthwhile. Clarity, simplicity, reviewability and are more
184 * important.
185 *
186 * There are some extra sanity and double checks in this code to help
187 * catch coding errors and simple memory corruption. They are helpful,
188 * but not a substitute for proper code review, input validation and
189 * such.
190 *
191 * This code consists of a lot of inline functions and a few that are
192 * not. It should not generate very much object code, especially with
193 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100194 */
195
196
197/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700198 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
199 * hold a pointer and length for binary data. In C99 this data
200 * structure can be passed on the stack making a lot of code cleaner
201 * than carrying around a pointer and length as two parameters.
202 *
203 * This is also conducive to secure coding practice as the length is
204 * always carried with the pointer and the convention for handling a
205 * pointer and a length is clear.
206 *
207 * While it might be possible to write buffer and pointer code more
208 * efficiently in some use cases, the thought is that unless there is
209 * an extreme need for performance (e.g., you are building a
210 * gigabit-per-second IP router), it is probably better to have
211 * cleaner code you can be most certain about the security of.
212 *
213 * The non-const @ref UsefulBuf is usually used to refer an empty
214 * buffer to be filled in. The length is the size of the buffer.
215 *
216 * The const @ref UsefulBufC is usually used to refer to some data
217 * that has been filled in. The length is amount of valid data pointed
218 * to.
219 *
220 * A common use mode is to pass a @ref UsefulBuf to a function, the
221 * function puts some data in it, then the function returns a @ref
222 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
223 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
224 * so the constness stays correct. There is no single "in,out"
225 * parameter (if there was, it would have to be non-const). Note that
226 * the pointer returned in the @ref UsefulBufC usually ends up being
227 * the same pointer passed in as a @ref UsefulBuf, though this is not
228 * striclty required.
229 *
230 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
231 * @c NULL.
232 *
233 * There are functions and macros for the following:
234 * - Initializing
235 * - Create initialized const @ref UsefulBufC from compiler literals
236 * - Create initialized const @ref UsefulBufC from NULL-terminated string
237 * - Make an empty @ref UsefulBuf on the stack
238 * - Checking whether a @ref UsefulBuf is null, empty or both
239 * - Copying, copying with offset, copying head or tail
240 * - Comparing and finding substrings
241 *
242 * See also @ref UsefulOutBuf. It is a richer structure that has both
243 * the size of the valid data and the size of the buffer.
244 *
245 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
246 * it can go on the stack and be a function parameter or return value.
247 *
248 * Another way to look at it is this. C has the NULL-terminated string
249 * as a means for handling text strings, but no means or convention
250 * for binary strings. Other languages do have such means, Rust, an
251 * efficient compiled language, for example.
252 *
253 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
254 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
255 * out like anything".
256 */
Michael Eckel5c531332020-03-02 01:35:30 +0100257typedef struct q_useful_buf_c {
258 const void *ptr;
259 size_t len;
260} UsefulBufC;
261
262
263/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700264 * This non-const @ref UsefulBuf is typically used for some allocated
265 * memory that is to be filled in. The @c len is the amount of memory,
266 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100267 */
268typedef struct q_useful_buf {
269 void *ptr;
270 size_t len;
271} UsefulBuf;
272
273
274/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700275 * A null @ref UsefulBufC is one that has no value in the same way a
276 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
277 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
278 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100279 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700280/*
281 * NULLUsefulBufC and few other macros have to be
282 * definied differently in C than C++ because there
283 * is no common construct for a literal structure.
284 *
285 * In C compound literals are used.
286 *
287 * In C++ list initalization is used. This only works
288 * in C++11 and later.
289 *
290 * Note that some popular C++ compilers can handle compound
291 * literals with on-by-default extensions, however
292 * this code aims for full correctness with strict
293 * compilers so they are not used.
294 */
295#ifdef __cplusplus
296#define NULLUsefulBufC {NULL, 0}
297#else
298#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
299#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100300
301/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700302 * A null @ref UsefulBuf is one that has no memory associated the same
303 * way @c NULL points to nothing. It does not matter what @c len is.
304 **/
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700305#ifdef __cplusplus
306#define NULLUsefulBuf {NULL, 0}
307#else
308#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
309#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100310
311
312/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700313 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
314 *
315 * @param[in] UB The UsefulBuf to check.
316 *
317 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100318 */
319static inline int UsefulBuf_IsNULL(UsefulBuf UB);
320
321
322/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700323 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
324 *
325 * @param[in] UB The @ref UsefulBufC to check.
326 *
327 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100328 */
329static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
330
331
332/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700333 * @brief Check if a @ref UsefulBuf is empty or not.
334 *
335 * @param[in] UB The @ref UsefulBuf to check.
336 *
337 * @return 1 if it is empty, 0 if not.
338 *
339 * An "empty" @ref UsefulBuf is one that has a value and can be
340 * considered to be set, but that value is of zero length. It is
341 * empty when @c len is zero. It doesn't matter what the @c ptr is.
342 *
343 * Many uses will not need to clearly distinguish a @c NULL @ref
344 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
345 * @c len 0. However if a use of @ref UsefulBuf needs to make a
346 * distinction then @c ptr should not be @c NULL when the @ref
347 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100348 */
349static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
350
351
352/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700353 * @brief Check if a @ref UsefulBufC is empty or not.
354 *
355 * @param[in] UB The @ref UsefulBufC to check.
356 *
357 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100358 */
359static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
360
361
362/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700363 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
364 *
365 * @param[in] UB The @ref UsefulBuf to check.
366 *
367 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100368 */
369static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
370
371
372/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700373 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
374 *
375 * @param[in] UB The @ref UsefulBufC to check.
376 *
377 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100378 */
379static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
380
381
382/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700383 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
384 *
385 * @param[in] UB The @ref UsefulBuf to convert.
386 *
387 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100388 */
389static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
390
391
392/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700393 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
394 *
395 * @param[in] UBC The @ref UsefulBuf to convert.
396 *
397 * @return A non-const @ref UsefulBuf struct.
398 *
399 * Use of this is not necessary for the intended use mode of @ref
400 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
401 * created to describe a buffer that has not had any data put in
402 * it. Then the data is put in it. Then a @ref UsefulBufC is create
403 * to describe the part with the data in it. This goes from non-const
404 * to const, so this function is not needed.
405 *
406 * If the -Wcast-qual warning is enabled, this function can be used to
407 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100408 */
409static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
410
411
412/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700413 * Convert a literal string to a @ref UsefulBufC.
414 *
415 * @c szString must be a literal string that @c sizeof() works on.
416 * This is better for literal strings than UsefulBuf_FromSZ() because
417 * it generates less code. It will not work on non-literal strings.
418 *
419 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100420 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700421#ifdef __cplusplus
422#define UsefulBuf_FROM_SZ_LITERAL(szString) {(szString), sizeof(szString)-1}
423#else
Michael Eckel5c531332020-03-02 01:35:30 +0100424#define UsefulBuf_FROM_SZ_LITERAL(szString) \
425 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700426#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100427
428
429/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700430 * Convert a literal byte array to a @ref UsefulBufC.
431 *
432 * @c pBytes must be a literal string that @c sizeof() works on. It
433 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100434 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700435#ifdef __cplusplus
436#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) {(pBytes), sizeof(pBytes)}
437#else
Michael Eckel5c531332020-03-02 01:35:30 +0100438#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700439 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
440#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100441
442/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700443 * Make an automatic variable named @c name of type @ref UsefulBuf and
444 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100445 */
446#define UsefulBuf_MAKE_STACK_UB(name, size) \
447 uint8_t __pBuf##name[(size)];\
448 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
449
450
451/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700452 * Make a byte array in to a @ref UsefulBuf. This is usually used on
453 * stack variables or static variables. Also see @ref
454 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100455 */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700456#ifdef __cplusplus
457#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) {(pBytes), sizeof(pBytes)}
458#else
Michael Eckel5c531332020-03-02 01:35:30 +0100459#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700460 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
461#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100462
463
464/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700465 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
466 *
467 * @param[in] szString The string to convert.
468 *
469 * @return A @ref UsefulBufC struct.
470 *
471 * @c UsefulBufC.ptr points to the string so its lifetime must be
472 * maintained.
473 *
474 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100475 */
476static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
477
478
479/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700480 * @brief Copy one @ref UsefulBuf into another at an offset.
481 *
482 * @param[in] Dest Destination buffer to copy into.
483 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
484 * @param[in] Src The bytes to copy.
485 *
486 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
487 *
488 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
489 * size of @c Dest.
490 *
491 * This fails and returns @ref NULLUsefulBufC if the @c Src length
492 * plus @c uOffset is greater than the length of @c Dest.
493 *
494 * The results are undefined if @c Dest and @c Src overlap.
495 *
496 * This assumes that there is valid data in @c Dest up to @c
497 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
498 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100499 */
500UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
501
502
503/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700504 * @brief Copy one @ref UsefulBuf into another.
505 *
506 * @param[in] Dest The destination buffer to copy into.
507 * @param[out] Src The source to copy from.
508 *
509 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
510 * on failure.
511 *
512 * This fails if @c Src.len is greater than @c Dest.len.
513 *
514 * Note that like @c memcpy(), the pointers are not checked and this
515 * will crash rather than return @ref NULLUsefulBufC if they are @c
516 * NULL or invalid.
517 *
518 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100519 */
520static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
521
522
523/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700524 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
525 *
526 * @param[in] pDest The destination buffer to copy into.
527 * @param[in] value The value to set the bytes to.
528 *
529 * Note that like @c memset(), the pointer in @c pDest is not checked
530 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100531 */
532static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
533
534
535/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700536 * @brief Copy a pointer into a @ref UsefulBuf.
537 *
538 * @param[in,out] Dest The destination buffer to copy into.
539 * @param[in] ptr The source to copy from.
540 * @param[in] uLen Length of the source; amount to copy.
541 *
542 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
543 * on failure.
544 *
545 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
546 * than @c pDest->len.
547 *
548 * Note that like @c memcpy(), the pointers are not checked and this
549 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100550 */
551static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
552 const void *ptr,
553 size_t uLen);
554
555
556/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700557 * @brief Returns a truncation of a @ref UsefulBufC.
558 *
559 * @param[in] UB The buffer to get the head of.
560 * @param[in] uAmount The number of bytes in the head.
561 *
562 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100563 */
564static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
565
566
567/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700568 * @brief Returns bytes from the end of a @ref UsefulBufC.
569 *
570 * @param[in] UB The buffer to get the tail of.
571 * @param[in] uAmount The offset from the start where the tail is to begin.
572 *
573 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
574 * if @c uAmount is greater than the length of the @ref UsefulBufC.
575 *
576 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
577 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
578 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100579 */
580static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
581
582
583/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700584 * @brief Compare one @ref UsefulBufC to another.
585 *
586 * @param[in] UB1 The first buffer to compare.
587 * @param[in] UB2 The second buffer to compare.
588 *
589 * @return 0, positive or negative value.
590 *
591 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
592 * less than @c UB2 if it is shorter or the first byte that is not the
593 * same is less.
594 *
595 * Returns 0 if the inputs are the same.
596 *
597 * Returns a positive value if @c UB2 is less than @c UB1.
598 *
599 * All that is of significance is that the result is positive, negative
600 * or 0. (This doesn't return the difference between the first
601 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100602 */
603int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
604
605
606/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700607 * @brief Find first byte that is not a particular byte value.
608 *
609 * @param[in] UB The destination buffer for byte comparison.
610 * @param[in] uValue The byte value to compare to.
611 *
612 * @return Offset of first byte that isn't @c uValue or
613 * @c SIZE_MAX if all bytes are @c uValue.
614 *
615 * Note that unlike most comparison functions, 0
616 * does not indicate a successful comparison, so the
617 * test for match is:
618 *
619 * UsefulBuf_IsValue(...) == SIZE_MAX
620 *
621 * If @c UB is null or empty, there is no match
622 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100623 */
624size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
625
626
627/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700628 * @brief Find one @ref UsefulBufC in another.
629 *
630 * @param[in] BytesToSearch Buffer to search through.
631 * @param[in] BytesToFind Buffer with bytes to be found.
632 *
633 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100634 */
635size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
636
637
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700638/**
639 @brief Convert a pointer to an offset with bounds checking.
640
641 @param[in] UB Pointer to the UsefulInputBuf.
642 @param[in] p Pointer to convert to offset.
643
644 @return SIZE_MAX if @c p is out of range, the byte offset if not.
645*/
646static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
647
648
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800649#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100650/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700651#define SZLiteralToUsefulBufC(szString) UsefulBuf_FROM_SZ_LITERAL(szString)
Michael Eckel5c531332020-03-02 01:35:30 +0100652
653/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
654#define MakeUsefulBufOnStack(name, size) \
655 uint8_t __pBuf##name[(size)];\
656 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
657
658/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
659#define ByteArrayLiteralToUsefulBufC(pBytes) \
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700660 UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
Michael Eckel5c531332020-03-02 01:35:30 +0100661
662/** Deprecated function; use UsefulBuf_Unconst() instead */
663static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
664{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700665 UsefulBuf UB;
666
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800667 // See UsefulBuf_Unconst() implementation for comment on pragmas
668#pragma GCC diagnostic push
669#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700670 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800671#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -0700672
673 UB.len = UBC.len;
674
675 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +0100676}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800677#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100678
679
680
681
682/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700683 * @brief Copy a @c float to a @c uint32_t.
684 *
685 * @param[in] f Float value to copy.
686 *
687 * @return A @c uint32_t with the float bits.
688 *
689 * Convenience function to avoid type punning, compiler warnings and
690 * such. The optimizer usually reduces this to a simple assignment. This
691 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100692 */
693static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
694
695
696/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700697 * @brief Copy a @c double to a @c uint64_t.
698 *
699 * @param[in] d Double value to copy.
700 *
701 * @return A @c uint64_t with the double bits.
702 *
703 * Convenience function to avoid type punning, compiler warnings and
704 * such. The optimizer usually reduces this to a simple assignment. This
705 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100706 */
707static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
708
709
710/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700711 * @brief Copy a @c uint32_t to a @c float.
712 *
713 * @param[in] u32 Integer value to copy.
714 *
715 * @return The value as a @c float.
716 *
717 * Convenience function to avoid type punning, compiler warnings and
718 * such. The optimizer usually reduces this to a simple assignment. This
719 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100720 */
721static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
722
723
724/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700725 * @brief Copy a @c uint64_t to a @c double.
726 *
727 * @param[in] u64 Integer value to copy.
728 *
729 * @return The value as a @c double.
730 *
731 * Convenience function to avoid type punning, compiler warnings and
732 * such. The optimizer usually reduces this to a simple assignment. This
733 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100734 */
735static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
736
737
738
739
740/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700741 * UsefulOutBuf is a structure and functions (an object) for
742 * serializing data into a buffer to encode for a network protocol or
743 * write data to a file.
744 *
745 * The main idea is that all the pointer manipulation is performed by
746 * @ref UsefulOutBuf functions so the caller doesn't have to do any
747 * pointer manipulation. The pointer manipulation is centralized.
748 * This code has been reviewed and written carefully so it
749 * spares the caller of much of this work and results in safer code
750 * with less effort.
751 *
752 * The @ref UsefulOutBuf methods that add data to the output buffer
753 * always check the length and will never write off the end of the
754 * output buffer. If an attempt to add data that will not fit is made,
755 * an internal error flag will be set and further attempts to add data
756 * will not do anything.
757 *
758 * There is no way to ever write off the end of that buffer when
759 * calling the @c UsefulOutBuf_AddXxx() and
760 * @c UsefulOutBuf_InsertXxx() functions.
761 *
762 * The functions to add data do not report success of failure. The
763 * caller only needs to check for an error in the final call, either
764 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
765 * result. This makes the calling code cleaner.
766 *
767 * There is a utility function to get the error status anytime along
768 * the way for a special circumstance. There are functions to see how
769 * much room is left and see if some data will fit too, but their use
770 * is generally unnecessary.
771 *
772 * The general call flow is:
773 *
774 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
775 * buffer given to it can be from the heap, stack or
776 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
777 * macro that makes a buffer on the stack and initializes it.
778 *
779 * - Call methods like UsefulOutBuf_InsertString(),
780 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
781 * to output data. The append calls add data to the end of the
782 * valid data. The insert calls take a position argument.
783 *
784 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
785 * there were no errors and to get the serialized output bytes.
786 *
787 * @ref UsefulOutBuf can be used in a size calculation mode to
788 * calculate the size of output that would be generated. This is
789 * useful to calculate the size of a buffer that is to be allocated to
790 * hold the output. To use @ref UsefulOutBuf in this mode, call
791 * UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
792 * @c (UsefulBuf){NULL, MAX_UINT32}. Then call all the Insert and Add
793 * functions. No attempt will be made to actually copy data, so only
794 * the lengths have to be valid for inputs to these calls.
795 *
796 * Methods like UsefulOutBuf_InsertUint64() always output in network
797 * bytes order (big endian).
798 *
799 * The possible errors are:
800 *
801 * - The @ref UsefulOutBuf was not initialized or was corrupted.
802 *
803 * - An attempt was made to add data that will not fit.
804 *
805 * - An attempt was made to insert data at a position beyond the end of
806 * the buffer.
807 *
808 * - An attempt was made to insert data at a position beyond the valid
809 * data in the buffer.
810 *
811 * Some inexpensive simple sanity checks are performed before every
812 * data addition to guard against use of an uninitialized or corrupted
813 * UsefulOutBuf.
814 *
815 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
816 * encoder has almost no pointer manipulation in it, is easier to
817 * read, and easier to review.
818 *
819 * A @ref UsefulOutBuf is small and can go on the stack:
820 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
821 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100822 */
823typedef struct useful_out_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700824 /* PRIVATE DATA STRUCTURE */
825 UsefulBuf UB; /* Memory that is being output to */
826 size_t data_len; /* length of the valid data, the insertion point */
827 uint16_t magic; /* Used to detect corruption and lack
828 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100829 uint8_t err;
830} UsefulOutBuf;
831
832
833/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700834 * @brief Initialize and supply the actual output buffer.
835 *
836 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
837 * @param[in] Storage Buffer to output into.
838 *
839 * This initializes the @ref UsefulOutBuf with storage, sets the
840 * current position to the beginning of the buffer and clears the
841 * error state.
842 *
843 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100844 */
845void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
846
847
848/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700849 * Convenience macro to make a @ref UsefulOutBuf on the stack and
850 * initialize it with a stack buffer of the given size. The variable
851 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100852 */
853#define UsefulOutBuf_MakeOnStack(name, size) \
854 uint8_t __pBuf##name[(size)];\
855 UsefulOutBuf name;\
856 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
857
858
859/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700860 * @brief Reset a @ref UsefulOutBuf for re use.
861 *
862 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
863 *
864 * This sets the amount of data in the output buffer to none and
865 * clears the error state.
866 *
867 * The output buffer is still the same one and size as from the
868 * UsefulOutBuf_Init() call.
869 *
870 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100871 */
872static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
873
874
875/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700876 * @brief Returns position of end of data in the @ref UsefulOutBuf.
877 *
878 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
879 *
880 * @return position of end of data.
881 *
882 * On a freshly initialized @ref UsefulOutBuf with no data added, this
883 * will return 0. After 10 bytes have been added, it will return 10
884 * and so on.
885 *
886 * Generally, there is no need to call this for most uses of @ref
887 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100888 */
889static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
890
891
892/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700893 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
894 *
895 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
896 *
897 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100898 */
899static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
900
901
902/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700903 * @brief Inserts bytes into the @ref UsefulOutBuf.
904 *
905 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
906 * @param[in] NewData The bytes to insert.
907 * @param[in] uPos Index in output buffer at which to insert.
908 *
909 * @c NewData is the pointer and length for the bytes to be added to
910 * the output buffer. There must be room in the output buffer for all
911 * of @c NewData or an error will occur.
912 *
913 * The insertion point must be between 0 and the current valid
914 * data. If not, an error will occur. Appending data to the output
915 * buffer is achieved by inserting at the end of the valid data. This
916 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
917 *
918 * When insertion is performed, the bytes between the insertion point
919 * and the end of data previously added to the output buffer are slid
920 * to the right to make room for the new data.
921 *
922 * Overlapping buffers are OK. @c NewData can point to data in the
923 * output buffer.
924 *
925 * If an error occurs, an error state is set in the @ref
926 * UsefulOutBuf. No error is returned. All subsequent attempts to add
927 * data will do nothing.
928 *
929 * The intended use is that all additions are made without checking
930 * for an error. The error will be taken into account when
931 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
932 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100933 */
934void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
935 UsefulBufC NewData,
936 size_t uPos);
937
938
939/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700940 * @brief Insert a data buffer into the @ref UsefulOutBuf.
941 *
942 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
943 * @param[in] pBytes Pointer to the bytes to insert
944 * @param[in] uLen Length of the bytes to insert
945 * @param[in] uPos Index in output buffer at which to insert
946 *
947 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
948 * the difference being a pointer and length is passed in rather than an
949 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100950 */
951static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
952 const void *pBytes,
953 size_t uLen,
954 size_t uPos);
955
956
957/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700958 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
959 *
960 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
961 * @param[in] szString NULL-terminated string to insert.
962 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100963 */
964static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
965 const char *szString,
966 size_t uPos);
967
968
969/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700970 * @brief Insert a byte into the @ref UsefulOutBuf.
971 *
972 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
973 * @param[in] byte Bytes to insert.
974 * @param[in] uPos Index in output buffer at which to insert.
975 *
976 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
977 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +0100978 */
979static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
980 uint8_t byte,
981 size_t uPos);
982
983
984/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -0700985 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
986 *
987 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
988 * @param[in] uInteger16 Integer to insert.
989 * @param[in] uPos Index in output buffer at which to insert.
990 *
991 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
992 * with the difference being a two-byte integer is to be inserted.
993 *
994 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +0100995 */
996static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
997 uint16_t uInteger16,
998 size_t uPos);
999
1000
1001/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001002 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
1003 *
1004 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1005 * @param[in] uInteger32 Integer to insert.
1006 * @param[in] uPos Index in output buffer at which to insert.
1007 *
1008 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1009 * with the difference being a four-byte integer is to be inserted.
1010 *
1011 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001012 */
1013static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
1014 uint32_t uInteger32,
1015 size_t uPos);
1016
1017
1018/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001019 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
1020 *
1021 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1022 * @param[in] uInteger64 Integer to insert.
1023 * @param[in] uPos Index in output buffer at which to insert.
1024 *
1025 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1026 * with the difference being an eight-byte integer is to be inserted.
1027 *
1028 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001029 */
1030static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
1031 uint64_t uInteger64,
1032 size_t uPos);
1033
1034
1035/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001036 * @brief Insert a @c float into the @ref UsefulOutBuf.
1037 *
1038 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1039 * @param[in] f @c float to insert.
1040 * @param[in] uPos Index in output buffer at which to insert.
1041 *
1042 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1043 * with the difference being a @c float is to be inserted.
1044 *
1045 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001046 */
1047static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1048 float f,
1049 size_t uPos);
1050
1051
1052/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001053 * @brief Insert a @c double into the @ref UsefulOutBuf.
1054 *
1055 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1056 * @param[in] d @c double to insert.
1057 * @param[in] uPos Index in output buffer at which to insert.
1058 *
1059 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1060 * with the difference being a @c double is to be inserted.
1061 *
1062 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001063 */
1064static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1065 double d,
1066 size_t uPos);
1067
1068
1069/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001070 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1071 *
1072 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1073 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1074 *
1075 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1076 * with the insertion point at the end of the valid data.
1077 */
Michael Eckel5c531332020-03-02 01:35:30 +01001078static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1079 UsefulBufC NewData);
1080
1081
1082/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001083 * @brief Append bytes to the @ref UsefulOutBuf.
1084 *
1085 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1086 * @param[in] pBytes Pointer to bytes to append.
1087 * @param[in] uLen Length of @c pBytes to append.
1088 *
1089 * See UsefulOutBuf_InsertData() for details. This does the same with
1090 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001091 */
1092static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1093 const void *pBytes,
1094 size_t uLen);
1095
1096
1097/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001098 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1099 *
1100 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1101 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001102 */
1103static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1104 const char *szString);
1105
1106
1107/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001108 * @brief Append a byte to the @ref UsefulOutBuf
1109 *
1110 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1111 * @param[in] byte Bytes to append.
1112 *
1113 * See UsefulOutBuf_InsertByte() for details. This does the same
1114 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001115 */
1116static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1117 uint8_t byte);
1118
1119
1120/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001121 * @brief Append an integer to the @ref UsefulOutBuf
1122 *
1123 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1124 * @param[in] uInteger16 Integer to append.
1125 *
1126 * See UsefulOutBuf_InsertUint16() for details. This does the same
1127 * with the insertion point at the end of the valid data.
1128 *
1129 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001130 */
1131static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1132 uint16_t uInteger16);
1133
1134
1135/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001136 * @brief Append an integer to the @ref UsefulOutBuf
1137 *
1138 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1139 * @param[in] uInteger32 Integer to append.
1140 *
1141 * See UsefulOutBuf_InsertUint32() for details. This does the same
1142 * with the insertion point at the end of the valid data.
1143 *
1144 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001145 */
1146static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1147 uint32_t uInteger32);
1148
1149
1150/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001151 * @brief Append an integer to the @ref UsefulOutBuf
1152 *
1153 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1154 * @param[in] uInteger64 Integer to append.
1155 *
1156 * See UsefulOutBuf_InsertUint64() for details. This does the same
1157 * with the insertion point at the end of the valid data.
1158 *
1159 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001160 */
1161static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1162 uint64_t uInteger64);
1163
1164
1165/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001166 * @brief Append a @c float to the @ref UsefulOutBuf
1167 *
1168 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1169 * @param[in] f @c float to append.
1170 *
1171 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1172 * the insertion point at the end of the valid data.
1173 *
1174 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001175 */
1176static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1177 float f);
1178
1179
1180/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001181 * @brief Append a @c double to the @ref UsefulOutBuf
1182 *
1183 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1184 * @param[in] d @c double to append.
1185 *
1186 * See UsefulOutBuf_InsertDouble() for details. This does the same
1187 * with the insertion point at the end of the valid data.
1188 *
1189 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001190 */
1191static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1192 double d);
1193
1194
1195/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001196 * @brief Returns the current error status.
1197 *
1198 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1199 *
1200 * @return 0 if all OK, 1 on error.
1201 *
1202 * This returns the error status since a call to either
1203 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
1204 * goes into the error state, it will stay until one of those
1205 * functions is called.
1206 *
1207 * Possible error conditions are:
1208 * - bytes to be inserted will not fit
1209 * - insertion point is out of buffer or past valid data
1210 * - current position is off end of buffer (probably corrupted or uninitialized)
1211 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001212 */
1213static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1214
1215
1216/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001217 * @brief Returns number of bytes unused used in the output buffer.
1218 *
1219 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1220 *
1221 * @return Number of unused bytes or zero.
1222 *
1223 * Because of the error handling strategy and checks in
1224 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1225 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001226 */
1227static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1228
1229
1230/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001231 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1232 *
1233 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1234 * @param[in] uLen Number of bytes for which to check
1235 *
1236 * @return 1 if @c uLen bytes will fit, 0 if not.
1237 *
1238 * Because of the error handling strategy and checks in
1239 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1240 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001241 */
1242static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1243
1244
1245 /**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001246 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1247 *
1248 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1249 *
1250 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1251 *
1252 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1253 * just calculating the length of the encoded data.
1254 */
Michael Eckel5c531332020-03-02 01:35:30 +01001255static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1256
1257
1258/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001259 * @brief Returns the resulting valid data in a UsefulOutBuf
1260 *
1261 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1262 *
1263 * @return The valid data in @ref UsefulOutBuf or
1264 * @ref NULLUsefulBufC if there was an error adding data.
1265 *
1266 * The storage for the returned data is the @c Storage parameter
1267 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1268 *
1269 * This can be called anytime and many times to get intermediate
1270 * results. It doesn't change the data or reset the current position,
1271 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001272 */
1273UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1274
1275
1276/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001277 * @brief Copies the valid data into a supplied buffer
1278 *
1279 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1280 * @param[out] Dest The destination buffer to copy into.
1281 *
1282 * @return Pointer and length of copied data or @c NULLUsefulBufC
1283 * if it will not fit in the @c Dest buffer or the error
1284 * state was entered.
1285 *
1286 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1287 * data to @c Dest.
1288 */
Michael Eckel5c531332020-03-02 01:35:30 +01001289UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1290
1291
1292
1293
1294/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001295 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
1296 * for parsing data received. Initialize it with the data from the
1297 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1298 * get data chunks of various types. A position cursor is maintained
1299 * internally.
1300 *
1301 * As long as the functions here are used, there will never be any
1302 * reference off the end of the given buffer (except
1303 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1304 * called incorrectly, an attempt is made to seek off the end of the
1305 * buffer or such. This makes it easier to write safe and correct
1306 * code. For example, the QCBOR decoder implementation is safer and
1307 * easier to review through its use of @ref UsefulInputBuf.
1308 *
1309 * @ref UsefulInputBuf maintains an internal error state. The
1310 * intended use is fetching data chunks without any error checks until
1311 * the end. If there was any error, such as an attempt to fetch data
1312 * off the end, the error state is entered and no further data will be
1313 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1314 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1315 * null is not dereferenced, the error check can be put off until the
1316 * end, simplifying the calling code.
1317 *
1318 * The integer and float parsing expects network byte order (big
1319 * endian). Network byte order is what is used by TCP/IP, CBOR and
1320 * most internet protocols.
1321 *
1322 * Lots of inline functions are used to keep code size down. The
1323 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1324 * code size a lot. The only non-inline code is
1325 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1326 * @ref UsefulInputBuf doesn't add much code for all the messy
1327 * hard-to-get right issues with parsing binary protocols in C that it
1328 * solves.
1329 *
1330 * The parse context size is:
1331 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1332 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001333 */
1334typedef struct useful_input_buf {
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001335 /* PRIVATE DATA STRUCTURE */
1336 UsefulBufC UB; /* Data being parsed */
1337 size_t cursor; /* Current offset in data being parse */
1338 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1339 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001340} UsefulInputBuf;
1341
1342#define UIB_MAGIC (0xB00F)
1343
1344
1345/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001346 * @brief Initialize the @ref UsefulInputBuf structure before use.
1347 *
1348 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1349 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001350 */
1351static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1352
1353
1354/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001355 * @brief Returns current position in input buffer.
1356 *
1357 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1358 *
1359 * @return Integer position of the cursor.
1360 *
1361 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001362 */
1363static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1364
1365
1366/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001367 * @brief Sets the current position in input buffer.
1368 *
1369 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1370 * @param[in] uPos Position to set to.
1371 *
1372 * If the position is off the end of the input buffer, the error state
1373 * is entered.
1374 *
1375 * Seeking to a valid position in the buffer will not reset the error
1376 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001377 */
1378static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1379
1380
1381/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001382 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1383 * the unconsumed bytes.
1384 *
1385 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1386 *
1387 * @return Number of bytes unconsumed or 0 on error.
1388 *
1389 * Returns 0 if the cursor is invalid or corruption of the
1390 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001391 */
1392static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1393
1394
1395/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001396 * @brief Check if there are unconsumed bytes.
1397 *
1398 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1399 * @param[in] uLen Number of bytes to check availability for.
1400 *
1401 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001402 */
1403static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1404
1405
1406/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001407 * @brief Convert a pointer to an offset with bounds checking.
1408 *
1409 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1410 * @param[in] p Pointer to convert to offset.
1411 *
1412 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
1413 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001414static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1415
1416
1417/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001418 * @brief Get pointer to bytes out of the input buffer.
1419 *
1420 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1421 * @param[in] uNum Number of bytes to get.
1422 *
1423 * @return Pointer to bytes.
1424 *
1425 * This consumes @c uNum bytes from the input buffer. This returns a
1426 * pointer to the start of the @c uNum bytes.
1427 *
1428 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1429 * returned and the error state is entered.
1430 *
1431 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001432 */
1433const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1434
1435
1436/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001437 * @brief Get @ref UsefulBuf out of the input buffer.
1438 *
1439 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1440 * @param[in] uNum Number of bytes to get.
1441 *
1442 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1443 *
1444 * This consumes @c uNum bytes from the input buffer and returns the
1445 * pointer and length for them as a @ref UsefulBufC. The length
1446 * returned will always be @c uNum. The position cursor is advanced by
1447 * @c uNum bytes.
1448 *
1449 * If there are not @c uNum bytes in the input buffer, @ref
1450 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001451 */
1452static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1453
1454
1455/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001456 * @brief Get a byte out of the input buffer.
1457 *
1458 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1459 *
1460 * @return The byte.
1461 *
1462 * This consumes 1 byte from the input buffer, returns it and advances
1463 * the position cursor by 1.
1464 *
1465 * If there is not 1 byte in the buffer, 0 will be returned for the
1466 * byte and the error state is entered. To know if the 0 returned was
1467 * in error or the real value, the error state must be checked. If
1468 * possible, put this off until all values are retrieved to have
1469 * smaller and simpler code, but if not possible
1470 * UsefulInputBuf_GetError() can be called. Also, in the error state
1471 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1472 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001473 */
1474static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1475
1476
1477/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001478 * @brief Get a @c uint16_t out of the input buffer.
1479 *
1480 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1481 *
1482 * @return The @c uint16_t.
1483 *
1484 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1485 * a @c uint16_t and two bytes are consumed.
1486 *
1487 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001488 */
1489static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1490
1491
1492/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001493 * @brief Get a @c uint32_t out of the input buffer.
1494 *
1495 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1496 *
1497 * @return The @c uint32_t.
1498 *
1499 * See UsefulInputBuf_GetByte(). This works the same, except it
1500 * returns a @c uint32_t and four bytes are consumed.
1501 *
1502 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001503 */
1504static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1505
1506
1507/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001508 * @brief Get a @c uint64_t out of the input buffer.
1509 *
1510 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1511 *
1512 * @return The uint64_t.
1513 *
1514 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1515 * a @c uint64_t and eight bytes are consumed.
1516 *
1517 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001518 */
1519static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1520
1521
1522/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001523 * @brief Get a float out of the input buffer.
1524 *
1525 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1526 *
1527 * @return The float.
1528 *
1529 * See UsefulInputBuf_GetByte(). This works the same, except it
1530 * returns a float and four bytes are consumed.
1531 *
1532 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001533 */
1534static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1535
1536
1537/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001538 * @brief Get a double out of the input buffer.
1539 *
1540 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1541 *
1542 * @return The double.
1543 *
1544 * See UsefulInputBuf_GetByte(). This works the same, except it
1545 * returns a double and eight bytes are consumed.
1546 *
1547 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001548 */
1549static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1550
1551
1552/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001553 * @brief Get the error status.
1554 *
1555 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1556 *
1557 * @return 0 if not in the error state, 1 if in the error state.
1558 *
1559 * This returns whether the @ref UsefulInputBuf is in the
1560 * error state or not.
1561 *
1562 * The error state is entered for one of these reasons:
1563 * - Attempt to fetch data past the end of the buffer
1564 * - Attempt to seek to a position past the end of the buffer
1565 * - Attempt to get data from an uninitialized or corrupt instance
1566 * of @ref UsefulInputBuf
1567 *
1568 * Once in the error state, it can only be cleared by calling
1569 * UsefulInputBuf_Init().
1570 *
1571 * For many use cases, it is possible to only call this once after all
1572 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
1573 * possible if no reference to the data returned are needed before the
1574 * error state is checked.
1575 *
1576 * In some cases UsefulInputBuf_GetUsefulBuf() or
1577 * UsefulInputBuf_GetBytes() can stand in for this because they return
1578 * @c NULL if the error state has been entered. (The others can't stand
1579 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001580 */
1581static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1582
1583
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001584/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001585 * @brief Gets the input buffer length.
1586 *
1587 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1588 *
1589 * @return The length of the input buffer.
1590 *
1591 * This returns the length of the input buffer set by
1592 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001593 */
1594static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1595
1596
1597/**
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001598 * @brief Alters the input buffer length (use with caution).
1599 *
1600 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1601 * @param[in] uNewLen The new length of the input buffer.
1602 *
1603 * This alters the internal remembered length of the input buffer set
1604 * when UsefulInputBuf_Init() was called.
1605 *
1606 * The new length given here should always be equal to or less than
1607 * the length given when UsefulInputBuf_Init() was called. Making it
1608 * larger allows @ref UsefulInputBuf to run off the input buffer.
1609 *
1610 * The typical use is to set a length shorter than that when
1611 * initialized to constrain parsing. If
1612 * UsefulInputBuf_GetBufferLength() was called before this, then the
1613 * original length can be restored with another call to this.
1614 *
1615 * This should be used with caution. It is the only
1616 * @ref UsefulInputBuf method that can violate the safety of input
1617 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001618 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001619static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001620
1621
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001622
1623
Michael Eckel5c531332020-03-02 01:35:30 +01001624/*----------------------------------------------------------
1625 Inline implementations.
1626 */
1627static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1628{
1629 return !UB.ptr;
1630}
1631
1632
1633static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1634{
1635 return !UB.ptr;
1636}
1637
1638
1639static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1640{
1641 return !UB.len;
1642}
1643
1644
1645static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1646{
1647 return !UB.len;
1648}
1649
1650
1651static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1652{
1653 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1654}
1655
1656
1657static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1658{
1659 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1660}
1661
1662
1663static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1664{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001665 UsefulBufC UBC;
1666 UBC.ptr = UB.ptr;
1667 UBC.len = UB.len;
1668
1669 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001670}
1671
Michael Eckel5c531332020-03-02 01:35:30 +01001672static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1673{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001674 UsefulBuf UB;
1675
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001676 /* -Wcast-qual is a good warning flag to use in general. This is
1677 * the one place in UsefulBuf where it needs to be quieted. Since
1678 * clang supports GCC pragmas, this works for clang too. */
1679#pragma GCC diagnostic push
1680#pragma GCC diagnostic ignored "-Wcast-qual"
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001681 UB.ptr = (void *)UBC.ptr;
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001682#pragma GCC diagnostic pop
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001683
1684 UB.len = UBC.len;
1685
1686 return UB;
Michael Eckel5c531332020-03-02 01:35:30 +01001687}
1688
1689
1690static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1691{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001692 UsefulBufC UBC;
1693 UBC.ptr = szString;
1694 UBC.len = strlen(szString);
1695 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001696}
1697
1698
1699static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1700{
1701 return UsefulBuf_CopyOffset(Dest, 0, Src);
1702}
1703
1704
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001705static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
Michael Eckel5c531332020-03-02 01:35:30 +01001706{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001707 memset(Dest.ptr, value, Dest.len);
1708
1709 UsefulBufC UBC;
1710 UBC.ptr = Dest.ptr;
1711 UBC.len = Dest.len;
1712
1713 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001714}
1715
1716
1717static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1718{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001719 UsefulBufC UBC;
1720 UBC.ptr = ptr;
1721 UBC.len = len;
1722 return UsefulBuf_Copy(Dest, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01001723}
1724
1725
1726static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1727{
1728 if(uAmount > UB.len) {
1729 return NULLUsefulBufC;
1730 }
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001731 UsefulBufC UBC;
1732
1733 UBC.ptr = UB.ptr;
1734 UBC.len = uAmount;
1735
1736 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01001737}
1738
1739
1740static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1741{
1742 UsefulBufC ReturnValue;
1743
1744 if(uAmount > UB.len) {
1745 ReturnValue = NULLUsefulBufC;
1746 } else if(UB.ptr == NULL) {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001747 ReturnValue.ptr = NULL;
1748 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001749 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001750 ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
1751 ReturnValue.len = UB.len - uAmount;
Michael Eckel5c531332020-03-02 01:35:30 +01001752 }
1753
1754 return ReturnValue;
1755}
1756
1757
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001758static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1759{
1760 if(UB.ptr == NULL) {
1761 return SIZE_MAX;
1762 }
1763
1764 if(p < UB.ptr) {
1765 /* given pointer is before start of buffer */
1766 return SIZE_MAX;
1767 }
1768
1769 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001770 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001771
1772 if(uOffset >= UB.len) {
1773 /* given pointer is off the end of the buffer */
1774 return SIZE_MAX;
1775 }
1776
1777 return uOffset;
1778}
1779
Michael Eckel5c531332020-03-02 01:35:30 +01001780
1781static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1782{
1783 uint32_t u32;
1784 memcpy(&u32, &f, sizeof(uint32_t));
1785 return u32;
1786}
1787
1788static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1789{
1790 uint64_t u64;
1791 memcpy(&u64, &d, sizeof(uint64_t));
1792 return u64;
1793}
1794
1795static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1796{
1797 double d;
1798 memcpy(&d, &u64, sizeof(uint64_t));
1799 return d;
1800}
1801
1802static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1803{
1804 float f;
1805 memcpy(&f, &u32, sizeof(uint32_t));
1806 return f;
1807}
1808
1809
1810
1811
1812static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1813{
1814 pMe->data_len = 0;
1815 pMe->err = 0;
1816}
1817
1818
1819static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1820{
1821 return pMe->data_len;
1822}
1823
1824
1825static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1826{
1827 return 0 == pMe->data_len;
1828}
1829
1830
1831static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1832 const void *pBytes,
1833 size_t uLen,
1834 size_t uPos)
1835{
1836 UsefulBufC Data = {pBytes, uLen};
1837 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1838}
1839
1840
1841static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1842 const char *szString,
1843 size_t uPos)
1844{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07001845 UsefulBufC UBC;
1846 UBC.ptr = szString;
1847 UBC.len = strlen(szString);
1848
1849 UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
Michael Eckel5c531332020-03-02 01:35:30 +01001850}
1851
1852
1853static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1854 uint8_t byte,
1855 size_t uPos)
1856{
1857 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1858}
1859
1860
1861static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1862 uint16_t uInteger16,
1863 size_t uPos)
1864{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001865 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001866
1867 const void *pBytes;
1868
1869#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1870 pBytes = &uInteger16;
1871
1872#elif defined(USEFULBUF_CONFIG_HTON)
1873 uint16_t uTmp = htons(uInteger16);
1874 pBytes = &uTmp;
1875
1876#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1877 uint16_t uTmp = __builtin_bswap16(uInteger16);
1878 pBytes = &uTmp;
1879
1880#else
1881 uint8_t aTmp[2];
1882
1883 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1884 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1885
1886 pBytes = aTmp;
1887#endif
1888
1889 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1890}
1891
1892
1893static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1894 uint32_t uInteger32,
1895 size_t uPos)
1896{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001897 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001898
1899 const void *pBytes;
1900
1901#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1902 pBytes = &uInteger32;
1903
1904#elif defined(USEFULBUF_CONFIG_HTON)
1905 uint32_t uTmp = htonl(uInteger32);
1906 pBytes = &uTmp;
1907
1908#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1909 uint32_t uTmp = __builtin_bswap32(uInteger32);
1910
1911 pBytes = &uTmp;
1912
1913#else
1914 uint8_t aTmp[4];
1915
1916 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1917 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1918 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1919 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1920
1921 pBytes = aTmp;
1922#endif
1923
1924 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1925}
1926
1927static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001928 uint64_t uInteger64,
1929 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01001930{
1931 const void *pBytes;
1932
1933#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001934 /* We have been told explicitly we are running on a big-endian
1935 * machine. Network byte order is big endian, so just copy. There
1936 * is no issue with alignment here because uInteger64 is always
1937 * aligned (and it doesn't matter if pBytes is aligned).
1938 */
Michael Eckel5c531332020-03-02 01:35:30 +01001939 pBytes = &uInteger64;
1940
1941#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001942 /* Use system function to handle big- and little-endian. This works
1943 * on both big- and little-endian machines, but hton() is not
1944 * always available or in a standard place so it is not used by
1945 * default. With some compilers and CPUs the code for this is very
1946 * compact through use of a special swap instruction and on
1947 * big-endian machines hton() will reduce to nothing.
1948 */
Michael Eckel5c531332020-03-02 01:35:30 +01001949 uint64_t uTmp = htonll(uInteger64);
1950
1951 pBytes = &uTmp;
1952
1953#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001954 /* Use built-in function for byte swapping. This usually compiles
1955 * to an efficient special byte swap instruction. Unlike hton() it
1956 * does not do this conditionally on the CPU endianness, so this
1957 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1958 */
Michael Eckel5c531332020-03-02 01:35:30 +01001959 uint64_t uTmp = __builtin_bswap64(uInteger64);
1960
1961 pBytes = &uTmp;
1962
1963#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001964 /* Default which works on every CPU with no dependency on anything
1965 * from the CPU, compiler, libraries or OS. This always works, but
1966 * it is usually a little larger and slower than hton().
1967 */
Michael Eckel5c531332020-03-02 01:35:30 +01001968 uint8_t aTmp[8];
1969
1970 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1971 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1972 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1973 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1974 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1975 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1976 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1977 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
1978
1979 pBytes = aTmp;
1980#endif
1981
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07001982 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01001983 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
1984}
1985
1986
1987static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1988 float f,
1989 size_t uPos)
1990{
1991 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
1992}
1993
1994
1995static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1996 double d,
1997 size_t uPos)
1998{
1999 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
2000}
2001
2002
2003static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
2004 UsefulBufC NewData)
2005{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002006 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01002007 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
2008}
2009
2010
2011static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
2012 const void *pBytes,
2013 size_t uLen)
2014{
2015 UsefulBufC Data = {pBytes, uLen};
2016 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
2017}
2018
2019
2020static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
2021 const char *szString)
2022{
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002023 UsefulBufC UBC;
2024 UBC.ptr = szString;
2025 UBC.len = strlen(szString);
2026
2027 UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
Michael Eckel5c531332020-03-02 01:35:30 +01002028}
2029
2030
2031static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
2032 uint8_t byte)
2033{
2034 UsefulOutBuf_AppendData(pMe, &byte, 1);
2035}
2036
2037
2038static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
2039 uint16_t uInteger16)
2040{
2041 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
2042}
2043
2044static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
2045 uint32_t uInteger32)
2046{
2047 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
2048}
2049
2050
2051static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
2052 uint64_t uInteger64)
2053{
2054 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
2055}
2056
2057
2058static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
2059 float f)
2060{
2061 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
2062}
2063
2064
2065static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
2066 double d)
2067{
2068 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
2069}
2070
2071
2072static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2073{
2074 return pMe->err;
2075}
2076
2077
2078static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2079{
2080 return pMe->UB.len - pMe->data_len;
2081}
2082
2083
2084static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2085{
2086 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2087}
2088
2089
2090static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2091{
2092 return pMe->UB.ptr == NULL;
2093}
2094
2095
2096
2097static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2098{
2099 pMe->cursor = 0;
2100 pMe->err = 0;
2101 pMe->magic = UIB_MAGIC;
2102 pMe->UB = UB;
2103}
2104
2105static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2106{
2107 return pMe->cursor;
2108}
2109
2110
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002111static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002112{
2113 return pMe->UB.len;
2114}
2115
2116
Michael Eckel5c531332020-03-02 01:35:30 +01002117static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2118{
2119 if(uPos > pMe->UB.len) {
2120 pMe->err = 1;
2121 } else {
2122 pMe->cursor = uPos;
2123 }
2124}
2125
2126
2127static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2128{
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002129 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002130
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002131 /* Magic number is messed up. Either the structure got overwritten
2132 * or was never initialized.
2133 */
Michael Eckel5c531332020-03-02 01:35:30 +01002134 if(pMe->magic != UIB_MAGIC) {
2135 return 0;
2136 }
2137
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002138 /* The cursor is off the end of the input buffer given.
2139 * Presuming there are no bugs in this code, this should never happen.
2140 * If it so, the struct was corrupted. The check is retained as
2141 * as a defense in case there is a bug in this code or the struct is
2142 * corrupted.
2143 */
Michael Eckel5c531332020-03-02 01:35:30 +01002144 if(pMe->cursor > pMe->UB.len) {
2145 return 0;
2146 }
2147
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002148 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002149 return pMe->UB.len - pMe->cursor;
2150}
2151
2152
2153static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2154{
2155 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2156}
2157
2158
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002159static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2160{
2161 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2162}
2163
2164
Michael Eckel5c531332020-03-02 01:35:30 +01002165static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2166{
2167 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2168 if(!pResult) {
2169 return NULLUsefulBufC;
2170 } else {
Laurence Lundblade48d8ace2021-08-19 22:00:26 -07002171 UsefulBufC UBC;
2172 UBC.ptr = pResult;
2173 UBC.len = uNum;
2174 return UBC;
Michael Eckel5c531332020-03-02 01:35:30 +01002175 }
2176}
2177
2178
2179static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2180{
2181 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2182
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002183 /* The ternary operator is subject to integer promotion, because
2184 * the operands are smaller than int, so cast back to uint8_t is
2185 * needed to be completely explicit about types (for static
2186 * analyzers).
2187 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002188 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002189}
2190
2191static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2192{
2193 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2194
2195 if(!pResult) {
2196 return 0;
2197 }
2198
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002199 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002200#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2201 uint16_t uTmp;
2202 memcpy(&uTmp, pResult, sizeof(uint16_t));
2203
2204#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2205 return uTmp;
2206
2207#elif defined(USEFULBUF_CONFIG_HTON)
2208 return ntohs(uTmp);
2209
2210#else
2211 return __builtin_bswap16(uTmp);
2212
2213#endif
2214
2215#else
2216
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002217 /* The operations here are subject to integer promotion because the
2218 * operands are smaller than int. They will be promoted to unsigned
2219 * int for the shift and addition. The cast back to uint16_t is is
2220 * needed to be completely explicit about types (for static
2221 * analyzers).
2222 */
Michael Eckel5c531332020-03-02 01:35:30 +01002223 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2224
2225#endif
2226}
2227
2228
2229static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2230{
2231 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2232
2233 if(!pResult) {
2234 return 0;
2235 }
2236
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002237 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002238#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2239 uint32_t uTmp;
2240 memcpy(&uTmp, pResult, sizeof(uint32_t));
2241
2242#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2243 return uTmp;
2244
2245#elif defined(USEFULBUF_CONFIG_HTON)
2246 return ntohl(uTmp);
2247
2248#else
2249 return __builtin_bswap32(uTmp);
2250
2251#endif
2252
2253#else
2254 return ((uint32_t)pResult[0]<<24) +
2255 ((uint32_t)pResult[1]<<16) +
2256 ((uint32_t)pResult[2]<<8) +
2257 (uint32_t)pResult[3];
2258#endif
2259}
2260
2261
2262static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2263{
2264 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2265
2266 if(!pResult) {
2267 return 0;
2268 }
2269
2270#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002271 /* pResult will probably not be aligned. This memcpy() moves the
2272 * bytes into a temp variable safely for CPUs that can or can't do
2273 * unaligned memory access. Many compilers will optimize the
2274 * memcpy() into a simple move instruction.
2275 */
Michael Eckel5c531332020-03-02 01:35:30 +01002276 uint64_t uTmp;
2277 memcpy(&uTmp, pResult, sizeof(uint64_t));
2278
2279#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002280 /* We have been told expliclity this is a big-endian CPU. Since
2281 * network byte order is big-endian, there is nothing to do.
2282 */
Michael Eckel5c531332020-03-02 01:35:30 +01002283
2284 return uTmp;
2285
2286#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002287 /* We have been told to use ntoh(), the system function to handle
2288 * big- and little-endian. This works on both big- and
2289 * little-endian machines, but ntoh() is not always available or in
2290 * a standard place so it is not used by default. On some CPUs the
2291 * code for this is very compact through use of a special swap
2292 * instruction.
2293 */
Michael Eckel5c531332020-03-02 01:35:30 +01002294
2295 return ntohll(uTmp);
2296
2297#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002298 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2299 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2300 * __builtin_bswap64() and friends are not conditional on CPU
2301 * endianness so this must only be used on little-endian machines.
2302 */
Michael Eckel5c531332020-03-02 01:35:30 +01002303
2304 return __builtin_bswap64(uTmp);
2305
2306
2307#endif
2308
2309#else
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002310 /* This is the default code that works on every CPU and every
2311 * endianness with no dependency on ntoh(). This works on CPUs
2312 * that either allow or do not allow unaligned access. It will
2313 * always work, but usually is a little less efficient than ntoh().
2314 */
Michael Eckel5c531332020-03-02 01:35:30 +01002315
2316 return ((uint64_t)pResult[0]<<56) +
2317 ((uint64_t)pResult[1]<<48) +
2318 ((uint64_t)pResult[2]<<40) +
2319 ((uint64_t)pResult[3]<<32) +
2320 ((uint64_t)pResult[4]<<24) +
2321 ((uint64_t)pResult[5]<<16) +
2322 ((uint64_t)pResult[6]<<8) +
2323 (uint64_t)pResult[7];
2324#endif
2325}
2326
2327
2328static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2329{
2330 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2331
2332 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2333}
2334
2335
2336static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2337{
2338 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2339
2340 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2341}
2342
2343
2344static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2345{
2346 return pMe->err;
2347}
2348
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002349
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002350static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002351{
2352 pMe->UB.len = uNewLen;
2353}
2354
2355
Michael Eckel5c531332020-03-02 01:35:30 +01002356#ifdef __cplusplus
2357}
2358#endif
2359
Laurence Lundbladedabaffe2021-05-11 10:47:46 -07002360#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002361
2362