Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
sapi_buffer.c
Go to the documentation of this file.
1
7#include <string.h>
8
9sapi_status_t sapi_buffer_init(sapi_buffer_t *buf, void *storage, size_t capacity)
10{
11 if ((buf == NULL) || (storage == NULL) || (capacity == 0U))
12 {
14 }
15 buf->data = storage;
16 buf->capacity = capacity;
17 buf->length = 0U;
18 return SAPI_STATUS_OK;
19}
20
22{
23 if ((buf == NULL) || (!sapi_buffer_is_valid(buf)))
24 {
26 }
27 buf->length = 0U;
28 return SAPI_STATUS_OK;
29}
30
32{
33 if ((buf == NULL) || (buf->data == NULL))
34 {
36 }
37 if (length > buf->capacity)
38 {
40 }
41 buf->length = length;
42 return SAPI_STATUS_OK;
43}
44
45sapi_status_t sapi_buffer_copy_in(sapi_buffer_t *buf, const void *src, size_t src_len)
46{
47 if ((buf == NULL) || (buf->data == NULL) || (src == NULL))
48 {
50 }
51 if (src_len > buf->capacity)
52 {
54 }
55 if (src_len > 0U)
56 {
57 (void)memcpy(buf->data, src, src_len);
58 }
59 buf->length = src_len;
60 return SAPI_STATUS_OK;
61}
62
64 void *dest,
65 size_t dest_capacity,
66 size_t *out_copied)
67{
68 if ((buf == NULL) || (buf->data == NULL) || (dest == NULL) || (out_copied == NULL))
69 {
71 }
72 if (buf->length > dest_capacity)
73 {
74 *out_copied = 0U;
76 }
77 if (buf->length > 0U)
78 {
79 (void)memcpy(dest, buf->data, buf->length);
80 }
81 *out_copied = buf->length;
82 return SAPI_STATUS_OK;
83}
84
86{
87 if ((buf == NULL) || (buf->data == NULL) || (out_view == NULL))
88 {
90 }
91 if (buf->length > buf->capacity)
92 {
94 }
95 out_view->data = buf->data;
96 out_view->length = buf->length;
97 return SAPI_STATUS_OK;
98}
99
101{
102 if (buf == NULL)
103 {
104 return false;
105 }
106 if (buf->data == NULL)
107 {
108 return false;
109 }
110 return (buf->length <= buf->capacity);
111}
112
123static sapi_status_t sapi_buffer_append_bytes(sapi_buffer_t *buf, const unsigned char *bytes, size_t n)
124{
125 unsigned char *dest;
126
127 if ((buf == NULL) || (bytes == NULL) || (!sapi_buffer_is_valid(buf)))
128 {
130 }
131 if ((buf->capacity - buf->length) < n)
132 {
134 }
135 dest = (unsigned char *)buf->data;
136 (void)memcpy(&dest[buf->length], bytes, n);
137 buf->length += n;
138 return SAPI_STATUS_OK;
139}
140
152static sapi_status_t sapi_buffer_peek_bytes(const sapi_buffer_t *buf, size_t offset,
153 unsigned char *out_bytes, size_t n)
154{
155 const unsigned char *src;
156
157 if ((buf == NULL) || (out_bytes == NULL) || (buf->data == NULL))
158 {
160 }
161 if ((offset > buf->length) || ((buf->length - offset) < n))
162 {
164 }
165 src = (const unsigned char *)buf->data;
166 (void)memcpy(out_bytes, &src[offset], n);
167 return SAPI_STATUS_OK;
168}
169
171{
172 unsigned char bytes[2];
173 bytes[0] = (unsigned char)(value & 0xFFU);
174 bytes[1] = (unsigned char)((value >> 8) & 0xFFU);
175 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
176}
177
179{
180 unsigned char bytes[2];
181 bytes[0] = (unsigned char)((value >> 8) & 0xFFU);
182 bytes[1] = (unsigned char)(value & 0xFFU);
183 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
184}
185
187{
188 unsigned char bytes[4];
189 bytes[0] = (unsigned char)(value & 0xFFU);
190 bytes[1] = (unsigned char)((value >> 8) & 0xFFU);
191 bytes[2] = (unsigned char)((value >> 16) & 0xFFU);
192 bytes[3] = (unsigned char)((value >> 24) & 0xFFU);
193 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
194}
195
197{
198 unsigned char bytes[4];
199 bytes[0] = (unsigned char)((value >> 24) & 0xFFU);
200 bytes[1] = (unsigned char)((value >> 16) & 0xFFU);
201 bytes[2] = (unsigned char)((value >> 8) & 0xFFU);
202 bytes[3] = (unsigned char)(value & 0xFFU);
203 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
204}
205
207{
208 unsigned char bytes[8];
209 size_t i;
210 for (i = 0U; i < sizeof(bytes); i++)
211 {
212 bytes[i] = (unsigned char)((value >> (8U * (uint64_t)i)) & 0xFFU);
213 }
214 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
215}
216
218{
219 unsigned char bytes[8];
220 size_t i;
221 for (i = 0U; i < sizeof(bytes); i++)
222 {
223 size_t shift = (sizeof(bytes) - 1U - i) * 8U;
224 bytes[i] = (unsigned char)((value >> (uint64_t)shift) & 0xFFU);
225 }
226 return sapi_buffer_append_bytes(buf, bytes, sizeof(bytes));
227}
228
229sapi_status_t sapi_buffer_read_u16_le(const sapi_buffer_t *buf, size_t offset, uint16_t *out_value)
230{
231 unsigned char bytes[2];
232 sapi_status_t st;
233 uint32_t v;
234
235 if (out_value == NULL)
236 {
238 }
239 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
240 if (st != SAPI_STATUS_OK)
241 {
242 return st;
243 }
244 v = (uint32_t)bytes[0] | ((uint32_t)bytes[1] << 8);
245 *out_value = (uint16_t)v;
246 return SAPI_STATUS_OK;
247}
248
249sapi_status_t sapi_buffer_read_u16_be(const sapi_buffer_t *buf, size_t offset, uint16_t *out_value)
250{
251 unsigned char bytes[2];
252 sapi_status_t st;
253 uint32_t v;
254
255 if (out_value == NULL)
256 {
258 }
259 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
260 if (st != SAPI_STATUS_OK)
261 {
262 return st;
263 }
264 v = ((uint32_t)bytes[0] << 8) | (uint32_t)bytes[1];
265 *out_value = (uint16_t)v;
266 return SAPI_STATUS_OK;
267}
268
269sapi_status_t sapi_buffer_read_u32_le(const sapi_buffer_t *buf, size_t offset, uint32_t *out_value)
270{
271 unsigned char bytes[4];
272 sapi_status_t st;
273
274 if (out_value == NULL)
275 {
277 }
278 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
279 if (st != SAPI_STATUS_OK)
280 {
281 return st;
282 }
283 *out_value = (uint32_t)bytes[0]
284 | ((uint32_t)bytes[1] << 8)
285 | ((uint32_t)bytes[2] << 16)
286 | ((uint32_t)bytes[3] << 24);
287 return SAPI_STATUS_OK;
288}
289
290sapi_status_t sapi_buffer_read_u32_be(const sapi_buffer_t *buf, size_t offset, uint32_t *out_value)
291{
292 unsigned char bytes[4];
293 sapi_status_t st;
294
295 if (out_value == NULL)
296 {
298 }
299 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
300 if (st != SAPI_STATUS_OK)
301 {
302 return st;
303 }
304 *out_value = ((uint32_t)bytes[0] << 24)
305 | ((uint32_t)bytes[1] << 16)
306 | ((uint32_t)bytes[2] << 8)
307 | (uint32_t)bytes[3];
308 return SAPI_STATUS_OK;
309}
310
311sapi_status_t sapi_buffer_read_u64_le(const sapi_buffer_t *buf, size_t offset, uint64_t *out_value)
312{
313 unsigned char bytes[8];
314 sapi_status_t st;
315 size_t i;
316 uint64_t v = 0U;
317
318 if (out_value == NULL)
319 {
321 }
322 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
323 if (st != SAPI_STATUS_OK)
324 {
325 return st;
326 }
327 for (i = 0U; i < sizeof(bytes); i++)
328 {
329 v |= ((uint64_t)bytes[i]) << (8U * (uint64_t)i);
330 }
331 *out_value = v;
332 return SAPI_STATUS_OK;
333}
334
335sapi_status_t sapi_buffer_read_u64_be(const sapi_buffer_t *buf, size_t offset, uint64_t *out_value)
336{
337 unsigned char bytes[8];
338 sapi_status_t st;
339 size_t i;
340 uint64_t v = 0U;
341
342 if (out_value == NULL)
343 {
345 }
346 st = sapi_buffer_peek_bytes(buf, offset, bytes, sizeof(bytes));
347 if (st != SAPI_STATUS_OK)
348 {
349 return st;
350 }
351 for (i = 0U; i < sizeof(bytes); i++)
352 {
353 size_t shift = (sizeof(bytes) - 1U - i) * 8U;
354 v |= ((uint64_t)bytes[i]) << (uint64_t)shift;
355 }
356 *out_value = v;
357 return SAPI_STATUS_OK;
358}
sapi_status_t sapi_buffer_write_u16_le(sapi_buffer_t *buf, uint16_t value)
Appends a little-endian uint16_t at buf's current length.
sapi_status_t sapi_buffer_write_u32_be(sapi_buffer_t *buf, uint32_t value)
Appends a big-endian uint32_t. See sapi_buffer_write_u32_le().
sapi_status_t sapi_buffer_write_u64_le(sapi_buffer_t *buf, uint64_t value)
Appends a little-endian uint64_t at buf's current length.
sapi_status_t sapi_buffer_write_u32_le(sapi_buffer_t *buf, uint32_t value)
Appends a little-endian uint32_t at buf's current length.
sapi_status_t sapi_buffer_clear(sapi_buffer_t *buf)
Resets length to 0; capacity and data are unchanged.
Definition sapi_buffer.c:21
sapi_status_t sapi_buffer_read_u64_le(const sapi_buffer_t *buf, size_t offset, uint64_t *out_value)
Reads a little-endian uint64_t at the given offset.
sapi_status_t sapi_buffer_read_u16_be(const sapi_buffer_t *buf, size_t offset, uint16_t *out_value)
Reads a big-endian uint16_t. See sapi_buffer_read_u16_le().
sapi_status_t sapi_buffer_read_u64_be(const sapi_buffer_t *buf, size_t offset, uint64_t *out_value)
Reads a big-endian uint64_t. See sapi_buffer_read_u64_le().
sapi_status_t sapi_buffer_copy_out(const sapi_buffer_t *buf, void *dest, size_t dest_capacity, size_t *out_copied)
Bounds-checked copy of the buffer's valid bytes to an external destination.
Definition sapi_buffer.c:63
sapi_status_t sapi_buffer_read_u16_le(const sapi_buffer_t *buf, size_t offset, uint16_t *out_value)
Reads a little-endian uint16_t at the given offset.
sapi_status_t sapi_buffer_read_u32_le(const sapi_buffer_t *buf, size_t offset, uint32_t *out_value)
Reads a little-endian uint32_t at the given offset.
sapi_status_t sapi_buffer_write_u64_be(sapi_buffer_t *buf, uint64_t value)
Appends a big-endian uint64_t. See sapi_buffer_write_u64_le().
sapi_status_t sapi_buffer_init(sapi_buffer_t *buf, void *storage, size_t capacity)
Binds a buffer view to caller-owned storage. Initial length is 0.
Definition sapi_buffer.c:9
sapi_status_t sapi_buffer_set_length(sapi_buffer_t *buf, size_t length)
Marks length bytes of already-written storage as valid.
Definition sapi_buffer.c:31
sapi_status_t sapi_buffer_copy_in(sapi_buffer_t *buf, const void *src, size_t src_len)
Bounds-checked copy of external data into the buffer; sets length.
Definition sapi_buffer.c:45
sapi_status_t sapi_buffer_read_u32_be(const sapi_buffer_t *buf, size_t offset, uint32_t *out_value)
Reads a big-endian uint32_t. See sapi_buffer_read_u32_le().
bool sapi_buffer_is_valid(const sapi_buffer_t *buf)
Defensive validity check: non-null data and length <= capacity.
sapi_status_t sapi_buffer_as_const(const sapi_buffer_t *buf, sapi_const_buffer_t *out_view)
Produces a read-only view of the buffer's current valid bytes. The view is only valid as long as the ...
Definition sapi_buffer.c:85
sapi_status_t sapi_buffer_write_u16_be(sapi_buffer_t *buf, uint16_t value)
Appends a big-endian uint16_t. See sapi_buffer_write_u16_le().
sapi_status_t
Common result/status codes.
Definition sapi_status.h:27
@ SAPI_STATUS_INTERNAL_ERROR
Definition sapi_status.h:38
@ SAPI_STATUS_INVALID_PARAM
Definition sapi_status.h:29
@ SAPI_STATUS_RESOURCE_EXHAUSTED
Definition sapi_status.h:33
@ SAPI_STATUS_OK
Definition sapi_status.h:28
static sapi_status_t sapi_buffer_append_bytes(sapi_buffer_t *buf, const unsigned char *bytes, size_t n)
Appends n raw bytes at buf's current length, advancing it. Shared by every sapi_buffer_write_*_le/be ...
static sapi_status_t sapi_buffer_peek_bytes(const sapi_buffer_t *buf, size_t offset, unsigned char *out_bytes, size_t n)
Reads n raw bytes starting at offset, without mutating buf. Shared by every sapi_buffer_read_*_le/be ...
Cross-layer data buffer abstraction (ADR-002).
Mutable, bounds-tracked view over caller-owned storage.
Definition sapi_buffer.h:36
size_t capacity
Definition sapi_buffer.h:38
Read-only view of a buffer's currently valid bytes. Grants no write access to the underlying storage.
Definition sapi_buffer.h:47
const void * data
Definition sapi_buffer.h:48