blob: 0aaa9b66f9bcb7c97a3d9928aca0c236a6366837 [file] [log] [blame]
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001/*==============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018-2019, Laurence Lundblade.
4 All rights reserved.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ==============================================================================*/
32
33/*===================================================================================
34 FILE: UsefulBuf.h
35
36 DESCRIPTION: General purpose input and output buffers
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- ---------------------------------------------------
45 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
46 12/13/2018 llundblade Documentation improvements
47 09/18/2018 llundblade Cleaner distinction between UsefulBuf and UsefulBufC
48 02/02/18 llundbla Full support for integers in and out; fix pointer
49 alignment bug. Incompatible change: integers in/out
50 are now in network byte order.
51 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
52 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
53 for < or > for unequal length buffers. Added
54 UsefulBuf_Set() function.
55 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
56 11/13/16 llundbla Initial Version.
57
58
59 =====================================================================================*/
60
61#ifndef _UsefulBuf_h
62#define _UsefulBuf_h
63
64
65#include <stdint.h> // for uint8_t, uint16_t....
66#include <string.h> // for strlen, memcpy, memmove, memset
67#include <stddef.h> // for size_t
68
Laurence Lundbladed425fb32019-02-18 10:56:18 -080069#ifdef __cplusplus
70extern "C" {
71#endif
72
Laurence Lundblade6ed34222018-12-18 09:46:23 -080073/**
74 @file UsefulBuf.h
75
76 The goal of this code is to make buffer and pointer manipulation
77 easier and safer when working with binary data.
78
79 You use the UsefulBuf, UsefulOutBuf and UsefulInputBuf
80 structures to represent buffers rather than ad hoc pointers and lengths.
81
82 With these it will often be possible to write code that does little or no
83 direct pointer manipulation for copying and formatting data. For example
84 the QCBOR encoder was rewritten using these and has no direct pointer
85 manipulation.
86
87 While it is true that object code using these functions will be a little
88 larger and slower than a white-knuckle clever use of pointers might be, but
89 not by that much or enough to have an affect for most use cases. For
90 security-oriented code this is highly worthwhile. Clarity, simplicity,
91 reviewability and are more important.
92
93 There are some extra sanity and double checks in this code to help catch
94 coding errors and simple memory corruption. They are helpful, but not a
95 substitute for proper code review, input validation and such.
96
97 This code consists of a lot of inline functions and a few that are not.
98 It should not generate very much object code, especially with the
99 optimizer turned up to -Os or -O3. The idea is that the inline
100 functions are easier to review and understand and the optimizer does
101 the work of making the code small.
102 */
103
104
105/*...... This is a ruler that is 80 characters long...........................*/
106
107/**
108 UsefulBufC and UsefulBuf are simple data structures to hold a pointer and
109 length for a binary data. In C99 this data structure can be passed on the
110 stack making a lot of code cleaner than carrying around a pointer and
111 length as two parameters.
112
113 This is also conducive to secure code practice as the lengths are
114 always carried with the pointer and the convention for handling a
115 pointer and a length is clear.
116
117 While it might be possible to write buffer and pointer code more
118 efficiently in some use cases, the thought is that unless there is an
119 extreme need for performance (e.g., you are building a gigabit-per-second
120 IP router), it is probably better to have cleaner code you can be most
121 certain about the security of.
122
123 The non-const UsefulBuf is usually used to refer a buffer to be filled in.
124 The length is the size of the buffer.
125
126 The const UsefulBufC is usually used to refer to some data that has been
127 filled in. The length is amount of valid data pointed to.
128
129 A common use is to pass a UsefulBuf to a function, the function fills it
130 in, the function returns a UsefulBufC. The pointer is the same in both.
131
132 A UsefulBuf is NULL, it has no value, when the ptr in it is NULL.
133
134 There are utility functions for the following:
135 - Checking for UsefulBufs that are NULL, empty or both
136 - Copying, copying with offset, copying head or tail
137 - Comparing and finding substrings
138 - Initializating
139 - Create initialized const UsefulBufC from compiler literals
140 - Create initialized const UsefulBufC from NULL-terminated string
141 - Make an empty UsefulBuf on the stack
142
143 See also UsefulOutBuf. It is a richer structure that has both the size of
144 the valid data and the size of the buffer.
145
146 UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it can go
147 on the stack and be a function parameter or return value.
148
149 UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his birthday.
150 Eeyore's balloon fits beautifully, "it goes in and out like anything".
151
152*/
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800153typedef struct q_useful_buf_c {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800154 const void *ptr;
155 size_t len;
156} UsefulBufC;
157
158
159/**
160 The non-const UsefulBuf typically used for some allocated memory
161 that is to be filled in. The len is the amount of memory,
162 not the length of the valid data in the buffer.
163 */
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800164typedef struct q_useful_buf {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800165 void *ptr;
166 size_t len;
167} UsefulBuf;
168
169
170/**
171 A "NULL" UsefulBufC is one that has no value in the same way a NULL pointer has no value.
172 A UsefulBuf is NULL when the ptr field is NULL. It doesn't matter what len is.
173 See UsefulBuf_IsEmpty() for the distinction between NULL and empty.
174 */
175#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
176
177/** A NULL UsefulBuf is one that has no memory associated the say way
178 NULL points to nothing. It does not matter what len is.
179 */
180#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
181
182
183/**
184 @brief Check if a UsefulBuf is NULL or not
185
186 @param[in] UB The UsefulBuf to check
187
188 @return 1 if it is NULL, 0 if not.
189 */
190static inline int UsefulBuf_IsNULL(UsefulBuf UB) {
191 return !UB.ptr;
192}
193
194
195/**
196 @brief Check if a UsefulBufC is NULL or not
197
198 @param[in] UB The UsefulBufC to check
199
200 @return 1 if it is NULL, 0 if not.
201 */
202static inline int UsefulBuf_IsNULLC(UsefulBufC UB) {
203 return !UB.ptr;
204}
205
206
207/**
208 @brief Check if a UsefulBuf is empty or not
209
210 @param[in] UB The UsefulBuf to check
211
212 @return 1 if it is empty, 0 if not.
213
214 An "Empty" UsefulBuf is one that has a value and can be considered to be set,
215 but that value is of zero length. It is empty when len is zero. It
216 doesn't matter what the ptr is.
217
218 A lot of uses will not need to clearly distinguish a NULL UsefulBuf
219 from an empty one and can have the ptr NULL and the len 0. However
220 if a use of UsefulBuf needs to make a distinction then ptr should
221 not be NULL when the UsefulBuf is considered empty, but not NULL.
222
223 */
224static inline int UsefulBuf_IsEmpty(UsefulBuf UB) {
225 return !UB.len;
226}
227
228
229/**
230 @brief Check if a UsefulBufC is empty or not
231
232 @param[in] UB The UsefulBufC to check
233
234 @return 1 if it is empty, 0 if not.
235 */
236static inline int UsefulBuf_IsEmptyC(UsefulBufC UB) {
237 return !UB.len;
238}
239
240
241/**
242 @brief Check if a UsefulBuf is NULL or empty
243
244 @param[in] UB The UsefulBuf to check
245
246 @return 1 if it is either NULL or empty, 0 if not.
247 */
248static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB) {
249 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
250}
251
252
253/**
254 @brief Check if a UsefulBufC is NULL or empty
255
256 @param[in] UB The UsefulBufC to check
257
258 @return 1 if it is either NULL or empty, 0 if not.
259 */
260static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB) {
261 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
262}
263
264
265/**
266 @brief Convert a non const UsefulBuf to a const UsefulBufC
267
268 @param[in] UB The UsefulBuf to convert
269
270 Returns: a UsefulBufC struct
271 */
272
273static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
274{
275 return (UsefulBufC){UB.ptr, UB.len};
276}
277
278
279/**
280 @brief Convert a const UsefulBufC to a non-const UsefulBuf
281
282 @param[in] UBC The UsefulBuf to convert
283
284 Returns: a non const UsefulBuf struct
285 */
286static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
287{
288 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
289}
290
291
292/**
293 Convert a literal string to a UsefulBufC.
294
295 szString must be a literal string that you can take sizeof.
296 This is better for literal strings than UsefulBuf_FromSZ()
297 because it generates less code. It will not work on
298 non-literal strings.
299
300 The terminating \0 (NULL) is NOT included in the length!
301
302 */
303#define UsefulBuf_FROM_SZ_LITERAL(szString) \
304 ((UsefulBufC) {(szString), sizeof(szString)-1})
305
306
307/**
308 Convert a literal byte array to a UsefulBufC.
309
310 pBytes must be a literal string that you can take sizeof.
311 It will not work on non-literal arrays.
312
313 */
314#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
315 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
316
317
318/**
319 Make an automatic variable with name of type UsefulBuf and point it to a stack
320 variable of the give size
321 */
322#define UsefulBuf_MAKE_STACK_UB(name, size) \
323 uint8_t __pBuf##name[(size)];\
324 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
325
326
327/**
328 Make a byte array in to a UsefulBuf
329 */
330#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
331 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
332
333/**
334 @brief Convert a NULL terminated string to a UsefulBufC.
335
336 @param[in] szString The string to convert
337
338 @return a UsefulBufC struct
339
340 UsefulBufC.ptr points to the string so it's lifetime
341 must be maintained.
342
343 The terminating \0 (NULL) is NOT included in the length!
344
345 */
346static inline UsefulBufC UsefulBuf_FromSZ(const char *szString){
347 return ((UsefulBufC) {szString, strlen(szString)});
348}
349
350
351/**
352 @brief Copy one UsefulBuf into another at an offset
353
354 @param[in] Dest Destiation buffer to copy into
355 @param[in] uOffset The byte offset in Dest at which to copy to
356 @param[in] Src The bytes to copy
357
358 @return Pointer and length of the copy
359
360 This fails and returns NULLUsefulBufC Src.len + uOffset > Dest.len.
361
362 Like memcpy, there is no check for NULL. If NULL is passed
363 this will crash.
364
365 There is an assumption that there is valid data in Dest up to
366 uOffset as the resulting UsefulBufC returned starts
367 at the beginning of Dest and goes to Src.len + uOffset.
368
369 */
370UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
371
372
373/**
374 @brief Copy one UsefulBuf into another
375
376 @param[in] Dest The destination buffer to copy into
377 @param[out] Src The source to copy from
378
379 @return filled in UsefulBufC on success, NULLUsefulBufC on failure
380
381 This fails if Src.len is greater than Dest.len.
382
383 Note that like memcpy, the pointers are not checked and
384 this will crash, rather than return NULLUsefulBufC if
385 they are NULL or invalid.
386
387 Results are undefined if Dest and Src overlap.
388
389 */
390static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src) {
391 return UsefulBuf_CopyOffset(Dest, 0, Src);
392}
393
394
395/**
396 @brief Set all bytes in a UsefulBuf to a value, for example 0
397
398 @param[in] pDest The destination buffer to copy into
399 @param[in] value The value to set the bytes to
400
401 Note that like memset, the pointer in pDest is not checked and
402 this will crash if NULL or invalid.
403
404 */
405static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
406{
407 memset(pDest.ptr, value, pDest.len);
408 return (UsefulBufC){pDest.ptr, pDest.len};
409}
410
411
412/**
413 @brief Copy a pointer into a UsefulBuf
414
415 @param[in,out] Dest The destination buffer to copy into
416 @param[in] ptr The source to copy from
417 @param[in] len Length of the source; amoutn to copy
418
419 @return 0 on success, 1 on failure
420
421 This fails and returns NULLUsefulBufC if len is greater than
422 pDest->len.
423
424 Note that like memcpy, the pointers are not checked and
425 this will crash, rather than return 1 if they are NULL
426 or invalid.
427
428 */
429inline static UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
430{
431 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
432}
433
434
435/**
436 @brief Returns a truncation of a UsefulBufC
437
438 @param[in] UB The buffer to get the head of
439 @param[in] uAmount The number of bytes in the head
440
441 @return A UsefulBufC that is the head of UB
442
443 */
444static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
445{
446 if(uAmount > UB.len) {
447 return NULLUsefulBufC;
448 }
449 return (UsefulBufC){UB.ptr, uAmount};
450}
451
452
453/**
454 @brief Returns bytes from the end of a UsefulBufC
455
456 @param[in] UB The buffer to get the tail of
457 @param[in] uAmount The offset from the start where the tail is to begin
458
459 @return A UsefulBufC that is the tail of UB or NULLUsefulBufC if
460 uAmount is greater than the length of the UsefulBufC
461
462 If the input UsefulBufC is NULL, but the len is not, then the
463 length of the tail will be calculated and returned along
464 with a NULL ptr.
465 */
466static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
467{
468 UsefulBufC ReturnValue;
469
470 if(uAmount > UB.len) {
471 ReturnValue = NULLUsefulBufC;
472 } else if(UB.ptr == NULL) {
473 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
474 } else {
475 ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
476 }
477
478 return ReturnValue;
479}
480
481
482/**
483 @brief Compare two UsefulBufCs
484
485 @param[in] UB1 The destination buffer to copy into
486 @param[in] UB2 The source to copy from
487
488 @return 0 if equal...
489
490 Returns a negative value if UB1 if is less than UB2. UB1 is
491 less than UB2 if it is shorter or the first byte that is not
492 the same is less.
493
494 Returns 0 if the UsefulBufs are the same.
495
496 Returns a positive value if UB2 is less than UB1.
497
498 All that is of significance is that the result is positive,
499 negative or 0. (This doesn't return the difference between
500 the first non-matching byte like memcmp).
501
502 */
503int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
504
505
506/**
507 @brief Find one UsefulBuf in another
508
509 @param[in] BytesToSearch UsefulBuf to search through
510 @param[in] BytesToFind UsefulBuf with bytes to be found
511
512 @return position of found bytes or SIZE_MAX if not found.
513
514 */
515size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
516
517
518
519
520#if 0 // NOT_DEPRECATED
521/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */
522#define SZLiteralToUsefulBufC(szString) \
523 ((UsefulBufC) {(szString), sizeof(szString)-1})
524
525/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
526#define MakeUsefulBufOnStack(name, size) \
527 uint8_t __pBuf##name[(size)];\
528 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
529
530/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
531#define ByteArrayLiteralToUsefulBufC(pBytes) \
532 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
533
534/** Deprecated function; use UsefulBuf_Unconst() instead */
535static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
536{
537 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
538}
539#endif
540
541
542
543/*
544 Convenient functions to avoid type punning, compiler warnings and such
545 The optimizer reduces them to a simple assignment
546 This is a crusty corner of C. It shouldn't be this hard.
547 */
548static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
549{
550 uint32_t u32;
551 memcpy(&u32, &f, sizeof(uint32_t));
552 return u32;
553}
554
555static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
556{
557 uint64_t u64;
558 memcpy(&u64, &d, sizeof(uint64_t));
559 return u64;
560}
561
562static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
563{
564 double d;
565 memcpy(&d, &u64, sizeof(uint64_t));
566 return d;
567}
568
569static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
570{
571 float f;
572 memcpy(&f, &u32, sizeof(uint32_t));
573 return f;
574}
575
576
577
578
579
580/**
581 UsefulOutBuf is a structure and functions (an object) that are good
582 for serializing data into a buffer such as is often done with network
583 protocols or data written to files.
584
585 The main idea is that all the pointer manipulation for adding data is
586 done by UsefulOutBuf functions so the caller doesn't have to do any.
587 All the pointer manipulation is centralized here. This code will
588 have been reviewed and written carefully so it spares the caller of
589 much of this work and results in much safer code with much less work.
590
591 The functions to add data to the output buffer always check the
592 length and will never write off the end of the output buffer. If an
593 attempt to add data that will not fit is made, an internal error flag
594 will be set and further attempts to add data will not do anything.
595
596 Basically, if you initialized with the correct buffer, there is no
597 way to ever write off the end of that buffer when calling the Add
598 and Insert functions here.
599
600 The functions to add data do not return an error. The working model
601 is that the caller just makes all the calls to add data without any
602 error checking on each one. The error is instead checked after all the
603 data is added when the result is to be used. This makes the caller's
604 code cleaner.
605
606 There is a utility function to get the error status anytime along the
607 way if the caller wants. There are functions to see how much room is
608 left and see if some data will fit too, but their use is generally
609 not necessary.
610
611 The general call flow is like this:
612
613 - Initialize the UsefulOutBuf with the buffer that is to have the
614 data added. The caller allocates the buffer. It can be heap
615 or stack or shared memory (or other).
616
617 - Make calls to add data to the output buffer. Insert and append
618 are both supported. The append and insert calls will never write
619 off the end of the buffer.
620
621 - When all data is added, check the error status to make sure
622 everything fit.
623
624 - Get the resulting serialized data either as a UsefulBuf (a
625 pointer and length) or have it copied to another buffer.
626
627 UsefulOutBuf can be initialized with just a buffer length by passing
628 NULL as the pointer to the output buffer. This is useful if you want
629 to go through the whole serialization process to either see if it
630 will fit into a given buffer or compute the size of the buffer
631 needed. Pass a very large buffer size when calling Init, if you want
632 just to compute the size.
633
634 Some inexpensive simple sanity checks are performed before every data
635 addition to guard against use of an uninitialized or corrupted
636 UsefulOutBuf.
637
638 This has been used to create a CBOR encoder. The CBOR encoder has
639 almost no pointer manipulation in it, is much easier to read, and
640 easier to review.
641
642 A UsefulOutBuf is 27 bytes or 15 bytes on 64- or 32-bit machines so it
643 can go on the stack or be a C99 function parameter.
644 */
645
646typedef struct useful_out_buf {
647 UsefulBuf UB; // Memory that is being output to
648 size_t data_len; // length of the data
649 uint16_t magic; // Used to detect corruption and lack of initialization
650 uint8_t err;
651} UsefulOutBuf;
652
653
654/**
655 @brief Initialize and supply the actual output buffer
656
657 @param[out] me The UsefulOutBuf to initialize
658 @param[in] Storage Buffer to output into
659
660 Intializes the UsefulOutBuf with storage. Sets the current position
661 to the beginning of the buffer clears the error.
662
663 This must be called before the UsefulOutBuf is used.
664 */
665void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage);
666
667
668
669
670/** Convenience marco to make a UsefulOutBuf on the stack and
671 initialize it with stack buffer
672 */
673#define UsefulOutBuf_MakeOnStack(name, size) \
674 uint8_t __pBuf##name[(size)];\
675 UsefulOutBuf name;\
676 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
677
678
679
680/**
681 @brief Reset a UsefulOutBuf for re use
682
683 @param[in] me Pointer to the UsefulOutBuf
684
685 This sets the amount of data in the output buffer to none and
686 clears the error state.
687
688 The output buffer is still the same one and size as from the
689 UsefulOutBuf_Init() call.
690
691 It doesn't zero the data, just resets to 0 bytes of valid data.
692 */
693static inline void UsefulOutBuf_Reset(UsefulOutBuf *me)
694{
695 me->data_len = 0;
696 me->err = 0;
697}
698
699
700/**
701 @brief Returns position of end of data in the UsefulOutBuf
702
703 @param[in] me Pointer to the UsefulOutBuf
704
705 @return position of end of data
706
707 On a freshly initialized UsefulOutBuf with no data added, this will
708 return 0. After ten bytes have been added, it will return 10 and so
709 on.
710
711 Generally callers will not need this function for most uses of
712 UsefulOutBuf.
713
714 */
715static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me)
716{
717 return me->data_len;
718}
719
720
721/**
722 @brief Returns whether any data has been added to the UsefulOutBuf
723
724 @param[in] me Pointer to the UsefulOutBuf
725
726 @return 1 if output position is at start
727
728 */
729static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me)
730{
731 return 0 == me->data_len;
732}
733
734
735/**
736 @brief Inserts bytes into the UsefulOutBuf
737
738 @param[in] me Pointer to the UsefulOutBuf
739 @param[in] NewData UsefulBuf with the bytes to insert
740 @param[in] uPos Index in output buffer at which to insert
741
742 NewData is the pointer and length for the bytes to be added to the
743 output buffer. There must be room in the output buffer for all of
744 NewData or an error will occur.
745
746 The insertion point must be between 0 and the current valid data. If
747 not an error will occur. Appending data to the output buffer is
748 achieved by inserting at the end of the valid data. This can be
749 retrieved by calling UsefulOutBuf_GetEndPosition().
750
751 When insertion is performed, the bytes between the insertion point and
752 the end of data previously added to the output buffer is slid to the
753 right to make room for the new data.
754
755 Overlapping buffers are OK. NewData can point to data in the output
756 buffer.
757
758 If an error occurs an error state is set in the UsefulOutBuf. No
759 error is returned. All subsequent attempts to add data will do
760 nothing.
761
762 Call UsefulOutBuf_GetError() to find out if there is an error. This
763 is usually not needed until all additions of data are complete.
764
765 */
766void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uPos);
767
768
769/**
770 @brief Insert a data buffer into the UsefulOutBuf
771
772 @param[in] me Pointer to the UsefulOutBul
773 @param[in] pBytes Pointer to the bytes to insert
774 @param[in] uLen Length of the bytes to insert
775 @param[in] uPos Index in output buffer at which to insert
776
777 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
778 the difference being a pointer and length is passed in rather than an
779 UsefulBuf.
780
781 */
782static inline void UsefulOutBuf_InsertData(UsefulOutBuf *me, const void *pBytes, size_t uLen, size_t uPos)
783{
784 UsefulBufC Data = {pBytes, uLen};
785 UsefulOutBuf_InsertUsefulBuf(me, Data, uPos);
786}
787
788
789/**
790 @brief Insert a NULL-terminated string into the UsefulOutBuf
791
792 @param[in] me Pointer to the UsefulOutBuf
793 @param[in] szString string to append
794
795 */
796static inline void UsefulOutBuf_InsertString(UsefulOutBuf *me, const char *szString, size_t uPos)
797{
798 UsefulOutBuf_InsertUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}, uPos);
799}
800
801
802/**
803 @brief Insert a byte into the UsefulOutBuf
804
805 @param[in] me Pointer to the UsefulOutBul
806 @param[in] byte Bytes to insert
807 @param[in] uPos Index in output buffer at which to insert
808
809 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
810 the difference being a single byte is to be inserted.
811 */
812static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me, uint8_t byte, size_t uPos)
813{
814 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
815}
816
817
818/**
819 @brief Insert a 16-bit integer into the UsefulOutBuf
820
821 @param[in] me Pointer to the UsefulOutBul
822 @param[in] uInteger16 Integer to insert
823 @param[in] uPos Index in output buffer at which to insert
824
825 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
826 the difference being a single byte is to be inserted.
827
828 The integer will be inserted in network byte order (big endian)
829 */
830static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me, uint16_t uInteger16, size_t uPos)
831{
832 // Converts native integer format to network byte order (big endian)
833 uint8_t tmp[2];
834 tmp[0] = (uInteger16 & 0xff00) >> 8;
835 tmp[1] = (uInteger16 & 0xff);
836 UsefulOutBuf_InsertData(me, tmp, 2, uPos);
837}
838
839
840/**
841 @brief Insert a 32-bit integer into the UsefulOutBuf
842
843 @param[in] me Pointer to the UsefulOutBul
844 @param[in] uInteger32 Integer to insert
845 @param[in] uPos Index in output buffer at which to insert
846
847 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
848 the difference being a single byte is to be inserted.
849
850 The integer will be inserted in network byte order (big endian)
851 */
852static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *me, uint32_t uInteger32, size_t uPos)
853{
854 // Converts native integer format to network byte order (big endian)
855 uint8_t tmp[4];
856 tmp[0] = (uInteger32 & 0xff000000) >> 24;
857 tmp[1] = (uInteger32 & 0xff0000) >> 16;
858 tmp[2] = (uInteger32 & 0xff00) >> 8;
859 tmp[3] = (uInteger32 & 0xff);
860 UsefulOutBuf_InsertData(me, tmp, 4, uPos);
861}
862
863
864/**
865 @brief Insert a 64-bit integer into the UsefulOutBuf
866
867 @param[in] me Pointer to the UsefulOutBul
868 @param[in] uInteger64 Integer to insert
869 @param[in] uPos Index in output buffer at which to insert
870
871 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
872 the difference being a single byte is to be inserted.
873
874 The integer will be inserted in network byte order (big endian)
875 */
876static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *me, uint64_t uInteger64, size_t uPos)
877{
878 // Converts native integer format to network byte order (big endian)
879 uint8_t tmp[8];
880 tmp[0] = (uInteger64 & 0xff00000000000000) >> 56;
881 tmp[1] = (uInteger64 & 0xff000000000000) >> 48;
882 tmp[2] = (uInteger64 & 0xff0000000000) >> 40;
883 tmp[3] = (uInteger64 & 0xff00000000) >> 32;
884 tmp[4] = (uInteger64 & 0xff000000) >> 24;
885 tmp[5] = (uInteger64 & 0xff0000) >> 16;
886 tmp[6] = (uInteger64 & 0xff00) >> 8;
887 tmp[7] = (uInteger64 & 0xff);
888 UsefulOutBuf_InsertData(me, tmp, 8, uPos);
889}
890
891
892/**
893 @brief Insert a float into the UsefulOutBuf
894
895 @param[in] me Pointer to the UsefulOutBul
896 @param[in] f Integer to insert
897 @param[in] uPos Index in output buffer at which to insert
898
899 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
900 the difference being a single byte is to be inserted.
901
902 The float will be inserted in network byte order (big endian)
903 */
904static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *me, float f, size_t uPos)
905{
906 UsefulOutBuf_InsertUint32(me, UsefulBufUtil_CopyFloatToUint32(f), uPos);
907}
908
909
910/**
911 @brief Insert a double into the UsefulOutBuf
912
913 @param[in] me Pointer to the UsefulOutBul
914 @param[in] d Integer to insert
915 @param[in] uPos Index in output buffer at which to insert
916
917 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
918 the difference being a single byte is to be inserted.
919
920 The double will be inserted in network byte order (big endian)
921 */
922static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *me, double d, size_t uPos)
923{
924 UsefulOutBuf_InsertUint64(me, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
925}
926
927
928
929/**
930 Append a UsefulBuf into the UsefulOutBuf
931
932 @param[in] me Pointer to the UsefulOutBuf
933 @param[in] NewData UsefulBuf with the bytes to append
934
935 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
936 with the insertion point at the end of the valid data.
937
938*/
939static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData)
940{
941 // An append is just a insert at the end
942 UsefulOutBuf_InsertUsefulBuf(me, NewData, UsefulOutBuf_GetEndPosition(me));
943}
944
945
946/**
947 Append bytes to the UsefulOutBuf
948
949 @param[in] me Pointer to the UsefulOutBuf
950 @param[in] pBytes Pointer to bytes to append
951 @param[in] uLen Index in output buffer at which to append
952
953 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
954 with the insertion point at the end of the valid data.
955 */
956
957static inline void UsefulOutBuf_AppendData(UsefulOutBuf *me, const void *pBytes, size_t uLen)
958{
959 UsefulBufC Data = {pBytes, uLen};
960 UsefulOutBuf_AppendUsefulBuf(me, Data);
961}
962
963
964/**
965 Append a NULL-terminated string to the UsefulOutBuf
966
967 @param[in] me Pointer to the UsefulOutBuf
968 @param[in] szString string to append
969
970 */
971static inline void UsefulOutBuf_AppendString(UsefulOutBuf *me, const char *szString)
972{
973 UsefulOutBuf_AppendUsefulBuf(me, (UsefulBufC){szString, strlen(szString)});
974}
975
976
977/**
978 @brief Append a byte to the UsefulOutBuf
979
980 @param[in] me Pointer to the UsefulOutBuf
981 @param[in] byte Bytes to append
982
983 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
984 with the insertion point at the end of the valid data.
985 */
986static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *me, uint8_t byte)
987{
988 UsefulOutBuf_AppendData(me, &byte, 1);
989}
990
991/**
992 @brief Append an integer to the UsefulOutBuf
993
994 @param[in] me Pointer to the UsefulOutBuf
995 @param[in] uInteger16 Integer to append
996
997 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
998 with the insertion point at the end of the valid data.
999
1000 The integer will be appended in network byte order (big endian).
1001 */
1002static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *me, uint16_t uInteger16){
1003 UsefulOutBuf_InsertUint16(me, uInteger16, UsefulOutBuf_GetEndPosition(me));
1004}
1005
1006/**
1007 @brief Append an integer to the UsefulOutBuf
1008
1009 @param[in] me Pointer to the UsefulOutBuf
1010 @param[in] uInteger32 Integer to append
1011
1012 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1013 with the insertion point at the end of the valid data.
1014
1015 The integer will be appended in network byte order (big endian).
1016 */
1017static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *me, uint32_t uInteger32){
1018 UsefulOutBuf_InsertUint32(me, uInteger32, UsefulOutBuf_GetEndPosition(me));
1019}
1020
1021/**
1022 @brief Append an integer to the UsefulOutBuf
1023
1024 @param[in] me Pointer to the UsefulOutBuf
1025 @param[in] uInteger64 Integer to append
1026
1027 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1028 with the insertion point at the end of the valid data.
1029
1030 The integer will be appended in network byte order (big endian).
1031 */
1032static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *me, uint64_t uInteger64){
1033 UsefulOutBuf_InsertUint64(me, uInteger64, UsefulOutBuf_GetEndPosition(me));
1034}
1035
1036
1037/**
1038 @brief Append a float to the UsefulOutBuf
1039
1040 @param[in] me Pointer to the UsefulOutBuf
1041 @param[in] f Float to append
1042
1043 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1044 with the insertion point at the end of the valid data.
1045
1046 The float will be appended in network byte order (big endian).
1047 */
1048static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *me, float f){
1049 UsefulOutBuf_InsertFloat(me, f, UsefulOutBuf_GetEndPosition(me));
1050}
1051
1052/**
1053 @brief Append a float to the UsefulOutBuf
1054
1055 @param[in] me Pointer to the UsefulOutBuf
1056 @param[in] d Double to append
1057
1058 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1059 with the insertion point at the end of the valid data.
1060
1061 The double will be appended in network byte order (big endian).
1062 */
1063static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *me, double d){
1064 UsefulOutBuf_InsertDouble(me, d, UsefulOutBuf_GetEndPosition(me));
1065}
1066
1067/**
1068 @brief Returns the current error status
1069
1070 @param[in] me Pointer to the UsefulOutBuf
1071
1072 @return 0 if all OK, 1 on error
1073
1074 This is the error status since the call to either
1075 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1076 state it will stay until one of those functions is called.
1077
1078 Possible error conditions are:
1079 - bytes to be inserted will not fit
1080 - insertion point is out of buffer or past valid data
1081 - current position is off end of buffer (probably corruption or uninitialized)
1082 - detect corruption / uninitialized by bad magic number
1083 */
1084
1085static inline int UsefulOutBuf_GetError(UsefulOutBuf *me)
1086{
1087 return me->err;
1088}
1089
1090
1091/**
1092 @brief Returns number of bytes unused used in the output buffer
1093
1094 @param[in] me Pointer to the UsefulOutBuf
1095
1096 @return Number of unused bytes or zero
1097
1098 Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
1099 it is usually not necessary to use this.
1100 */
1101
1102static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me)
1103{
1104 return me->UB.len - me->data_len;
1105}
1106
1107
1108/**
1109 @brief Returns true / false if some number of bytes will fit in the UsefulOutBuf
1110
1111 @param[in] me Pointer to the UsefulOutBuf
1112 @param[in] uLen Number of bytes for which to check
1113
1114 @return 1 or 0 if nLen bytes would fit
1115
1116 Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
1117 it is usually not necessary to use this.
1118 */
1119
1120static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *me, size_t uLen)
1121{
1122 return uLen <= UsefulOutBuf_RoomLeft(me);
1123}
1124
1125
1126/**
1127 @brief Returns the resulting valid data in a UsefulOutBuf
1128
1129 @param[in] me Pointer to the UsefulOutBuf.
1130
1131 @return The valid data in UsefulOutBuf.
1132
1133 The storage for the returned data is Storage parameter passed
1134 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1135
1136 This can be called anytime and many times to get intermediate
1137 results. It doesn't change the data or reset the current position
1138 so you can keep adding data.
1139 */
1140
1141UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me);
1142
1143
1144/**
1145 @brief Copies the valid data out into a supplied buffer
1146
1147 @param[in] me Pointer to the UsefulOutBuf
1148 @param[out] Dest The destination buffer to copy into
1149
1150 @return Pointer and length of copied data.
1151
1152 This is the same as UsefulOutBuf_OutUBuf() except it copies the data.
1153*/
1154
1155UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf Dest);
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169/**
1170 UsefulInputBuf is the counterpart to UsefulOutBuf and is for parsing
1171 data read or received. Initialize it with the data
1172 from the network and its length. Then use the functions
1173 here to get the various data types out of it. It maintains a position
1174 for getting the next item. This means you don't have to track a
1175 pointer as you get each object. UsefulInputBuf does that for you and
1176 makes sure it never goes off the end of the buffer. The QCBOR
1177 implementation parser makes use of this for all its pointer math and
1178 length checking.
1179
1180 UsefulInputBuf also maintains an internal error state so you do not have
1181 to. Once data has been requested off the end of the buffer, it goes
1182 into an error state. You can keep calling functions to get more data
1183 but they will either return 0 or NULL. As long as you don't
1184 dereference the NULL, you can wait until all data items have been
1185 fetched before checking for the error and this can simplify your
1186 code.
1187
1188 The integer and float parsing expects network byte order (big endian).
1189 Network byte order is what is used by TCP/IP, CBOR and most internet
1190 protocols.
1191
1192 Lots of inlining is used to keep code size down. The code optimizer,
1193 particularly with the -Os, also reduces code size a lot. The only
1194 non-inline code is UsefulInputBuf_GetBytes() which is less than 100
1195 bytes so use of UsefulInputBuf doesn't add much code for all the messy
1196 hard-to-get right issues with parsing in C that is solves.
1197
1198 The parse context size is:
1199 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1200 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1201
1202 */
1203
1204#define UIB_MAGIC (0xB00F)
1205
1206typedef struct useful_input_buf {
1207 // Private data structure
1208 UsefulBufC UB; // Data being parsed
1209 size_t cursor; // Current offset in data being parse
1210 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1211 uint8_t err; // Set request goes off end or magic number is bad
1212} UsefulInputBuf;
1213
1214
1215
1216/**
1217 @brief Initialize the UsefulInputBuf structure before use.
1218
1219 @param[in] me Pointer to the UsefulInputBuf instance.
1220 @param[in] UB Pointer to the data to parse.
1221
1222 */
1223static inline void UsefulInputBuf_Init(UsefulInputBuf *me, UsefulBufC UB)
1224{
1225 me->cursor = 0;
1226 me->err = 0;
1227 me->magic = UIB_MAGIC;
1228 me->UB = UB;
1229}
1230
1231
1232/**
1233 @brief Returns current position in input buffer
1234
1235 @param[in] me Pointer to the UsefulInputBuf.
1236
1237 @return Integer position of the cursor
1238
1239 The position that the next bytes will be returned from.
1240
1241 */
1242static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *me)
1243{
1244 return me->cursor;
1245}
1246
1247
1248/**
1249 @brief Sets current position in input buffer
1250
1251 @param[in] me Pointer to the UsefulInputBuf.
1252 @param[in] uPos Position to set to
1253
1254 If the position is off the end of the input buffer, the error state
1255 is entered and all functions will do nothing.
1256
1257 Seeking to a valid position in the buffer will not reset the error
1258 state. Only re initialization will do that.
1259
1260 */
1261static inline void UsefulInputBuf_Seek(UsefulInputBuf *me, size_t uPos)
1262{
1263 if(uPos > me->UB.len) {
1264 me->err = 1;
1265 } else {
1266 me->cursor = uPos;
1267 }
1268}
1269
1270
1271/**
1272 @brief Returns the number of bytes from the cursor to the end of the buffer,
1273 the uncomsummed bytes.
1274
1275 @param[in] me Pointer to the UsefulInputBuf.
1276
1277 @return number of bytes unconsumed or 0 on error.
1278
1279 This is a critical function for input length validation. This does
1280 some pointer / offset math.
1281
1282 Returns 0 if the cursor it invalid or corruption of the structure is
1283 detected.
1284
1285 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1286 */
1287static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *me)
1288{
1289 // Magic number is messed up. Either the structure got overwritten
1290 // or was never initialized.
1291 if(me->magic != UIB_MAGIC) {
1292 return 0;
1293 }
1294
1295 // The cursor is off the end of the input buffer given
1296 // Presuming there are no bugs in this code, this should never happen.
1297 // If it so, the struct was corrupted. The check is retained as
1298 // as a defense in case there is a bug in this code or the struct is corrupted.
1299 if(me->cursor > me->UB.len) {
1300 return 0;
1301 }
1302
1303 // subtraction can't go neative because of check above
1304 return me->UB.len - me->cursor;
1305}
1306
1307
1308/**
1309 @brief Check if there are any unconsumed bytes
1310
1311 @param[in] me Pointer to the UsefulInputBuf.
1312
1313 @return 1 if len bytes are available after the cursor, and 0 if not
1314
1315 */
1316static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *me, size_t uLen)
1317{
1318 return UsefulInputBuf_BytesUnconsumed(me) >= uLen ? 1 : 0;
1319}
1320
1321
1322/**
1323 @brief Get pointer to bytes out of the input buffer
1324
1325 @param[in] me Pointer to the UsefulInputBuf.
1326 @param[in] uNum Number of bytes to get
1327
1328 @return Pointer to bytes.
1329
1330 This consumes n bytes from the input buffer. It returns a pointer to
1331 the start of the n bytes.
1332
1333 If there are not n bytes in the input buffer, NULL will be returned
1334 and an error will be set.
1335
1336 It advances the current position by n bytes.
1337 */
1338const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uNum);
1339
1340
1341/**
1342 @brief Get UsefulBuf out of the input buffer
1343
1344 @param[in] me Pointer to the UsefulInputBuf.
1345 @param[in] uNum Number of bytes to get
1346
1347 @return UsefulBufC with ptr and length for bytes consumed.
1348
1349 This consumes n bytes from the input buffer and returns the pointer
1350 and len to them as a UsefulBufC. The len returned will always be n.
1351
1352 If there are not n bytes in the input buffer, UsefulBufC.ptr will be
1353 NULL and UsefulBufC.len will be 0. An error will be set.
1354
1355 It advances the current position by n bytes.
1356 */
1357static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum)
1358{
1359 const void *pResult = UsefulInputBuf_GetBytes(me, uNum);
1360 if(!pResult) {
1361 return NULLUsefulBufC;
1362 } else {
1363 return (UsefulBufC){pResult, uNum};
1364 }
1365}
1366
1367
1368/**
1369 @brief Get a byte out of the input buffer.
1370
1371 @param[in] me Pointer to the UsefulInputBuf.
1372
1373 @return The byte
1374
1375 This consumes 1 byte from the input buffer. It returns the byte.
1376
1377 If there is not 1 byte in the buffer, 0 will be returned for the byte
1378 and an error set internally. You must check the error at some point
1379 to know whether the 0 was the real value or just returned in error,
1380 but you may not have to do that right away. Check the error state
1381 with UsefulInputBuf_GetError(). You can also know you are in the
1382 error state if UsefulInputBuf_GetBytes() returns NULL or the ptr from
1383 UsefulInputBuf_GetUsefulBuf() is NULL.
1384
1385 It advances the current position by 1 byte.
1386 */
1387static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *me)
1388{
1389 const void *pResult = UsefulInputBuf_GetBytes(me, sizeof(uint8_t));
1390
1391 return pResult ? *(uint8_t *)pResult : 0;
1392}
1393
1394
1395/**
1396 @brief Get a uint16_t out of the input buffer
1397
1398 @param[in] me Pointer to the UsefulInputBuf.
1399
1400 @return The uint16_t
1401
1402 See UsefulInputBuf_GetByte(). This works the same, except it returns
1403 a uint16_t and two bytes are consumed.
1404
1405 The input bytes must be in network order (big endian).
1406 */
1407static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *me)
1408{
1409 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint16_t));
1410
1411 if(!pResult) {
1412 return 0;
1413 }
1414
1415 return ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1];
1416}
1417
1418
1419/**
1420 @brief Get a uint32_t out of the input buffer
1421
1422 @param[in] me Pointer to the UsefulInputBuf.
1423
1424 @return The uint32_t
1425
1426 See UsefulInputBuf_GetByte(). This works the same, except it returns
1427 a uint32_t and four bytes are consumed.
1428
1429 The input bytes must be in network order (big endian).
1430 */
1431static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *me)
1432{
1433 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint32_t));
1434
1435 if(!pResult) {
1436 return 0;
1437 }
1438
1439 return ((uint32_t)pResult[0]<<24) +
1440 ((uint32_t)pResult[1]<<16) +
1441 ((uint32_t)pResult[2]<<8) +
1442 (uint32_t)pResult[3];
1443}
1444
1445
1446/**
1447 @brief Get a uint64_t out of the input buffer
1448
1449 @param[in] me Pointer to the UsefulInputBuf.
1450
1451 @return The uint64_t
1452
1453 See UsefulInputBuf_GetByte(). This works the same, except it returns
1454 a uint64_t and eight bytes are consumed.
1455
1456 The input bytes must be in network order (big endian).
1457 */
1458static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *me)
1459{
1460 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint64_t));
1461
1462 if(!pResult) {
1463 return 0;
1464 }
1465
1466 return ((uint64_t)pResult[0]<<56) +
1467 ((uint64_t)pResult[1]<<48) +
1468 ((uint64_t)pResult[2]<<40) +
1469 ((uint64_t)pResult[3]<<32) +
1470 ((uint64_t)pResult[4]<<24) +
1471 ((uint64_t)pResult[5]<<16) +
1472 ((uint64_t)pResult[6]<<8) +
1473 (uint64_t)pResult[7];
1474}
1475
1476
1477/**
1478 @brief Get a float out of the input buffer
1479
1480 @param[in] me Pointer to the UsefulInputBuf.
1481
1482 @return The float
1483
1484 See UsefulInputBuf_GetByte(). This works the same, except it returns
1485 a float and four bytes are consumed.
1486
1487 The input bytes must be in network order (big endian).
1488 */
1489static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *me)
1490{
1491 uint32_t uResult = UsefulInputBuf_GetUint32(me);
1492
1493 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
1494}
1495
1496/**
1497 @brief Get a double out of the input buffer
1498
1499 @param[in] me Pointer to the UsefulInputBuf.
1500
1501 @return The double
1502
1503 See UsefulInputBuf_GetByte(). This works the same, except it returns
1504 a double and eight bytes are consumed.
1505
1506 The input bytes must be in network order (big endian).
1507 */
1508static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *me)
1509{
1510 uint64_t uResult = UsefulInputBuf_GetUint64(me);
1511
1512 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
1513}
1514
1515
1516/**
1517 @brief Get the error status
1518
1519 @param[in] me Pointer to the UsefulInputBuf.
1520
1521 @return The error.
1522
1523 Zero is success, non-zero is error. Once in the error state, the only
1524 way to clear it is to call Init again.
1525
1526 You may be able to only check the error state at the end after all
1527 the Get()'s have been done, but if what you get later depends on what
1528 you get sooner you cannot. For example if you get a length or count
1529 of following items you will have to check the error.
1530
1531 */
1532static inline int UsefulInputBuf_GetError(UsefulInputBuf *me)
1533{
1534 return me->err;
1535}
1536
1537
Laurence Lundbladed425fb32019-02-18 10:56:18 -08001538#ifdef __cplusplus
1539}
1540#endif
1541
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001542#endif // _UsefulBuf_h
1543
1544