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