blob: 91ffda1cac0fcb9f2e06447cd9de3aaaaebe3b92 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002 * Copyright (c) 2016-2018, The Linux Foundation.
3 * Copyright (c) 2018-2024, Laurence Lundblade.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of The Linux Foundation nor the names of its
16 * contributors, nor the name "Laurence Lundblade" may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * ========================================================================= */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade624405d2018-09-18 20:10:47 -070034
Laurence Lundbladeee851742020-01-08 08:37:05 -080035/*=============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036 FILE: UsefulBuf.c
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038 DESCRIPTION: General purpose input and output buffers
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070040 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042 This section contains comments describing changes made to the module.
43 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080044
Laurence Lundbladeee851742020-01-08 08:37:05 -080045 when who what, where, why
46 -------- ---- ---------------------------------------------------
Laurence Lundbladeb239c652024-05-26 08:07:05 -070047 21/05/2024 llundblade Comment formatting and some code tidiness.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -070048 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070049 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
50 19/11/2023 llundblade Add UsefulOutBuf_Swap().
51 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070052 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
53 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070054 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080055 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
56 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080057 11/08/2019 llundblade Re check pointer math and update comments
58 3/6/2019 llundblade Add UsefulBuf_IsValue()
59 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
60 the end of memory when the bytes to find is longer
61 than the bytes to search.
62 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
63 for < or > for unequal length buffers. Added
64 UsefulBuf_Set() function.
65 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
66 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080067
Laurence Lundbladeee851742020-01-08 08:37:05 -080068 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070069
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070070#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070071
Laurence Lundbladeb239c652024-05-26 08:07:05 -070072/* used to catch use of uninitialized or corrupted UsefulOutBuf */
Laurence Lundbladeee851742020-01-08 08:37:05 -080073#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074
Laurence Lundblade041ffa52018-10-07 11:43:51 +070075
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053076/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070077 * Public function -- see UsefulBuf.h
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053078 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070079UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
80{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070081 /* Do this with subtraction so it doesn't give an erroneous
82 * result if uOffset + Src.len overflows. Right side is equivalent to
83 * uOffset + Src.len > Dest.len
84 */
85 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080086 return NULLUsefulBufC;
87 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080088
Laurence Lundblade570fab52018-10-13 18:28:27 +080089 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080090
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080091 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070092}
93
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053094
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070095/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070096 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097 */
98int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
99{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700100 /* Use comparisons rather than subtracting lengths to
101 * return an int instead of a size_t
102 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700103 if(UB1.len < UB2.len) {
104 return -1;
105 } else if (UB1.len > UB2.len) {
106 return 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700107 } /* else UB1.len == UB2.len */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800108
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700109 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
110}
111
112
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800113/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700114 * Public function -- see UsefulBuf.h
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800115 */
116size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
117{
118 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
119 /* Not a match */
120 return 0;
121 }
122
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800123 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800124 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
125 if(*p != uValue) {
126 /* Byte didn't match */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700127 /* Cast from signed to unsigned. Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800128 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800129 }
130 }
131
132 /* Success. All bytes matched */
133 return SIZE_MAX;
134}
135
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700136
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700137/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700138 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139 */
140size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
141{
142 if(BytesToSearch.len < BytesToFind.len) {
143 return SIZE_MAX;
144 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800145
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700147 UsefulBufC SearchNext;
148
149 SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
150 SearchNext.len = BytesToFind.len;
151 if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152 return uPos;
153 }
154 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800155
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156 return SIZE_MAX;
157}
158
159
160/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700161 * Public function -- see UsefulBuf.h
162 *
163 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100165void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700166{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100167 pMe->magic = USEFUL_OUT_BUF_MAGIC;
168 UsefulOutBuf_Reset(pMe);
169 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800170
Laurence Lundblade2296db52018-09-14 18:08:39 -0700171#if 0
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700172 /* This check is off by default.
173 *
174 * The following check fails on ThreadX
175 *
176 * Sanity check on the pointer and size to be sure we are not
177 * passed a buffer that goes off the end of the address space.
178 * Given this test, we know that all unsigned lengths less than
179 * me->size are valid and won't wrap in any pointer additions
180 * based off of pStorage in the rest of this code.
181 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530182 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700183 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700184 me->err = 1;
185#endif
186}
187
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700188
189
190/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700191 * Public function -- see UsefulBuf.h
192 *
193 * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
194 * the end of it.
195 *
196 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
197 *
198 * This function inserts the source buffer, NewData, into the destination
199 * buffer, me->UB.ptr.
200 *
201 * Destination is represented as:
202 * me->UB.ptr -- start of the buffer
203 * me->UB.len -- size of the buffer UB.ptr
204 * me->data_len -- length of value data in UB
205 *
206 * Source is data:
207 * NewData.ptr -- start of source buffer
208 * NewData.len -- length of source buffer
209 *
210 * Insertion point:
211 * uInsertionPos.
212 *
213 * Steps:
214 *
215 * 0. Corruption checks on UsefulOutBuf
216 *
217 * 1. Figure out if the new data will fit or not
218 *
219 * 2. Is insertion position in the range of valid data?
220 *
221 * 3. If insertion point is not at the end, slide data to the right of the
222 * insertion point to the right
223 *
224 * 4. Put the new data in at the insertion position.
225 *
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700226 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100227void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700228{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100229 if(pMe->err) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700230 /* Already in error state. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700231 return;
232 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800233
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700234 /* 0. Sanity check the UsefulOutBuf structure
235 * A "counter measure". If magic number is not the right number it
236 * probably means pMe was not initialized or it was corrupted. Attackers
237 * can defeat this, but it is a hurdle and does good with very
238 * little code.
239 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100240 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
241 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700242 return; /* Magic number is wrong due to uninitalization or corrption */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700243 }
244
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700245 /* Make sure valid data is less than buffer size. This would only occur
246 * if there was corruption of me, but it is also part of the checks to
247 * be sure there is no pointer arithmatic under/overflow.
248 */
249 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100250 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700251 /* Offset of valid data is off the end of the UsefulOutBuf due to
252 * uninitialization or corruption
253 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800254 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800256
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700257 /* 1. Will it fit?
258 * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
259 * Check #1 makes sure subtraction in RoomLeft will not wrap around
260 */
261 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
262 /* The new data will not fit into the the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100263 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700264 return;
265 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800266
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700267 /* 2. Check the Insertion Position
268 * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
269 * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
270 * address space.
271 */
272 if(uInsertionPos > pMe->data_len) { /* Check #3 */
273 /* Off the end of the valid data in the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100274 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 return;
276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800277
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700278 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300279 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700280 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
281 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
282 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800283
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700284 /* To know memmove won't go off end of destination, see PtrMath #4.
285 * Use memove because it handles overlapping buffers
286 */
Laurence Lundblade74f68412018-09-13 12:18:49 -0700287 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800288
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300289 /* 4. Put the new data in */
290 uint8_t *pInsertionPoint = pSourceOfMove;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700291 /* To know memmove won't go off end of destination, see PtrMath #5 */
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700292 if(NewData.ptr != NULL) {
293 memmove(pInsertionPoint, NewData.ptr, NewData.len);
294 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700295 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300296
Laurence Lundblade61209742019-11-08 13:16:43 -0800297 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298}
299
300
301/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700302 * Rationale that describes why the above pointer math is safe
303 *
304 * PtrMath #1 will never wrap around over because
305 * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
306 * Check #1 makes sure me->data_len is less than me->UB.len
307 * Check #3 makes sure uInsertionPos is less than me->data_len
308 *
309 * PtrMath #2 will never wrap around under because
310 * Check #3 makes sure uInsertionPos is less than me->data_len
311 *
312 * PtrMath #3 will never wrap around over because
313 * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
314 * Check #2 that NewData.len will fit in the unused space left in me->UB
315 *
316 * PtrMath #4 will never wrap under because
317 * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
318 * Check #3 makes sure uInsertionPos is less than me->data_len
319 * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
320 * This algebraically rearranges to me->size > uInsertionPos + NewData.len
321 *
322 * PtrMath #5 will never wrap under because
323 * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
324 * Check #1 makes sure me->data_len is less than me->size
325 * Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700326 */
327
328
329/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600330 * Public function for advancing data length. See qcbor/UsefulBuf.h
331 */
332void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
333{
334 /* This function is a trimmed down version of
335 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
336 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
337 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
338 * rarely used.
339 */
340
341 if(pMe->err) {
342 /* Already in error state. */
343 return;
344 }
345
346 /* 0. Sanity check the UsefulOutBuf structure
347 *
348 * A "counter measure". If magic number is not the right number it
349 * probably means me was not initialized or it was
350 * corrupted. Attackers can defeat this, but it is a hurdle and
351 * does good with very little code.
352 */
353 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
354 pMe->err = 1;
355 return; /* Magic number is wrong due to uninitalization or corrption */
356 }
357
358 /* Make sure valid data is less than buffer size. This would only
359 * occur if there was corruption of me, but it is also part of the
360 * checks to be sure there is no pointer arithmatic
361 * under/overflow.
362 */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700363 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600364 pMe->err = 1;
365 /* Offset of valid data is off the end of the UsefulOutBuf due
366 * to uninitialization or corruption.
367 */
368 return;
369 }
370
371 /* 1. Will it fit?
372 *
373 * WillItFit() is the same as: NewData.len <= (me->UB.len -
374 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
375 * not wrap around
376 */
377 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
378 /* The new data will not fit into the the buffer. */
379 pMe->err = 1;
380 return;
381 }
382
383 pMe->data_len += uAmount;
384}
385
386
387/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700388 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700389 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100390UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700391{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100392 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700393 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700394 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800395
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100396 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
397 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700398 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700399 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800400
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100401 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700402}
403
404
405/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700406 * Public function -- see UsefulBuf.h
407 *
408 * Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100410UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700411{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100412 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530413 if(UsefulBuf_IsNULLC(Tmp)) {
414 return NULLUsefulBufC;
415 }
416 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700417}
418
419
420
421
422/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700423 * Public function -- see UsefulBuf.h
424 *
425 * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
426 *
427 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700428 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100429const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700430{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700431 /* Already in error state. Do nothing. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100432 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700433 return NULL;
434 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800435
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100436 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700437 /* Number of bytes asked for is more than available */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100438 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700439 return NULL;
440 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800441
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700442 /* This is going to succeed */
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800443 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700444 /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800445 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700446 return result;
447}
448
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700449
450/*
451 * Public function -- see UsefulBuf.h
452 *
453 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
454 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700455int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
456 const size_t uStart1, const size_t uLen1,
457 const size_t uStart2, const size_t uLen2)
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700458{
459 const uint8_t *pBase;
460 const uint8_t *pEnd;
461 const uint8_t *p1;
462 const uint8_t *p2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700463 const uint8_t *p1End;
464 const uint8_t *p2End;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700465 int uComparison;
466
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700467 pBase = pMe->UB.ptr;
468 pEnd = (const uint8_t *)pBase + pMe->data_len;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700469 p1 = pBase + uStart1;
470 p2 = pBase + uStart2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700471 p1End = p1 + uLen1;
472 p2End = p2 + uLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700473
474 uComparison = 0;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700475 while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700476 uComparison = *p2 - *p1;
477 if(uComparison != 0) {
478 break;;
479 }
480 p1++;
481 p2++;
482 }
483
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700484 if(uComparison == 0 && p1 != p1End && p2 != p2End) {
485 if(uLen1 > uLen2) {
486 uComparison = 1;
487 } else if(uLen2 < uLen1){
488 uComparison = -1;
489 } else {
490 return 0;
491 }
492 }
493
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700494 return uComparison;
495}
496
497
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700498
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700499/**
500 * @brief Reverse order of bytes in a buffer.
501 *
502 * This reverses bytes starting at pStart, up to, but not including
503 * the byte at pEnd
504 */
505static void
506UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
507{
508 uint8_t uTmp;
509
510 while(pStart < pEnd) {
511 pEnd--;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700512 uTmp = *pStart;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700513 *pStart = *pEnd;
514 *pEnd = uTmp;
515 pStart++;
516 }
517}
518
519
520/*
521 * Public function -- see UsefulBuf.h
522 *
523 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
524 */
525void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
526{
527 uint8_t *pBase;
528
529 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
530 return;
531 }
532
533 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
534 return;
535 }
536
537 /* This is the "reverse" algorithm to swap two memory regions */
538 pBase = pMe->UB.ptr;
539 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
540 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
541 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
542}
543
544
545/*
546 * Public function -- see UsefulBuf.h
547 */
548UsefulBufC
549UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
550{
551 UsefulBufC ReturnValue;
552
553 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
554
555 if(UsefulBuf_IsNULLC(ReturnValue)) {
556 return NULLUsefulBufC;
557 }
558
559 if(uOffset >= ReturnValue.len) {
560 return NULLUsefulBufC;
561 }
562
563 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
564 ReturnValue.len -= uOffset;
565
566 return ReturnValue;
567}