blob: a8da83b643b5429f2d9f55918941a7e531131b95 [file] [log] [blame]
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001/*============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladec5fef682020-01-25 11:38:45 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08004
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07005Redistribution 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.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080018
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070019THIS 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 Lundblade5cc25682019-03-26 21:58:35 +010030 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070031
Laurence Lundblade5cc25682019-03-26 21:58:35 +010032/*============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033 FILE: UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070035 DESCRIPTION: General purpose input and output buffers
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070039 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080041
Laurence Lundblade5cc25682019-03-26 21:58:35 +010042 when who what, where, why
43 -------- ---- --------------------------------------------------
Laurence Lundbladec5fef682020-01-25 11:38:45 -080044 1/25/2020 llundblade Add some casts so static anlyzers don't complain.
Laurence Lundblade635993b2019-03-25 03:06:14 +010045 5/21/2019 llundblade #define configs for efficient endianness handling.
Laurence Lundblade30dd0ba2019-05-26 23:37:30 +030046 5/16/2019 llundblade Add UsefulOutBuf_IsBufferNULL().
Laurence Lundblade5cc25682019-03-26 21:58:35 +010047 3/23/2019 llundblade Big documentation & style update. No interface
48 change.
49 3/6/2019 llundblade Add UsefulBuf_IsValue()
50 12/17/2018 llundblade Remove const from UsefulBuf and UsefulBufC .len
51 12/13/2018 llundblade Documentation improvements
52 09/18/2018 llundblade Cleaner distinction between UsefulBuf and
53 UsefulBufC.
54 02/02/18 llundbla Full support for integers in and out; fix pointer
55 alignment bug. Incompatible change: integers
56 in/out are now in network byte order.
57 08/12/17 llundbla Added UsefulOutBuf_AtStart and UsefulBuf_Find
58 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected
59 comparison for < or > for unequal length buffers.
60 Added UsefulBuf_Set() function.
61 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
62 11/13/16 llundbla Initial Version.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070063
Laurence Lundblade5cc25682019-03-26 21:58:35 +010064 =============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070065
66#ifndef _UsefulBuf_h
67#define _UsefulBuf_h
68
69
Laurence Lundblade635993b2019-03-25 03:06:14 +010070/*
71 Configuration Options
72
73 This code is designed so it will work correctly and completely by
74 default. No configuration is necessary to make it work. None of the
75 following #defines need to be enabled. The code works and is very
76 portable with them all turned off.
77
78 All configuration options (USEFULBUF_CONFIG_XXX)
79 1) Reduce code size
80 2) Improve efficiency
81 3) Both of the above
82
83 The efficiency improvements are not large, so the main reason really
84 is to reduce code size.
Laurence Lundblade1e67a942019-05-18 14:48:07 -070085
Laurence Lundblade635993b2019-03-25 03:06:14 +010086 */
87
88
89/*
90 Endianness Configuration
91
Laurence Lundblade7f08cba2019-03-25 19:27:36 +010092 By default, UsefulBuf does not need to know what the endianness of
93 the device is. All the code will run correctly on either big or
94 little endian CPUs.
Laurence Lundblade635993b2019-03-25 03:06:14 +010095
Laurence Lundbladeaf9cbc62019-06-09 08:02:18 -070096 Here's the recipe for configuring the endianness-related #defines
97 to use more efficient CPU/OS/compiler dependent features to reduce
98 code size. Note these only affect the integer arrays (tagged
99 arrays) feature of QCBOR. All other endianness handling in
100 QCBOR is integrated with code that also handles alignment and
101 preferred encoding.
Laurence Lundblade635993b2019-03-25 03:06:14 +0100102
103 The first option is to not define anything. This will work fine on
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100104 with all CPU's, OS's and compilers. The code for encoding
105 integers will be a little larger and slower.
Laurence Lundblade635993b2019-03-25 03:06:14 +0100106
107 If your CPU is big-endian then define USEFULBUF_CONFIG_BIG_ENDIAN. This
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100108 will give the most efficient code for big-endian CPUs. It will be small
Laurence Lundblade635993b2019-03-25 03:06:14 +0100109 and efficient because there will be no byte swapping.
110
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100111 Try defining USEFULBUF_CONFIG_HTON. This will work on most CPU's,
112 OS's and compilers, but not all. On big-endian CPUs this should give
113 the most efficient code, the same as USEFULBUF_CONFIG_BIG_ENDIAN
114 does. On little-endian CPUs it should call the system-defined byte
115 swapping method which is presumably implemented efficiently. In some
Laurence Lundbladeaf9cbc62019-06-09 08:02:18 -0700116 cases, this will be a dedicated byte swap instruction like Intel's
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100117 bswap.
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -0700118
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100119 If USEFULBUF_CONFIG_HTON works and you know your CPU is
120 little-endian, it is also good to define
121 USEFULBUF_CONFIG_LITTLE_ENDIAN.
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -0700122
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100123 if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
124 little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
125 USEFULBUF_CONFIG_BSWAP. This should call the most efficient
126 system-defined byte swap method. However, note
127 https://hardwarebug.org/2010/01/14/beware-the-builtins/. Perhaps
128 this is fixed now. Often hton() and ntoh() will call the built-in
Laurence Lundbladeaf9cbc62019-06-09 08:02:18 -0700129 __builtin_bswapXX()() function, so this size issue could affect
130 USEFULBUF_CONFIG_HTON.
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -0700131
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100132 Last, run the tests. They must all pass.
Laurence Lundblade635993b2019-03-25 03:06:14 +0100133
Laurence Lundblade7f08cba2019-03-25 19:27:36 +0100134 These #define config options affect the inline implementation of
135 UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64(). They
136 also affect the 16-, 32-bit, float and double versions of these
137 instructions. Since they are inline, they size effect is not in the
138 UsefulBuf object code, but in the calling code.
Laurence Lundblade427b4742019-05-18 15:06:35 -0700139
Laurence Lundbladef7ce8ba2019-06-01 11:53:50 -0700140 Summary:
141 USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
142 USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
143 USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
144 handle big and little-endian with system option.
145 USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
146 use __builtin_bswapXX().
Laurence Lundblade635993b2019-03-25 03:06:14 +0100147 */
148
149#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
150#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
151#endif
152
153
Laurence Lundblade74f68412018-09-13 12:18:49 -0700154#include <stdint.h> // for uint8_t, uint16_t....
155#include <string.h> // for strlen, memcpy, memmove, memset
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156#include <stddef.h> // for size_t
157
Laurence Lundblade635993b2019-03-25 03:06:14 +0100158
159#ifdef USEFULBUF_CONFIG_HTON
160#include <arpa/inet.h> // for htons, htonl, htonll, ntohs...
161#endif
162
Laurence Lundbladec5a61c62019-02-21 14:21:38 -0800163#ifdef __cplusplus
164extern "C" {
165#endif
166
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700167/**
Laurence Lundblade2296db52018-09-14 18:08:39 -0700168 @file UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800169
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170 The goal of this code is to make buffer and pointer manipulation
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700171 easier and safer when working with binary data.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800172
Laurence Lundblade077475f2019-04-26 09:06:33 -0700173 The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100174 structures are used to represent buffers rather than ad hoc pointers and
175 lengths.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800176
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100177 With these it will often be possible to write code that does little
178 or no direct pointer manipulation for copying and formatting
179 data. For example, the QCBOR encoder was written using these and
180 has no less pointer manipulation.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800181
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100182 While it is true that object code using these functions will be a
183 little larger and slower than a white-knuckle clever use of pointers
184 might be, but not by that much or enough to have an effect for most
185 use cases. For security-oriented code this is highly
186 worthwhile. Clarity, simplicity, reviewability and are more
187 important.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700188
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100189 There are some extra sanity and double checks in this code to help
190 catch coding errors and simple memory corruption. They are helpful,
191 but not a substitute for proper code review, input validation and
192 such.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700193
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100194 This code consists of a lot of inline functions and a few that are
195 not. It should not generate very much object code, especially with
Laurence Lundblade077475f2019-04-26 09:06:33 -0700196 the optimizer turned up to @c -Os or @c -O3.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197 */
198
199
200/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700201 @ref UsefulBufC and @ref UsefulBuf are simple data structures to hold
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100202 a pointer and length for binary data. In C99 this data structure can
203 be passed on the stack making a lot of code cleaner than carrying
204 around a pointer and length as two parameters.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100206 This is also conducive to secure coding practice as the length is
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700207 always carried with the pointer and the convention for handling a
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700208 pointer and a length is clear.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800209
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700210 While it might be possible to write buffer and pointer code more
211 efficiently in some use cases, the thought is that unless there is an
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100212 extreme need for performance (e.g., you are building a
213 gigabit-per-second IP router), it is probably better to have cleaner
214 code you can be most certain about the security of.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800215
Laurence Lundblade077475f2019-04-26 09:06:33 -0700216 The non-const @ref UsefulBuf is usually used to refer a buffer to be
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100217 filled in. The length is the size of the buffer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800218
Laurence Lundblade077475f2019-04-26 09:06:33 -0700219 The const @ref UsefulBufC is usually used to refer to some data that
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100220 has been filled in. The length is amount of valid data pointed to.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800221
Laurence Lundblade077475f2019-04-26 09:06:33 -0700222 A common use is to pass a @ref UsefulBuf to a function, the function
223 fills it in, the function returns a @ref UsefulBufC. The pointer is
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100224 the same in both.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800225
Laurence Lundblade077475f2019-04-26 09:06:33 -0700226 A @ref UsefulBuf is null, it has no value, when @c ptr in it is @c NULL.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800227
Laurence Lundbladeeae73ba2018-11-15 16:51:27 -0800228 There are utility functions for the following:
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100229 - Initializing
Laurence Lundblade077475f2019-04-26 09:06:33 -0700230 - Create initialized const @ref UsefulBufC from compiler literals
231 - Create initialized const @ref UsefulBufC from NULL-terminated string
232 - Make an empty @ref UsefulBuf on the stack
233 - Checking whether a @ref UsefulBuf is null, empty or both
Laurence Lundbladeeae73ba2018-11-15 16:51:27 -0800234 - Copying, copying with offset, copying head or tail
235 - Comparing and finding substrings
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800236
Laurence Lundblade077475f2019-04-26 09:06:33 -0700237 See also @ref UsefulOutBuf. It is a richer structure that has both
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100238 the size of the valid data and the size of the buffer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800239
Laurence Lundblade077475f2019-04-26 09:06:33 -0700240 @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so it
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100241 can go on the stack and be a function parameter or return value.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800242
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100243 Another way to look at it is this. C has the NULL-terminated string
244 as a means for handling text strings, but no means or convention for
245 binary strings. Other languages do have such means, Rust, an
246 efficient compiled language, for example.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800247
Laurence Lundblade077475f2019-04-26 09:06:33 -0700248 @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on his
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100249 birthday. Eeyore's balloon fits beautifully, "it goes in and out
250 like anything".
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251*/
Laurence Lundblade6ca805a2019-02-20 10:43:43 -0800252typedef struct q_useful_buf_c {
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700253 const void *ptr;
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800254 size_t len;
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700255} UsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700257
258/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700259 This non-const @ref UsefulBuf is typically used for some allocated
260 memory that is to be filled in. The @c len is the amount of memory,
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700261 not the length of the valid data in the buffer.
262 */
Laurence Lundblade6ca805a2019-02-20 10:43:43 -0800263typedef struct q_useful_buf {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700264 void *ptr;
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800265 size_t len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700266} UsefulBuf;
267
268
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700269/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700270 A null @ref UsefulBufC is one that has no value in the same way a @c
271 NULL pointer has no value. A @ref UsefulBufC is @c NULL when the @c
272 ptr field is @c NULL. It doesn't matter what @c len is. See
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100273 UsefulBuf_IsEmpty() for the distinction between null and empty.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700274 */
275#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
276
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100277
278/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700279 A null @ref UsefulBuf is one that has no memory associated the same
280 way @c NULL points to nothing. It does not matter what @c len is.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700281 */
282#define NULLUsefulBuf ((UsefulBuf) {NULL, 0})
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700283
284
Laurence Lundblade2296db52018-09-14 18:08:39 -0700285/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700286 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800287
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100288 @param[in] UB The UsefulBuf to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundblade077475f2019-04-26 09:06:33 -0700290 @return 1 if it is @ref NULLUsefulBuf, 0 if not.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700291 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100292static inline int UsefulBuf_IsNULL(UsefulBuf UB);
Laurence Lundblade2296db52018-09-14 18:08:39 -0700293
Laurence Lundblade2296db52018-09-14 18:08:39 -0700294
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700295/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700296 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundblade077475f2019-04-26 09:06:33 -0700298 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800299
Laurence Lundblade077475f2019-04-26 09:06:33 -0700300 @return 1 if it is @c NULLUsefulBufC, 0 if not.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700301 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100302static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
Laurence Lundblade2296db52018-09-14 18:08:39 -0700303
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700304
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700305/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700306 @brief Check if a @ref UsefulBuf is empty or not.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800307
Laurence Lundblade077475f2019-04-26 09:06:33 -0700308 @param[in] UB The @ref UsefulBuf to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800309
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700310 @return 1 if it is empty, 0 if not.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Laurence Lundblade077475f2019-04-26 09:06:33 -0700312 An "empty" @ref UsefulBuf is one that has a value and can be
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100313 considered to be set, but that value is of zero length. It is empty
Laurence Lundblade077475f2019-04-26 09:06:33 -0700314 when @c len is zero. It doesn't matter what the @c ptr is.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800315
Laurence Lundblade077475f2019-04-26 09:06:33 -0700316 A lot of uses will not need to clearly distinguish a @c NULL @ref
317 UsefulBuf from an empty one and can have the @c ptr @c NULL and the
318 @c len 0. However if a use of @ref UsefulBuf needs to make a
319 distinction then @c ptr should not be @c NULL when the @ref UsefulBuf
320 is considered empty, but not @c NULL.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700321 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100322static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700323
324
325/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700326 @brief Check if a @ref UsefulBufC is empty or not.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800327
Laurence Lundblade077475f2019-04-26 09:06:33 -0700328 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800329
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700330 @return 1 if it is empty, 0 if not.
331 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100332static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700333
334
335/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700336 @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800337
Laurence Lundblade077475f2019-04-26 09:06:33 -0700338 @param[in] UB The @ref UsefulBuf to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800339
Laurence Lundblade077475f2019-04-26 09:06:33 -0700340 @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700341 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100342static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700343
344
345/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700346 @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800347
Laurence Lundblade077475f2019-04-26 09:06:33 -0700348 @param[in] UB The @ref UsefulBufC to check.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800349
Laurence Lundblade077475f2019-04-26 09:06:33 -0700350 @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700351 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100352static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700353
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700354
355/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700356 @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800357
Laurence Lundblade077475f2019-04-26 09:06:33 -0700358 @param[in] UB The @ref UsefulBuf to convert.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800359
Laurence Lundblade077475f2019-04-26 09:06:33 -0700360 @return A @ref UsefulBufC struct.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700361 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100362static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700363
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700364
365/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700366 @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800367
Laurence Lundblade077475f2019-04-26 09:06:33 -0700368 @param[in] UBC The @ref UsefulBuf to convert.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800369
Laurence Lundblade077475f2019-04-26 09:06:33 -0700370 @return A non-const @ref UsefulBuf struct.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700371 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100372static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700373
374
375/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700376 Convert a literal string to a @ref UsefulBufC.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800377
Laurence Lundblade077475f2019-04-26 09:06:33 -0700378 @c szString must be a literal string that @c sizeof() works on. This
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100379 is better for literal strings than UsefulBuf_FromSZ() because it
380 generates less code. It will not work on non-literal strings.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800381
Laurence Lundblade2296db52018-09-14 18:08:39 -0700382 The terminating \0 (NULL) is NOT included in the length!
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700383 */
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530384#define UsefulBuf_FROM_SZ_LITERAL(szString) \
Laurence Lundblade2296db52018-09-14 18:08:39 -0700385 ((UsefulBufC) {(szString), sizeof(szString)-1})
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700386
Laurence Lundblade2296db52018-09-14 18:08:39 -0700387
388/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700389 Convert a literal byte array to a @ref UsefulBufC.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800390
Laurence Lundblade077475f2019-04-26 09:06:33 -0700391 @c pBytes must be a literal string that @c sizeof() works on. It
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100392 will not work on non-literal arrays.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700393 */
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530394#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
Laurence Lundblade2296db52018-09-14 18:08:39 -0700395 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
396
397
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700398/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700399 Make an automatic variable named @c name of type @ref UsefulBuf and
400 point it to a stack variable of the given @c size.
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700401 */
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530402#define UsefulBuf_MAKE_STACK_UB(name, size) \
Laurence Lundblade2296db52018-09-14 18:08:39 -0700403 uint8_t __pBuf##name[(size)];\
404 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700405
406
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700407/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700408 Make a byte array in to a @ref UsefulBuf. This is usually used on
409 stack variables or static variables. Also see @ref
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100410 UsefulBuf_MAKE_STACK_UB.
Laurence Lundblade369b90a2018-10-22 02:04:37 +0530411 */
Laurence Lundblade4fe9f312018-10-22 10:22:39 +0530412#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
Laurence Lundblade369b90a2018-10-22 02:04:37 +0530413 ((UsefulBuf) {(pBytes), sizeof(pBytes)})
414
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100415
Laurence Lundblade369b90a2018-10-22 02:04:37 +0530416/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700417 @brief Convert a NULL-terminated string to a @ref UsefulBufC.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100419 @param[in] szString The string to convert.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800420
Laurence Lundblade077475f2019-04-26 09:06:33 -0700421 @return A @ref UsefulBufC struct.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700422
Laurence Lundblade077475f2019-04-26 09:06:33 -0700423 @c UsefulBufC.ptr points to the string so its lifetime must be
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100424 maintained.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800425
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100426 The terminating \0 (NULL) is NOT included in the length.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700427 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100428static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700429
430
431/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700432 @brief Copy one @ref UsefulBuf into another at an offset.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800433
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100434 @param[in] Dest Destination buffer to copy into.
Laurence Lundblade077475f2019-04-26 09:06:33 -0700435 @param[in] uOffset The byte offset in @c Dest at which to copy to.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100436 @param[in] Src The bytes to copy.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800437
Laurence Lundblade077475f2019-04-26 09:06:33 -0700438 @return Pointer and length of the copy or @ref NULLUsefulBufC.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800439
Laurence Lundblade077475f2019-04-26 09:06:33 -0700440 This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
441 size of @c Dest.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800442
Laurence Lundblade077475f2019-04-26 09:06:33 -0700443 This fails and returns @ref NULLUsefulBufC if the @c Src length plus
444 @c uOffset is greater than the length of @c Dest.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800445
Laurence Lundblade077475f2019-04-26 09:06:33 -0700446 The results are undefined if @c Dest and @c Src overlap.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800447
Laurence Lundblade077475f2019-04-26 09:06:33 -0700448 This assumes that there is valid data in @c Dest up to @c
449 uOffset. The @ref UsefulBufC returned starts at the beginning of @c
450 Dest and goes to @c Src.len @c + @c uOffset.
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530451 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700452UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
453
454
Laurence Lundblade981ab672018-10-26 13:11:29 +0700455/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700456 @brief Copy one @ref UsefulBuf into another.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800457
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100458 @param[in] Dest The destination buffer to copy into.
459 @param[out] Src The source to copy from.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800460
Laurence Lundblade077475f2019-04-26 09:06:33 -0700461 @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100462 on failure.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800463
Laurence Lundblade077475f2019-04-26 09:06:33 -0700464 This fails if @c Src.len is greater than @c Dest.len.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800465
Laurence Lundblade077475f2019-04-26 09:06:33 -0700466 Note that like @c memcpy(), the pointers are not checked and this
467 will crash rather than return @ref NULLUsefulBufC if they are @c
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100468 NULL or invalid.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800469
Laurence Lundblade077475f2019-04-26 09:06:33 -0700470 The results are undefined if @c Dest and @c Src overlap.
Laurence Lundblade981ab672018-10-26 13:11:29 +0700471 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100472static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
473
474
475/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700476 @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100477
478 @param[in] pDest The destination buffer to copy into.
479 @param[in] value The value to set the bytes to.
480
Laurence Lundblade077475f2019-04-26 09:06:33 -0700481 Note that like @c memset(), the pointer in @c pDest is not checked
482 and this will crash if @c NULL or invalid.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100483 */
484static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
485
486
487/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700488 @brief Copy a pointer into a @ref UsefulBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100489
490 @param[in,out] Dest The destination buffer to copy into.
491 @param[in] ptr The source to copy from.
492 @param[in] uLen Length of the source; amount to copy.
493
494 @return 0 on success, 1 on failure.
495
Laurence Lundblade077475f2019-04-26 09:06:33 -0700496 This fails and returns @ref NULLUsefulBufC if @c uLen is greater than
497 @c pDest->len.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100498
Laurence Lundblade077475f2019-04-26 09:06:33 -0700499 Note that like @c memcpy(), the pointers are not checked and this
500 will crash, rather than return 1 if they are @c NULL or invalid.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100501 */
502static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
503 const void *ptr,
504 size_t uLen);
505
506
507/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700508 @brief Returns a truncation of a @ref UsefulBufC.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100509
510 @param[in] UB The buffer to get the head of.
511 @param[in] uAmount The number of bytes in the head.
512
Laurence Lundblade077475f2019-04-26 09:06:33 -0700513 @return A @ref UsefulBufC that is the head of UB.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100514 */
515static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
516
517
518/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700519 @brief Returns bytes from the end of a @ref UsefulBufC.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100520
521 @param[in] UB The buffer to get the tail of.
522 @param[in] uAmount The offset from the start where the tail is to begin.
523
Laurence Lundblade077475f2019-04-26 09:06:33 -0700524 @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
525 if @c uAmount is greater than the length of the @ref UsefulBufC.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100526
Laurence Lundblade077475f2019-04-26 09:06:33 -0700527 If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
528 be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100529 of the tail.
530 */
531static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
532
533
534/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700535 @brief Compare one @ref UsefulBufC to another.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100536
537 @param[in] UB1 The first buffer to compare.
538 @param[in] UB2 The second buffer to compare.
539
540 @return 0, positive or negative value.
541
Laurence Lundblade077475f2019-04-26 09:06:33 -0700542 Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
543 less than @c UB2 if it is shorter or the first byte that is not the
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100544 same is less.
545
546 Returns 0 if the inputs are the same.
547
Laurence Lundblade077475f2019-04-26 09:06:33 -0700548 Returns a positive value if @c UB2 is less than @c UB1.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100549
550 All that is of significance is that the result is positive, negative
551 or 0. (This doesn't return the difference between the first
Laurence Lundblade077475f2019-04-26 09:06:33 -0700552 non-matching byte like @c memcmp() ).
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100553 */
554int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
555
556
557/**
558 @brief Find first byte that is not a particular byte value.
559
560 @param[in] UB The destination buffer for byte comparison.
561 @param[in] uValue The byte value to compare to.
562
Laurence Lundblade077475f2019-04-26 09:06:33 -0700563 @return Offset of first byte that isn't @c uValue or
564 @c SIZE_MAX if all bytes are @c uValue.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100565
566 Note that unlike most comparison functions, 0
567 does not indicate a successful comparison, so the
568 test for match is:
569
570 UsefulBuf_IsValue(...) == SIZE_MAX
571
Laurence Lundblade077475f2019-04-26 09:06:33 -0700572 If @c UB is null or empty, there is no match
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100573 and 0 is returned.
574 */
575size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
576
577
578/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700579 @brief Find one @ref UsefulBufC in another.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100580
581 @param[in] BytesToSearch Buffer to search through.
582 @param[in] BytesToFind Buffer with bytes to be found.
583
Laurence Lundblade077475f2019-04-26 09:06:33 -0700584 @return Position of found bytes or @c SIZE_MAX if not found.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100585 */
586size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
587
588
589#if 1 // NOT_DEPRECATED
Laurence Lundblade077475f2019-04-26 09:06:33 -0700590/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100591#define SZLiteralToUsefulBufC(szString) \
592 ((UsefulBufC) {(szString), sizeof(szString)-1})
593
594/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
595#define MakeUsefulBufOnStack(name, size) \
596 uint8_t __pBuf##name[(size)];\
597 UsefulBuf name = {__pBuf##name , sizeof( __pBuf##name )}
598
Laurence Lundblade077475f2019-04-26 09:06:33 -0700599/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100600#define ByteArrayLiteralToUsefulBufC(pBytes) \
601 ((UsefulBufC) {(pBytes), sizeof(pBytes)})
602
603/** Deprecated function; use UsefulBuf_Unconst() instead */
604static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
605{
606 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
607}
608#endif
609
610
611
612
613/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700614 @brief Copy a @c float to a @c uint32_t.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100615
616 @param[in] f Float value to copy.
617
Laurence Lundblade077475f2019-04-26 09:06:33 -0700618 @return A @c uint32_t with the float bits.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100619
620 Convenience function to avoid type punning, compiler warnings and
621 such. The optimizer usually reduces this to a simple assignment. This
622 is a crusty corner of C.
623 */
624static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
625
626
627/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700628 @brief Copy a @c double to a @c uint64_t.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100629
630 @param[in] d Double value to copy.
631
Laurence Lundblade077475f2019-04-26 09:06:33 -0700632 @return A @c uint64_t with the double bits.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100633
634 Convenience function to avoid type punning, compiler warnings and
635 such. The optimizer usually reduces this to a simple assignment. This
636 is a crusty corner of C.
637 */
638static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
639
640
641/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700642 @brief Copy a @c uint32_t to a @c float.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100643
644 @param[in] u32 Integer value to copy.
645
Laurence Lundblade077475f2019-04-26 09:06:33 -0700646 @return The value as a @c float.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100647
648 Convenience function to avoid type punning, compiler warnings and
649 such. The optimizer usually reduces this to a simple assignment. This
650 is a crusty corner of C.
651 */
652static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
653
654
655/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700656 @brief Copy a @c uint64_t to a @c double.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100657
658 @param[in] u64 Integer value to copy.
659
Laurence Lundblade077475f2019-04-26 09:06:33 -0700660 @return The value as a @c double.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100661
662 Convenience function to avoid type punning, compiler warnings and
663 such. The optimizer usually reduces this to a simple assignment. This
664 is a crusty corner of C.
665 */
666static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
667
668
669
670
671/**
672 UsefulOutBuf is a structure and functions (an object) for serializing
673 data into a buffer when encoding a network protocol or writing data
674 to file.
675
676 The main idea is that all the pointer manipulation is performed by
Laurence Lundblade077475f2019-04-26 09:06:33 -0700677 @ref UsefulOutBuf functions so the caller doesn't have to do any
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100678 pointer manipulation. The pointer manipulation is centralized. This
679 code will have been reviewed and written carefully so it spares the
680 caller of much of this work and results in safer code with less work.
681
Laurence Lundblade077475f2019-04-26 09:06:33 -0700682 The @ref UsefulOutBuf methods that add data to the output buffer
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100683 always check the length and will never write off the end of the
684 output buffer. If an attempt to add data that will not fit is made,
685 an internal error flag will be set and further attempts to add data
686 will not do anything.
687
688 There is no way to ever write off the end of that buffer when calling
Laurence Lundblade077475f2019-04-26 09:06:33 -0700689 the @c UsefulOutBuf_AddXxx() and @c UsefulOutBuf_InsertXxx()
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100690 functions.
691
692 The functions to add data do not return an error. The working model
693 is that all calls to add data are made without an error check. Errors
694 are just checked for once after all the data has been added before the
695 and before serialized data is to be used. This makes the calling code
696 cleaner.
697
698 There is a utility function to get the error status anytime along the
699 way for a special circumstance. There are functions to see how much
700 room is left and see if some data will fit too, but their use is
701 generally not necessary.
702
703 The general call flow is:
704
Laurence Lundblade077475f2019-04-26 09:06:33 -0700705 - Initialize by calling @ref UsefulOutBuf_Init(). The output
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100706 buffer given to it can be from the heap, stack or
Laurence Lundblade077475f2019-04-26 09:06:33 -0700707 otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience macro
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100708 that makes a buffer on the stack and initializes it.
709
710 - Call methods like UsefulOutBuf_InsertString(),
711 UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
712 to output data. The append calls add data to the end of the
713 valid data. The insert calls take a position argument.
714
715 - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
716 there were no errors and to get the serialized output bytes.
717
Laurence Lundblade077475f2019-04-26 09:06:33 -0700718 @ref UsefulOutBuf can be used in a size calculation mode to calculate
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100719 the size of output that would be generated. This is useful to
720 calculate the size of a buffer that is to be allocated to hold the
Laurence Lundblade077475f2019-04-26 09:06:33 -0700721 output. To use @ref UsefulOutBuf in this mode, call
722 UsefulOutBuf_Init() with the @c Storage @ref UsefulBuf as
723 @c (UsefulBuf){NULL,MAX_UINT32}. Then call all the Insert and Add
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100724 functions. No attempt will made to actually copy data, so only the
725 lengths have to be valid for these calls.
726
727 Methods like UsefulOutBuf_InsertUint64() always output in network
728 bytes order (big endian).
729
730 The possible errors are:
Laurence Lundblade077475f2019-04-26 09:06:33 -0700731 - The @ref UsefulOutBuf was not initialized or was corrupted.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100732
733 - An attempt was made to add data that will not fit.
734
735 - An attempt was made to insert data at a position beyond the end of
736 the buffer.
737
738 - An attempt was made to insert data at a position beyond the valid
739 data in the buffer.
740
741 Some inexpensive simple sanity checks are performed before every data
742 addition to guard against use of an uninitialized or corrupted
743 UsefulOutBuf.
744
745 This has been used to create a CBOR encoder. The CBOR encoder has
746 almost no pointer manipulation in it, is easier to read, and easier
747 to review.
748
Laurence Lundblade077475f2019-04-26 09:06:33 -0700749 A @ref UsefulOutBuf is small and can go on the stack:
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100750 - 32 bytes (27 bytes plus alignment padding) on a 64-bit machine
751 - 16 bytes (15 bytes plus alignment padding) on a 32-bit machines
752 */
753typedef struct useful_out_buf {
754 // PRIVATE DATA STRUCTURE
755 UsefulBuf UB; // Memory that is being output to
756 size_t data_len; // length of the data
757 uint16_t magic; // Used to detect corruption and lack of initialization
758 uint8_t err;
759} UsefulOutBuf;
760
761
762/**
763 @brief Initialize and supply the actual output buffer.
764
Laurence Lundblade077475f2019-04-26 09:06:33 -0700765 @param[out] pUOutBuf The @ref UsefulOutBuf to initialize.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100766 @param[in] Storage Buffer to output into.
767
Laurence Lundblade077475f2019-04-26 09:06:33 -0700768 Initializes the @ref UsefulOutBuf with storage. Sets the current
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100769 position to the beginning of the buffer clears the error.
770
Laurence Lundblade077475f2019-04-26 09:06:33 -0700771 This must be called before the @ref UsefulOutBuf is used.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100772 */
773void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
774
775
776/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700777 Convenience macro to make a @ref UsefulOutBuf on the stack and
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100778 initialize it with a stack buffer of the given size. The variable
Laurence Lundblade077475f2019-04-26 09:06:33 -0700779 will be named @c name.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100780 */
781#define UsefulOutBuf_MakeOnStack(name, size) \
782 uint8_t __pBuf##name[(size)];\
783 UsefulOutBuf name;\
784 UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
785
786
787/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700788 @brief Reset a @ref UsefulOutBuf for re use
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100789
Laurence Lundblade077475f2019-04-26 09:06:33 -0700790 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100791
792 This sets the amount of data in the output buffer to none and clears
793 the error state.
794
795 The output buffer is still the same one and size as from the
796 UsefulOutBuf_Init() call.
797
798 This doesn't zero the data, just resets to 0 bytes of valid data.
799 */
800static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
801
802
803/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700804 @brief Returns position of end of data in the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100805
Laurence Lundblade077475f2019-04-26 09:06:33 -0700806 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100807
808 @return position of end of data.
809
Laurence Lundblade077475f2019-04-26 09:06:33 -0700810 On a freshly initialized @ref UsefulOutBuf with no data added, this
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100811 will return 0. After 10 bytes have been added, it will return 10 and
812 so on.
813
Laurence Lundblade077475f2019-04-26 09:06:33 -0700814 Generally callers will not need this function for most uses of @ref
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100815 UsefulOutBuf.
816 */
817static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
818
819
820/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700821 @brief Returns whether any data has been added to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100822
Laurence Lundblade077475f2019-04-26 09:06:33 -0700823 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100824
825 @return 1 if output position is at start.
826 */
827static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
828
829
830/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700831 @brief Inserts bytes into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100832
Laurence Lundblade077475f2019-04-26 09:06:33 -0700833 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100834 @param[in] NewData The bytes to insert.
835 @param[in] uPos Index in output buffer at which to insert.
836
Laurence Lundblade077475f2019-04-26 09:06:33 -0700837 @c NewData is the pointer and length for the bytes to be added to the
838 output buffer. There must be room in the output buffer for all of @c
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100839 NewData or an error will occur.
840
841 The insertion point must be between 0 and the current valid data. If
842 not, an error will occur. Appending data to the output buffer is
843 achieved by inserting at the end of the valid data. This can be
844 retrieved by calling UsefulOutBuf_GetEndPosition().
845
846 When insertion is performed, the bytes between the insertion point
847 and the end of data previously added to the output buffer are slid to
848 the right to make room for the new data.
849
Laurence Lundblade077475f2019-04-26 09:06:33 -0700850 Overlapping buffers are OK. @c NewData can point to data in the
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100851 output buffer.
852
Laurence Lundblade077475f2019-04-26 09:06:33 -0700853 If an error occurs an error state is set in the @ref UsefulOutBuf. No
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100854 error is returned. All subsequent attempts to add data will do
855 nothing.
856
857 The intended use is that all additions are made without checking for
858 an error. The error will be taken into account when
Laurence Lundblade077475f2019-04-26 09:06:33 -0700859 UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100860 UsefulOutBuf_GetError() can also be called to check for an error.
861 */
862void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
863 UsefulBufC NewData,
864 size_t uPos);
865
866
867/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700868 @brief Insert a data buffer into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100869
Laurence Lundblade077475f2019-04-26 09:06:33 -0700870 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100871 @param[in] pBytes Pointer to the bytes to insert
872 @param[in] uLen Length of the bytes to insert
873 @param[in] uPos Index in output buffer at which to insert
874
875 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
876 the difference being a pointer and length is passed in rather than an
Laurence Lundblade077475f2019-04-26 09:06:33 -0700877 @ref UsefulBufC.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100878 */
879static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
880 const void *pBytes,
881 size_t uLen,
882 size_t uPos);
883
884
885/**
886 @brief Insert a NULL-terminated string into the UsefulOutBuf.
887
Laurence Lundblade077475f2019-04-26 09:06:33 -0700888 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100889 @param[in] szString NULL-terminated string to insert.
890 @param[in] uPos Index in output buffer at which to insert.
891 */
892static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
893 const char *szString,
894 size_t uPos);
895
896
897/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700898 @brief Insert a byte into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100899
900 @param[in] pUOutBuf Pointer to the UsefulOutBuf.
901 @param[in] byte Bytes to insert.
902 @param[in] uPos Index in output buffer at which to insert.
903
904 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
905 the difference being a single byte is to be inserted.
906 */
907static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
908 uint8_t byte,
909 size_t uPos);
910
911
912/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700913 @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100914
Laurence Lundblade077475f2019-04-26 09:06:33 -0700915 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100916 @param[in] uInteger16 Integer to insert.
917 @param[in] uPos Index in output buffer at which to insert.
918
919 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
920 the difference being a two-byte integer is to be inserted.
921
922 The integer will be inserted in network byte order (big endian).
923 */
924static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
925 uint16_t uInteger16,
926 size_t uPos);
927
928
929/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700930 @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100931
Laurence Lundblade077475f2019-04-26 09:06:33 -0700932 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100933 @param[in] uInteger32 Integer to insert.
934 @param[in] uPos Index in output buffer at which to insert.
935
936 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
937 the difference being a four-byte integer is to be inserted.
938
939 The integer will be inserted in network byte order (big endian).
940 */
941static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
942 uint32_t uInteger32,
943 size_t uPos);
944
945
946/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700947 @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100948
Laurence Lundblade077475f2019-04-26 09:06:33 -0700949 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100950 @param[in] uInteger64 Integer to insert.
951 @param[in] uPos Index in output buffer at which to insert.
952
953 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
954 the difference being an eight-byte integer is to be inserted.
955
956 The integer will be inserted in network byte order (big endian).
957 */
958static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
959 uint64_t uInteger64,
960 size_t uPos);
961
962
963/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700964 @brief Insert a @c float into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100965
Laurence Lundblade077475f2019-04-26 09:06:33 -0700966 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
967 @param[in] f @c float to insert.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100968 @param[in] uPos Index in output buffer at which to insert.
969
970 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
Laurence Lundblade077475f2019-04-26 09:06:33 -0700971 the difference being a @c float is to be inserted.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100972
Laurence Lundblade077475f2019-04-26 09:06:33 -0700973 The @c float will be inserted in network byte order (big endian).
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100974 */
975static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
976 float f,
977 size_t uPos);
978
979
980/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700981 @brief Insert a @c double into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100982
Laurence Lundblade077475f2019-04-26 09:06:33 -0700983 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
984 @param[in] d @c double to insert.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100985 @param[in] uPos Index in output buffer at which to insert.
986
987 See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
Laurence Lundblade077475f2019-04-26 09:06:33 -0700988 the difference being a @c double is to be inserted.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100989
Laurence Lundblade077475f2019-04-26 09:06:33 -0700990 The @c double will be inserted in network byte order (big endian).
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100991 */
992static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
993 double d,
994 size_t uPos);
995
996
997/**
Laurence Lundblade077475f2019-04-26 09:06:33 -0700998 @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100999
Laurence Lundblade077475f2019-04-26 09:06:33 -07001000 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1001 @param[in] NewData The @ref UsefulBuf with the bytes to append.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001002
1003 See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
1004 with the insertion point at the end of the valid data.
1005*/
1006static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
1007 UsefulBufC NewData);
1008
1009
1010/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001011 @brief Append bytes to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001012
Laurence Lundblade077475f2019-04-26 09:06:33 -07001013 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001014 @param[in] pBytes Pointer to bytes to append.
Laurence Lundblade077475f2019-04-26 09:06:33 -07001015 @param[in] uLen Length of @c pBytes to append.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001016
1017 See UsefulOutBuf_InsertData() for details. This does the same
1018 with the insertion point at the end of the valid data.
1019 */
1020static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
1021 const void *pBytes,
1022 size_t uLen);
1023
1024
1025/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001026 @brief Append a NULL-terminated string to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001027
Laurence Lundblade077475f2019-04-26 09:06:33 -07001028 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001029 @param[in] szString NULL-terminated string to append.
1030 */
1031static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
1032 const char *szString);
1033
1034
1035/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001036 @brief Append a byte to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001037
Laurence Lundblade077475f2019-04-26 09:06:33 -07001038 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001039 @param[in] byte Bytes to append.
1040
1041 See UsefulOutBuf_InsertByte() for details. This does the same
1042 with the insertion point at the end of the valid data.
1043 */
1044static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
1045 uint8_t byte);
1046
1047
1048/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001049 @brief Append an integer to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001050
Laurence Lundblade077475f2019-04-26 09:06:33 -07001051 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001052 @param[in] uInteger16 Integer to append.
1053
1054 See UsefulOutBuf_InsertUint16() for details. This does the same
1055 with the insertion point at the end of the valid data.
1056
1057 The integer will be appended in network byte order (big endian).
1058 */
1059static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
1060 uint16_t uInteger16);
1061
1062
1063/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001064 @brief Append an integer to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001065
Laurence Lundblade077475f2019-04-26 09:06:33 -07001066 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001067 @param[in] uInteger32 Integer to append.
1068
1069 See UsefulOutBuf_InsertUint32() for details. This does the same
1070 with the insertion point at the end of the valid data.
1071
1072 The integer will be appended in network byte order (big endian).
1073 */
1074static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
1075 uint32_t uInteger32);
1076
1077
1078/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001079 @brief Append an integer to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001080
Laurence Lundblade077475f2019-04-26 09:06:33 -07001081 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001082 @param[in] uInteger64 Integer to append.
1083
1084 See UsefulOutBuf_InsertUint64() for details. This does the same
1085 with the insertion point at the end of the valid data.
1086
1087 The integer will be appended in network byte order (big endian).
1088 */
1089static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
1090 uint64_t uInteger64);
1091
1092
1093/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001094 @brief Append a @c float to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001095
Laurence Lundblade077475f2019-04-26 09:06:33 -07001096 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1097 @param[in] f @c float to append.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001098
1099 See UsefulOutBuf_InsertFloat() for details. This does the same
1100 with the insertion point at the end of the valid data.
1101
1102 The float will be appended in network byte order (big endian).
1103 */
1104static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
1105 float f);
1106
1107
1108/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001109 @brief Append a @c double to the @ref UsefulOutBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001110
Laurence Lundblade077475f2019-04-26 09:06:33 -07001111 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
1112 @param[in] d @c double to append.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001113
1114 See UsefulOutBuf_InsertDouble() for details. This does the same
1115 with the insertion point at the end of the valid data.
1116
1117 The double will be appended in network byte order (big endian).
1118 */
1119static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
1120 double d);
1121
1122
1123/**
1124 @brief Returns the current error status.
1125
Laurence Lundblade077475f2019-04-26 09:06:33 -07001126 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001127
1128 @return 0 if all OK, 1 on error.
1129
1130 This is the error status since the call to either
1131 UsefulOutBuf_Reset() of UsefulOutBuf_Init(). Once it goes into error
1132 state it will stay until one of those functions is called.
1133
1134 Possible error conditions are:
1135 - bytes to be inserted will not fit
1136 - insertion point is out of buffer or past valid data
1137 - current position is off end of buffer (probably corrupted or uninitialized)
1138 - detect corruption / uninitialized by bad magic number
1139 */
1140static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
1141
1142
1143/**
1144 @brief Returns number of bytes unused used in the output buffer.
1145
Laurence Lundblade077475f2019-04-26 09:06:33 -07001146 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001147
1148 @return Number of unused bytes or zero.
1149
1150 Because of the error handling strategy and checks in
1151 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1152 this.
1153 */
1154static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
1155
1156
1157/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001158 @brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001159
Laurence Lundblade30dd0ba2019-05-26 23:37:30 +03001160 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1161 @param[in] uLen Number of bytes for which to check
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001162
Laurence Lundblade077475f2019-04-26 09:06:33 -07001163 @return 1 if @c uLen bytes will fit, 0 if not.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001164
1165 Because of the error handling strategy and checks in
1166 UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
1167 this.
1168 */
1169static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
1170
1171
Laurence Lundblade30dd0ba2019-05-26 23:37:30 +03001172 /**
1173 @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1174
1175 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
1176
1177 @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
1178
1179 Giving a @c NULL output buffer to UsefulOutBuf_Init() is used
1180 when just calculating the length of the encoded data.
1181 */
1182static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
1183
1184
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001185/**
1186 @brief Returns the resulting valid data in a UsefulOutBuf
1187
Laurence Lundblade077475f2019-04-26 09:06:33 -07001188 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001189
Laurence Lundblade077475f2019-04-26 09:06:33 -07001190 @return The valid data in @ref UsefulOutBuf or
1191 @ref NULLUsefulBufC if there was an error adding data.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001192
Laurence Lundblade077475f2019-04-26 09:06:33 -07001193 The storage for the returned data is the @c Storage parameter passed
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001194 to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
1195
1196 This can be called anytime and many times to get intermediate
1197 results. It doesn't change the data or reset the current position
1198 so you can keep adding data.
1199 */
1200UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
1201
1202
1203/**
1204 @brief Copies the valid data into a supplied buffer
1205
Laurence Lundblade077475f2019-04-26 09:06:33 -07001206 @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001207 @param[out] Dest The destination buffer to copy into.
1208
Laurence Lundblade077475f2019-04-26 09:06:33 -07001209 @return Pointer and length of copied data or @c NULLUsefulBufC
1210 if it will not fit in the @c Dest buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001211
1212 This is the same as UsefulOutBuf_OutUBuf() except it copies the data
Laurence Lundblade077475f2019-04-26 09:06:33 -07001213 to @c Dest.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001214*/
1215UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
1216
1217
1218
1219
1220/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001221 @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf and is
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001222 for parsing data read or received. Initialize it with the data from
1223 the network. Then use the functions here to get data chunks of
1224 various types. A position cursor is maintained internally.
1225
1226 As long as the functions here are used, there will never be a
1227 reference off the end of the given buffer. This is true even if they
1228 care called incorrectly, an attempt is made to seek of the end of the
1229 buffer, etc. This makes it easier to write safe and correct code.
1230 For example, the QCBOR decoder implementation is safer and easier to
Laurence Lundblade077475f2019-04-26 09:06:33 -07001231 review through its use of @ref UsefulInputBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001232
Laurence Lundblade077475f2019-04-26 09:06:33 -07001233 @ref UsefulInputBuf maintains an internal error state. The
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001234 intended use is that data chunks can be fetched without error
1235 checking until the end. Once data has been requested off the end of
1236 the buffer, the error state is entered. In the error state the
Laurence Lundblade077475f2019-04-26 09:06:33 -07001237 @c UsefulInputBuf_GetXxxx() functions return 0, or @c NULL or
1238 @ref NULLUsefulBufC. As long as null are not dereferenced, the
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001239 error check can be put off until the end, simplifying the calling
1240 code.
1241
1242 The integer and float parsing expects network byte order (big
1243 endian). Network byte order is what is used by TCP/IP, CBOR and most
1244 internet protocols.
1245
1246 Lots of inline functions are used to keep code size down. The code
Laurence Lundblade077475f2019-04-26 09:06:33 -07001247 optimizer, particularly with the @c -Os or @c -O3, also reduces code
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001248 size a lot. The only non-inline code is UsefulInputBuf_GetBytes()
Laurence Lundblade077475f2019-04-26 09:06:33 -07001249 which is less than 100 bytes so use of @ref UsefulInputBuf doesn't
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001250 add much code for all the messy hard-to-get right issues with parsing
1251 in C that is solves.
1252
1253 The parse context size is:
1254 - 64-bit machine: 16 + 8 + 2 + 1 (5 bytes padding to align) = 32 bytes
1255 - 32-bit machine: 8 + 4 + 2 + 1 (1 byte padding to align) = 16 bytes
1256 */
1257typedef struct useful_input_buf {
1258 // PRIVATE DATA STRUCTURE
1259 UsefulBufC UB; // Data being parsed
1260 size_t cursor; // Current offset in data being parse
1261 uint16_t magic; // Check for corrupted or uninitialized UsefulInputBuf
1262 uint8_t err; // Set request goes off end or magic number is bad
1263} UsefulInputBuf;
1264
1265#define UIB_MAGIC (0xB00F)
1266
1267
1268/**
1269 @brief Initialize the UsefulInputBuf structure before use.
1270
1271 @param[in] pUInBuf Pointer to the UsefulInputBuf instance.
1272 @param[in] UB The data to parse.
1273 */
1274static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
1275
1276
1277/**
1278 @brief Returns current position in input buffer.
1279
1280 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1281
1282 @return Integer position of the cursor.
1283
1284 The position that the next bytes will be returned from.
1285 */
1286static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
1287
1288
1289/**
1290 @brief Sets the current position in input buffer.
1291
1292 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1293 @param[in] uPos Position to set to.
1294
1295 If the position is off the end of the input buffer, the error state
1296 is entered, and all functions will do nothing.
1297
1298 Seeking to a valid position in the buffer will not reset the error
1299 state. Only re initialization will do that.
1300 */
1301static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
1302
1303
1304/**
1305 @brief Returns the number of bytes from the cursor to the end of the buffer,
1306 the unconsumed bytes.
1307
1308 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1309
1310 @return Number of bytes unconsumed or 0 on error.
1311
1312 This is a critical function for input length validation.
1313
1314 Returns 0 if the cursor it invalid or corruption of the structure is
1315 detected.
1316 */
1317static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
1318
1319
1320/**
1321 @brief Check if there are any unconsumed bytes.
1322
1323 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1324 @param[in] uLen Number of bytes to check availability for.
1325
Laurence Lundblade077475f2019-04-26 09:06:33 -07001326 @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001327 */
1328static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
1329
1330
1331/**
1332 @brief Get pointer to bytes out of the input buffer.
1333
1334 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1335 @param[in] uNum Number of bytes to get.
1336
1337 @return Pointer to bytes.
1338
Laurence Lundblade077475f2019-04-26 09:06:33 -07001339 This consumes @c uNum bytes from the input buffer. It returns a
1340 pointer to the start of the @c uNum bytes.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001341
Laurence Lundblade077475f2019-04-26 09:06:33 -07001342 If there are not @c uNum bytes in the input buffer, @c NULL will be
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001343 returned and an error will be set.
1344
Laurence Lundblade077475f2019-04-26 09:06:33 -07001345 It advances the current position by @c uNum bytes.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001346 */
1347const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
1348
1349
1350/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001351 @brief Get @ref UsefulBuf out of the input buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001352
1353 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1354 @param[in] uNum Number of bytes to get.
1355
Laurence Lundblade077475f2019-04-26 09:06:33 -07001356 @return A @ref UsefulBufC with ptr and length of bytes consumed.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001357
Laurence Lundblade077475f2019-04-26 09:06:33 -07001358 This consumes @c uNum bytes from the input buffer and returns the
1359 pointer and length for them as a @ref UsefulBufC. The length returned
1360 will always be @c uNum.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001361
Laurence Lundblade077475f2019-04-26 09:06:33 -07001362 If there are not @c uNum bytes in the input buffer, @ref NULLUsefulBufC
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001363 will be returned and the error state is set.
1364
Laurence Lundblade077475f2019-04-26 09:06:33 -07001365 It advances the current position by @c uNum bytes.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001366 */
1367static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
1368
1369
1370/**
1371 @brief Get a byte out of the input buffer.
1372
Laurence Lundblade077475f2019-04-26 09:06:33 -07001373 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001374
1375 @return The byte.
1376
1377 This consumes 1 byte from the input buffer. It returns the byte.
1378
1379 If there is not 1 byte in the buffer, 0 will be returned for the byte
1380 and an error set internally. You must check the error at some point
1381 to know whether the 0 was the real value or just returned in error,
1382 but you may not have to do that right away. Check the error state
1383 with UsefulInputBuf_GetError(). You can also know you are in the
Laurence Lundblade077475f2019-04-26 09:06:33 -07001384 error state if UsefulInputBuf_GetBytes() returns @c NULL or the @c
1385 ptr from UsefulInputBuf_GetUsefulBuf() is @c NULL.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001386
1387 It advances the current position by 1 byte.
1388 */
1389static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
1390
1391
1392/**
Laurence Lundblade077475f2019-04-26 09:06:33 -07001393 @brief Get a @c uint16_t out of the input buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001394
1395 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1396
Laurence Lundblade077475f2019-04-26 09:06:33 -07001397 @return The @c uint16_t.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001398
1399 See UsefulInputBuf_GetByte(). This works the same, except it returns
Laurence Lundblade077475f2019-04-26 09:06:33 -07001400 a @c uint16_t and two bytes are consumed.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001401
1402 The input bytes must be in network order (big endian).
1403 */
1404static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
1405
1406
1407/**
1408 @brief Get a uint32_t out of the input buffer.
1409
1410 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1411
Laurence Lundblade077475f2019-04-26 09:06:33 -07001412 @return The @c uint32_t.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001413
1414 See UsefulInputBuf_GetByte(). This works the same, except it returns
Laurence Lundblade077475f2019-04-26 09:06:33 -07001415 a @c uint32_t and four bytes are consumed.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001416
1417 The input bytes must be in network order (big endian).
1418 */
1419static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
1420
1421
1422/**
1423 @brief Get a uint64_t out of the input buffer.
1424
1425 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1426
1427 @return The uint64_t.
1428
1429 See UsefulInputBuf_GetByte(). This works the same, except it returns
Laurence Lundblade077475f2019-04-26 09:06:33 -07001430 a @c uint64_t and eight bytes are consumed.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001431
1432 The input bytes must be in network order (big endian).
1433 */
1434static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
1435
1436
1437/**
1438 @brief Get a float out of the input buffer.
1439
1440 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1441
1442 @return The float.
1443
1444 See UsefulInputBuf_GetByte(). This works the same, except it returns
1445 a float and four bytes are consumed.
1446
1447 The input bytes must be in network order (big endian).
1448 */
1449static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
1450
1451
1452/**
1453 @brief Get a double out of the input buffer.
1454
1455 @param[in] pUInBuf Pointer to the UsefulInputBuf.
1456
1457 @return The double.
1458
1459 See UsefulInputBuf_GetByte(). This works the same, except it returns
1460 a double and eight bytes are consumed.
1461
1462 The input bytes must be in network order (big endian).
1463 */
1464static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
1465
1466
1467/**
1468 @brief Get the error status.
1469
Laurence Lundblade077475f2019-04-26 09:06:33 -07001470 @param[in] pUInBuf Pointer to the @ref UsefulInputBuf.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001471
1472 @return 0 if there is no error, 1 if there is.
1473
1474 The error state is entered for one of these reasons:
1475 - Attempt to fetch data past the end of the buffer
1476 - Attempt to seek to a position past the end of the buffer
1477 - Attempt to get data from an uninitialized or corrupt instance
Laurence Lundblade077475f2019-04-26 09:06:33 -07001478 of @ref UsefulInputBuf
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001479
1480 Once in the error state, it can only be cleared by calling
1481 UsefulInputBuf_Init().
1482
1483 You may be able to only check the error state at the end after all
1484 the UsefulInputBuf_GetXxxx() calls have been made, but if what you
1485 get later depends on what you get sooner you cannot. For example,
1486 if you get a length or count of following items you will have to
1487 check the error.
1488 */
1489static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
1490
1491
1492
1493
1494/*----------------------------------------------------------
1495 Inline implementations.
1496 */
1497static inline int UsefulBuf_IsNULL(UsefulBuf UB)
1498{
1499 return !UB.ptr;
1500}
1501
1502
1503static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
1504{
1505 return !UB.ptr;
1506}
1507
1508
1509static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
1510{
1511 return !UB.len;
1512}
1513
1514
1515static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
1516{
1517 return !UB.len;
1518}
1519
1520
1521static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
1522{
1523 return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
1524}
1525
1526
1527static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
1528{
1529 return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
1530}
1531
1532
1533static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
1534{
1535 return (UsefulBufC){UB.ptr, UB.len};
1536}
1537
1538
1539static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
1540{
1541 return (UsefulBuf){(void *)UBC.ptr, UBC.len};
1542}
1543
1544
1545static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
1546{
1547 return ((UsefulBufC) {szString, strlen(szString)});
1548}
1549
1550
1551static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
1552{
Laurence Lundblade981ab672018-10-26 13:11:29 +07001553 return UsefulBuf_CopyOffset(Dest, 0, Src);
1554}
1555
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001556
Laurence Lundblade05ec57b2018-10-21 01:50:03 +05301557static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value)
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001558{
Laurence Lundblade05ec57b2018-10-21 01:50:03 +05301559 memset(pDest.ptr, value, pDest.len);
1560 return (UsefulBufC){pDest.ptr, pDest.len};
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001561}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001562
1563
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001564static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001565{
Laurence Lundblade2296db52018-09-14 18:08:39 -07001566 return UsefulBuf_Copy(Dest, (UsefulBufC){ptr, len});
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001567}
1568
1569
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001570static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
1571{
1572 if(uAmount > UB.len) {
1573 return NULLUsefulBufC;
1574 }
1575 return (UsefulBufC){UB.ptr, uAmount};
1576}
1577
1578
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001579static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
1580{
Laurence Lundblade7412f812019-01-01 18:49:36 -08001581 UsefulBufC ReturnValue;
Laurence Lundbladef0ea5f32019-01-11 20:10:26 -08001582
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001583 if(uAmount > UB.len) {
Laurence Lundblade7412f812019-01-01 18:49:36 -08001584 ReturnValue = NULLUsefulBufC;
1585 } else if(UB.ptr == NULL) {
1586 ReturnValue = (UsefulBufC){NULL, UB.len - uAmount};
1587 } else {
1588 ReturnValue = (UsefulBufC){(uint8_t *)UB.ptr + uAmount, UB.len - uAmount};
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001589 }
Laurence Lundbladef0ea5f32019-01-11 20:10:26 -08001590
Laurence Lundblade7412f812019-01-01 18:49:36 -08001591 return ReturnValue;
Laurence Lundbladeda3f0822018-09-18 19:49:02 -07001592}
1593
1594
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001595
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001596static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
1597{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001598 uint32_t u32;
1599 memcpy(&u32, &f, sizeof(uint32_t));
1600 return u32;
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001601}
1602
1603static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
1604{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001605 uint64_t u64;
1606 memcpy(&u64, &d, sizeof(uint64_t));
1607 return u64;
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001608}
1609
1610static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
1611{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001612 double d;
1613 memcpy(&d, &u64, sizeof(uint64_t));
1614 return d;
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001615}
1616
1617static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
1618{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001619 float f;
1620 memcpy(&f, &u32, sizeof(uint32_t));
1621 return f;
Laurence Lundblade12d32c52018-09-19 11:25:27 -07001622}
1623
1624
1625
1626
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001627static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001628{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001629 pMe->data_len = 0;
1630 pMe->err = 0;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001631}
1632
1633
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001634static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001635{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001636 return pMe->data_len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001637}
1638
1639
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001640static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001641{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001642 return 0 == pMe->data_len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001643}
1644
1645
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001646static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
1647 const void *pBytes,
1648 size_t uLen,
1649 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001650{
1651 UsefulBufC Data = {pBytes, uLen};
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001652 UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001653}
1654
1655
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001656static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
1657 const char *szString,
1658 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001659{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001660 UsefulOutBuf_InsertUsefulBuf(pMe,
1661 (UsefulBufC){szString, strlen(szString)},
1662 uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001663}
1664
1665
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001666static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
1667 uint8_t byte,
1668 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001669{
1670 UsefulOutBuf_InsertData(me, &byte, 1, uPos);
1671}
1672
Laurence Lundblade1e67a942019-05-18 14:48:07 -07001673
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001674static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
1675 uint16_t uInteger16,
1676 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001677{
Laurence Lundblade635993b2019-03-25 03:06:14 +01001678 // See UsefulOutBuf_InsertUint64() for comments on this code
1679
1680 const void *pBytes;
1681
1682#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1683 pBytes = &uInteger16;
1684
1685#elif defined(USEFULBUF_CONFIG_HTON)
1686 uint16_t uTmp = htons(uInteger16);
1687 pBytes = &uTmp;
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07001688
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001689#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1690 uint16_t uTmp = __builtin_bswap16(uInteger16);
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001691 pBytes = &uTmp;
Laurence Lundblade635993b2019-03-25 03:06:14 +01001692
1693#else
1694 uint8_t aTmp[2];
1695
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001696 aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
1697 aTmp[1] = (uint8_t)(uInteger16 & 0xff);
Laurence Lundblade635993b2019-03-25 03:06:14 +01001698
1699 pBytes = aTmp;
1700#endif
1701
1702 UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001703}
1704
1705
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001706static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
1707 uint32_t uInteger32,
1708 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001709{
Laurence Lundblade635993b2019-03-25 03:06:14 +01001710 // See UsefulOutBuf_InsertUint64() for comments on this code
1711
1712 const void *pBytes;
1713
1714#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1715 pBytes = &uInteger32;
1716
1717#elif defined(USEFULBUF_CONFIG_HTON)
1718 uint32_t uTmp = htonl(uInteger32);
1719 pBytes = &uTmp;
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07001720
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001721#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1722 uint32_t uTmp = __builtin_bswap32(uInteger32);
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07001723
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001724 pBytes = &uTmp;
Laurence Lundblade635993b2019-03-25 03:06:14 +01001725
1726#else
1727 uint8_t aTmp[4];
1728
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001729 aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
1730 aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
1731 aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
1732 aTmp[3] = (uint8_t)(uInteger32 & 0xff);
Laurence Lundblade635993b2019-03-25 03:06:14 +01001733
1734 pBytes = aTmp;
1735#endif
1736
1737 UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001738}
1739
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001740static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
1741 uint64_t uInteger64,
1742 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001743{
Laurence Lundblade635993b2019-03-25 03:06:14 +01001744 const void *pBytes;
1745
1746#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1747 // We have been told explicitly we are running on a big-endian
1748 // machine. Network byte order is big endian, so just copy. There
1749 // is no issue with alignment here because uInter64 is always
1750 // aligned (and it doesn't matter if pBytes is aligned).
1751 pBytes = &uInteger64;
1752
1753#elif defined(USEFULBUF_CONFIG_HTON)
1754 // Use system function to handle big- and little-endian. This works
1755 // on both big- and little-endian machines, but hton() is not
1756 // always available or in a standard place so it is not used by
1757 // default. With some compilers and CPUs the code for this is very
1758 // compact through use of a special swap instruction and on
1759 // big-endian machines hton() will reduce to nothing.
1760 uint64_t uTmp = htonll(uInteger64);
1761
1762 pBytes = &uTmp;
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07001763
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001764#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
1765 // Use built-in function for byte swapping. This usually compiles
1766 // to an efficient special byte swap instruction. Unlike hton() it
1767 // does not do this conditionally on the CPU endianness, so this
1768 // code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
1769 uint64_t uTmp = __builtin_bswap64(uInteger64);
1770
1771 pBytes = &uTmp;
Laurence Lundblade635993b2019-03-25 03:06:14 +01001772
1773#else
1774 // Default which works on every CPU with no dependency on anything
1775 // from the CPU, compiler, libraries or OS. This always works, but
1776 // it is usually a little larger and slower than hton().
1777 uint8_t aTmp[8];
1778
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001779 aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
1780 aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
1781 aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
1782 aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
1783 aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
1784 aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
1785 aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
1786 aTmp[7] = (uint8_t)(uInteger64 & 0xff);
Laurence Lundblade635993b2019-03-25 03:06:14 +01001787
1788 pBytes = aTmp;
1789#endif
1790
1791 // Do the insert
1792 UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001793}
1794
1795
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001796static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
1797 float f,
1798 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001799{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001800 UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001801}
1802
1803
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001804static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
1805 double d,
1806 size_t uPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001807{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001808 UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001809}
1810
1811
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001812static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
1813 UsefulBufC NewData)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001814{
1815 // An append is just a insert at the end
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001816 UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001817}
1818
1819
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001820static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
1821 const void *pBytes,
1822 size_t uLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001823{
1824 UsefulBufC Data = {pBytes, uLen};
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001825 UsefulOutBuf_AppendUsefulBuf(pMe, Data);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001826}
1827
1828
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001829static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
1830 const char *szString)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001831{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001832 UsefulOutBuf_AppendUsefulBuf(pMe, (UsefulBufC){szString, strlen(szString)});
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001833}
1834
1835
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001836static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
1837 uint8_t byte)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001838{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001839 UsefulOutBuf_AppendData(pMe, &byte, 1);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001840}
1841
1842
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001843static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
1844 uint16_t uInteger16)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001845{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001846 UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
1847}
1848
1849static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
1850 uint32_t uInteger32)
1851{
1852 UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001853}
1854
1855
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001856static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
1857 uint64_t uInteger64)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001858{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001859 UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001860}
1861
1862
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001863static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
1864 float f)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001865{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001866 UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001867}
1868
1869
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001870static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
1871 double d)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001872{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001873 UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001874}
1875
1876
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001877static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08001878{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001879 return pMe->err;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001880}
1881
1882
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001883static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001884{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001885 return pMe->UB.len - pMe->data_len;
1886}
1887
1888
1889static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
1890{
1891 return uLen <= UsefulOutBuf_RoomLeft(pMe);
1892}
1893
1894
Laurence Lundblade30dd0ba2019-05-26 23:37:30 +03001895static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
1896{
1897 return pMe->UB.ptr == NULL;
1898}
1899
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001900
1901
1902static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
1903{
1904 pMe->cursor = 0;
1905 pMe->err = 0;
1906 pMe->magic = UIB_MAGIC;
1907 pMe->UB = UB;
1908}
1909
1910static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
1911{
1912 return pMe->cursor;
1913}
1914
1915
1916static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
1917{
1918 if(uPos > pMe->UB.len) {
1919 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001920 } else {
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001921 pMe->cursor = uPos;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001922 }
1923}
1924
1925
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001926static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001927{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001928 // Code Reviewers: THIS FUNCTION DOES POINTER MATH
1929
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08001930 // Magic number is messed up. Either the structure got overwritten
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001931 // or was never initialized.
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001932 if(pMe->magic != UIB_MAGIC) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001933 return 0;
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08001934 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001935
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001936 // The cursor is off the end of the input buffer given.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001937 // Presuming there are no bugs in this code, this should never happen.
1938 // If it so, the struct was corrupted. The check is retained as
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001939 // as a defense in case there is a bug in this code or the struct is
1940 // corrupted.
1941 if(pMe->cursor > pMe->UB.len) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001942 return 0;
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08001943 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001944
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001945 // subtraction can't go neative because of check above
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001946 return pMe->UB.len - pMe->cursor;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001947}
1948
1949
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001950static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001951{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001952 return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001953}
1954
1955
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001956static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001957{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001958 const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08001959 if(!pResult) {
1960 return NULLUsefulBufC;
1961 } else {
1962 return (UsefulBufC){pResult, uNum};
1963 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001964}
1965
1966
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001967static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001968{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001969 const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001970
Laurence Lundbladec5fef682020-01-25 11:38:45 -08001971 // The ternery operator is subject to integer promotion, because the
1972 // operands are smaller than int, so cast back to uint8_t is needed
1973 // to be completely explicit about types (for static analyzers)
1974 return (uint8_t)(pResult ? *(uint8_t *)pResult : 0);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001975}
1976
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001977static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001978{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01001979 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001980
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001981 if(!pResult) {
1982 return 0;
1983 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08001984
Laurence Lundblade635993b2019-03-25 03:06:14 +01001985 // See UsefulInputBuf_GetUint64() for comments on this code
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001986#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundblade635993b2019-03-25 03:06:14 +01001987 uint16_t uTmp;
1988 memcpy(&uTmp, pResult, sizeof(uint16_t));
1989
1990#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
1991 return uTmp;
1992
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001993#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundblade635993b2019-03-25 03:06:14 +01001994 return ntohs(uTmp);
1995
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01001996#else
1997 return __builtin_bswap16(uTmp);
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07001998
Laurence Lundblade635993b2019-03-25 03:06:14 +01001999#endif
2000
2001#else
Laurence Lundbladec5fef682020-01-25 11:38:45 -08002002
2003 // The operations here are subject to integer promotion because the
2004 // operands are smaller than int. They will be promoted to unsigned
2005 // int for the shift and addition. The cast back to uint16_t is is needed
2006 // to be completely explicit about types (for static analyzers)
2007 return (uint16_t)((pResult[0] << 8) + pResult[1]);
Laurence Lundblade635993b2019-03-25 03:06:14 +01002008
2009#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002010}
2011
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08002012
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002013static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002014{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002015 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002016
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002017 if(!pResult) {
2018 return 0;
2019 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002020
Laurence Lundblade635993b2019-03-25 03:06:14 +01002021 // See UsefulInputBuf_GetUint64() for comments on this code
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002022#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundblade635993b2019-03-25 03:06:14 +01002023 uint32_t uTmp;
2024 memcpy(&uTmp, pResult, sizeof(uint32_t));
2025
2026#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2027 return uTmp;
2028
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002029#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundblade635993b2019-03-25 03:06:14 +01002030 return ntohl(uTmp);
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07002031
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002032#else
2033 return __builtin_bswap32(uTmp);
Laurence Lundblade635993b2019-03-25 03:06:14 +01002034
2035#endif
2036
2037#else
Laurence Lundbladed1d20ce2019-01-19 16:40:31 -08002038 return ((uint32_t)pResult[0]<<24) +
Laurence Lundblade635993b2019-03-25 03:06:14 +01002039 ((uint32_t)pResult[1]<<16) +
2040 ((uint32_t)pResult[2]<<8) +
2041 (uint32_t)pResult[3];
2042#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002043}
2044
Laurence Lundblade8fab62c2018-10-12 12:07:57 +08002045
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002046static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002047{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002048 const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002049
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002050 if(!pResult) {
2051 return 0;
2052 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002053
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002054#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
Laurence Lundblade635993b2019-03-25 03:06:14 +01002055 // pResult will probably not be aligned. This memcpy() moves the
2056 // bytes into a temp variable safely for CPUs that can or can't do
2057 // unaligned memory access. Many compilers will optimize the
2058 // memcpy() into a simple move instruction.
2059 uint64_t uTmp;
2060 memcpy(&uTmp, pResult, sizeof(uint64_t));
2061
2062#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
2063 // We have been told expliclity this is a big-endian CPU. Since
2064 // network byte order is big-endian, there is nothing to do.
2065
2066 return uTmp;
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07002067
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002068#elif defined(USEFULBUF_CONFIG_HTON)
Laurence Lundblade635993b2019-03-25 03:06:14 +01002069 // We have been told to use ntoh(), the system function to handle
2070 // big- and little-endian. This works on both big- and
2071 // little-endian machines, but ntoh() is not always available or in
2072 // a standard place so it is not used by default. On some CPUs the
2073 // code for this is very compact through use of a special swap
2074 // instruction.
2075
2076 return ntohll(uTmp);
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07002077
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002078#else
2079 // Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
2080 // USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
2081 // __builtin_bswap64() and friends are not conditional on CPU
2082 // endianness so this must only be used on little-endian machines.
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07002083
Laurence Lundblade7f08cba2019-03-25 19:27:36 +01002084 return __builtin_bswap64(uTmp);
Laurence Lundblade1e67a942019-05-18 14:48:07 -07002085
Laurence Lundbladeeb8772d2019-06-11 08:46:23 -07002086
Laurence Lundblade635993b2019-03-25 03:06:14 +01002087#endif
2088
2089#else
2090 // This is the default code that works on every CPU and every
2091 // endianness with no dependency on ntoh(). This works on CPUs
2092 // that either allow or do not allow unaligned access. It will
2093 // always work, but usually is a little less efficient than ntoh().
Laurence Lundblade1e67a942019-05-18 14:48:07 -07002094
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002095 return ((uint64_t)pResult[0]<<56) +
Laurence Lundblade635993b2019-03-25 03:06:14 +01002096 ((uint64_t)pResult[1]<<48) +
2097 ((uint64_t)pResult[2]<<40) +
2098 ((uint64_t)pResult[3]<<32) +
2099 ((uint64_t)pResult[4]<<24) +
2100 ((uint64_t)pResult[5]<<16) +
2101 ((uint64_t)pResult[6]<<8) +
2102 (uint64_t)pResult[7];
2103#endif
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002104}
2105
2106
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002107static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002108{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002109 uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002110
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +05302111 return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002112}
2113
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08002114
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002115static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002116{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002117 uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002118
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +05302119 return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002120}
2121
2122
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002123static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002124{
Laurence Lundblade5cc25682019-03-26 21:58:35 +01002125 return pMe->err;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002126}
2127
Laurence Lundbladec5a61c62019-02-21 14:21:38 -08002128#ifdef __cplusplus
2129}
2130#endif
2131
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07002132#endif // _UsefulBuf_h
2133
2134