blob: 682646e7df5f7cf8a565c0bce2cc6c1ed6d7c353 [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.
Laurence Lundblade6ed34222018-12-18 09:46:23 -08004
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above
11 copyright notice, this list of conditions and the following
12 disclaimer in the documentation and/or other materials provided
13 with the distribution.
14 * Neither the name of The Linux Foundation nor the names of its
15 contributors, nor the name "Laurence Lundblade" may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ==============================================================================*/
31
32/*===================================================================================
33 FILE: UsefulBuf.h
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42 when who what, where, why
43 -------- ---- ---------------------------------------------------
Laurence Lundbladed85dbb72019-03-07 18:27:18 -080044 3/6/2019 llundblade Add UsefulBuf_IsValue()
Laurence Lundblade6ed34222018-12-18 09:46:23 -080045 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/**
Laurence Lundbladed85dbb72019-03-07 18:27:18 -0800483 @brief Compare two UsefulBufCs.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800484
Laurence Lundbladed85dbb72019-03-07 18:27:18 -0800485 @param[in] UB1 First UsefulBufC to compare.
486 @param[in] UB2 Second UsefulBufC to compare.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800487
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/**
Laurence Lundbladed85dbb72019-03-07 18:27:18 -0800507 @brief Find first byte that is not a particular byte value.
508
509 @param[in] UB The destination buffer for byte comparison.
510 @param[in] uValue The byte value to compare to.
511
512 @return Offset of first byte that isn't \c uValue or
513 SIZE_MAX if all bytes are \c uValue.
514
515 Note that unlike most comparison functions, 0
516 does not indicate a successful comparison, so the
517 test for match is:
518
519 UsefulBuf_IsValue(...) == SIZE_MAX
520
521 If \c UB is NULL or empty, there is no match
522 and 0 is returned.
523 */
524size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
525
526
527/**
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800528 @brief Find one UsefulBuf in another
529
530 @param[in] BytesToSearch UsefulBuf to search through
531 @param[in] BytesToFind UsefulBuf with bytes to be found
532
533 @return position of found bytes or SIZE_MAX if not found.
534
535 */
536size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
537
538
539
540
541#if 0 // NOT_DEPRECATED
542/** Deprecated macro; use UsefulBuf_FROM_SZ_LITERAL instead */
543#define SZLiteralToUsefulBufC(szString) \
544 ((UsefulBufC) {(szString), sizeof(szString)-1})
545
546/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
547#define MakeUsefulBufOnStack(name, size) \
548 uint8_t __pBuf##name[(size)];\
549 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
550
551/** Deprecated macro; use UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
552#define ByteArrayLiteralToUsefulBufC(pBytes) \
553 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
554
555/** Deprecated function; use UsefulBuf_Unconst() instead */
556static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
557{
558 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
559}
560#endif
561
562
563
564/*
565 Convenient functions to avoid type punning, compiler warnings and such
566 The optimizer reduces them to a simple assignment
567 This is a crusty corner of C. It shouldn't be this hard.
568 */
569static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
570{
571 uint32_t u32;
572 memcpy(&u32, &f, sizeof(uint32_t));
573 return u32;
574}
575
576static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
577{
578 uint64_t u64;
579 memcpy(&u64, &d, sizeof(uint64_t));
580 return u64;
581}
582
583static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
584{
585 double d;
586 memcpy(&d, &u64, sizeof(uint64_t));
587 return d;
588}
589
590static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
591{
592 float f;
593 memcpy(&f, &u32, sizeof(uint32_t));
594 return f;
595}
596
597
598
599
600
601/**
602 UsefulOutBuf is a structure and functions (an object) that are good
603 for serializing data into a buffer such as is often done with network
604 protocols or data written to files.
605
606 The main idea is that all the pointer manipulation for adding data is
607 done by UsefulOutBuf functions so the caller doesn't have to do any.
608 All the pointer manipulation is centralized here. This code will
609 have been reviewed and written carefully so it spares the caller of
610 much of this work and results in much safer code with much less work.
611
612 The functions to add data to the output buffer always check the
613 length and will never write off the end of the output buffer. If an
614 attempt to add data that will not fit is made, an internal error flag
615 will be set and further attempts to add data will not do anything.
616
617 Basically, if you initialized with the correct buffer, there is no
618 way to ever write off the end of that buffer when calling the Add
619 and Insert functions here.
620
621 The functions to add data do not return an error. The working model
622 is that the caller just makes all the calls to add data without any
623 error checking on each one. The error is instead checked after all the
624 data is added when the result is to be used. This makes the caller's
625 code cleaner.
626
627 There is a utility function to get the error status anytime along the
628 way if the caller wants. There are functions to see how much room is
629 left and see if some data will fit too, but their use is generally
630 not necessary.
631
632 The general call flow is like this:
633
634 - Initialize the UsefulOutBuf with the buffer that is to have the
635 data added. The caller allocates the buffer. It can be heap
636 or stack or shared memory (or other).
637
638 - Make calls to add data to the output buffer. Insert and append
639 are both supported. The append and insert calls will never write
640 off the end of the buffer.
641
642 - When all data is added, check the error status to make sure
643 everything fit.
644
645 - Get the resulting serialized data either as a UsefulBuf (a
646 pointer and length) or have it copied to another buffer.
647
648 UsefulOutBuf can be initialized with just a buffer length by passing
649 NULL as the pointer to the output buffer. This is useful if you want
650 to go through the whole serialization process to either see if it
651 will fit into a given buffer or compute the size of the buffer
652 needed. Pass a very large buffer size when calling Init, if you want
653 just to compute the size.
654
655 Some inexpensive simple sanity checks are performed before every data
656 addition to guard against use of an uninitialized or corrupted
657 UsefulOutBuf.
658
659 This has been used to create a CBOR encoder. The CBOR encoder has
660 almost no pointer manipulation in it, is much easier to read, and
661 easier to review.
662
663 A UsefulOutBuf is 27 bytes or 15 bytes on 64- or 32-bit machines so it
664 can go on the stack or be a C99 function parameter.
665 */
666
667typedef struct useful_out_buf {
668 UsefulBuf UB; // Memory that is being output to
669 size_t data_len; // length of the data
670 uint16_t magic; // Used to detect corruption and lack of initialization
671 uint8_t err;
672} UsefulOutBuf;
673
674
675/**
676 @brief Initialize and supply the actual output buffer
677
678 @param[out] me The UsefulOutBuf to initialize
679 @param[in] Storage Buffer to output into
680
681 Intializes the UsefulOutBuf with storage. Sets the current position
682 to the beginning of the buffer clears the error.
683
684 This must be called before the UsefulOutBuf is used.
685 */
686void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage);
687
688
689
690
691/** Convenience marco to make a UsefulOutBuf on the stack and
692 initialize it with stack buffer
693 */
694#define UsefulOutBuf_MakeOnStack(name, size) \
695 uint8_t __pBuf##name[(size)];\
696 UsefulOutBuf name;\
697 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
698
699
700
701/**
702 @brief Reset a UsefulOutBuf for re use
703
704 @param[in] me Pointer to the UsefulOutBuf
705
706 This sets the amount of data in the output buffer to none and
707 clears the error state.
708
709 The output buffer is still the same one and size as from the
710 UsefulOutBuf_Init() call.
711
712 It doesn't zero the data, just resets to 0 bytes of valid data.
713 */
714static inline void UsefulOutBuf_Reset(UsefulOutBuf *me)
715{
716 me->data_len = 0;
717 me->err = 0;
718}
719
720
721/**
722 @brief Returns position of end of data in the UsefulOutBuf
723
724 @param[in] me Pointer to the UsefulOutBuf
725
726 @return position of end of data
727
728 On a freshly initialized UsefulOutBuf with no data added, this will
729 return 0. After ten bytes have been added, it will return 10 and so
730 on.
731
732 Generally callers will not need this function for most uses of
733 UsefulOutBuf.
734
735 */
736static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *me)
737{
738 return me->data_len;
739}
740
741
742/**
743 @brief Returns whether any data has been added to the UsefulOutBuf
744
745 @param[in] me Pointer to the UsefulOutBuf
746
747 @return 1 if output position is at start
748
749 */
750static inline int UsefulOutBuf_AtStart(UsefulOutBuf *me)
751{
752 return 0 == me->data_len;
753}
754
755
756/**
757 @brief Inserts bytes into the UsefulOutBuf
758
759 @param[in] me Pointer to the UsefulOutBuf
760 @param[in] NewData UsefulBuf with the bytes to insert
761 @param[in] uPos Index in output buffer at which to insert
762
763 NewData is the pointer and length for the bytes to be added to the
764 output buffer. There must be room in the output buffer for all of
765 NewData or an error will occur.
766
767 The insertion point must be between 0 and the current valid data. If
768 not an error will occur. Appending data to the output buffer is
769 achieved by inserting at the end of the valid data. This can be
770 retrieved by calling UsefulOutBuf_GetEndPosition().
771
772 When insertion is performed, the bytes between the insertion point and
773 the end of data previously added to the output buffer is slid to the
774 right to make room for the new data.
775
776 Overlapping buffers are OK. NewData can point to data in the output
777 buffer.
778
779 If an error occurs an error state is set in the UsefulOutBuf. No
780 error is returned. All subsequent attempts to add data will do
781 nothing.
782
783 Call UsefulOutBuf_GetError() to find out if there is an error. This
784 is usually not needed until all additions of data are complete.
785
786 */
787void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uPos);
788
789
790/**
791 @brief Insert a data buffer into the UsefulOutBuf
792
793 @param[in] me Pointer to the UsefulOutBul
794 @param[in] pBytes Pointer to the bytes to insert
795 @param[in] uLen Length of the bytes to insert
796 @param[in] uPos Index in output buffer at which to insert
797
798 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
799 the difference being a pointer and length is passed in rather than an
800 UsefulBuf.
801
802 */
803static inline void UsefulOutBuf_InsertData(UsefulOutBuf *me, const void *pBytes, size_t uLen, size_t uPos)
804{
805 UsefulBufC Data = {pBytes, uLen};
806 UsefulOutBuf_InsertUsefulBuf(me, Data, uPos);
807}
808
809
810/**
811 @brief Insert a NULL-terminated string into the UsefulOutBuf
812
813 @param[in] me Pointer to the UsefulOutBuf
814 @param[in] szString string to append
815
816 */
817static inline void UsefulOutBuf_InsertString(UsefulOutBuf *me, const char *szString, size_t uPos)
818{
819 UsefulOutBuf_InsertUsefulBuf(me, (UsefulBufC){szString, strlen(szString)}, uPos);
820}
821
822
823/**
824 @brief Insert a byte into the UsefulOutBuf
825
826 @param[in] me Pointer to the UsefulOutBul
827 @param[in] byte Bytes to insert
828 @param[in] uPos Index in output buffer at which to insert
829
830 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
831 the difference being a single byte is to be inserted.
832 */
833static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me, uint8_t byte, size_t uPos)
834{
835 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
836}
837
838
839/**
840 @brief Insert a 16-bit integer into the UsefulOutBuf
841
842 @param[in] me Pointer to the UsefulOutBul
843 @param[in] uInteger16 Integer to insert
844 @param[in] uPos Index in output buffer at which to insert
845
846 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
847 the difference being a single byte is to be inserted.
848
849 The integer will be inserted in network byte order (big endian)
850 */
851static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me, uint16_t uInteger16, size_t uPos)
852{
853 // Converts native integer format to network byte order (big endian)
854 uint8_t tmp[2];
855 tmp[0] = (uInteger16 & 0xff00) >> 8;
856 tmp[1] = (uInteger16 & 0xff);
857 UsefulOutBuf_InsertData(me, tmp, 2, uPos);
858}
859
860
861/**
862 @brief Insert a 32-bit integer into the UsefulOutBuf
863
864 @param[in] me Pointer to the UsefulOutBul
865 @param[in] uInteger32 Integer to insert
866 @param[in] uPos Index in output buffer at which to insert
867
868 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
869 the difference being a single byte is to be inserted.
870
871 The integer will be inserted in network byte order (big endian)
872 */
873static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *me, uint32_t uInteger32, size_t uPos)
874{
875 // Converts native integer format to network byte order (big endian)
876 uint8_t tmp[4];
877 tmp[0] = (uInteger32 & 0xff000000) >> 24;
878 tmp[1] = (uInteger32 & 0xff0000) >> 16;
879 tmp[2] = (uInteger32 & 0xff00) >> 8;
880 tmp[3] = (uInteger32 & 0xff);
881 UsefulOutBuf_InsertData(me, tmp, 4, uPos);
882}
883
884
885/**
886 @brief Insert a 64-bit integer into the UsefulOutBuf
887
888 @param[in] me Pointer to the UsefulOutBul
889 @param[in] uInteger64 Integer to insert
890 @param[in] uPos Index in output buffer at which to insert
891
892 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
893 the difference being a single byte is to be inserted.
894
895 The integer will be inserted in network byte order (big endian)
896 */
897static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *me, uint64_t uInteger64, size_t uPos)
898{
899 // Converts native integer format to network byte order (big endian)
900 uint8_t tmp[8];
901 tmp[0] = (uInteger64 & 0xff00000000000000) >> 56;
902 tmp[1] = (uInteger64 & 0xff000000000000) >> 48;
903 tmp[2] = (uInteger64 & 0xff0000000000) >> 40;
904 tmp[3] = (uInteger64 & 0xff00000000) >> 32;
905 tmp[4] = (uInteger64 & 0xff000000) >> 24;
906 tmp[5] = (uInteger64 & 0xff0000) >> 16;
907 tmp[6] = (uInteger64 & 0xff00) >> 8;
908 tmp[7] = (uInteger64 & 0xff);
909 UsefulOutBuf_InsertData(me, tmp, 8, uPos);
910}
911
912
913/**
914 @brief Insert a float into the UsefulOutBuf
915
916 @param[in] me Pointer to the UsefulOutBul
917 @param[in] f Integer to insert
918 @param[in] uPos Index in output buffer at which to insert
919
920 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
921 the difference being a single byte is to be inserted.
922
923 The float will be inserted in network byte order (big endian)
924 */
925static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *me, float f, size_t uPos)
926{
927 UsefulOutBuf_InsertUint32(me, UsefulBufUtil_CopyFloatToUint32(f), uPos);
928}
929
930
931/**
932 @brief Insert a double into the UsefulOutBuf
933
934 @param[in] me Pointer to the UsefulOutBul
935 @param[in] d Integer to insert
936 @param[in] uPos Index in output buffer at which to insert
937
938 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
939 the difference being a single byte is to be inserted.
940
941 The double will be inserted in network byte order (big endian)
942 */
943static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *me, double d, size_t uPos)
944{
945 UsefulOutBuf_InsertUint64(me, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
946}
947
948
949
950/**
951 Append a UsefulBuf into the UsefulOutBuf
952
953 @param[in] me Pointer to the UsefulOutBuf
954 @param[in] NewData UsefulBuf with the bytes to append
955
956 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
957 with the insertion point at the end of the valid data.
958
959*/
960static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData)
961{
962 // An append is just a insert at the end
963 UsefulOutBuf_InsertUsefulBuf(me, NewData, UsefulOutBuf_GetEndPosition(me));
964}
965
966
967/**
968 Append bytes to the UsefulOutBuf
969
970 @param[in] me Pointer to the UsefulOutBuf
971 @param[in] pBytes Pointer to bytes to append
972 @param[in] uLen Index in output buffer at which to append
973
974 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
975 with the insertion point at the end of the valid data.
976 */
977
978static inline void UsefulOutBuf_AppendData(UsefulOutBuf *me, const void *pBytes, size_t uLen)
979{
980 UsefulBufC Data = {pBytes, uLen};
981 UsefulOutBuf_AppendUsefulBuf(me, Data);
982}
983
984
985/**
986 Append a NULL-terminated string to the UsefulOutBuf
987
988 @param[in] me Pointer to the UsefulOutBuf
989 @param[in] szString string to append
990
991 */
992static inline void UsefulOutBuf_AppendString(UsefulOutBuf *me, const char *szString)
993{
994 UsefulOutBuf_AppendUsefulBuf(me, (UsefulBufC){szString, strlen(szString)});
995}
996
997
998/**
999 @brief Append a byte to the UsefulOutBuf
1000
1001 @param[in] me Pointer to the UsefulOutBuf
1002 @param[in] byte Bytes to append
1003
1004 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1005 with the insertion point at the end of the valid data.
1006 */
1007static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *me, uint8_t byte)
1008{
1009 UsefulOutBuf_AppendData(me, &byte, 1);
1010}
1011
1012/**
1013 @brief Append an integer to the UsefulOutBuf
1014
1015 @param[in] me Pointer to the UsefulOutBuf
1016 @param[in] uInteger16 Integer to append
1017
1018 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1019 with the insertion point at the end of the valid data.
1020
1021 The integer will be appended in network byte order (big endian).
1022 */
1023static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *me, uint16_t uInteger16){
1024 UsefulOutBuf_InsertUint16(me, uInteger16, UsefulOutBuf_GetEndPosition(me));
1025}
1026
1027/**
1028 @brief Append an integer to the UsefulOutBuf
1029
1030 @param[in] me Pointer to the UsefulOutBuf
1031 @param[in] uInteger32 Integer to append
1032
1033 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1034 with the insertion point at the end of the valid data.
1035
1036 The integer will be appended in network byte order (big endian).
1037 */
1038static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *me, uint32_t uInteger32){
1039 UsefulOutBuf_InsertUint32(me, uInteger32, UsefulOutBuf_GetEndPosition(me));
1040}
1041
1042/**
1043 @brief Append an integer to the UsefulOutBuf
1044
1045 @param[in] me Pointer to the UsefulOutBuf
1046 @param[in] uInteger64 Integer to append
1047
1048 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1049 with the insertion point at the end of the valid data.
1050
1051 The integer will be appended in network byte order (big endian).
1052 */
1053static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *me, uint64_t uInteger64){
1054 UsefulOutBuf_InsertUint64(me, uInteger64, UsefulOutBuf_GetEndPosition(me));
1055}
1056
1057
1058/**
1059 @brief Append a float to the UsefulOutBuf
1060
1061 @param[in] me Pointer to the UsefulOutBuf
1062 @param[in] f Float to append
1063
1064 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1065 with the insertion point at the end of the valid data.
1066
1067 The float will be appended in network byte order (big endian).
1068 */
1069static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *me, float f){
1070 UsefulOutBuf_InsertFloat(me, f, UsefulOutBuf_GetEndPosition(me));
1071}
1072
1073/**
1074 @brief Append a float to the UsefulOutBuf
1075
1076 @param[in] me Pointer to the UsefulOutBuf
1077 @param[in] d Double to append
1078
1079 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1080 with the insertion point at the end of the valid data.
1081
1082 The double will be appended in network byte order (big endian).
1083 */
1084static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *me, double d){
1085 UsefulOutBuf_InsertDouble(me, d, UsefulOutBuf_GetEndPosition(me));
1086}
1087
1088/**
1089 @brief Returns the current error status
1090
1091 @param[in] me Pointer to the UsefulOutBuf
1092
1093 @return 0 if all OK, 1 on error
1094
1095 This is the error status since the call to either
1096 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1097 state it will stay until one of those functions is called.
1098
1099 Possible error conditions are:
1100 - bytes to be inserted will not fit
1101 - insertion point is out of buffer or past valid data
1102 - current position is off end of buffer (probably corruption or uninitialized)
1103 - detect corruption / uninitialized by bad magic number
1104 */
1105
1106static inline int UsefulOutBuf_GetError(UsefulOutBuf *me)
1107{
1108 return me->err;
1109}
1110
1111
1112/**
1113 @brief Returns number of bytes unused used in the output buffer
1114
1115 @param[in] me Pointer to the UsefulOutBuf
1116
1117 @return Number of unused bytes or zero
1118
1119 Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
1120 it is usually not necessary to use this.
1121 */
1122
1123static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *me)
1124{
1125 return me->UB.len - me->data_len;
1126}
1127
1128
1129/**
1130 @brief Returns true / false if some number of bytes will fit in the UsefulOutBuf
1131
1132 @param[in] me Pointer to the UsefulOutBuf
1133 @param[in] uLen Number of bytes for which to check
1134
1135 @return 1 or 0 if nLen bytes would fit
1136
1137 Because of the error handling strategy and checks in UsefulOutBuf_InsertUsefulBuf()
1138 it is usually not necessary to use this.
1139 */
1140
1141static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *me, size_t uLen)
1142{
1143 return uLen <= UsefulOutBuf_RoomLeft(me);
1144}
1145
1146
1147/**
1148 @brief Returns the resulting valid data in a UsefulOutBuf
1149
1150 @param[in] me Pointer to the UsefulOutBuf.
1151
1152 @return The valid data in UsefulOutBuf.
1153
1154 The storage for the returned data is Storage parameter passed
1155 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1156
1157 This can be called anytime and many times to get intermediate
1158 results. It doesn't change the data or reset the current position
1159 so you can keep adding data.
1160 */
1161
1162UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me);
1163
1164
1165/**
1166 @brief Copies the valid data out into a supplied buffer
1167
1168 @param[in] me Pointer to the UsefulOutBuf
1169 @param[out] Dest The destination buffer to copy into
1170
1171 @return Pointer and length of copied data.
1172
1173 This is the same as UsefulOutBuf_OutUBuf() except it copies the data.
1174*/
1175
1176UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf Dest);
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190/**
1191 UsefulInputBuf is the counterpart to UsefulOutBuf and is for parsing
1192 data read or received. Initialize it with the data
1193 from the network and its length. Then use the functions
1194 here to get the various data types out of it. It maintains a position
1195 for getting the next item. This means you don't have to track a
1196 pointer as you get each object. UsefulInputBuf does that for you and
1197 makes sure it never goes off the end of the buffer. The QCBOR
1198 implementation parser makes use of this for all its pointer math and
1199 length checking.
1200
1201 UsefulInputBuf also maintains an internal error state so you do not have
1202 to. Once data has been requested off the end of the buffer, it goes
1203 into an error state. You can keep calling functions to get more data
1204 but they will either return 0 or NULL. As long as you don't
1205 dereference the NULL, you can wait until all data items have been
1206 fetched before checking for the error and this can simplify your
1207 code.
1208
1209 The integer and float parsing expects network byte order (big endian).
1210 Network byte order is what is used by TCP/IP, CBOR and most internet
1211 protocols.
1212
1213 Lots of inlining is used to keep code size down. The code optimizer,
1214 particularly with the -Os, also reduces code size a lot. The only
1215 non-inline code is UsefulInputBuf_GetBytes() which is less than 100
1216 bytes so use of UsefulInputBuf doesn't add much code for all the messy
1217 hard-to-get right issues with parsing in C that is solves.
1218
1219 The parse context size is:
1220 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1221 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1222
1223 */
1224
1225#define UIB_MAGIC (0xB00F)
1226
1227typedef struct useful_input_buf {
1228 // Private data structure
1229 UsefulBufC UB; // Data being parsed
1230 size_t cursor; // Current offset in data being parse
1231 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1232 uint8_t err; // Set request goes off end or magic number is bad
1233} UsefulInputBuf;
1234
1235
1236
1237/**
1238 @brief Initialize the UsefulInputBuf structure before use.
1239
1240 @param[in] me Pointer to the UsefulInputBuf instance.
1241 @param[in] UB Pointer to the data to parse.
1242
1243 */
1244static inline void UsefulInputBuf_Init(UsefulInputBuf *me, UsefulBufC UB)
1245{
1246 me->cursor = 0;
1247 me->err = 0;
1248 me->magic = UIB_MAGIC;
1249 me->UB = UB;
1250}
1251
1252
1253/**
1254 @brief Returns current position in input buffer
1255
1256 @param[in] me Pointer to the UsefulInputBuf.
1257
1258 @return Integer position of the cursor
1259
1260 The position that the next bytes will be returned from.
1261
1262 */
1263static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *me)
1264{
1265 return me->cursor;
1266}
1267
1268
1269/**
1270 @brief Sets current position in input buffer
1271
1272 @param[in] me Pointer to the UsefulInputBuf.
1273 @param[in] uPos Position to set to
1274
1275 If the position is off the end of the input buffer, the error state
1276 is entered and all functions will do nothing.
1277
1278 Seeking to a valid position in the buffer will not reset the error
1279 state. Only re initialization will do that.
1280
1281 */
1282static inline void UsefulInputBuf_Seek(UsefulInputBuf *me, size_t uPos)
1283{
1284 if(uPos > me->UB.len) {
1285 me->err = 1;
1286 } else {
1287 me->cursor = uPos;
1288 }
1289}
1290
1291
1292/**
1293 @brief Returns the number of bytes from the cursor to the end of the buffer,
1294 the uncomsummed bytes.
1295
1296 @param[in] me Pointer to the UsefulInputBuf.
1297
1298 @return number of bytes unconsumed or 0 on error.
1299
1300 This is a critical function for input length validation. This does
1301 some pointer / offset math.
1302
1303 Returns 0 if the cursor it invalid or corruption of the structure is
1304 detected.
1305
1306 Code Reviewers: THIS FUNCTION DOES POINTER MATH
1307 */
1308static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *me)
1309{
1310 // Magic number is messed up. Either the structure got overwritten
1311 // or was never initialized.
1312 if(me->magic != UIB_MAGIC) {
1313 return 0;
1314 }
1315
1316 // The cursor is off the end of the input buffer given
1317 // Presuming there are no bugs in this code, this should never happen.
1318 // If it so, the struct was corrupted. The check is retained as
1319 // as a defense in case there is a bug in this code or the struct is corrupted.
1320 if(me->cursor > me->UB.len) {
1321 return 0;
1322 }
1323
1324 // subtraction can't go neative because of check above
1325 return me->UB.len - me->cursor;
1326}
1327
1328
1329/**
1330 @brief Check if there are any unconsumed bytes
1331
1332 @param[in] me Pointer to the UsefulInputBuf.
1333
1334 @return 1 if len bytes are available after the cursor, and 0 if not
1335
1336 */
1337static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *me, size_t uLen)
1338{
1339 return UsefulInputBuf_BytesUnconsumed(me) >= uLen ? 1 : 0;
1340}
1341
1342
1343/**
1344 @brief Get pointer to bytes out of the input buffer
1345
1346 @param[in] me Pointer to the UsefulInputBuf.
1347 @param[in] uNum Number of bytes to get
1348
1349 @return Pointer to bytes.
1350
1351 This consumes n bytes from the input buffer. It returns a pointer to
1352 the start of the n bytes.
1353
1354 If there are not n bytes in the input buffer, NULL will be returned
1355 and an error will be set.
1356
1357 It advances the current position by n bytes.
1358 */
1359const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uNum);
1360
1361
1362/**
1363 @brief Get UsefulBuf out of the input buffer
1364
1365 @param[in] me Pointer to the UsefulInputBuf.
1366 @param[in] uNum Number of bytes to get
1367
1368 @return UsefulBufC with ptr and length for bytes consumed.
1369
1370 This consumes n bytes from the input buffer and returns the pointer
1371 and len to them as a UsefulBufC. The len returned will always be n.
1372
1373 If there are not n bytes in the input buffer, UsefulBufC.ptr will be
1374 NULL and UsefulBufC.len will be 0. An error will be set.
1375
1376 It advances the current position by n bytes.
1377 */
1378static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *me, size_t uNum)
1379{
1380 const void *pResult = UsefulInputBuf_GetBytes(me, uNum);
1381 if(!pResult) {
1382 return NULLUsefulBufC;
1383 } else {
1384 return (UsefulBufC){pResult, uNum};
1385 }
1386}
1387
1388
1389/**
1390 @brief Get a byte out of the input buffer.
1391
1392 @param[in] me Pointer to the UsefulInputBuf.
1393
1394 @return The byte
1395
1396 This consumes 1 byte from the input buffer. It returns the byte.
1397
1398 If there is not 1 byte in the buffer, 0 will be returned for the byte
1399 and an error set internally. You must check the error at some point
1400 to know whether the 0 was the real value or just returned in error,
1401 but you may not have to do that right away. Check the error state
1402 with UsefulInputBuf_GetError(). You can also know you are in the
1403 error state if UsefulInputBuf_GetBytes() returns NULL or the ptr from
1404 UsefulInputBuf_GetUsefulBuf() is NULL.
1405
1406 It advances the current position by 1 byte.
1407 */
1408static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *me)
1409{
1410 const void *pResult = UsefulInputBuf_GetBytes(me, sizeof(uint8_t));
1411
1412 return pResult ? *(uint8_t *)pResult : 0;
1413}
1414
1415
1416/**
1417 @brief Get a uint16_t out of the input buffer
1418
1419 @param[in] me Pointer to the UsefulInputBuf.
1420
1421 @return The uint16_t
1422
1423 See UsefulInputBuf_GetByte(). This works the same, except it returns
1424 a uint16_t and two bytes are consumed.
1425
1426 The input bytes must be in network order (big endian).
1427 */
1428static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *me)
1429{
1430 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint16_t));
1431
1432 if(!pResult) {
1433 return 0;
1434 }
1435
1436 return ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1];
1437}
1438
1439
1440/**
1441 @brief Get a uint32_t out of the input buffer
1442
1443 @param[in] me Pointer to the UsefulInputBuf.
1444
1445 @return The uint32_t
1446
1447 See UsefulInputBuf_GetByte(). This works the same, except it returns
1448 a uint32_t and four bytes are consumed.
1449
1450 The input bytes must be in network order (big endian).
1451 */
1452static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *me)
1453{
1454 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint32_t));
1455
1456 if(!pResult) {
1457 return 0;
1458 }
1459
1460 return ((uint32_t)pResult[0]<<24) +
1461 ((uint32_t)pResult[1]<<16) +
1462 ((uint32_t)pResult[2]<<8) +
1463 (uint32_t)pResult[3];
1464}
1465
1466
1467/**
1468 @brief Get a uint64_t out of the input buffer
1469
1470 @param[in] me Pointer to the UsefulInputBuf.
1471
1472 @return The uint64_t
1473
1474 See UsefulInputBuf_GetByte(). This works the same, except it returns
1475 a uint64_t and eight bytes are consumed.
1476
1477 The input bytes must be in network order (big endian).
1478 */
1479static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *me)
1480{
1481 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(me, sizeof(uint64_t));
1482
1483 if(!pResult) {
1484 return 0;
1485 }
1486
1487 return ((uint64_t)pResult[0]<<56) +
1488 ((uint64_t)pResult[1]<<48) +
1489 ((uint64_t)pResult[2]<<40) +
1490 ((uint64_t)pResult[3]<<32) +
1491 ((uint64_t)pResult[4]<<24) +
1492 ((uint64_t)pResult[5]<<16) +
1493 ((uint64_t)pResult[6]<<8) +
1494 (uint64_t)pResult[7];
1495}
1496
1497
1498/**
1499 @brief Get a float out of the input buffer
1500
1501 @param[in] me Pointer to the UsefulInputBuf.
1502
1503 @return The float
1504
1505 See UsefulInputBuf_GetByte(). This works the same, except it returns
1506 a float and four bytes are consumed.
1507
1508 The input bytes must be in network order (big endian).
1509 */
1510static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *me)
1511{
1512 uint32_t uResult = UsefulInputBuf_GetUint32(me);
1513
1514 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
1515}
1516
1517/**
1518 @brief Get a double out of the input buffer
1519
1520 @param[in] me Pointer to the UsefulInputBuf.
1521
1522 @return The double
1523
1524 See UsefulInputBuf_GetByte(). This works the same, except it returns
1525 a double and eight bytes are consumed.
1526
1527 The input bytes must be in network order (big endian).
1528 */
1529static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *me)
1530{
1531 uint64_t uResult = UsefulInputBuf_GetUint64(me);
1532
1533 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
1534}
1535
1536
1537/**
1538 @brief Get the error status
1539
1540 @param[in] me Pointer to the UsefulInputBuf.
1541
1542 @return The error.
1543
1544 Zero is success, non-zero is error. Once in the error state, the only
1545 way to clear it is to call Init again.
1546
1547 You may be able to only check the error state at the end after all
1548 the Get()'s have been done, but if what you get later depends on what
1549 you get sooner you cannot. For example if you get a length or count
1550 of following items you will have to check the error.
1551
1552 */
1553static inline int UsefulInputBuf_GetError(UsefulInputBuf *me)
1554{
1555 return me->err;
1556}
1557
1558
Laurence Lundbladed425fb32019-02-18 10:56:18 -08001559#ifdef __cplusplus
1560}
1561#endif
1562
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001563#endif // _UsefulBuf_h
1564
1565