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