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