blob: 4a7970f9e133ac074311214a77396857058c1b0c [file] [log] [blame]
Laurence Lundbladeb239c652024-05-26 08:07:05 -07001/* ==========================================================================
2 * 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 Lundbladee2226742024-08-16 10:50:23 -070047 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladeb239c652024-05-26 08:07:05 -070048 21/05/2024 llundblade Comment formatting and some code tidiness.
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070049 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
50 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladeb239c652024-05-26 08:07:05 -070051 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080052 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
53 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080054 11/08/2019 llundblade Re check pointer math and update comments
55 3/6/2019 llundblade Add UsefulBuf_IsValue()
56 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
57 the end of memory when the bytes to find is longer
58 than the bytes to search.
59 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
60 for < or > for unequal length buffers. Added
61 UsefulBuf_Set() function.
62 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
63 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080064
Laurence Lundbladeee851742020-01-08 08:37:05 -080065 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070066
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070067#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070068
Laurence Lundbladeb239c652024-05-26 08:07:05 -070069/* used to catch use of uninitialized or corrupted UsefulOutBuf */
Laurence Lundbladeee851742020-01-08 08:37:05 -080070#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070071
Laurence Lundblade041ffa52018-10-07 11:43:51 +070072
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053073/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070074 * Public function -- see UsefulBuf.h
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053075 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070076UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
77{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070078 /* Do this with subtraction so it doesn't give an erroneous
79 * result if uOffset + Src.len overflows. Right side is equivalent to
80 * uOffset + Src.len > Dest.len
81 */
82 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080083 return NULLUsefulBufC;
84 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080085
Laurence Lundblade570fab52018-10-13 18:28:27 +080086 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080087
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080088 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070089}
90
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053091
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070092/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070093 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094 */
95int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
96{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070097 /* Use comparisons rather than subtracting lengths to
98 * return an int instead of a size_t
99 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100 if(UB1.len < UB2.len) {
101 return -1;
102 } else if (UB1.len > UB2.len) {
103 return 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700104 } /* else UB1.len == UB2.len */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800105
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700106 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
107}
108
109
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800110/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700111 * Public function -- see UsefulBuf.h
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800112 */
113size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
114{
115 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
116 /* Not a match */
117 return 0;
118 }
119
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800120 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800121 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
122 if(*p != uValue) {
123 /* Byte didn't match */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700124 /* Cast from signed to unsigned. Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800125 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800126 }
127 }
128
129 /* Success. All bytes matched */
130 return SIZE_MAX;
131}
132
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700133
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700134/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700135 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700136 */
137size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
138{
139 if(BytesToSearch.len < BytesToFind.len) {
140 return SIZE_MAX;
141 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800142
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700143 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700144 UsefulBufC SearchNext;
145
146 SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
147 SearchNext.len = BytesToFind.len;
148 if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700149 return uPos;
150 }
151 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800152
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153 return SIZE_MAX;
154}
155
156
157/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700158 * Public function -- see UsefulBuf.h
159 *
160 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100162void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700163{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100164 pMe->magic = USEFUL_OUT_BUF_MAGIC;
165 UsefulOutBuf_Reset(pMe);
166 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800167
Laurence Lundblade2296db52018-09-14 18:08:39 -0700168#if 0
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700169 /* This check is off by default.
170 *
171 * The following check fails on ThreadX
172 *
173 * Sanity check on the pointer and size to be sure we are not
174 * passed a buffer that goes off the end of the address space.
175 * Given this test, we know that all unsigned lengths less than
176 * me->size are valid and won't wrap in any pointer additions
177 * based off of pStorage in the rest of this code.
178 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530179 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700180 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700181 me->err = 1;
182#endif
183}
184
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700185
186
187/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700188 * Public function -- see UsefulBuf.h
189 *
190 * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
191 * the end of it.
192 *
193 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
194 *
195 * This function inserts the source buffer, NewData, into the destination
196 * buffer, me->UB.ptr.
197 *
198 * Destination is represented as:
199 * me->UB.ptr -- start of the buffer
200 * me->UB.len -- size of the buffer UB.ptr
201 * me->data_len -- length of value data in UB
202 *
203 * Source is data:
204 * NewData.ptr -- start of source buffer
205 * NewData.len -- length of source buffer
206 *
207 * Insertion point:
208 * uInsertionPos.
209 *
210 * Steps:
211 *
212 * 0. Corruption checks on UsefulOutBuf
213 *
214 * 1. Figure out if the new data will fit or not
215 *
216 * 2. Is insertion position in the range of valid data?
217 *
218 * 3. If insertion point is not at the end, slide data to the right of the
219 * insertion point to the right
220 *
221 * 4. Put the new data in at the insertion position.
222 *
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700223 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100224void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700225{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100226 if(pMe->err) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700227 /* Already in error state. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700228 return;
229 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800230
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700231 /* 0. Sanity check the UsefulOutBuf structure
232 * A "counter measure". If magic number is not the right number it
233 * probably means pMe was not initialized or it was corrupted. Attackers
234 * can defeat this, but it is a hurdle and does good with very
235 * little code.
236 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100237 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
238 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700239 return; /* Magic number is wrong due to uninitalization or corrption */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240 }
241
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700242 /* Make sure valid data is less than buffer size. This would only occur
243 * if there was corruption of me, but it is also part of the checks to
244 * be sure there is no pointer arithmatic under/overflow.
245 */
246 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100247 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700248 /* Offset of valid data is off the end of the UsefulOutBuf due to
249 * uninitialization or corruption
250 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800251 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800253
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700254 /* 1. Will it fit?
255 * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
256 * Check #1 makes sure subtraction in RoomLeft will not wrap around
257 */
258 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
259 /* The new data will not fit into the the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100260 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261 return;
262 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800263
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700264 /* 2. Check the Insertion Position
265 * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
266 * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
267 * address space.
268 */
269 if(uInsertionPos > pMe->data_len) { /* Check #3 */
270 /* Off the end of the valid data in the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100271 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700272 return;
273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800274
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300276 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700277 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
278 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
279 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800280
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700281 /* To know memmove won't go off end of destination, see PtrMath #4.
282 * Use memove because it handles overlapping buffers
283 */
Laurence Lundblade74f68412018-09-13 12:18:49 -0700284 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800285
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300286 /* 4. Put the new data in */
287 uint8_t *pInsertionPoint = pSourceOfMove;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700288 /* To know memmove won't go off end of destination, see PtrMath #5 */
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700289 if(NewData.ptr != NULL) {
290 memmove(pInsertionPoint, NewData.ptr, NewData.len);
291 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700292 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300293
Laurence Lundblade61209742019-11-08 13:16:43 -0800294 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700295}
296
297
298/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700299 * Rationale that describes why the above pointer math is safe
300 *
301 * PtrMath #1 will never wrap around over because
302 * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
303 * Check #1 makes sure me->data_len is less than me->UB.len
304 * Check #3 makes sure uInsertionPos is less than me->data_len
305 *
306 * PtrMath #2 will never wrap around under because
307 * Check #3 makes sure uInsertionPos is less than me->data_len
308 *
309 * PtrMath #3 will never wrap around over because
310 * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
311 * Check #2 that NewData.len will fit in the unused space left in me->UB
312 *
313 * PtrMath #4 will never wrap under because
314 * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
315 * Check #3 makes sure uInsertionPos is less than me->data_len
316 * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
317 * This algebraically rearranges to me->size > uInsertionPos + NewData.len
318 *
319 * PtrMath #5 will never wrap under because
320 * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
321 * Check #1 makes sure me->data_len is less than me->size
322 * Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700323 */
324
325
326/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600327 * Public function for advancing data length. See qcbor/UsefulBuf.h
328 */
329void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
330{
331 /* This function is a trimmed down version of
332 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
333 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
334 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
335 * rarely used.
336 */
337
338 if(pMe->err) {
339 /* Already in error state. */
340 return;
341 }
342
343 /* 0. Sanity check the UsefulOutBuf structure
344 *
345 * A "counter measure". If magic number is not the right number it
346 * probably means me was not initialized or it was
347 * corrupted. Attackers can defeat this, but it is a hurdle and
348 * does good with very little code.
349 */
350 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
351 pMe->err = 1;
352 return; /* Magic number is wrong due to uninitalization or corrption */
353 }
354
355 /* Make sure valid data is less than buffer size. This would only
356 * occur if there was corruption of me, but it is also part of the
357 * checks to be sure there is no pointer arithmatic
358 * under/overflow.
359 */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700360 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600361 pMe->err = 1;
362 /* Offset of valid data is off the end of the UsefulOutBuf due
363 * to uninitialization or corruption.
364 */
365 return;
366 }
367
368 /* 1. Will it fit?
369 *
370 * WillItFit() is the same as: NewData.len <= (me->UB.len -
371 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
372 * not wrap around
373 */
374 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
375 /* The new data will not fit into the the buffer. */
376 pMe->err = 1;
377 return;
378 }
379
380 pMe->data_len += uAmount;
381}
382
383
384/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700385 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700386 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100387UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700388{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100389 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700390 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700391 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800392
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100393 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
394 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700395 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700396 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800397
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100398 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700399}
400
401
402/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700403 * Public function -- see UsefulBuf.h
404 *
405 * Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700406 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100407UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700408{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100409 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530410 if(UsefulBuf_IsNULLC(Tmp)) {
411 return NULLUsefulBufC;
412 }
413 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414}
415
416
Laurence Lundbladee2226742024-08-16 10:50:23 -0700417/*
418 * Public function -- see UsefulBuf.h
419 *
420 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
421 */
422UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pMe,
423 const size_t uStart,
424 const size_t uLen)
425{
426 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
427
428 if(UsefulBuf_IsNULLC(Tmp)) {
429 return NULLUsefulBufC;
430 }
431
432 if(uStart > Tmp.len) {
433 return NULLUsefulBufC;
434 }
435
436 if(Tmp.len - uStart < uLen) {
437 return NULLUsefulBufC;
438 }
439
440 UsefulBufC SubString;
441 SubString.ptr = (const uint8_t *)Tmp.ptr + uStart;
442 SubString.len = uLen;
443
444 return SubString;
445}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700446
447
448/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700449 * Public function -- see UsefulBuf.h
450 *
451 * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
452 *
453 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700454 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100455const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700456{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700457 /* Already in error state. Do nothing. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100458 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700459 return NULL;
460 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800461
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100462 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700463 /* Number of bytes asked for is more than available */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100464 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700465 return NULL;
466 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800467
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700468 /* This is going to succeed */
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800469 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700470 /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800471 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700472 return result;
473}