blob: 89ed64367f29a8a6267670e7a9b8dce7b4405611 [file] [log] [blame]
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001/*============================================================================
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002 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.
Laurence Lundblade852a33c2019-06-11 09:00:07 -070030 =============================================================================*/
Laurence Lundblade6ed34222018-12-18 09:46:23 -080031
Laurence Lundblade852a33c2019-06-11 09:00:07 -070032/*============================================================================
Laurence Lundblade6ed34222018-12-18 09:46:23 -080033 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
Laurence Lundblade852a33c2019-06-11 09:00:07 -070042 when who what, where, why
43 -------- ---- --------------------------------------------------
44 5/21/2019 llundblade #define configs for efficient endianness handling.
45 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
46 3/23/2019 llundblade Big documentation & style update. No interface
47 change.
48 3/6/2019 llundblade Add UsefulBuf_IsValue()
49 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
50 12/13/2018 llundblade Documentation improvements
51 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
52 UsefulBufC.
53 02/02/18 llundbla Full support for integers in and out; fix pointer
54 alignment bug. Incompatible change: integers
55 in/out are now in network byte order.
56 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
57 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
58 comparison for < or > for unequal length buffers.
59 Added UsefulBuf_Set() function.
60 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
61 11/13/16 llundbla Initial Version.
Laurence Lundblade6ed34222018-12-18 09:46:23 -080062
Laurence Lundblade852a33c2019-06-11 09:00:07 -070063 =============================================================================*/
Laurence Lundblade6ed34222018-12-18 09:46:23 -080064
65#ifndef _UsefulBuf_h
66#define _UsefulBuf_h
67
68
Laurence Lundblade852a33c2019-06-11 09:00:07 -070069/*
70 Configuration Options
71
72 This code is designed so it will work correctly and completely by
73 default. No configuration is necessary to make it work. None of the
74 following #defines need to be enabled. The code works and is very
75 portable with them all turned off.
76
77 All configuration options (USEFULBUF_CONFIG_XXX)
78 1) Reduce code size
79 2) Improve efficiency
80 3) Both of the above
81
82 The efficiency improvements are not large, so the main reason really
83 is to reduce code size.
84
85 */
86
87
88/*
89 Endianness Configuration
90
91 By default, UsefulBuf does not need to know what the endianness of
92 the device is. All the code will run correctly on either big or
93 little endian CPUs.
94
95 Here's the recipe for configuring the endianness-related #defines
96 to use more efficient CPU/OS/compiler dependent features to reduce
97 code size. Note these only affect the integer arrays (tagged
98 arrays) feature of QCBOR. All other endianness handling in
99 QCBOR is integrated with code that also handles alignment and
100 preferred encoding.
101
102 The first option is to not define anything. This will work fine on
103 with all CPU's, OS's and compilers. The code for encoding
104 integers will be a little larger and slower.
105
106 If your CPU is big-endian then define USEFULBUF_CONFIG_BIG_ENDIAN. This
107 will give the most efficient code for big-endian CPUs. It will be small
108 and efficient because there will be no byte swapping.
109
110 Try defining USEFULBUF_CONFIG_HTON. This will work on most CPU's,
111 OS's and compilers, but not all. On big-endian CPUs this should give
112 the most efficient code, the same as USEFULBUF_CONFIG_BIG_ENDIAN
113 does. On little-endian CPUs it should call the system-defined byte
114 swapping method which is presumably implemented efficiently. In some
115 cases, this will be a dedicated byte swap instruction like Intel's
116 bswap.
117
118 If USEFULBUF_CONFIG_HTON works and you know your CPU is
119 little-endian, it is also good to define
120 USEFULBUF_CONFIG_LITTLE_ENDIAN.
121
122 if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
123 little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
124 USEFULBUF_CONFIG_BSWAP. This should call the most efficient
125 system-defined byte swap method. However, note
126 https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
127 this is fixed now. Often hton() and ntoh() will call the built-in
128 __builtin_bswapXX()() function, so this size issue could affect
129 USEFULBUF_CONFIG_HTON.
130
131 Last, run the tests. They must all pass.
132
133 These #define config options affect the inline implementation of
134 UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
135 also affect the 16-, 32-bit, float and double versions of these
136 instructions. Since they are inline, they size effect is not in the
137 UsefulBuf object code, but in the calling code.
138
139 Summary:
140 USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
141 USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
142 USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
143 handle big and little-endian with system option.
144 USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
145 use __builtin_bswapXX().
146 */
147
148#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
149#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
150#endif
151
152
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800153#include <stdint.h> // for uint8_t, uint16_t....
154#include <string.h> // for strlen, memcpy, memmove, memset
155#include <stddef.h> // for size_t
156
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700157
158#ifdef USEFULBUF_CONFIG_HTON
159#include <arpa/inet.h> // for htons, htonl, htonll, ntohs...
160#endif
161
Laurence Lundbladed425fb32019-02-18 10:56:18 -0800162#ifdef __cplusplus
163extern "C" {
164#endif
165
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800166/**
167 @file UsefulBuf.h
168
169 The goal of this code is to make buffer and pointer manipulation
170 easier and safer when working with binary data.
171
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700172 The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
173 structures are used to represent buffers rather than ad hoc pointers and
174 lengths.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800175
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700176 With these it will often be possible to write code that does little
177 or no direct pointer manipulation for copying and formatting
178 data. For example, the QCBOR encoder was written using these and
179 has no less pointer manipulation.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800180
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700181 While it is true that object code using these functions will be a
182 little larger and slower than a white-knuckle clever use of pointers
183 might be, but not by that much or enough to have an effect for most
184 use cases. For security-oriented code this is highly
185 worthwhile. Clarity, simplicity, reviewability and are more
186 important.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800187
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700188 There are some extra sanity and double checks in this code to help
189 catch coding errors and simple memory corruption. They are helpful,
190 but not a substitute for proper code review, input validation and
191 such.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800192
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700193 This code consists of a lot of inline functions and a few that are
194 not. It should not generate very much object code, especially with
195 the optimizer turned up to @c -Os or @c -O3.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800196 */
197
198
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800199/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700200 @ref UsefulBufC and @ref UsefulBuf are simple data structures to hold
201 a pointer and length for binary data. In C99 this data structure can
202 be passed on the stack making a lot of code cleaner than carrying
203 around a pointer and length as two parameters.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800204
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700205 This is also conducive to secure coding practice as the length is
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800206 always carried with the pointer and the convention for handling a
207 pointer and a length is clear.
208
209 While it might be possible to write buffer and pointer code more
210 efficiently in some use cases, the thought is that unless there is an
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700211 extreme need for performance (e.g., you are building a
212 gigabit-per-second IP router), it is probably better to have cleaner
213 code you can be most certain about the security of.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800214
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700215 The non-const @ref UsefulBuf is usually used to refer a buffer to be
216 filled in. The length is the size of the buffer.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800217
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700218 The const @ref UsefulBufC is usually used to refer to some data that
219 has been filled in. The length is amount of valid data pointed to.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800220
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700221 A common use is to pass a @ref UsefulBuf to a function, the function
222 fills it in, the function returns a @ref UsefulBufC. The pointer is
223 the same in both.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800224
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700225 A @ref UsefulBuf is null, it has no value, when @c ptr in it is @c NULL.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800226
227 There are utility functions for the following:
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700228 - Initializing
229 - Create initialized const @ref UsefulBufC from compiler literals
230 - Create initialized const @ref UsefulBufC from NULL-terminated string
231 - Make an empty @ref UsefulBuf on the stack
232 - Checking whether a @ref UsefulBuf is null, empty or both
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800233 - Copying, copying with offset, copying head or tail
234 - Comparing and finding substrings
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800235
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700236 See also @ref UsefulOutBuf. It is a richer structure that has both
237 the size of the valid data and the size of the buffer.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800238
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700239 @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it
240 can go on the stack and be a function parameter or return value.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800241
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700242 Another way to look at it is this. C has the NULL-terminated string
243 as a means for handling text strings, but no means or convention for
244 binary strings. Other languages do have such means, Rust, an
245 efficient compiled language, for example.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800246
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700247 @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his
248 birthday. Eeyore's balloon fits beautifully, "it goes in and out
249 like anything".
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800250*/
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800251typedef struct q_useful_buf_c {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800252 const void *ptr;
253 size_t len;
254} UsefulBufC;
255
256
257/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700258 This non-const @ref UsefulBuf is typically used for some allocated
259 memory that is to be filled in. The @c len is the amount of memory,
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800260 not the length of the valid data in the buffer.
261 */
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800262typedef struct q_useful_buf {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800263 void *ptr;
264 size_t len;
265} UsefulBuf;
266
267
268/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700269 A null @ref UsefulBufC is one that has no value in the same way a @c
270 NULL pointer has no value. A @ref UsefulBufC is @c NULL when the @c
271 ptr field is @c NULL. It doesn't matter what @c len is. See
272 UsefulBuf_IsEmpty() for the distinction between null and empty.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800273 */
274#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
275
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700276
277/**
278 A null @ref UsefulBuf is one that has no memory associated the same
279 way @c NULL points to nothing. It does not matter what @c len is.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800280 */
281#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
282
283
284/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700285 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800286
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700287 @param[in] UB The UsefulBuf to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800288
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700289 @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800290 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700291static inline int UsefulBuf_IsNULL(UsefulBuf UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800292
293
294/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700295 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800296
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700297 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800298
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700299 @return 1 if it is @c NULLUsefulBufC, 0 if not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800300 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700301static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800302
303
304/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700305 @brief Check if a @ref UsefulBuf is empty or not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800306
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700307 @param[in] UB The @ref UsefulBuf to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800308
309 @return 1 if it is empty, 0 if not.
310
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700311 An "empty" @ref UsefulBuf is one that has a value and can be
312 considered to be set, but that value is of zero length. It is empty
313 when @c len is zero. It doesn't matter what the @c ptr is.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800314
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700315 A lot of uses will not need to clearly distinguish a @c NULL @ref
316 UsefulBuf from an empty one and can have the @c ptr @c NULL and the
317 @c len 0. However if a use of @ref UsefulBuf needs to make a
318 distinction then @c ptr should not be @c NULL when the @ref UsefulBuf
319 is considered empty, but not @c NULL.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800320 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700321static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800322
323
324/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700325 @brief Check if a @ref UsefulBufC is empty or not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800326
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700327 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800328
329 @return 1 if it is empty, 0 if not.
330 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700331static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800332
333
334/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700335 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800336
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700337 @param[in] UB The @ref UsefulBuf to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800338
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700339 @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800340 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700341static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800342
343
344/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700345 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800346
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700347 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800348
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700349 @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800350 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700351static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800352
353
354/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700355 @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800356
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700357 @param[in] UB The @ref UsefulBuf to convert.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800358
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700359 @return A @ref UsefulBufC struct.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800360 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700361static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800362
363
364/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700365 @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800366
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700367 @param[in] UBC The @ref UsefulBuf to convert.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800368
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700369 @return A non-const @ref UsefulBuf struct.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800370 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700371static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800372
373
374/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700375 Convert a literal string to a @ref UsefulBufC.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800376
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700377 @c szString must be a literal string that @c sizeof() works on. This
378 is better for literal strings than UsefulBuf_FromSZ() because it
379 generates less code. It will not work on non-literal strings.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800380
381 The terminating \0 (NULL) is NOT included in the length!
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800382 */
383#define UsefulBuf_FROM_SZ_LITERAL(szString) \
384 ((UsefulBufC) {(szString), sizeof(szString)-1})
385
386
387/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700388 Convert a literal byte array to a @ref UsefulBufC.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800389
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700390 @c pBytes must be a literal string that @c sizeof() works on. It
391 will not work on non-literal arrays.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800392 */
393#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
394 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
395
396
397/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700398 Make an automatic variable named @c name of type @ref UsefulBuf and
399 point it to a stack variable of the given @c size.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800400 */
401#define UsefulBuf_MAKE_STACK_UB(name, size) \
402 uint8_t __pBuf##name[(size)];\
403 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
404
405
406/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700407 Make a byte array in to a @ref UsefulBuf. This is usually used on
408 stack variables or static variables. Also see @ref
409 UsefulBuf_MAKE_STACK_UB.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800410 */
411#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
412 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
413
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700414
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800415/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700416 @brief Convert a NULL-terminated string to a @ref UsefulBufC.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800417
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700418 @param[in] szString The string to convert.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800419
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700420 @return A @ref UsefulBufC struct.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800421
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700422 @c UsefulBufC.ptr points to the string so its lifetime must be
423 maintained.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800424
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700425 The terminating \0 (NULL) is NOT included in the length.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800426 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700427static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800428
429
430/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700431 @brief Copy one @ref UsefulBuf into another at an offset.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800432
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700433 @param[in] Dest Destination buffer to copy into.
434 @param[in] uOffset The byte offset in @c Dest at which to copy to.
435 @param[in] Src The bytes to copy.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800436
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700437 @return Pointer and length of the copy or @ref NULLUsefulBufC.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800438
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700439 This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
440 size of @c Dest.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800441
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700442 This fails and returns @ref NULLUsefulBufC if the @c Src length plus
443 @c uOffset is greater than the length of @c Dest.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800444
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700445 The results are undefined if @c Dest and @c Src overlap.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800446
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700447 This assumes that there is valid data in @c Dest up to @c
448 uOffset. The @ref UsefulBufC returned starts at the beginning of @c
449 Dest and goes to @c Src.len @c + @c uOffset.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800450 */
451UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
452
453
454/**
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700455 @brief Copy one @ref UsefulBuf into another.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800456
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700457 @param[in] Dest The destination buffer to copy into.
458 @param[out] Src The source to copy from.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800459
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700460 @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
461 on failure.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800462
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700463 This fails if @c Src.len is greater than @c Dest.len.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800464
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700465 Note that like @c memcpy(), the pointers are not checked and this
466 will crash rather than return @ref NULLUsefulBufC if they are @c
467 NULL or invalid.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800468
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700469 The results are undefined if @c Dest and @c Src overlap.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800470 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700471static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
472
473
474/**
475 @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
476
477 @param[in] pDest The destination buffer to copy into.
478 @param[in] value The value to set the bytes to.
479
480 Note that like @c memset(), the pointer in @c pDest is not checked
481 and this will crash if @c NULL or invalid.
482 */
483static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
484
485
486/**
487 @brief Copy a pointer into a @ref UsefulBuf.
488
489 @param[in,out] Dest The destination buffer to copy into.
490 @param[in] ptr The source to copy from.
491 @param[in] uLen Length of the source; amount to copy.
492
493 @return 0 on success, 1 on failure.
494
495 This fails and returns @ref NULLUsefulBufC if @c uLen is greater than
496 @c pDest->len.
497
498 Note that like @c memcpy(), the pointers are not checked and this
499 will crash, rather than return 1 if they are @c NULL or invalid.
500 */
501static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
502 const void *ptr,
503 size_t uLen);
504
505
506/**
507 @brief Returns a truncation of a @ref UsefulBufC.
508
509 @param[in] UB The buffer to get the head of.
510 @param[in] uAmount The number of bytes in the head.
511
512 @return A @ref UsefulBufC that is the head of UB.
513 */
514static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
515
516
517/**
518 @brief Returns bytes from the end of a @ref UsefulBufC.
519
520 @param[in] UB The buffer to get the tail of.
521 @param[in] uAmount The offset from the start where the tail is to begin.
522
523 @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
524 if @c uAmount is greater than the length of the @ref UsefulBufC.
525
526 If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
527 be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
528 of the tail.
529 */
530static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
531
532
533/**
534 @brief Compare one @ref UsefulBufC to another.
535
536 @param[in] UB1 The first buffer to compare.
537 @param[in] UB2 The second buffer to compare.
538
539 @return 0, positive or negative value.
540
541 Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
542 less than @c UB2 if it is shorter or the first byte that is not the
543 same is less.
544
545 Returns 0 if the inputs are the same.
546
547 Returns a positive value if @c UB2 is less than @c UB1.
548
549 All that is of significance is that the result is positive, negative
550 or 0. (This doesn't return the difference between the first
551 non-matching byte like @c memcmp() ).
552 */
553int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
554
555
556/**
557 @brief Find first byte that is not a particular byte value.
558
559 @param[in] UB The destination buffer for byte comparison.
560 @param[in] uValue The byte value to compare to.
561
562 @return Offset of first byte that isn't @c uValue or
563 @c SIZE_MAX if all bytes are @c uValue.
564
565 Note that unlike most comparison functions, 0
566 does not indicate a successful comparison, so the
567 test for match is:
568
569 UsefulBuf_IsValue(...) == SIZE_MAX
570
571 If @c UB is null or empty, there is no match
572 and 0 is returned.
573 */
574size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
575
576
577/**
578 @brief Find one @ref UsefulBufC in another.
579
580 @param[in] BytesToSearch Buffer to search through.
581 @param[in] BytesToFind Buffer with bytes to be found.
582
583 @return Position of found bytes or @c SIZE_MAX if not found.
584 */
585size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
586
587
588#if 1 // NOT_DEPRECATED
589/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
590#define SZLiteralToUsefulBufC(szString) \
591 ((UsefulBufC) {(szString), sizeof(szString)-1})
592
593/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
594#define MakeUsefulBufOnStack(name, size) \
595 uint8_t __pBuf##name[(size)];\
596 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
597
598/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
599#define ByteArrayLiteralToUsefulBufC(pBytes) \
600 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
601
602/** Deprecated function; use UsefulBuf_Unconst() instead */
603static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
604{
605 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
606}
607#endif
608
609
610
611
612/**
613 @brief Copy a @c float to a @c uint32_t.
614
615 @param[in] f Float value to copy.
616
617 @return A @c uint32_t with the float bits.
618
619 Convenience function to avoid type punning, compiler warnings and
620 such. The optimizer usually reduces this to a simple assignment. This
621 is a crusty corner of C.
622 */
623static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
624
625
626/**
627 @brief Copy a @c double to a @c uint64_t.
628
629 @param[in] d Double value to copy.
630
631 @return A @c uint64_t with the double bits.
632
633 Convenience function to avoid type punning, compiler warnings and
634 such. The optimizer usually reduces this to a simple assignment. This
635 is a crusty corner of C.
636 */
637static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
638
639
640/**
641 @brief Copy a @c uint32_t to a @c float.
642
643 @param[in] u32 Integer value to copy.
644
645 @return The value as a @c float.
646
647 Convenience function to avoid type punning, compiler warnings and
648 such. The optimizer usually reduces this to a simple assignment. This
649 is a crusty corner of C.
650 */
651static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
652
653
654/**
655 @brief Copy a @c uint64_t to a @c double.
656
657 @param[in] u64 Integer value to copy.
658
659 @return The value as a @c double.
660
661 Convenience function to avoid type punning, compiler warnings and
662 such. The optimizer usually reduces this to a simple assignment. This
663 is a crusty corner of C.
664 */
665static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
666
667
668
669
670/**
671 UsefulOutBuf is a structure and functions (an object) for serializing
672 data into a buffer when encoding a network protocol or writing data
673 to file.
674
675 The main idea is that all the pointer manipulation is performed by
676 @ref UsefulOutBuf functions so the caller doesn't have to do any
677 pointer manipulation. The pointer manipulation is centralized. This
678 code will have been reviewed and written carefully so it spares the
679 caller of much of this work and results in safer code with less work.
680
681 The @ref UsefulOutBuf methods that add data to the output buffer
682 always check the length and will never write off the end of the
683 output buffer. If an attempt to add data that will not fit is made,
684 an internal error flag will be set and further attempts to add data
685 will not do anything.
686
687 There is no way to ever write off the end of that buffer when calling
688 the @c UsefulOutBuf_AddXxx() and @c UsefulOutBuf_InsertXxx()
689 functions.
690
691 The functions to add data do not return an error. The working model
692 is that all calls to add data are made without an error check. Errors
693 are just checked for once after all the data has been added before the
694 and before serialized data is to be used. This makes the calling code
695 cleaner.
696
697 There is a utility function to get the error status anytime along the
698 way for a special circumstance. There are functions to see how much
699 room is left and see if some data will fit too, but their use is
700 generally not necessary.
701
702 The general call flow is:
703
704 - Initialize by calling @ref UsefulOutBuf_Init(). The output
705 buffer given to it can be from the heap, stack or
706 otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience macro
707 that makes a buffer on the stack and initializes it.
708
709 - Call methods like UsefulOutBuf_InsertString(),
710 UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
711 to output data. The append calls add data to the end of the
712 valid data. The insert calls take a position argument.
713
714 - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
715 there were no errors and to get the serialized output bytes.
716
717 @ref UsefulOutBuf can be used in a size calculation mode to calculate
718 the size of output that would be generated. This is useful to
719 calculate the size of a buffer that is to be allocated to hold the
720 output. To use @ref UsefulOutBuf in this mode, call
721 UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
722 @c (UsefulBuf){NULL,MAX_UINT32}. Then call all the Insert and Add
723 functions. No attempt will made to actually copy data, so only the
724 lengths have to be valid for these calls.
725
726 Methods like UsefulOutBuf_InsertUint64() always output in network
727 bytes order (big endian).
728
729 The possible errors are:
730 - The @ref UsefulOutBuf was not initialized or was corrupted.
731
732 - An attempt was made to add data that will not fit.
733
734 - An attempt was made to insert data at a position beyond the end of
735 the buffer.
736
737 - An attempt was made to insert data at a position beyond the valid
738 data in the buffer.
739
740 Some inexpensive simple sanity checks are performed before every data
741 addition to guard against use of an uninitialized or corrupted
742 UsefulOutBuf.
743
744 This has been used to create a CBOR encoder. The CBOR encoder has
745 almost no pointer manipulation in it, is easier to read, and easier
746 to review.
747
748 A @ref UsefulOutBuf is small and can go on the stack:
749 - 32 bytes (27 bytes plus alignment padding) on a 64-bit machine
750 - 16 bytes (15 bytes plus alignment padding) on a 32-bit machines
751 */
752typedef struct useful_out_buf {
753 // PRIVATE DATA STRUCTURE
754 UsefulBuf UB; // Memory that is being output to
755 size_t data_len; // length of the data
756 uint16_t magic; // Used to detect corruption and lack of initialization
757 uint8_t err;
758} UsefulOutBuf;
759
760
761/**
762 @brief Initialize and supply the actual output buffer.
763
764 @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
765 @param[in] Storage Buffer to output into.
766
767 Initializes the @ref UsefulOutBuf with storage. Sets the current
768 position to the beginning of the buffer clears the error.
769
770 This must be called before the @ref UsefulOutBuf is used.
771 */
772void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
773
774
775/**
776 Convenience macro to make a @ref UsefulOutBuf on the stack and
777 initialize it with a stack buffer of the given size. The variable
778 will be named @c name.
779 */
780#define UsefulOutBuf_MakeOnStack(name, size) \
781 uint8_t __pBuf##name[(size)];\
782 UsefulOutBuf name;\
783 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
784
785
786/**
787 @brief Reset a @ref UsefulOutBuf for re use
788
789 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
790
791 This sets the amount of data in the output buffer to none and clears
792 the error state.
793
794 The output buffer is still the same one and size as from the
795 UsefulOutBuf_Init() call.
796
797 This doesn't zero the data, just resets to 0 bytes of valid data.
798 */
799static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
800
801
802/**
803 @brief Returns position of end of data in the @ref UsefulOutBuf.
804
805 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
806
807 @return position of end of data.
808
809 On a freshly initialized @ref UsefulOutBuf with no data added, this
810 will return 0. After 10 bytes have been added, it will return 10 and
811 so on.
812
813 Generally callers will not need this function for most uses of @ref
814 UsefulOutBuf.
815 */
816static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
817
818
819/**
820 @brief Returns whether any data has been added to the @ref UsefulOutBuf.
821
822 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
823
824 @return 1 if output position is at start.
825 */
826static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
827
828
829/**
830 @brief Inserts bytes into the @ref UsefulOutBuf.
831
832 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
833 @param[in] NewData The bytes to insert.
834 @param[in] uPos Index in output buffer at which to insert.
835
836 @c NewData is the pointer and length for the bytes to be added to the
837 output buffer. There must be room in the output buffer for all of @c
838 NewData or an error will occur.
839
840 The insertion point must be between 0 and the current valid data. If
841 not, an error will occur. Appending data to the output buffer is
842 achieved by inserting at the end of the valid data. This can be
843 retrieved by calling UsefulOutBuf_GetEndPosition().
844
845 When insertion is performed, the bytes between the insertion point
846 and the end of data previously added to the output buffer are slid to
847 the right to make room for the new data.
848
849 Overlapping buffers are OK. @c NewData can point to data in the
850 output buffer.
851
852 If an error occurs an error state is set in the @ref UsefulOutBuf. No
853 error is returned. All subsequent attempts to add data will do
854 nothing.
855
856 The intended use is that all additions are made without checking for
857 an error. The error will be taken into account when
858 UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
859 UsefulOutBuf_GetError() can also be called to check for an error.
860 */
861void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
862 UsefulBufC NewData,
863 size_t uPos);
864
865
866/**
867 @brief Insert a data buffer into the @ref UsefulOutBuf.
868
869 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
870 @param[in] pBytes Pointer to the bytes to insert
871 @param[in] uLen Length of the bytes to insert
872 @param[in] uPos Index in output buffer at which to insert
873
874 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
875 the difference being a pointer and length is passed in rather than an
876 @ref UsefulBufC.
877 */
878static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
879 const void *pBytes,
880 size_t uLen,
881 size_t uPos);
882
883
884/**
885 @brief Insert a NULL-terminated string into the UsefulOutBuf.
886
887 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
888 @param[in] szString NULL-terminated string to insert.
889 @param[in] uPos Index in output buffer at which to insert.
890 */
891static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
892 const char *szString,
893 size_t uPos);
894
895
896/**
897 @brief Insert a byte into the @ref UsefulOutBuf.
898
899 @param[in] pUOutBuf Pointer to the UsefulOutBuf.
900 @param[in] byte Bytes to insert.
901 @param[in] uPos Index in output buffer at which to insert.
902
903 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
904 the difference being a single byte is to be inserted.
905 */
906static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
907 uint8_t byte,
908 size_t uPos);
909
910
911/**
912 @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
913
914 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
915 @param[in] uInteger16 Integer to insert.
916 @param[in] uPos Index in output buffer at which to insert.
917
918 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
919 the difference being a two-byte integer is to be inserted.
920
921 The integer will be inserted in network byte order (big endian).
922 */
923static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
924 uint16_t uInteger16,
925 size_t uPos);
926
927
928/**
929 @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
930
931 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
932 @param[in] uInteger32 Integer to insert.
933 @param[in] uPos Index in output buffer at which to insert.
934
935 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
936 the difference being a four-byte integer is to be inserted.
937
938 The integer will be inserted in network byte order (big endian).
939 */
940static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
941 uint32_t uInteger32,
942 size_t uPos);
943
944
945/**
946 @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
947
948 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
949 @param[in] uInteger64 Integer to insert.
950 @param[in] uPos Index in output buffer at which to insert.
951
952 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
953 the difference being an eight-byte integer is to be inserted.
954
955 The integer will be inserted in network byte order (big endian).
956 */
957static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
958 uint64_t uInteger64,
959 size_t uPos);
960
961
962/**
963 @brief Insert a @c float into the @ref UsefulOutBuf.
964
965 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
966 @param[in] f @c float to insert.
967 @param[in] uPos Index in output buffer at which to insert.
968
969 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
970 the difference being a @c float is to be inserted.
971
972 The @c float will be inserted in network byte order (big endian).
973 */
974static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
975 float f,
976 size_t uPos);
977
978
979/**
980 @brief Insert a @c double into the @ref UsefulOutBuf.
981
982 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
983 @param[in] d @c double to insert.
984 @param[in] uPos Index in output buffer at which to insert.
985
986 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
987 the difference being a @c double is to be inserted.
988
989 The @c double will be inserted in network byte order (big endian).
990 */
991static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
992 double d,
993 size_t uPos);
994
995
996/**
997 @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
998
999 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1000 @param[in] NewData The @ref UsefulBuf with the bytes to append.
1001
1002 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1003 with the insertion point at the end of the valid data.
1004*/
1005static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1006 UsefulBufC NewData);
1007
1008
1009/**
1010 @brief Append bytes to the @ref UsefulOutBuf.
1011
1012 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1013 @param[in] pBytes Pointer to bytes to append.
1014 @param[in] uLen Length of @c pBytes to append.
1015
1016 See UsefulOutBuf_InsertData() for details. This does the same
1017 with the insertion point at the end of the valid data.
1018 */
1019static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1020 const void *pBytes,
1021 size_t uLen);
1022
1023
1024/**
1025 @brief Append a NULL-terminated string to the @ref UsefulOutBuf
1026
1027 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1028 @param[in] szString NULL-terminated string to append.
1029 */
1030static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1031 const char *szString);
1032
1033
1034/**
1035 @brief Append a byte to the @ref UsefulOutBuf
1036
1037 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1038 @param[in] byte Bytes to append.
1039
1040 See UsefulOutBuf_InsertByte() for details. This does the same
1041 with the insertion point at the end of the valid data.
1042 */
1043static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1044 uint8_t byte);
1045
1046
1047/**
1048 @brief Append an integer to the @ref UsefulOutBuf
1049
1050 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1051 @param[in] uInteger16 Integer to append.
1052
1053 See UsefulOutBuf_InsertUint16() for details. This does the same
1054 with the insertion point at the end of the valid data.
1055
1056 The integer will be appended in network byte order (big endian).
1057 */
1058static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1059 uint16_t uInteger16);
1060
1061
1062/**
1063 @brief Append an integer to the @ref UsefulOutBuf
1064
1065 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1066 @param[in] uInteger32 Integer to append.
1067
1068 See UsefulOutBuf_InsertUint32() for details. This does the same
1069 with the insertion point at the end of the valid data.
1070
1071 The integer will be appended in network byte order (big endian).
1072 */
1073static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1074 uint32_t uInteger32);
1075
1076
1077/**
1078 @brief Append an integer to the @ref UsefulOutBuf
1079
1080 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1081 @param[in] uInteger64 Integer to append.
1082
1083 See UsefulOutBuf_InsertUint64() for details. This does the same
1084 with the insertion point at the end of the valid data.
1085
1086 The integer will be appended in network byte order (big endian).
1087 */
1088static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1089 uint64_t uInteger64);
1090
1091
1092/**
1093 @brief Append a @c float to the @ref UsefulOutBuf
1094
1095 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1096 @param[in] f @c float to append.
1097
1098 See UsefulOutBuf_InsertFloat() for details. This does the same
1099 with the insertion point at the end of the valid data.
1100
1101 The float will be appended in network byte order (big endian).
1102 */
1103static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1104 float f);
1105
1106
1107/**
1108 @brief Append a @c double to the @ref UsefulOutBuf
1109
1110 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1111 @param[in] d @c double to append.
1112
1113 See UsefulOutBuf_InsertDouble() for details. This does the same
1114 with the insertion point at the end of the valid data.
1115
1116 The double will be appended in network byte order (big endian).
1117 */
1118static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1119 double d);
1120
1121
1122/**
1123 @brief Returns the current error status.
1124
1125 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1126
1127 @return 0 if all OK, 1 on error.
1128
1129 This is the error status since the call to either
1130 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1131 state it will stay until one of those functions is called.
1132
1133 Possible error conditions are:
1134 - bytes to be inserted will not fit
1135 - insertion point is out of buffer or past valid data
1136 - current position is off end of buffer (probably corrupted or uninitialized)
1137 - detect corruption / uninitialized by bad magic number
1138 */
1139static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1140
1141
1142/**
1143 @brief Returns number of bytes unused used in the output buffer.
1144
1145 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1146
1147 @return Number of unused bytes or zero.
1148
1149 Because of the error handling strategy and checks in
1150 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1151 this.
1152 */
1153static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1154
1155
1156/**
1157 @brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
1158
1159 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1160 @param[in] uLen Number of bytes for which to check
1161
1162 @return 1 if @c uLen bytes will fit, 0 if not.
1163
1164 Because of the error handling strategy and checks in
1165 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1166 this.
1167 */
1168static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1169
1170
1171 /**
1172 @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1173
1174 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1175
1176 @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1177
1178 Giving a @c NULL output buffer to UsefulOutBuf_Init() is used
1179 when just calculating the length of the encoded data.
1180 */
1181static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1182
1183
1184/**
1185 @brief Returns the resulting valid data in a UsefulOutBuf
1186
1187 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1188
1189 @return The valid data in @ref UsefulOutBuf or
1190 @ref NULLUsefulBufC if there was an error adding data.
1191
1192 The storage for the returned data is the @c Storage parameter passed
1193 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1194
1195 This can be called anytime and many times to get intermediate
1196 results. It doesn't change the data or reset the current position
1197 so you can keep adding data.
1198 */
1199UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1200
1201
1202/**
1203 @brief Copies the valid data into a supplied buffer
1204
1205 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1206 @param[out] Dest The destination buffer to copy into.
1207
1208 @return Pointer and length of copied data or @c NULLUsefulBufC
1209 if it will not fit in the @c Dest buffer.
1210
1211 This is the same as UsefulOutBuf_OutUBuf() except it copies the data
1212 to @c Dest.
1213*/
1214UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1215
1216
1217
1218
1219/**
1220 @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf and is
1221 for parsing data read or received. Initialize it with the data from
1222 the network. Then use the functions here to get data chunks of
1223 various types. A position cursor is maintained internally.
1224
1225 As long as the functions here are used, there will never be a
1226 reference off the end of the given buffer. This is true even if they
1227 care called incorrectly, an attempt is made to seek of the end of the
1228 buffer, etc. This makes it easier to write safe and correct code.
1229 For example, the QCBOR decoder implementation is safer and easier to
1230 review through its use of @ref UsefulInputBuf.
1231
1232 @ref UsefulInputBuf maintains an internal error state. The
1233 intended use is that data chunks can be fetched without error
1234 checking until the end. Once data has been requested off the end of
1235 the buffer, the error state is entered. In the error state the
1236 @c UsefulInputBuf_GetXxxx() functions return 0, or @c NULL or
1237 @ref NULLUsefulBufC. As long as null are not dereferenced, the
1238 error check can be put off until the end, simplifying the calling
1239 code.
1240
1241 The integer and float parsing expects network byte order (big
1242 endian). Network byte order is what is used by TCP/IP, CBOR and most
1243 internet protocols.
1244
1245 Lots of inline functions are used to keep code size down. The code
1246 optimizer, particularly with the @c -Os or @c -O3, also reduces code
1247 size a lot. The only non-inline code is UsefulInputBuf_GetBytes()
1248 which is less than 100 bytes so use of @ref UsefulInputBuf doesn't
1249 add much code for all the messy hard-to-get right issues with parsing
1250 in C that is solves.
1251
1252 The parse context size is:
1253 - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1254 - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1255 */
1256typedef struct useful_input_buf {
1257 // PRIVATE DATA STRUCTURE
1258 UsefulBufC UB; // Data being parsed
1259 size_t cursor; // Current offset in data being parse
1260 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1261 uint8_t err; // Set request goes off end or magic number is bad
1262} UsefulInputBuf;
1263
1264#define UIB_MAGIC (0xB00F)
1265
1266
1267/**
1268 @brief Initialize the UsefulInputBuf structure before use.
1269
1270 @param[in] pUInBuf Pointer to the UsefulInputBuf instance.
1271 @param[in] UB The data to parse.
1272 */
1273static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1274
1275
1276/**
1277 @brief Returns current position in input buffer.
1278
1279 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1280
1281 @return Integer position of the cursor.
1282
1283 The position that the next bytes will be returned from.
1284 */
1285static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1286
1287
1288/**
1289 @brief Sets the current position in input buffer.
1290
1291 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1292 @param[in] uPos Position to set to.
1293
1294 If the position is off the end of the input buffer, the error state
1295 is entered, and all functions will do nothing.
1296
1297 Seeking to a valid position in the buffer will not reset the error
1298 state. Only re initialization will do that.
1299 */
1300static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1301
1302
1303/**
1304 @brief Returns the number of bytes from the cursor to the end of the buffer,
1305 the unconsumed bytes.
1306
1307 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1308
1309 @return Number of bytes unconsumed or 0 on error.
1310
1311 This is a critical function for input length validation.
1312
1313 Returns 0 if the cursor it invalid or corruption of the structure is
1314 detected.
1315 */
1316static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1317
1318
1319/**
1320 @brief Check if there are any unconsumed bytes.
1321
1322 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1323 @param[in] uLen Number of bytes to check availability for.
1324
1325 @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
1326 */
1327static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1328
1329
1330/**
1331 @brief Get pointer to bytes out of the input buffer.
1332
1333 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1334 @param[in] uNum Number of bytes to get.
1335
1336 @return Pointer to bytes.
1337
1338 This consumes @c uNum bytes from the input buffer. It returns a
1339 pointer to the start of the @c uNum bytes.
1340
1341 If there are not @c uNum bytes in the input buffer, @c NULL will be
1342 returned and an error will be set.
1343
1344 It advances the current position by @c uNum bytes.
1345 */
1346const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1347
1348
1349/**
1350 @brief Get @ref UsefulBuf out of the input buffer.
1351
1352 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1353 @param[in] uNum Number of bytes to get.
1354
1355 @return A @ref UsefulBufC with ptr and length of bytes consumed.
1356
1357 This consumes @c uNum bytes from the input buffer and returns the
1358 pointer and length for them as a @ref UsefulBufC. The length returned
1359 will always be @c uNum.
1360
1361 If there are not @c uNum bytes in the input buffer, @ref NULLUsefulBufC
1362 will be returned and the error state is set.
1363
1364 It advances the current position by @c uNum bytes.
1365 */
1366static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1367
1368
1369/**
1370 @brief Get a byte out of the input buffer.
1371
1372 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1373
1374 @return The byte.
1375
1376 This consumes 1 byte from the input buffer. It returns the byte.
1377
1378 If there is not 1 byte in the buffer, 0 will be returned for the byte
1379 and an error set internally. You must check the error at some point
1380 to know whether the 0 was the real value or just returned in error,
1381 but you may not have to do that right away. Check the error state
1382 with UsefulInputBuf_GetError(). You can also know you are in the
1383 error state if UsefulInputBuf_GetBytes() returns @c NULL or the @c
1384 ptr from UsefulInputBuf_GetUsefulBuf() is @c NULL.
1385
1386 It advances the current position by 1 byte.
1387 */
1388static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1389
1390
1391/**
1392 @brief Get a @c uint16_t out of the input buffer.
1393
1394 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1395
1396 @return The @c uint16_t.
1397
1398 See UsefulInputBuf_GetByte(). This works the same, except it returns
1399 a @c 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 *pUInBuf);
1404
1405
1406/**
1407 @brief Get a uint32_t out of the input buffer.
1408
1409 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1410
1411 @return The @c uint32_t.
1412
1413 See UsefulInputBuf_GetByte(). This works the same, except it returns
1414 a @c uint32_t and four bytes are consumed.
1415
1416 The input bytes must be in network order (big endian).
1417 */
1418static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1419
1420
1421/**
1422 @brief Get a uint64_t out of the input buffer.
1423
1424 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1425
1426 @return The uint64_t.
1427
1428 See UsefulInputBuf_GetByte(). This works the same, except it returns
1429 a @c uint64_t and eight bytes are consumed.
1430
1431 The input bytes must be in network order (big endian).
1432 */
1433static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1434
1435
1436/**
1437 @brief Get a float out of the input buffer.
1438
1439 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1440
1441 @return The float.
1442
1443 See UsefulInputBuf_GetByte(). This works the same, except it returns
1444 a float and four bytes are consumed.
1445
1446 The input bytes must be in network order (big endian).
1447 */
1448static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1449
1450
1451/**
1452 @brief Get a double out of the input buffer.
1453
1454 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1455
1456 @return The double.
1457
1458 See UsefulInputBuf_GetByte(). This works the same, except it returns
1459 a double and eight bytes are consumed.
1460
1461 The input bytes must be in network order (big endian).
1462 */
1463static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1464
1465
1466/**
1467 @brief Get the error status.
1468
1469 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
1470
1471 @return 0 if there is no error, 1 if there is.
1472
1473 The error state is entered for one of these reasons:
1474 - Attempt to fetch data past the end of the buffer
1475 - Attempt to seek to a position past the end of the buffer
1476 - Attempt to get data from an uninitialized or corrupt instance
1477 of @ref UsefulInputBuf
1478
1479 Once in the error state, it can only be cleared by calling
1480 UsefulInputBuf_Init().
1481
1482 You may be able to only check the error state at the end after all
1483 the UsefulInputBuf_GetXxxx() calls have been made, but if what you
1484 get later depends on what you get sooner you cannot. For example,
1485 if you get a length or count of following items you will have to
1486 check the error.
1487 */
1488static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1489
1490
1491
1492
1493/*----------------------------------------------------------
1494 Inline implementations.
1495 */
1496static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1497{
1498 return !UB.ptr;
1499}
1500
1501
1502static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1503{
1504 return !UB.ptr;
1505}
1506
1507
1508static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1509{
1510 return !UB.len;
1511}
1512
1513
1514static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1515{
1516 return !UB.len;
1517}
1518
1519
1520static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1521{
1522 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1523}
1524
1525
1526static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1527{
1528 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1529}
1530
1531
1532static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1533{
1534 return (UsefulBufC){UB.ptr, UB.len};
1535}
1536
1537
1538static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1539{
1540 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
1541}
1542
1543
1544static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1545{
1546 return ((UsefulBufC) {szString, strlen(szString)});
1547}
1548
1549
1550static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1551{
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001552 return UsefulBuf_CopyOffset(Dest, 0, Src);
1553}
1554
1555
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001556static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
1557{
1558 memset(pDest.ptr, value, pDest.len);
1559 return (UsefulBufC){pDest.ptr, pDest.len};
1560}
1561
1562
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001563static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001564{
1565 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
1566}
1567
1568
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001569static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1570{
1571 if(uAmount > UB.len) {
1572 return NULLUsefulBufC;
1573 }
1574 return (UsefulBufC){UB.ptr, uAmount};
1575}
1576
1577
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001578static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1579{
1580 UsefulBufC ReturnValue;
1581
1582 if(uAmount > UB.len) {
1583 ReturnValue = NULLUsefulBufC;
1584 } else if(UB.ptr == NULL) {
1585 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
1586 } else {
1587 ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
1588 }
1589
1590 return ReturnValue;
1591}
1592
1593
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001594
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001595static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1596{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001597 uint32_t u32;
1598 memcpy(&u32, &f, sizeof(uint32_t));
1599 return u32;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001600}
1601
1602static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1603{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001604 uint64_t u64;
1605 memcpy(&u64, &d, sizeof(uint64_t));
1606 return u64;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001607}
1608
1609static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1610{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001611 double d;
1612 memcpy(&d, &u64, sizeof(uint64_t));
1613 return d;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001614}
1615
1616static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1617{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001618 float f;
1619 memcpy(&f, &u32, sizeof(uint32_t));
1620 return f;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001621}
1622
1623
1624
1625
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001626static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001627{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001628 pMe->data_len = 0;
1629 pMe->err = 0;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001630}
1631
1632
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001633static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001634{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001635 return pMe->data_len;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001636}
1637
1638
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001639static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001640{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001641 return 0 == pMe->data_len;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001642}
1643
1644
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001645static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1646 const void *pBytes,
1647 size_t uLen,
1648 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001649{
1650 UsefulBufC Data = {pBytes, uLen};
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001651 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001652}
1653
1654
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001655static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1656 const char *szString,
1657 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001658{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001659 UsefulOutBuf_InsertUsefulBuf(pMe,
1660 (UsefulBufC){szString, strlen(szString)},
1661 uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001662}
1663
1664
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001665static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1666 uint8_t byte,
1667 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001668{
1669 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1670}
1671
1672
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001673static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1674 uint16_t uInteger16,
1675 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001676{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001677 // See UsefulOutBuf_InsertUint64() for comments on this code
1678
1679 const void *pBytes;
1680
1681#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1682 pBytes = &uInteger16;
1683
1684#elif defined(USEFULBUF_CONFIG_HTON)
1685 uint16_t uTmp = htons(uInteger16);
1686 pBytes = &uTmp;
1687
1688#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1689 uint16_t uTmp = __builtin_bswap16(uInteger16);
1690 pBytes = &uTmp;
1691
1692#else
1693 uint8_t aTmp[2];
1694
1695 aTmp[0] = (uInteger16 & 0xff00) >> 8;
1696 aTmp[1] = (uInteger16 & 0xff);
1697
1698 pBytes = aTmp;
1699#endif
1700
1701 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001702}
1703
1704
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001705static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1706 uint32_t uInteger32,
1707 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001708{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001709 // See UsefulOutBuf_InsertUint64() for comments on this code
1710
1711 const void *pBytes;
1712
1713#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1714 pBytes = &uInteger32;
1715
1716#elif defined(USEFULBUF_CONFIG_HTON)
1717 uint32_t uTmp = htonl(uInteger32);
1718 pBytes = &uTmp;
1719
1720#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1721 uint32_t uTmp = __builtin_bswap32(uInteger32);
1722
1723 pBytes = &uTmp;
1724
1725#else
1726 uint8_t aTmp[4];
1727
1728 aTmp[0] = (uInteger32 & 0xff000000) >> 24;
1729 aTmp[1] = (uInteger32 & 0xff0000) >> 16;
1730 aTmp[2] = (uInteger32 & 0xff00) >> 8;
1731 aTmp[3] = (uInteger32 & 0xff);
1732
1733 pBytes = aTmp;
1734#endif
1735
1736 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
1737}
1738
1739static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
1740 uint64_t uInteger64,
1741 size_t uPos)
1742{
1743 const void *pBytes;
1744
1745#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1746 // We have been told explicitly we are running on a big-endian
1747 // machine. Network byte order is big endian, so just copy. There
1748 // is no issue with alignment here because uInter64 is always
1749 // aligned (and it doesn't matter if pBytes is aligned).
1750 pBytes = &uInteger64;
1751
1752#elif defined(USEFULBUF_CONFIG_HTON)
1753 // Use system function to handle big- and little-endian. This works
1754 // on both big- and little-endian machines, but hton() is not
1755 // always available or in a standard place so it is not used by
1756 // default. With some compilers and CPUs the code for this is very
1757 // compact through use of a special swap instruction and on
1758 // big-endian machines hton() will reduce to nothing.
1759 uint64_t uTmp = htonll(uInteger64);
1760
1761 pBytes = &uTmp;
1762
1763#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1764 // Use built-in function for byte swapping. This usually compiles
1765 // to an efficient special byte swap instruction. Unlike hton() it
1766 // does not do this conditionally on the CPU endianness, so this
1767 // code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1768 uint64_t uTmp = __builtin_bswap64(uInteger64);
1769
1770 pBytes = &uTmp;
1771
1772#else
1773 // Default which works on every CPU with no dependency on anything
1774 // from the CPU, compiler, libraries or OS. This always works, but
1775 // it is usually a little larger and slower than hton().
1776 uint8_t aTmp[8];
1777
1778 aTmp[0] = (uInteger64 & 0xff00000000000000) >> 56;
1779 aTmp[1] = (uInteger64 & 0xff000000000000) >> 48;
1780 aTmp[2] = (uInteger64 & 0xff0000000000) >> 40;
1781 aTmp[3] = (uInteger64 & 0xff00000000) >> 32;
1782 aTmp[4] = (uInteger64 & 0xff000000) >> 24;
1783 aTmp[5] = (uInteger64 & 0xff0000) >> 16;
1784 aTmp[6] = (uInteger64 & 0xff00) >> 8;
1785 aTmp[7] = (uInteger64 & 0xff);
1786
1787 pBytes = aTmp;
1788#endif
1789
1790 // Do the insert
1791 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001792}
1793
1794
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001795static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1796 float f,
1797 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001798{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001799 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001800}
1801
1802
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001803static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1804 double d,
1805 size_t uPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001806{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001807 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001808}
1809
1810
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001811static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
1812 UsefulBufC NewData)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001813{
1814 // An append is just a insert at the end
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001815 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001816}
1817
1818
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001819static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
1820 const void *pBytes,
1821 size_t uLen)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001822{
1823 UsefulBufC Data = {pBytes, uLen};
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001824 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001825}
1826
1827
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001828static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
1829 const char *szString)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001830{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001831 UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001832}
1833
1834
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001835static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
1836 uint8_t byte)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001837{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001838 UsefulOutBuf_AppendData(pMe, &byte, 1);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001839}
1840
1841
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001842static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
1843 uint16_t uInteger16)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001844{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001845 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
1846}
1847
1848static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
1849 uint32_t uInteger32)
1850{
1851 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001852}
1853
1854
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001855static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
1856 uint64_t uInteger64)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001857{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001858 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001859}
1860
1861
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001862static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
1863 float f)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001864{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001865 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001866}
1867
1868
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001869static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
1870 double d)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001871{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001872 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001873}
1874
1875
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001876static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001877{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001878 return pMe->err;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001879}
1880
1881
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001882static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001883{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001884 return pMe->UB.len - pMe->data_len;
1885}
1886
1887
1888static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
1889{
1890 return uLen <= UsefulOutBuf_RoomLeft(pMe);
1891}
1892
1893
1894static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
1895{
1896 return pMe->UB.ptr == NULL;
1897}
1898
1899
1900
1901static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
1902{
1903 pMe->cursor = 0;
1904 pMe->err = 0;
1905 pMe->magic = UIB_MAGIC;
1906 pMe->UB = UB;
1907}
1908
1909static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
1910{
1911 return pMe->cursor;
1912}
1913
1914
1915static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
1916{
1917 if(uPos > pMe->UB.len) {
1918 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001919 } else {
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001920 pMe->cursor = uPos;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001921 }
1922}
1923
1924
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001925static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001926{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001927 // Code Reviewers: THIS FUNCTION DOES POINTER MATH
1928
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001929 // Magic number is messed up. Either the structure got overwritten
1930 // or was never initialized.
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001931 if(pMe->magic != UIB_MAGIC) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001932 return 0;
1933 }
1934
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001935 // The cursor is off the end of the input buffer given.
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001936 // Presuming there are no bugs in this code, this should never happen.
1937 // If it so, the struct was corrupted. The check is retained as
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001938 // as a defense in case there is a bug in this code or the struct is
1939 // corrupted.
1940 if(pMe->cursor > pMe->UB.len) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001941 return 0;
1942 }
1943
1944 // subtraction can't go neative because of check above
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001945 return pMe->UB.len - pMe->cursor;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001946}
1947
1948
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001949static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001950{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001951 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001952}
1953
1954
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001955static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001956{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001957 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001958 if(!pResult) {
1959 return NULLUsefulBufC;
1960 } else {
1961 return (UsefulBufC){pResult, uNum};
1962 }
1963}
1964
1965
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001966static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001967{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001968 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001969
1970 return pResult ? *(uint8_t *)pResult : 0;
1971}
1972
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001973static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001974{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001975 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001976
1977 if(!pResult) {
1978 return 0;
1979 }
1980
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001981 // See UsefulInputBuf_GetUint64() for comments on this code
1982#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
1983 uint16_t uTmp;
1984 memcpy(&uTmp, pResult, sizeof(uint16_t));
1985
1986#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1987 return uTmp;
1988
1989#elif defined(USEFULBUF_CONFIG_HTON)
1990 return ntohs(uTmp);
1991
1992#else
1993 return __builtin_bswap16(uTmp);
1994
1995#endif
1996
1997#else
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001998 return ((uint16_t)pResult[0] << 8) + (uint16_t)pResult[1];
Laurence Lundblade852a33c2019-06-11 09:00:07 -07001999
2000#endif
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002001}
2002
2003
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002004static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002005{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002006 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002007
2008 if(!pResult) {
2009 return 0;
2010 }
2011
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002012 // See UsefulInputBuf_GetUint64() for comments on this code
2013#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2014 uint32_t uTmp;
2015 memcpy(&uTmp, pResult, sizeof(uint32_t));
2016
2017#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2018 return uTmp;
2019
2020#elif defined(USEFULBUF_CONFIG_HTON)
2021 return ntohl(uTmp);
2022
2023#else
2024 return __builtin_bswap32(uTmp);
2025
2026#endif
2027
2028#else
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002029 return ((uint32_t)pResult[0]<<24) +
2030 ((uint32_t)pResult[1]<<16) +
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002031 ((uint32_t)pResult[2]<<8) +
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002032 (uint32_t)pResult[3];
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002033#endif
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002034}
2035
2036
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002037static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002038{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002039 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002040
2041 if(!pResult) {
2042 return 0;
2043 }
2044
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002045#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
2046 // pResult will probably not be aligned. This memcpy() moves the
2047 // bytes into a temp variable safely for CPUs that can or can't do
2048 // unaligned memory access. Many compilers will optimize the
2049 // memcpy() into a simple move instruction.
2050 uint64_t uTmp;
2051 memcpy(&uTmp, pResult, sizeof(uint64_t));
2052
2053#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2054 // We have been told expliclity this is a big-endian CPU. Since
2055 // network byte order is big-endian, there is nothing to do.
2056
2057 return uTmp;
2058
2059#elif defined(USEFULBUF_CONFIG_HTON)
2060 // We have been told to use ntoh(), the system function to handle
2061 // big- and little-endian. This works on both big- and
2062 // little-endian machines, but ntoh() is not always available or in
2063 // a standard place so it is not used by default. On some CPUs the
2064 // code for this is very compact through use of a special swap
2065 // instruction.
2066
2067 return ntohll(uTmp);
2068
2069#else
2070 // Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2071 // USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2072 // __builtin_bswap64() and friends are not conditional on CPU
2073 // endianness so this must only be used on little-endian machines.
2074
2075 return __builtin_bswap64(uTmp);
2076
2077
2078#endif
2079
2080#else
2081 // This is the default code that works on every CPU and every
2082 // endianness with no dependency on ntoh(). This works on CPUs
2083 // that either allow or do not allow unaligned access. It will
2084 // always work, but usually is a little less efficient than ntoh().
2085
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002086 return ((uint64_t)pResult[0]<<56) +
2087 ((uint64_t)pResult[1]<<48) +
2088 ((uint64_t)pResult[2]<<40) +
2089 ((uint64_t)pResult[3]<<32) +
2090 ((uint64_t)pResult[4]<<24) +
2091 ((uint64_t)pResult[5]<<16) +
2092 ((uint64_t)pResult[6]<<8) +
2093 (uint64_t)pResult[7];
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002094#endif
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002095}
2096
2097
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002098static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002099{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002100 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002101
2102 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
2103}
2104
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002105
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002106static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002107{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002108 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002109
2110 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
2111}
2112
2113
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002114static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002115{
Laurence Lundblade852a33c2019-06-11 09:00:07 -07002116 return pMe->err;
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002117}
2118
Laurence Lundbladed425fb32019-02-18 10:56:18 -08002119#ifdef __cplusplus
2120}
2121#endif
2122
Laurence Lundblade6ed34222018-12-18 09:46:23 -08002123#endif // _UsefulBuf_h
2124
2125