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