blob: 990191af37f15eb66c8fdd65a5357233872a028c [file] [log] [blame]
Michael Eckel5c531332020-03-02 01:35:30 +01001/*============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -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 Lundblade3d0d7cb2021-05-10 21:13:11 -070044 5/11/2021 llundblade Improve comments and comment formatting.
Laurence Lundbladeb9702452021-03-08 21:02:57 -080045 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundbladecf41c522021-02-20 10:19:07 -070046 2/17/2021 llundblade Add method to go from a pointer to an offset.
Michael Eckel5c531332020-03-02 01:35:30 +010047 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
48 5/21/2019 llundblade #define configs for efficient endianness handling.
49 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
50 3/23/2019 llundblade Big documentation & style update. No interface
51 change.
52 3/6/2019 llundblade Add UsefulBuf_IsValue()
53 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
54 12/13/2018 llundblade Documentation improvements
55 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
56 UsefulBufC.
57 02/02/18 llundbla Full support for integers in and out; fix pointer
58 alignment bug. Incompatible change: integers
59 in/out are now in network byte order.
60 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
61 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
62 comparison for < or > for unequal length buffers.
63 Added UsefulBuf_Set() function.
64 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
65 11/13/16 llundbla Initial Version.
66
67 =============================================================================*/
68
69#ifndef _UsefulBuf_h
70#define _UsefulBuf_h
71
72
73/*
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -070074 * Endianness Configuration
75 *
76 * This code is written so it will work correctly on big- and
77 * little-endian CPUs without configuration or any auto-detection of
78 * endianness. All code here will run correctly regardless of the
79 * endianness of the CPU it is running on.
80 *
81 * There are four C preprocessor macros that can be set with #define
82 * to explicitly configure endianness handling. Setting them can
83 * reduce code size a little and improve efficiency a little.
84 *
85 * Note that most of QCBOR is unaffected by this configuration. Its
86 * endianness handling is integrated with the code that handles
87 * alignment and preferred serialization. This configuration does
88 * affect QCBOR's (planned) implementation of integer arrays (tagged
89 * arrays) and use of the functions here to serialize or deserialize
90 * integers and floating-point values.
91 *
92 * Following is the recipe for configuring the endianness-related
93 * #defines.
94 *
95 * The first option is to not define anything. This will work fine
96 * with all CPUs, OS's and compilers. The code for encoding integers
97 * may be a little larger and slower.
98 *
99 * If your CPU is big-endian then define
100 * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
101 * for big-endian CPUs. It will be small and efficient because there
102 * will be no byte swapping.
103 *
104 * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
105 * OS's and compilers, but not all. On big-endian CPUs this should
106 * give the most efficient code, the same as
107 * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
108 * call the system-defined byte swapping method which is presumably
109 * implemented efficiently. In some cases, this will be a dedicated
110 * byte swap instruction like Intel's bswap.
111 *
112 * If USEFULBUF_CONFIG_HTON works and you know your CPU is
113 * little-endian, it is also good to define
114 * USEFULBUF_CONFIG_LITTLE_ENDIAN.
115 *
116 * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
117 * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
118 * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
119 * system-defined byte swap method. However, note
120 * https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
121 * this is fixed now. Often hton() and ntoh() will call the built-in
122 * __builtin_bswapXX()() function, so this size issue could affect
123 * USEFULBUF_CONFIG_HTON.
124 *
125 * Last, run the tests. They must all pass.
126 *
127 * These #define config options affect the inline implementation of
128 * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
129 * also affect the 16-, 32-bit, float and double versions of these
130 * functions. Since they are inline, the size effect is not in the
131 * UsefulBuf object code, but in the calling code.
132 *
133 * Summary:
134 * USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
135 * USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
136 * USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
137 * handle big and little-endian with system option.
138 * USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
139 * use __builtin_bswapXX().
Michael Eckel5c531332020-03-02 01:35:30 +0100140 */
141
142#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
143#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
144#endif
145
146
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700147#include <stdint.h> /* for uint8_t, uint16_t.... */
148#include <string.h> /* for strlen, memcpy, memmove, memset */
149#include <stddef.h> /* for size_t */
Michael Eckel5c531332020-03-02 01:35:30 +0100150
151
152#ifdef USEFULBUF_CONFIG_HTON
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700153#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
Michael Eckel5c531332020-03-02 01:35:30 +0100154#endif
155
156#ifdef __cplusplus
157extern "C" {
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700158#if 0
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700159} /* Keep editor indention formatting happy */
Laurence Lundblade24d509a2020-06-06 18:43:15 -0700160#endif
Michael Eckel5c531332020-03-02 01:35:30 +0100161#endif
162
163/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700164 * @file UsefulBuf.h
165 *
166 * The goal of this code is to make buffer and pointer manipulation
167 * easier and safer when working with binary data.
168 *
169 * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
170 * structures are used to represent buffers rather than ad hoc
171 * pointers and lengths.
172 *
173 * With these it is possible to write code that does little or no
174 * direct pointer manipulation for copying and formatting data. For
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700175 * example, the QCBOR encoder was written using these and has less
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700176 * pointer manipulation.
177 *
178 * While it is true that object code using these functions will be a
179 * little larger and slower than a white-knuckle clever use of
180 * pointers might be, but not by that much or enough to have an effect
181 * for most use cases. For security-oriented code this is highly
182 * worthwhile. Clarity, simplicity, reviewability and are more
183 * important.
184 *
185 * There are some extra sanity and double checks in this code to help
186 * catch coding errors and simple memory corruption. They are helpful,
187 * but not a substitute for proper code review, input validation and
188 * such.
189 *
190 * This code consists of a lot of inline functions and a few that are
191 * not. It should not generate very much object code, especially with
192 * the optimizer turned up to @c -Os or @c -O3.
Michael Eckel5c531332020-03-02 01:35:30 +0100193 */
194
195
196/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700197 * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
198 * hold a pointer and length for binary data. In C99 this data
199 * structure can be passed on the stack making a lot of code cleaner
200 * than carrying around a pointer and length as two parameters.
201 *
202 * This is also conducive to secure coding practice as the length is
203 * always carried with the pointer and the convention for handling a
204 * pointer and a length is clear.
205 *
206 * While it might be possible to write buffer and pointer code more
207 * efficiently in some use cases, the thought is that unless there is
208 * an extreme need for performance (e.g., you are building a
209 * gigabit-per-second IP router), it is probably better to have
210 * cleaner code you can be most certain about the security of.
211 *
212 * The non-const @ref UsefulBuf is usually used to refer an empty
213 * buffer to be filled in. The length is the size of the buffer.
214 *
215 * The const @ref UsefulBufC is usually used to refer to some data
216 * that has been filled in. The length is amount of valid data pointed
217 * to.
218 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700219 * A common use mode is to pass a @ref UsefulBuf to a function, the
Laurence Lundblade3d0d7cb2021-05-10 21:13:11 -0700220 * function puts some data in it, then the function returns a @ref
221 * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
222 * "in" parameter and the @ref UsefulBufC is a const "out" parameter
223 * so the constness stays correct. There is no single "in,out"
224 * parameter (if there was, it would have to be non-const). Note that
225 * the pointer returned in the @ref UsefulBufC usually ends up being
226 * the same pointer passed in as a @ref UsefulBuf, though this is not
227 * striclty required.
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700228 *
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700229 * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
230 * @c NULL.
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700231 *
232 * There are functions and macros for the following:
233 * - Initializing
234 * - Create initialized const @ref UsefulBufC from compiler literals
235 * - Create initialized const @ref UsefulBufC from NULL-terminated string
236 * - Make an empty @ref UsefulBuf on the stack
237 * - Checking whether a @ref UsefulBuf is null, empty or both
238 * - Copying, copying with offset, copying head or tail
239 * - Comparing and finding substrings
240 *
241 * See also @ref UsefulOutBuf. It is a richer structure that has both
242 * the size of the valid data and the size of the buffer.
243 *
244 * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
245 * it can go on the stack and be a function parameter or return value.
246 *
247 * Another way to look at it is this. C has the NULL-terminated string
248 * as a means for handling text strings, but no means or convention
249 * for binary strings. Other languages do have such means, Rust, an
250 * efficient compiled language, for example.
251 *
252 * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
253 * his birthday. Eeyore's balloon fits beautifully, "it goes in and
254 * out like anything".
255 */
Michael Eckel5c531332020-03-02 01:35:30 +0100256typedef struct q_useful_buf_c {
257 const void *ptr;
258 size_t len;
259} UsefulBufC;
260
261
262/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700263 * This non-const @ref UsefulBuf is typically used for some allocated
264 * memory that is to be filled in. The @c len is the amount of memory,
265 * not the length of the valid data in the buffer.
Michael Eckel5c531332020-03-02 01:35:30 +0100266 */
267typedef struct q_useful_buf {
268 void *ptr;
269 size_t len;
270} UsefulBuf;
271
272
273/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700274 * A null @ref UsefulBufC is one that has no value in the same way a
275 * @c NULL pointer has no value. A @ref UsefulBufC is @c NULL when
276 * the @c ptr field is @c NULL. It doesn't matter what @c len is. See
277 * UsefulBuf_IsEmpty() for the distinction between null and empty.
Michael Eckel5c531332020-03-02 01:35:30 +0100278 */
279#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
280
281
282/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700283 * A null @ref UsefulBuf is one that has no memory associated the same
284 * way @c NULL points to nothing. It does not matter what @c len is.
285 **/
Michael Eckel5c531332020-03-02 01:35:30 +0100286#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
287
288
289/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700290 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
291 *
292 * @param[in] UB The UsefulBuf to check.
293 *
294 * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100295 */
296static inline int UsefulBuf_IsNULL(UsefulBuf UB);
297
298
299/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700300 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
301 *
302 * @param[in] UB The @ref UsefulBufC to check.
303 *
304 * @return 1 if it is @c NULLUsefulBufC, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100305 */
306static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
307
308
309/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700310 * @brief Check if a @ref UsefulBuf is empty or not.
311 *
312 * @param[in] UB The @ref UsefulBuf to check.
313 *
314 * @return 1 if it is empty, 0 if not.
315 *
316 * An "empty" @ref UsefulBuf is one that has a value and can be
317 * considered to be set, but that value is of zero length. It is
318 * empty when @c len is zero. It doesn't matter what the @c ptr is.
319 *
320 * Many uses will not need to clearly distinguish a @c NULL @ref
321 * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
322 * @c len 0. However if a use of @ref UsefulBuf needs to make a
323 * distinction then @c ptr should not be @c NULL when the @ref
324 * UsefulBuf is considered empty, but not @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +0100325 */
326static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
327
328
329/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700330 * @brief Check if a @ref UsefulBufC is empty or not.
331 *
332 * @param[in] UB The @ref UsefulBufC to check.
333 *
334 * @return 1 if it is empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100335 */
336static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
337
338
339/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700340 * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
341 *
342 * @param[in] UB The @ref UsefulBuf to check.
343 *
344 * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100345 */
346static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
347
348
349/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700350 * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
351 *
352 * @param[in] UB The @ref UsefulBufC to check.
353 *
354 * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100355 */
356static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
357
358
359/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700360 * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
361 *
362 * @param[in] UB The @ref UsefulBuf to convert.
363 *
364 * @return A @ref UsefulBufC struct.
Michael Eckel5c531332020-03-02 01:35:30 +0100365 */
366static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
367
368
369/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700370 * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
371 *
372 * @param[in] UBC The @ref UsefulBuf to convert.
373 *
374 * @return A non-const @ref UsefulBuf struct.
Laurence Lundblade3d0d7cb2021-05-10 21:13:11 -0700375 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700376 * Use of this is not necessary for the intended use mode of @ref
377 * UsefulBufC and @ref UsefulBuf. In that mode, the @ref UsefulBuf is
378 * created to describe a buffer that has not had any data put in
379 * it. Then the data is put in it. Then a @ref UsefulBufC is create
380 * to describe the part with the data in it. This goes from non-const
381 * to const, so this function is not needed.
Laurence Lundblade3d0d7cb2021-05-10 21:13:11 -0700382 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700383 * If the -Wcast-qual warning is enabled, this function can be used to
384 * avoid that warning.
Michael Eckel5c531332020-03-02 01:35:30 +0100385 */
386static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
387
388
389/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700390 * Convert a literal string to a @ref UsefulBufC.
391 *
392 * @c szString must be a literal string that @c sizeof() works on.
393 * This is better for literal strings than UsefulBuf_FromSZ() because
394 * it generates less code. It will not work on non-literal strings.
395 *
396 * The terminating \0 (NULL) is NOT included in the length!
Michael Eckel5c531332020-03-02 01:35:30 +0100397 */
398#define UsefulBuf_FROM_SZ_LITERAL(szString) \
399 ((UsefulBufC) {(szString), sizeof(szString)-1})
400
401
402/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700403 * Convert a literal byte array to a @ref UsefulBufC.
404 *
405 * @c pBytes must be a literal string that @c sizeof() works on. It
406 * will not work on non-literal arrays.
Michael Eckel5c531332020-03-02 01:35:30 +0100407 */
408#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
409 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
410
411
412/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700413 * Make an automatic variable named @c name of type @ref UsefulBuf and
414 * point it to a stack variable of the given @c size.
Michael Eckel5c531332020-03-02 01:35:30 +0100415 */
416#define UsefulBuf_MAKE_STACK_UB(name, size) \
417 uint8_t __pBuf##name[(size)];\
418 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
419
420
421/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700422 * Make a byte array in to a @ref UsefulBuf. This is usually used on
423 * stack variables or static variables. Also see @ref
424 * UsefulBuf_MAKE_STACK_UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100425 */
426#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
427 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
428
429
430/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700431 * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
432 *
433 * @param[in] szString The string to convert.
434 *
435 * @return A @ref UsefulBufC struct.
436 *
437 * @c UsefulBufC.ptr points to the string so its lifetime must be
438 * maintained.
439 *
440 * The terminating \0 (NULL) is NOT included in the length.
Michael Eckel5c531332020-03-02 01:35:30 +0100441 */
442static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
443
444
445/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700446 * @brief Copy one @ref UsefulBuf into another at an offset.
447 *
448 * @param[in] Dest Destination buffer to copy into.
449 * @param[in] uOffset The byte offset in @c Dest at which to copy to.
450 * @param[in] Src The bytes to copy.
451 *
452 * @return Pointer and length of the copy or @ref NULLUsefulBufC.
453 *
454 * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
455 * size of @c Dest.
456 *
457 * This fails and returns @ref NULLUsefulBufC if the @c Src length
458 * plus @c uOffset is greater than the length of @c Dest.
459 *
460 * The results are undefined if @c Dest and @c Src overlap.
461 *
462 * This assumes that there is valid data in @c Dest up to @c
463 * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
464 * Dest and goes to @c Src.len @c + @c uOffset.
Michael Eckel5c531332020-03-02 01:35:30 +0100465 */
466UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
467
468
469/**
Laurence Lundblade7b8db8a2021-05-04 22:27:45 -0700470 * @brief Copy one @ref UsefulBuf into another.
471 *
472 * @param[in] Dest The destination buffer to copy into.
473 * @param[out] Src The source to copy from.
474 *
475 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
476 * on failure.
477 *
478 * This fails if @c Src.len is greater than @c Dest.len.
479 *
480 * Note that like @c memcpy(), the pointers are not checked and this
481 * will crash rather than return @ref NULLUsefulBufC if they are @c
482 * NULL or invalid.
483 *
484 * The results are undefined if @c Dest and @c Src overlap.
Michael Eckel5c531332020-03-02 01:35:30 +0100485 */
486static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
487
488
489/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700490 * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
491 *
492 * @param[in] pDest The destination buffer to copy into.
493 * @param[in] value The value to set the bytes to.
494 *
495 * Note that like @c memset(), the pointer in @c pDest is not checked
496 * and this will crash if @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100497 */
498static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
499
500
501/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700502 * @brief Copy a pointer into a @ref UsefulBuf.
503 *
504 * @param[in,out] Dest The destination buffer to copy into.
505 * @param[in] ptr The source to copy from.
506 * @param[in] uLen Length of the source; amount to copy.
507 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700508 * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
509 * on failure.
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700510 *
511 * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
512 * than @c pDest->len.
513 *
514 * Note that like @c memcpy(), the pointers are not checked and this
515 * will crash, rather than return 1 if they are @c NULL or invalid.
Michael Eckel5c531332020-03-02 01:35:30 +0100516 */
517static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
518 const void *ptr,
519 size_t uLen);
520
521
522/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700523 * @brief Returns a truncation of a @ref UsefulBufC.
524 *
525 * @param[in] UB The buffer to get the head of.
526 * @param[in] uAmount The number of bytes in the head.
527 *
528 * @return A @ref UsefulBufC that is the head of UB.
Michael Eckel5c531332020-03-02 01:35:30 +0100529 */
530static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
531
532
533/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700534 * @brief Returns bytes from the end of a @ref UsefulBufC.
535 *
536 * @param[in] UB The buffer to get the tail of.
537 * @param[in] uAmount The offset from the start where the tail is to begin.
538 *
539 * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
540 * if @c uAmount is greater than the length of the @ref UsefulBufC.
541 *
542 * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
543 * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
544 * of the tail.
Michael Eckel5c531332020-03-02 01:35:30 +0100545 */
546static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
547
548
549/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700550 * @brief Compare one @ref UsefulBufC to another.
551 *
552 * @param[in] UB1 The first buffer to compare.
553 * @param[in] UB2 The second buffer to compare.
554 *
555 * @return 0, positive or negative value.
556 *
557 * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
558 * less than @c UB2 if it is shorter or the first byte that is not the
559 * same is less.
560 *
561 * Returns 0 if the inputs are the same.
562 *
563 * Returns a positive value if @c UB2 is less than @c UB1.
564 *
565 * All that is of significance is that the result is positive, negative
566 * or 0. (This doesn't return the difference between the first
567 * non-matching byte like @c memcmp() ).
Michael Eckel5c531332020-03-02 01:35:30 +0100568 */
569int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
570
571
572/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700573 * @brief Find first byte that is not a particular byte value.
574 *
575 * @param[in] UB The destination buffer for byte comparison.
576 * @param[in] uValue The byte value to compare to.
577 *
578 * @return Offset of first byte that isn't @c uValue or
579 * @c SIZE_MAX if all bytes are @c uValue.
580 *
581 * Note that unlike most comparison functions, 0
582 * does not indicate a successful comparison, so the
583 * test for match is:
584 *
585 * UsefulBuf_IsValue(...) == SIZE_MAX
586 *
587 * If @c UB is null or empty, there is no match
588 * and 0 is returned.
Michael Eckel5c531332020-03-02 01:35:30 +0100589 */
590size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
591
592
593/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700594 * @brief Find one @ref UsefulBufC in another.
595 *
596 * @param[in] BytesToSearch Buffer to search through.
597 * @param[in] BytesToFind Buffer with bytes to be found.
598 *
599 * @return Position of found bytes or @c SIZE_MAX if not found.
Michael Eckel5c531332020-03-02 01:35:30 +0100600 */
601size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
602
603
Laurence Lundbladecf41c522021-02-20 10:19:07 -0700604/**
605 @brief Convert a pointer to an offset with bounds checking.
606
607 @param[in] UB Pointer to the UsefulInputBuf.
608 @param[in] p Pointer to convert to offset.
609
610 @return SIZE_MAX if @c p is out of range, the byte offset if not.
611*/
612static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
613
614
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800615#ifndef USEFULBUF_DISABLE_DEPRECATED
Michael Eckel5c531332020-03-02 01:35:30 +0100616/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
617#define SZLiteralToUsefulBufC(szString) \
618 ((UsefulBufC) {(szString), sizeof(szString)-1})
619
620/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
621#define MakeUsefulBufOnStack(name, size) \
622 uint8_t __pBuf##name[(size)];\
623 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
624
625/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
626#define ByteArrayLiteralToUsefulBufC(pBytes) \
627 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
628
629/** Deprecated function; use UsefulBuf_Unconst() instead */
630static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
631{
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800632 // See UsefulBuf_Unconst() implementation for comment on pragmas
633#pragma GCC diagnostic push
634#pragma GCC diagnostic ignored "-Wcast-qual"
Michael Eckel5c531332020-03-02 01:35:30 +0100635 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800636#pragma GCC diagnostic pop
Michael Eckel5c531332020-03-02 01:35:30 +0100637}
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800638#endif /* USEFULBUF_DISABLE_DEPRECATED */
Michael Eckel5c531332020-03-02 01:35:30 +0100639
640
641
642
643/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700644 * @brief Copy a @c float to a @c uint32_t.
645 *
646 * @param[in] f Float value to copy.
647 *
648 * @return A @c uint32_t with the float bits.
649 *
650 * Convenience function to avoid type punning, compiler warnings and
651 * such. The optimizer usually reduces this to a simple assignment. This
652 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100653 */
654static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
655
656
657/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700658 * @brief Copy a @c double to a @c uint64_t.
659 *
660 * @param[in] d Double value to copy.
661 *
662 * @return A @c uint64_t with the double bits.
663 *
664 * Convenience function to avoid type punning, compiler warnings and
665 * such. The optimizer usually reduces this to a simple assignment. This
666 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100667 */
668static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
669
670
671/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700672 * @brief Copy a @c uint32_t to a @c float.
673 *
674 * @param[in] u32 Integer value to copy.
675 *
676 * @return The value as a @c float.
677 *
678 * Convenience function to avoid type punning, compiler warnings and
679 * such. The optimizer usually reduces this to a simple assignment. This
680 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100681 */
682static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
683
684
685/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700686 * @brief Copy a @c uint64_t to a @c double.
687 *
688 * @param[in] u64 Integer value to copy.
689 *
690 * @return The value as a @c double.
691 *
692 * Convenience function to avoid type punning, compiler warnings and
693 * such. The optimizer usually reduces this to a simple assignment. This
694 * is a crusty corner of C.
Michael Eckel5c531332020-03-02 01:35:30 +0100695 */
696static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
697
698
699
700
701/**
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700702 * UsefulOutBuf is a structure and functions (an object) for
703 * serializing data into a buffer to encode for a network protocol or
704 * write data to a file.
705 *
706 * The main idea is that all the pointer manipulation is performed by
707 * @ref UsefulOutBuf functions so the caller doesn't have to do any
708 * pointer manipulation. The pointer manipulation is centralized.
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700709 * This code has been reviewed and written carefully so it
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700710 * spares the caller of much of this work and results in safer code
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700711 * with less effort.
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700712 *
713 * The @ref UsefulOutBuf methods that add data to the output buffer
714 * always check the length and will never write off the end of the
715 * output buffer. If an attempt to add data that will not fit is made,
716 * an internal error flag will be set and further attempts to add data
717 * will not do anything.
718 *
719 * There is no way to ever write off the end of that buffer when
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700720 * calling the @c UsefulOutBuf_AddXxx() and
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700721 * @c UsefulOutBuf_InsertXxx() functions.
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700722 *
723 * The functions to add data do not report success of failure. The
724 * caller only needs to check for an error in the final call, either
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700725 * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700726 * result. This makes the calling code cleaner.
727 *
728 * There is a utility function to get the error status anytime along
729 * the way for a special circumstance. There are functions to see how
730 * much room is left and see if some data will fit too, but their use
731 * is generally unnecessary.
732 *
733 * The general call flow is:
734 *
735 * - Initialize by calling @ref UsefulOutBuf_Init(). The output
736 * buffer given to it can be from the heap, stack or
737 * otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
738 * macro that makes a buffer on the stack and initializes it.
739 *
740 * - Call methods like UsefulOutBuf_InsertString(),
741 * UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
742 * to output data. The append calls add data to the end of the
743 * valid data. The insert calls take a position argument.
744 *
745 * - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
746 * there were no errors and to get the serialized output bytes.
747 *
748 * @ref UsefulOutBuf can be used in a size calculation mode to
749 * calculate the size of output that would be generated. This is
750 * useful to calculate the size of a buffer that is to be allocated to
751 * hold the output. To use @ref UsefulOutBuf in this mode, call
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700752 * UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
753 * @c (UsefulBuf){NULL, MAX_UINT32}. Then call all the Insert and Add
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700754 * functions. No attempt will be made to actually copy data, so only
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700755 * the lengths have to be valid for inputs to these calls.
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700756 *
757 * Methods like UsefulOutBuf_InsertUint64() always output in network
758 * bytes order (big endian).
759 *
760 * The possible errors are:
761 *
762 * - The @ref UsefulOutBuf was not initialized or was corrupted.
763 *
764 * - An attempt was made to add data that will not fit.
765 *
766 * - An attempt was made to insert data at a position beyond the end of
767 * the buffer.
768 *
769 * - An attempt was made to insert data at a position beyond the valid
770 * data in the buffer.
771 *
772 * Some inexpensive simple sanity checks are performed before every
773 * data addition to guard against use of an uninitialized or corrupted
774 * UsefulOutBuf.
775 *
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700776 * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
Laurence Lundblade83495bd2021-05-05 12:48:00 -0700777 * encoder has almost no pointer manipulation in it, is easier to
778 * read, and easier to review.
779 *
780 * A @ref UsefulOutBuf is small and can go on the stack:
781 * - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
782 * - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
Michael Eckel5c531332020-03-02 01:35:30 +0100783 */
784typedef struct useful_out_buf {
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -0700785 /* PRIVATE DATA STRUCTURE */
786 UsefulBuf UB; /* Memory that is being output to */
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -0700787 size_t data_len; /* length of the valid data, the insertion point */
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -0700788 uint16_t magic; /* Used to detect corruption and lack
789 * of initialization */
Michael Eckel5c531332020-03-02 01:35:30 +0100790 uint8_t err;
791} UsefulOutBuf;
792
793
794/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700795 * @brief Initialize and supply the actual output buffer.
796 *
797 * @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
798 * @param[in] Storage Buffer to output into.
799 *
800 * This initializes the @ref UsefulOutBuf with storage, sets the
801 * current position to the beginning of the buffer and clears the
802 * error state.
803 *
804 * This must be called before the @ref UsefulOutBuf is used.
Michael Eckel5c531332020-03-02 01:35:30 +0100805 */
806void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
807
808
809/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700810 * Convenience macro to make a @ref UsefulOutBuf on the stack and
811 * initialize it with a stack buffer of the given size. The variable
812 * will be named @c name.
Michael Eckel5c531332020-03-02 01:35:30 +0100813 */
814#define UsefulOutBuf_MakeOnStack(name, size) \
815 uint8_t __pBuf##name[(size)];\
816 UsefulOutBuf name;\
817 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
818
819
820/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700821 * @brief Reset a @ref UsefulOutBuf for re use.
822 *
823 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
824 *
825 * This sets the amount of data in the output buffer to none and
826 * clears the error state.
827 *
828 * The output buffer is still the same one and size as from the
829 * UsefulOutBuf_Init() call.
830 *
831 * This doesn't zero the data, just resets to 0 bytes of valid data.
Michael Eckel5c531332020-03-02 01:35:30 +0100832 */
833static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
834
835
836/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700837 * @brief Returns position of end of data in the @ref UsefulOutBuf.
838 *
839 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
840 *
841 * @return position of end of data.
842 *
843 * On a freshly initialized @ref UsefulOutBuf with no data added, this
844 * will return 0. After 10 bytes have been added, it will return 10
845 * and so on.
846 *
847 * Generally, there is no need to call this for most uses of @ref
848 * UsefulOutBuf.
Michael Eckel5c531332020-03-02 01:35:30 +0100849 */
850static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
851
852
853/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700854 * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
855 *
856 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
857 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -0700858 * @return 1 if output position is at start, 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +0100859 */
860static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
861
862
863/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700864 * @brief Inserts bytes into the @ref UsefulOutBuf.
865 *
866 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
867 * @param[in] NewData The bytes to insert.
868 * @param[in] uPos Index in output buffer at which to insert.
869 *
870 * @c NewData is the pointer and length for the bytes to be added to
871 * the output buffer. There must be room in the output buffer for all
872 * of @c NewData or an error will occur.
873 *
874 * The insertion point must be between 0 and the current valid
875 * data. If not, an error will occur. Appending data to the output
876 * buffer is achieved by inserting at the end of the valid data. This
877 * can be retrieved by calling UsefulOutBuf_GetEndPosition().
878 *
879 * When insertion is performed, the bytes between the insertion point
880 * and the end of data previously added to the output buffer are slid
881 * to the right to make room for the new data.
882 *
883 * Overlapping buffers are OK. @c NewData can point to data in the
884 * output buffer.
885 *
886 * If an error occurs, an error state is set in the @ref
887 * UsefulOutBuf. No error is returned. All subsequent attempts to add
888 * data will do nothing.
889 *
890 * The intended use is that all additions are made without checking
891 * for an error. The error will be taken into account when
892 * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
893 * UsefulOutBuf_GetError() can also be called to check for an error.
Michael Eckel5c531332020-03-02 01:35:30 +0100894 */
895void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
896 UsefulBufC NewData,
897 size_t uPos);
898
899
900/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700901 * @brief Insert a data buffer into the @ref UsefulOutBuf.
902 *
903 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
904 * @param[in] pBytes Pointer to the bytes to insert
905 * @param[in] uLen Length of the bytes to insert
906 * @param[in] uPos Index in output buffer at which to insert
907 *
908 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
909 * the difference being a pointer and length is passed in rather than an
910 * @ref UsefulBufC.
Michael Eckel5c531332020-03-02 01:35:30 +0100911 */
912static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
913 const void *pBytes,
914 size_t uLen,
915 size_t uPos);
916
917
918/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700919 * @brief Insert a NULL-terminated string into the UsefulOutBuf.
920 *
921 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
922 * @param[in] szString NULL-terminated string to insert.
923 * @param[in] uPos Index in output buffer at which to insert.
Michael Eckel5c531332020-03-02 01:35:30 +0100924 */
925static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
926 const char *szString,
927 size_t uPos);
928
929
930/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700931 * @brief Insert a byte into the @ref UsefulOutBuf.
932 *
933 * @param[in] pUOutBuf Pointer to the UsefulOutBuf.
934 * @param[in] byte Bytes to insert.
935 * @param[in] uPos Index in output buffer at which to insert.
936 *
937 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
938 * with the difference being a single byte is to be inserted.
Michael Eckel5c531332020-03-02 01:35:30 +0100939 */
940static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
941 uint8_t byte,
942 size_t uPos);
943
944
945/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700946 * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
947 *
948 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
949 * @param[in] uInteger16 Integer to insert.
950 * @param[in] uPos Index in output buffer at which to insert.
951 *
952 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
953 * with the difference being a two-byte integer is to be inserted.
954 *
955 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +0100956 */
957static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
958 uint16_t uInteger16,
959 size_t uPos);
960
961
962/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700963 * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
964 *
965 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
966 * @param[in] uInteger32 Integer to insert.
967 * @param[in] uPos Index in output buffer at which to insert.
968 *
969 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
970 * with the difference being a four-byte integer is to be inserted.
971 *
972 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +0100973 */
974static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
975 uint32_t uInteger32,
976 size_t uPos);
977
978
979/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700980 * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
981 *
982 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
983 * @param[in] uInteger64 Integer to insert.
984 * @param[in] uPos Index in output buffer at which to insert.
985 *
986 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
987 * with the difference being an eight-byte integer is to be inserted.
988 *
989 * The integer will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +0100990 */
991static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
992 uint64_t uInteger64,
993 size_t uPos);
994
995
996/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -0700997 * @brief Insert a @c float into the @ref UsefulOutBuf.
998 *
999 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1000 * @param[in] f @c float to insert.
1001 * @param[in] uPos Index in output buffer at which to insert.
1002 *
1003 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1004 * with the difference being a @c float is to be inserted.
1005 *
1006 * The @c float will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001007 */
1008static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
1009 float f,
1010 size_t uPos);
1011
1012
1013/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001014 * @brief Insert a @c double into the @ref UsefulOutBuf.
1015 *
1016 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1017 * @param[in] d @c double to insert.
1018 * @param[in] uPos Index in output buffer at which to insert.
1019 *
1020 * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
1021 * with the difference being a @c double is to be inserted.
1022 *
1023 * The @c double will be inserted in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001024 */
1025static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
1026 double d,
1027 size_t uPos);
1028
1029
1030/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001031 * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
1032 *
1033 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1034 * @param[in] NewData The @ref UsefulBuf with the bytes to append.
1035 *
1036 * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1037 * with the insertion point at the end of the valid data.
1038 */
Michael Eckel5c531332020-03-02 01:35:30 +01001039static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1040 UsefulBufC NewData);
1041
1042
1043/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001044 * @brief Append bytes to the @ref UsefulOutBuf.
1045 *
1046 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1047 * @param[in] pBytes Pointer to bytes to append.
1048 * @param[in] uLen Length of @c pBytes to append.
1049 *
1050 * See UsefulOutBuf_InsertData() for details. This does the same with
1051 * the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001052 */
1053static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1054 const void *pBytes,
1055 size_t uLen);
1056
1057
1058/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001059 * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1060 *
1061 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1062 * @param[in] szString NULL-terminated string to append.
Michael Eckel5c531332020-03-02 01:35:30 +01001063 */
1064static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1065 const char *szString);
1066
1067
1068/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001069 * @brief Append a byte to the @ref UsefulOutBuf
1070 *
1071 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1072 * @param[in] byte Bytes to append.
1073 *
1074 * See UsefulOutBuf_InsertByte() for details. This does the same
1075 * with the insertion point at the end of the valid data.
Michael Eckel5c531332020-03-02 01:35:30 +01001076 */
1077static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1078 uint8_t byte);
1079
1080
1081/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001082 * @brief Append an integer to the @ref UsefulOutBuf
1083 *
1084 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1085 * @param[in] uInteger16 Integer to append.
1086 *
1087 * See UsefulOutBuf_InsertUint16() for details. This does the same
1088 * with the insertion point at the end of the valid data.
1089 *
1090 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001091 */
1092static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1093 uint16_t uInteger16);
1094
1095
1096/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001097 * @brief Append an integer to the @ref UsefulOutBuf
1098 *
1099 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1100 * @param[in] uInteger32 Integer to append.
1101 *
1102 * See UsefulOutBuf_InsertUint32() for details. This does the same
1103 * with the insertion point at the end of the valid data.
1104 *
1105 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001106 */
1107static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1108 uint32_t uInteger32);
1109
1110
1111/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001112 * @brief Append an integer to the @ref UsefulOutBuf
1113 *
1114 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1115 * @param[in] uInteger64 Integer to append.
1116 *
1117 * See UsefulOutBuf_InsertUint64() for details. This does the same
1118 * with the insertion point at the end of the valid data.
1119 *
1120 * The integer will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001121 */
1122static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1123 uint64_t uInteger64);
1124
1125
1126/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001127 * @brief Append a @c float to the @ref UsefulOutBuf
1128 *
1129 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1130 * @param[in] f @c float to append.
1131 *
1132 * See UsefulOutBuf_InsertFloat() for details. This does the same with
1133 * the insertion point at the end of the valid data.
1134 *
1135 * The float will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001136 */
1137static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1138 float f);
1139
1140
1141/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001142 * @brief Append a @c double to the @ref UsefulOutBuf
1143 *
1144 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1145 * @param[in] d @c double to append.
1146 *
1147 * See UsefulOutBuf_InsertDouble() for details. This does the same
1148 * with the insertion point at the end of the valid data.
1149 *
1150 * The double will be appended in network byte order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001151 */
1152static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1153 double d);
1154
1155
1156/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001157 * @brief Returns the current error status.
1158 *
1159 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1160 *
1161 * @return 0 if all OK, 1 on error.
1162 *
1163 * This returns the error status since a call to either
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001164 * UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once a @ref UsefulOutBuf
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07001165 * goes into the error state, it will stay until one of those
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001166 * functions is called.
1167 *
1168 * Possible error conditions are:
1169 * - bytes to be inserted will not fit
1170 * - insertion point is out of buffer or past valid data
1171 * - current position is off end of buffer (probably corrupted or uninitialized)
1172 * - detect corruption / uninitialized by bad magic number
Michael Eckel5c531332020-03-02 01:35:30 +01001173 */
1174static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1175
1176
1177/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001178 * @brief Returns number of bytes unused used in the output buffer.
1179 *
1180 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1181 *
1182 * @return Number of unused bytes or zero.
1183 *
1184 * Because of the error handling strategy and checks in
1185 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1186 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001187 */
1188static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1189
1190
1191/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001192 *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1193 *
1194 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1195 * @param[in] uLen Number of bytes for which to check
1196 *
1197 * @return 1 if @c uLen bytes will fit, 0 if not.
1198 *
1199 * Because of the error handling strategy and checks in
1200 * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1201 * this.
Michael Eckel5c531332020-03-02 01:35:30 +01001202 */
1203static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1204
1205
1206 /**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001207 * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1208 *
1209 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1210 *
1211 * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1212 *
1213 * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
1214 * just calculating the length of the encoded data.
1215 */
Michael Eckel5c531332020-03-02 01:35:30 +01001216static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1217
1218
1219/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001220 * @brief Returns the resulting valid data in a UsefulOutBuf
1221 *
1222 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1223 *
1224 * @return The valid data in @ref UsefulOutBuf or
1225 * @ref NULLUsefulBufC if there was an error adding data.
1226 *
1227 * The storage for the returned data is the @c Storage parameter
1228 * passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1229 *
1230 * This can be called anytime and many times to get intermediate
1231 * results. It doesn't change the data or reset the current position,
1232 * so further data can be added.
Michael Eckel5c531332020-03-02 01:35:30 +01001233 */
1234UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1235
1236
1237/**
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001238 * @brief Copies the valid data into a supplied buffer
1239 *
1240 * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1241 * @param[out] Dest The destination buffer to copy into.
1242 *
1243 * @return Pointer and length of copied data or @c NULLUsefulBufC
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001244 * if it will not fit in the @c Dest buffer or the error
1245 * state was entered.
Laurence Lundbladebeed3f52021-05-07 12:36:28 -07001246 *
1247 * This is the same as UsefulOutBuf_OutUBuf() except it copies the
1248 * data to @c Dest.
1249 */
Michael Eckel5c531332020-03-02 01:35:30 +01001250UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1251
1252
1253
1254
1255/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001256 * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001257 * for parsing data received. Initialize it with the data from the
1258 * network. Then use the functions like UsefulInputBuf_GetBytes() to
1259 * get data chunks of various types. A position cursor is maintained
1260 * internally.
Laurence Lundblade9005b992021-05-07 18:10:07 -07001261 *
Laurence Lundblade419a1952021-05-10 03:44:49 -07001262 * As long as the functions here are used, there will never be any
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001263 * reference off the end of the given buffer (except
1264 * UsefulInputBuf_SetBufferLength()). This is true even if they are
1265 * called incorrectly, an attempt is made to seek off the end of the
1266 * buffer or such. This makes it easier to write safe and correct
1267 * code. For example, the QCBOR decoder implementation is safer and
1268 * easier to review through its use of @ref UsefulInputBuf.
Laurence Lundblade9005b992021-05-07 18:10:07 -07001269 *
1270 * @ref UsefulInputBuf maintains an internal error state. The
Laurence Lundblade419a1952021-05-10 03:44:49 -07001271 * intended use is fetching data chunks without any error checks until
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001272 * the end. If there was any error, such as an attempt to fetch data
1273 * off the end, the error state is entered and no further data will be
1274 * returned. In the error state the @c UsefulInputBuf_GetXxxx()
1275 * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
1276 * null is not dereferenced, the error check can be put off until the
1277 * end, simplifying the calling code.
Laurence Lundblade9005b992021-05-07 18:10:07 -07001278 *
1279 * The integer and float parsing expects network byte order (big
1280 * endian). Network byte order is what is used by TCP/IP, CBOR and
1281 * most internet protocols.
1282 *
1283 * Lots of inline functions are used to keep code size down. The
1284 * optimizer, particularly with the @c -Os or @c -O3, also reduces
1285 * code size a lot. The only non-inline code is
1286 * UsefulInputBuf_GetBytes(). It is less than 100 bytes so use of
1287 * @ref UsefulInputBuf doesn't add much code for all the messy
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001288 * hard-to-get right issues with parsing binary protocols in C that it
1289 * solves.
Laurence Lundblade9005b992021-05-07 18:10:07 -07001290 *
1291 * The parse context size is:
Laurence Lundblade419a1952021-05-10 03:44:49 -07001292 * - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
1293 * - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
Michael Eckel5c531332020-03-02 01:35:30 +01001294 */
1295typedef struct useful_input_buf {
Laurence Lundblade9005b992021-05-07 18:10:07 -07001296 /* PRIVATE DATA STRUCTURE */
1297 UsefulBufC UB; /* Data being parsed */
1298 size_t cursor; /* Current offset in data being parse */
1299 uint16_t magic; /* Check for corrupted or uninitialized UsefulInputBuf */
1300 uint8_t err; /* Set request goes off end or magic number is bad */
Michael Eckel5c531332020-03-02 01:35:30 +01001301} UsefulInputBuf;
1302
1303#define UIB_MAGIC (0xB00F)
1304
1305
1306/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001307 * @brief Initialize the @ref UsefulInputBuf structure before use.
1308 *
1309 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1310 * @param[in] UB The data to parse.
Michael Eckel5c531332020-03-02 01:35:30 +01001311 */
1312static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1313
1314
1315/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001316 * @brief Returns current position in input buffer.
1317 *
1318 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1319 *
1320 * @return Integer position of the cursor.
1321 *
1322 * The position that the next bytes will be returned from.
Michael Eckel5c531332020-03-02 01:35:30 +01001323 */
1324static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1325
1326
1327/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001328 * @brief Sets the current position in input buffer.
1329 *
1330 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1331 * @param[in] uPos Position to set to.
1332 *
1333 * If the position is off the end of the input buffer, the error state
1334 * is entered.
1335 *
1336 * Seeking to a valid position in the buffer will not reset the error
1337 * state. Only re-initialization will do that.
Michael Eckel5c531332020-03-02 01:35:30 +01001338 */
1339static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1340
1341
1342/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001343 * @brief Returns the number of bytes from the cursor to the end of the buffer,
1344 * the unconsumed bytes.
1345 *
1346 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1347 *
1348 * @return Number of bytes unconsumed or 0 on error.
1349 *
1350 * Returns 0 if the cursor is invalid or corruption of the
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001351 * @ref UsefulInputBuf structure is detected.
Michael Eckel5c531332020-03-02 01:35:30 +01001352 */
1353static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1354
1355
1356/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001357 * @brief Check if there are unconsumed bytes.
1358 *
1359 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1360 * @param[in] uLen Number of bytes to check availability for.
1361 *
1362 * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Michael Eckel5c531332020-03-02 01:35:30 +01001363 */
1364static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1365
1366
1367/**
Laurence Lundblade3d0d7cb2021-05-10 21:13:11 -07001368 * @brief Convert a pointer to an offset with bounds checking.
1369 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001370 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
Laurence Lundblade3d0d7cb2021-05-10 21:13:11 -07001371 * @param[in] p Pointer to convert to offset.
1372 *
1373 * @return SIZE_MAX if @c p is out of range, the byte offset if not.
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001374 */
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001375static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
1376
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001377
Michael Eckel5c531332020-03-02 01:35:30 +01001378/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001379 * @brief Get pointer to bytes out of the input buffer.
1380 *
1381 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1382 * @param[in] uNum Number of bytes to get.
1383 *
1384 * @return Pointer to bytes.
1385 *
1386 * This consumes @c uNum bytes from the input buffer. This returns a
1387 * pointer to the start of the @c uNum bytes.
1388 *
1389 * If there are not @c uNum bytes in the input buffer, @c NULL will be
1390 * returned and the error state is entered.
1391 *
1392 * This advances the position cursor by @c uNum bytes.
Michael Eckel5c531332020-03-02 01:35:30 +01001393 */
1394const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1395
1396
1397/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001398 * @brief Get @ref UsefulBuf out of the input buffer.
1399 *
1400 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1401 * @param[in] uNum Number of bytes to get.
1402 *
1403 * @return A @ref UsefulBufC with ptr and length of bytes consumed.
1404 *
1405 * This consumes @c uNum bytes from the input buffer and returns the
1406 * pointer and length for them as a @ref UsefulBufC. The length
1407 * returned will always be @c uNum. The position cursor is advanced by
1408 * @c uNum bytes.
1409 *
1410 * If there are not @c uNum bytes in the input buffer, @ref
1411 * NULLUsefulBufC will be returned and the error state is entered.
Michael Eckel5c531332020-03-02 01:35:30 +01001412 */
1413static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1414
1415
1416/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001417 * @brief Get a byte out of the input buffer.
1418 *
1419 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1420 *
1421 * @return The byte.
1422 *
1423 * This consumes 1 byte from the input buffer, returns it and advances
1424 * the position cursor by 1.
1425 *
1426 * If there is not 1 byte in the buffer, 0 will be returned for the
1427 * byte and the error state is entered. To know if the 0 returned was
1428 * in error or the real value, the error state must be checked. If
1429 * possible, put this off until all values are retrieved to have
1430 * smaller and simpler code, but if not possible
1431 * UsefulInputBuf_GetError() can be called. Also, in the error state
1432 * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
1433 * UsefulInputBuf_GetUsefulBuf() is @c NULL.
Michael Eckel5c531332020-03-02 01:35:30 +01001434 */
1435static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1436
1437
1438/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001439 * @brief Get a @c uint16_t out of the input buffer.
1440 *
1441 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1442 *
1443 * @return The @c uint16_t.
1444 *
1445 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1446 * a @c uint16_t and two bytes are consumed.
1447 *
1448 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001449 */
1450static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1451
1452
1453/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001454 * @brief Get a @c uint32_t out of the input buffer.
1455 *
1456 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1457 *
1458 * @return The @c uint32_t.
1459 *
1460 * See UsefulInputBuf_GetByte(). This works the same, except it
1461 * returns a @c uint32_t and four bytes are consumed.
1462 *
1463 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001464 */
1465static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1466
1467
1468/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001469 * @brief Get a @c uint64_t out of the input buffer.
1470 *
1471 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1472 *
1473 * @return The uint64_t.
1474 *
1475 * See UsefulInputBuf_GetByte(). This works the same, except it returns
1476 * a @c uint64_t and eight bytes are consumed.
1477 *
1478 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001479 */
1480static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1481
1482
1483/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001484 * @brief Get a float out of the input buffer.
1485 *
1486 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1487 *
1488 * @return The float.
1489 *
1490 * See UsefulInputBuf_GetByte(). This works the same, except it
1491 * returns a float and four bytes are consumed.
1492 *
1493 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001494 */
1495static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1496
1497
1498/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001499 * @brief Get a double out of the input buffer.
1500 *
1501 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1502 *
1503 * @return The double.
1504 *
1505 * See UsefulInputBuf_GetByte(). This works the same, except it
1506 * returns a double and eight bytes are consumed.
1507 *
1508 * The input bytes are interpreted in network order (big endian).
Michael Eckel5c531332020-03-02 01:35:30 +01001509 */
1510static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1511
1512
1513/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001514 * @brief Get the error status.
1515 *
1516 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1517 *
1518 * @return 0 if not in the error state, 1 if in the error state.
1519 *
1520 * This returns whether the @ref UsefulInputBuf is in the
1521 * error state or not.
1522 *
1523 * The error state is entered for one of these reasons:
1524 * - Attempt to fetch data past the end of the buffer
1525 * - Attempt to seek to a position past the end of the buffer
1526 * - Attempt to get data from an uninitialized or corrupt instance
1527 * of @ref UsefulInputBuf
1528 *
1529 * Once in the error state, it can only be cleared by calling
1530 * UsefulInputBuf_Init().
1531 *
1532 * For many use cases, it is possible to only call this once after all
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001533 * the @c UsefulInputBuf_GetXxxx() calls have been made. This is
Laurence Lundblade419a1952021-05-10 03:44:49 -07001534 * possible if no reference to the data returned are needed before the
1535 * error state is checked.
1536 *
1537 * In some cases UsefulInputBuf_GetUsefulBuf() or
1538 * UsefulInputBuf_GetBytes() can stand in for this because they return
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001539 * @c NULL if the error state has been entered. (The others can't stand
Laurence Lundblade419a1952021-05-10 03:44:49 -07001540 * in because they don't return a clearly distinct error value.)
Michael Eckel5c531332020-03-02 01:35:30 +01001541 */
1542static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1543
1544
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001545/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001546 * @brief Gets the input buffer length.
1547 *
1548 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1549 *
1550 * @return The length of the input buffer.
1551 *
1552 * This returns the length of the input buffer set by
1553 * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001554 */
1555static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
1556
1557
1558/**
Laurence Lundblade419a1952021-05-10 03:44:49 -07001559 * @brief Alters the input buffer length (use with caution).
1560 *
1561 * @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001562 * @param[in] uNewLen The new length of the input buffer.
Laurence Lundblade419a1952021-05-10 03:44:49 -07001563 *
1564 * This alters the internal remembered length of the input buffer set
1565 * when UsefulInputBuf_Init() was called.
1566 *
1567 * The new length given here should always be equal to or less than
1568 * the length given when UsefulInputBuf_Init() was called. Making it
1569 * larger allows @ref UsefulInputBuf to run off the input buffer.
1570 *
1571 * The typical use is to set a length shorter than that when
1572 * initialized to constrain parsing. If
1573 * UsefulInputBuf_GetBufferLength() was called before this, then the
1574 * original length can be restored with another call to this.
1575 *
Laurence Lundblade9a26de92021-05-10 22:29:55 -07001576 * This should be used with caution. It is the only
1577 * @ref UsefulInputBuf method that can violate the safety of input
1578 * buffer parsing.
Laurence Lundblade24d509a2020-06-06 18:43:15 -07001579 */
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07001580static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
Michael Eckel5c531332020-03-02 01:35:30 +01001581
1582
Laurence Lundblade419a1952021-05-10 03:44:49 -07001583
1584
Michael Eckel5c531332020-03-02 01:35:30 +01001585/*----------------------------------------------------------
1586 Inline implementations.
1587 */
1588static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1589{
1590 return !UB.ptr;
1591}
1592
1593
1594static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1595{
1596 return !UB.ptr;
1597}
1598
1599
1600static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1601{
1602 return !UB.len;
1603}
1604
1605
1606static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1607{
1608 return !UB.len;
1609}
1610
1611
1612static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1613{
1614 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1615}
1616
1617
1618static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1619{
1620 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1621}
1622
1623
1624static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1625{
1626 return (UsefulBufC){UB.ptr, UB.len};
1627}
1628
Michael Eckel5c531332020-03-02 01:35:30 +01001629static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1630{
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001631 /* -Wcast-qual is a good warning flag to use in general. This is
1632 * the one place in UsefulBuf where it needs to be quieted. Since
1633 * clang supports GCC pragmas, this works for clang too. */
1634#pragma GCC diagnostic push
1635#pragma GCC diagnostic ignored "-Wcast-qual"
Michael Eckel5c531332020-03-02 01:35:30 +01001636 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001637#pragma GCC diagnostic pop
Michael Eckel5c531332020-03-02 01:35:30 +01001638}
1639
1640
1641static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1642{
1643 return ((UsefulBufC) {szString, strlen(szString)});
1644}
1645
1646
1647static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1648{
1649 return UsefulBuf_CopyOffset(Dest, 0, Src);
1650}
1651
1652
1653static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
1654{
1655 memset(pDest.ptr, value, pDest.len);
1656 return (UsefulBufC){pDest.ptr, pDest.len};
1657}
1658
1659
1660static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
1661{
1662 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
1663}
1664
1665
1666static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1667{
1668 if(uAmount > UB.len) {
1669 return NULLUsefulBufC;
1670 }
1671 return (UsefulBufC){UB.ptr, uAmount};
1672}
1673
1674
1675static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1676{
1677 UsefulBufC ReturnValue;
1678
1679 if(uAmount > UB.len) {
1680 ReturnValue = NULLUsefulBufC;
1681 } else if(UB.ptr == NULL) {
1682 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
1683 } else {
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001684 ReturnValue = (UsefulBufC){(const uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
Michael Eckel5c531332020-03-02 01:35:30 +01001685 }
1686
1687 return ReturnValue;
1688}
1689
1690
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001691static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
1692{
1693 if(UB.ptr == NULL) {
1694 return SIZE_MAX;
1695 }
1696
1697 if(p < UB.ptr) {
1698 /* given pointer is before start of buffer */
1699 return SIZE_MAX;
1700 }
1701
1702 // Cast to size_t (from ptrdiff_t) is OK because of check above
Laurence Lundbladeb9702452021-03-08 21:02:57 -08001703 const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
Laurence Lundbladecf41c522021-02-20 10:19:07 -07001704
1705 if(uOffset >= UB.len) {
1706 /* given pointer is off the end of the buffer */
1707 return SIZE_MAX;
1708 }
1709
1710 return uOffset;
1711}
1712
Michael Eckel5c531332020-03-02 01:35:30 +01001713
1714static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1715{
1716 uint32_t u32;
1717 memcpy(&u32, &f, sizeof(uint32_t));
1718 return u32;
1719}
1720
1721static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1722{
1723 uint64_t u64;
1724 memcpy(&u64, &d, sizeof(uint64_t));
1725 return u64;
1726}
1727
1728static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1729{
1730 double d;
1731 memcpy(&d, &u64, sizeof(uint64_t));
1732 return d;
1733}
1734
1735static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1736{
1737 float f;
1738 memcpy(&f, &u32, sizeof(uint32_t));
1739 return f;
1740}
1741
1742
1743
1744
1745static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
1746{
1747 pMe->data_len = 0;
1748 pMe->err = 0;
1749}
1750
1751
1752static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
1753{
1754 return pMe->data_len;
1755}
1756
1757
1758static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
1759{
1760 return 0 == pMe->data_len;
1761}
1762
1763
1764static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1765 const void *pBytes,
1766 size_t uLen,
1767 size_t uPos)
1768{
1769 UsefulBufC Data = {pBytes, uLen};
1770 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
1771}
1772
1773
1774static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1775 const char *szString,
1776 size_t uPos)
1777{
1778 UsefulOutBuf_InsertUsefulBuf(pMe,
1779 (UsefulBufC){szString, strlen(szString)},
1780 uPos);
1781}
1782
1783
1784static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1785 uint8_t byte,
1786 size_t uPos)
1787{
1788 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1789}
1790
1791
1792static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1793 uint16_t uInteger16,
1794 size_t uPos)
1795{
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07001796 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001797
1798 const void *pBytes;
1799
1800#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1801 pBytes = &uInteger16;
1802
1803#elif defined(USEFULBUF_CONFIG_HTON)
1804 uint16_t uTmp = htons(uInteger16);
1805 pBytes = &uTmp;
1806
1807#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1808 uint16_t uTmp = __builtin_bswap16(uInteger16);
1809 pBytes = &uTmp;
1810
1811#else
1812 uint8_t aTmp[2];
1813
1814 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1815 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
1816
1817 pBytes = aTmp;
1818#endif
1819
1820 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
1821}
1822
1823
1824static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1825 uint32_t uInteger32,
1826 size_t uPos)
1827{
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001828 /* See UsefulOutBuf_InsertUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01001829
1830 const void *pBytes;
1831
1832#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1833 pBytes = &uInteger32;
1834
1835#elif defined(USEFULBUF_CONFIG_HTON)
1836 uint32_t uTmp = htonl(uInteger32);
1837 pBytes = &uTmp;
1838
1839#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1840 uint32_t uTmp = __builtin_bswap32(uInteger32);
1841
1842 pBytes = &uTmp;
1843
1844#else
1845 uint8_t aTmp[4];
1846
1847 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1848 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1849 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1850 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
1851
1852 pBytes = aTmp;
1853#endif
1854
1855 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1856}
1857
1858static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001859 uint64_t uInteger64,
1860 size_t uPos)
Michael Eckel5c531332020-03-02 01:35:30 +01001861{
1862 const void *pBytes;
1863
1864#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001865 /* We have been told explicitly we are running on a big-endian
1866 * machine. Network byte order is big endian, so just copy. There
1867 * is no issue with alignment here because uInteger64 is always
1868 * aligned (and it doesn't matter if pBytes is aligned).
1869 */
Michael Eckel5c531332020-03-02 01:35:30 +01001870 pBytes = &uInteger64;
1871
1872#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001873 /* Use system function to handle big- and little-endian. This works
1874 * on both big- and little-endian machines, but hton() is not
1875 * always available or in a standard place so it is not used by
1876 * default. With some compilers and CPUs the code for this is very
1877 * compact through use of a special swap instruction and on
1878 * big-endian machines hton() will reduce to nothing.
1879 */
Michael Eckel5c531332020-03-02 01:35:30 +01001880 uint64_t uTmp = htonll(uInteger64);
1881
1882 pBytes = &uTmp;
1883
1884#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001885 /* Use built-in function for byte swapping. This usually compiles
1886 * to an efficient special byte swap instruction. Unlike hton() it
1887 * does not do this conditionally on the CPU endianness, so this
1888 * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1889 */
Michael Eckel5c531332020-03-02 01:35:30 +01001890 uint64_t uTmp = __builtin_bswap64(uInteger64);
1891
1892 pBytes = &uTmp;
1893
1894#else
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001895 /* Default which works on every CPU with no dependency on anything
1896 * from the CPU, compiler, libraries or OS. This always works, but
1897 * it is usually a little larger and slower than hton().
1898 */
Michael Eckel5c531332020-03-02 01:35:30 +01001899 uint8_t aTmp[8];
1900
1901 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1902 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1903 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1904 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1905 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1906 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1907 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1908 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
1909
1910 pBytes = aTmp;
1911#endif
1912
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001913 /* Do the insert */
Michael Eckel5c531332020-03-02 01:35:30 +01001914 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
1915}
1916
1917
1918static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1919 float f,
1920 size_t uPos)
1921{
1922 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
1923}
1924
1925
1926static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1927 double d,
1928 size_t uPos)
1929{
1930 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
1931}
1932
1933
1934static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
1935 UsefulBufC NewData)
1936{
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07001937 /* An append is just a insert at the end */
Michael Eckel5c531332020-03-02 01:35:30 +01001938 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
1939}
1940
1941
1942static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
1943 const void *pBytes,
1944 size_t uLen)
1945{
1946 UsefulBufC Data = {pBytes, uLen};
1947 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
1948}
1949
1950
1951static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
1952 const char *szString)
1953{
1954 UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
1955}
1956
1957
1958static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
1959 uint8_t byte)
1960{
1961 UsefulOutBuf_AppendData(pMe, &byte, 1);
1962}
1963
1964
1965static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
1966 uint16_t uInteger16)
1967{
1968 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
1969}
1970
1971static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
1972 uint32_t uInteger32)
1973{
1974 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
1975}
1976
1977
1978static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
1979 uint64_t uInteger64)
1980{
1981 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
1982}
1983
1984
1985static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
1986 float f)
1987{
1988 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
1989}
1990
1991
1992static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
1993 double d)
1994{
1995 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
1996}
1997
1998
1999static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
2000{
2001 return pMe->err;
2002}
2003
2004
2005static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
2006{
2007 return pMe->UB.len - pMe->data_len;
2008}
2009
2010
2011static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
2012{
2013 return uLen <= UsefulOutBuf_RoomLeft(pMe);
2014}
2015
2016
2017static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
2018{
2019 return pMe->UB.ptr == NULL;
2020}
2021
2022
2023
2024static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
2025{
2026 pMe->cursor = 0;
2027 pMe->err = 0;
2028 pMe->magic = UIB_MAGIC;
2029 pMe->UB = UB;
2030}
2031
2032static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
2033{
2034 return pMe->cursor;
2035}
2036
2037
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002038static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
Laurence Lundblade0750fc42020-06-20 21:02:34 -07002039{
2040 return pMe->UB.len;
2041}
2042
2043
Michael Eckel5c531332020-03-02 01:35:30 +01002044static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
2045{
2046 if(uPos > pMe->UB.len) {
2047 pMe->err = 1;
2048 } else {
2049 pMe->cursor = uPos;
2050 }
2051}
2052
2053
2054static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
2055{
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002056 /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
Michael Eckel5c531332020-03-02 01:35:30 +01002057
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002058 /* Magic number is messed up. Either the structure got overwritten
2059 * or was never initialized.
2060 */
Michael Eckel5c531332020-03-02 01:35:30 +01002061 if(pMe->magic != UIB_MAGIC) {
2062 return 0;
2063 }
2064
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002065 /* The cursor is off the end of the input buffer given.
2066 * Presuming there are no bugs in this code, this should never happen.
2067 * If it so, the struct was corrupted. The check is retained as
2068 * as a defense in case there is a bug in this code or the struct is
2069 * corrupted.
2070 */
Michael Eckel5c531332020-03-02 01:35:30 +01002071 if(pMe->cursor > pMe->UB.len) {
2072 return 0;
2073 }
2074
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002075 /* subtraction can't go negative because of check above */
Michael Eckel5c531332020-03-02 01:35:30 +01002076 return pMe->UB.len - pMe->cursor;
2077}
2078
2079
2080static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
2081{
2082 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
2083}
2084
2085
Laurence Lundbladecf41c522021-02-20 10:19:07 -07002086static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
2087{
2088 return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
2089}
2090
2091
Michael Eckel5c531332020-03-02 01:35:30 +01002092static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
2093{
2094 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
2095 if(!pResult) {
2096 return NULLUsefulBufC;
2097 } else {
2098 return (UsefulBufC){pResult, uNum};
2099 }
2100}
2101
2102
2103static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
2104{
2105 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
2106
Laurence Lundblade0cc6c6b2021-05-07 01:42:06 -07002107 /* The ternary operator is subject to integer promotion, because
2108 * the operands are smaller than int, so cast back to uint8_t is
2109 * needed to be completely explicit about types (for static
2110 * analyzers).
2111 */
Laurence Lundbladeb9702452021-03-08 21:02:57 -08002112 return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
Michael Eckel5c531332020-03-02 01:35:30 +01002113}
2114
2115static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
2116{
2117 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
2118
2119 if(!pResult) {
2120 return 0;
2121 }
2122
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002123 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002124#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2125 uint16_t uTmp;
2126 memcpy(&uTmp, pResult, sizeof(uint16_t));
2127
2128#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2129 return uTmp;
2130
2131#elif defined(USEFULBUF_CONFIG_HTON)
2132 return ntohs(uTmp);
2133
2134#else
2135 return __builtin_bswap16(uTmp);
2136
2137#endif
2138
2139#else
2140
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002141 /* The operations here are subject to integer promotion because the
2142 * operands are smaller than int. They will be promoted to unsigned
2143 * int for the shift and addition. The cast back to uint16_t is is
2144 * needed to be completely explicit about types (for static
2145 * analyzers).
2146 */
Michael Eckel5c531332020-03-02 01:35:30 +01002147 return (uint16_t)((pResult[0] << 8) + pResult[1]);
2148
2149#endif
2150}
2151
2152
2153static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
2154{
2155 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
2156
2157 if(!pResult) {
2158 return 0;
2159 }
2160
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002161 /* See UsefulInputBuf_GetUint64() for comments on this code */
Michael Eckel5c531332020-03-02 01:35:30 +01002162#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2163 uint32_t uTmp;
2164 memcpy(&uTmp, pResult, sizeof(uint32_t));
2165
2166#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2167 return uTmp;
2168
2169#elif defined(USEFULBUF_CONFIG_HTON)
2170 return ntohl(uTmp);
2171
2172#else
2173 return __builtin_bswap32(uTmp);
2174
2175#endif
2176
2177#else
2178 return ((uint32_t)pResult[0]<<24) +
2179 ((uint32_t)pResult[1]<<16) +
2180 ((uint32_t)pResult[2]<<8) +
2181 (uint32_t)pResult[3];
2182#endif
2183}
2184
2185
2186static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
2187{
2188 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
2189
2190 if(!pResult) {
2191 return 0;
2192 }
2193
2194#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002195 /* pResult will probably not be aligned. This memcpy() moves the
2196 * bytes into a temp variable safely for CPUs that can or can't do
2197 * unaligned memory access. Many compilers will optimize the
2198 * memcpy() into a simple move instruction.
2199 */
Michael Eckel5c531332020-03-02 01:35:30 +01002200 uint64_t uTmp;
2201 memcpy(&uTmp, pResult, sizeof(uint64_t));
2202
2203#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002204 /* We have been told expliclity this is a big-endian CPU. Since
2205 * network byte order is big-endian, there is nothing to do.
2206 */
Michael Eckel5c531332020-03-02 01:35:30 +01002207
2208 return uTmp;
2209
2210#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002211 /* We have been told to use ntoh(), the system function to handle
2212 * big- and little-endian. This works on both big- and
2213 * little-endian machines, but ntoh() is not always available or in
2214 * a standard place so it is not used by default. On some CPUs the
2215 * code for this is very compact through use of a special swap
2216 * instruction.
2217 */
Michael Eckel5c531332020-03-02 01:35:30 +01002218
2219 return ntohll(uTmp);
2220
2221#else
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002222 /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2223 * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2224 * __builtin_bswap64() and friends are not conditional on CPU
2225 * endianness so this must only be used on little-endian machines.
2226 */
Michael Eckel5c531332020-03-02 01:35:30 +01002227
2228 return __builtin_bswap64(uTmp);
2229
2230
2231#endif
2232
2233#else
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002234 /* This is the default code that works on every CPU and every
2235 * endianness with no dependency on ntoh(). This works on CPUs
2236 * that either allow or do not allow unaligned access. It will
2237 * always work, but usually is a little less efficient than ntoh().
2238 */
Michael Eckel5c531332020-03-02 01:35:30 +01002239
2240 return ((uint64_t)pResult[0]<<56) +
2241 ((uint64_t)pResult[1]<<48) +
2242 ((uint64_t)pResult[2]<<40) +
2243 ((uint64_t)pResult[3]<<32) +
2244 ((uint64_t)pResult[4]<<24) +
2245 ((uint64_t)pResult[5]<<16) +
2246 ((uint64_t)pResult[6]<<8) +
2247 (uint64_t)pResult[7];
2248#endif
2249}
2250
2251
2252static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
2253{
2254 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
2255
2256 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2257}
2258
2259
2260static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
2261{
2262 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
2263
2264 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2265}
2266
2267
2268static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
2269{
2270 return pMe->err;
2271}
2272
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002273
Laurence Lundblade1ba100d2020-09-19 21:41:02 -07002274static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
Laurence Lundblade24d509a2020-06-06 18:43:15 -07002275{
2276 pMe->UB.len = uNewLen;
2277}
2278
2279
Michael Eckel5c531332020-03-02 01:35:30 +01002280#ifdef __cplusplus
2281}
2282#endif
2283
Laurence Lundbladeb7d0d572021-05-10 17:43:53 -07002284#endif /* _UsefulBuf_h */
Michael Eckel5c531332020-03-02 01:35:30 +01002285
2286