41 if ((str == NULL) || (out_cstr == NULL))
55 *out_cstr = (
const char *)str->
buf.
data;
61 if ((dest == NULL) || (src == NULL))
72 bool found_nul =
false;
74 if ((dest == NULL) || (src == NULL))
85 for (i = 0U; i <= max_scan; i++)
104 bool found_nul =
false;
107 if ((dest == NULL) || (src == NULL))
119 for (i = 0U; i <= remaining; i++)
134 (void)memcpy(&data[dest->
buf.
length], src, i);
145 const unsigned char *pa;
146 const unsigned char *pb;
148 if ((a == NULL) || (b == NULL) || (out_cmp == NULL))
157 pa = (
const unsigned char *)a->
buf.
data;
158 pb = (
const unsigned char *)b->
buf.
data;
159 for (i = 0U; i < min_len; i++)
163 result = (pa[i] < pb[i]) ? -1 : 1;
187 bool *out_found,
size_t *out_index)
192 if ((str == NULL) || (out_found == NULL) || (out_index == NULL))
200 data = (
const char *)str->
buf.
data;
215 bool *out_found,
size_t *out_index)
222 if ((haystack == NULL) || (needle == NULL) || (out_found == NULL) || (out_index == NULL))
241 hdata = (
const char *)haystack->
buf.
data;
242 ndata = (
const char *)needle->
buf.
data;
244 for (i = 0U; i <= max_start; i++)
246 if (memcmp(&hdata[i], ndata, needle->
buf.
length) == 0)
266 if ((str == NULL) || (io_cursor == NULL) || (out_token == NULL) || (out_has_token == NULL))
280 *out_has_token =
false;
283 data = (
const char *)str->
buf.
data;
286 while ((i < str->buf.length) && (data[i] != delimiter))
290 out_token->
data = &data[start];
291 out_token->
length = i - start;
292 *out_has_token =
true;
293 if (i < str->buf.length)
326 char digit = (char)(v % 10U);
327 rev[n] = (char)(
'0' + digit);
333 for (i = 0U; i < n; i++)
335 out[i] = rev[(n - 1U) - i];
365 negative = (value < 0);
370 magnitude = (uint64_t)(-(value + 1)) + 1U;
374 magnitude = (uint64_t)value;
388 uint64_t widened = 0U;
457 (void)memcpy(&data[dest->
buf.
length], src, n);
487 negative = (value < 0);
491 magnitude = (uint64_t)(-(value + 1)) + 1U;
496 magnitude = (uint64_t)value;
503 uint64_t widened = 0U;
539 static const char hex_lc[16] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
540 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'};
543 size_t real_digits = 1U;
553 width = (size_t)min_digits;
567 n = (real_digits > width) ? real_digits : width;
568 for (i = 0U; i < n; i++)
573 size_t shift = (n - 1U) - i;
574 if (shift >= real_digits)
580 out[i] = hex_lc[(value >> (4U * (uint32_t)shift)) & 0x0FU];
592 if ((str == NULL) || (out_value == NULL))
604 data = (
const char *)str->
buf.
data;
610 if ((c <
'0') || (c >
'9'))
614 digit = (uint64_t)(c -
'0');
615 if (acc > ((UINT64_MAX - digit) / 10U))
619 acc = (acc * 10U) + digit;
633 if ((str == NULL) || (out_value == NULL))
645 data = (
const char *)str->
buf.
data;
657 for (i = start; i < str->
buf.
length; i++)
662 if ((c <
'0') || (c >
'9'))
666 digit = (uint64_t)(c -
'0');
667 if (acc > ((UINT64_MAX - digit) / 10U))
671 acc = (acc * 10U) + digit;
675 uint64_t min_magnitude = (uint64_t)INT64_MAX + 1U;
676 if (acc > min_magnitude)
680 if (acc == min_magnitude)
682 *out_value = INT64_MIN;
686 *out_value = -(int64_t)acc;
691 if (acc > (uint64_t)INT64_MAX)
695 *out_value = (int64_t)acc;
705 if (out_value == NULL)
722 if (out_value == NULL)
sapi_status_t sapi_buffer_clear(sapi_buffer_t *buf)
Resets length to 0; capacity and data are unchanged.
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.
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.
bool sapi_buffer_is_valid(const sapi_buffer_t *buf)
Defensive validity check: non-null data and length <= capacity.
sapi_status_t sapi_cast_u64_to_u32(uint64_t in, uint32_t *out)
Checked cast from uint64_t to uint32_t.
sapi_status_t sapi_cast_i64_to_i32(int64_t in, int32_t *out)
Checked cast from int64_t to int32_t.
sapi_status_t sapi_cast_i32_to_i64(int32_t in, int64_t *out)
Checked cast from int32_t to int64_t.
sapi_status_t sapi_cast_u32_to_u64(uint32_t in, uint64_t *out)
Checked cast from uint32_t to uint64_t.
sapi_status_t
Common result/status codes.
@ SAPI_STATUS_INVALID_PARAM
@ SAPI_STATUS_VALUE_OUT_OF_RANGE
@ SAPI_STATUS_RESOURCE_EXHAUSTED
sapi_status_t sapi_string_from_i32(sapi_string_t *dest, int32_t value)
Bounded base-10 itoa equivalent for int32_t. Replaces dest's content.
sapi_status_t sapi_string_from_u64(sapi_string_t *dest, uint64_t value)
Bounded base-10 itoa equivalent for uint64_t. Replaces dest's content.
sapi_status_t sapi_string_split_next(const sapi_string_t *str, char delimiter, size_t *io_cursor, sapi_const_buffer_t *out_token, bool *out_has_token)
Reentrant, bounded string splitting - unlike strtok(), all state is caller-owned via io_cursor,...
sapi_status_t sapi_string_init(sapi_string_t *str, char *storage, size_t capacity)
Binds a string to caller-owned storage. Initial length is 0 (empty string).
sapi_status_t sapi_string_from_i64(sapi_string_t *dest, int64_t value)
Bounded base-10 itoa equivalent for int64_t. Replaces dest's content.
sapi_status_t sapi_string_c_str(sapi_string_t *str, const char **out_cstr)
Ensures a NUL terminator is present within capacity (without incrementing length) and returns a point...
sapi_status_t sapi_string_append_hex_u32(sapi_string_t *dest, uint32_t value, uint8_t min_digits)
Bounded append of a uint32_t formatted as lowercase hexadecimal (no "0x" prefix - the caller prepends...
sapi_status_t sapi_string_append_i64(sapi_string_t *dest, int64_t value)
Bounded base-10 append of an int64_t; a leading '-' is emitted for negative values....
size_t sapi_string_length(const sapi_string_t *str)
Returns a string's current length (not counting a NUL terminator).
sapi_status_t sapi_string_concat(sapi_string_t *dest, const char *src)
Bounded strcat equivalent. Never calls strlen(src) - scans for a NUL only up to dest's remaining capa...
sapi_status_t sapi_string_clear(sapi_string_t *str)
Resets a string to empty. Capacity and storage are unchanged.
sapi_status_t sapi_string_append_u32(sapi_string_t *dest, uint32_t value)
Bounded base-10 append of a uint32_t to dest's existing content (unlike sapi_string_from_u32(),...
sapi_status_t sapi_string_copy(sapi_string_t *dest, const char *src)
Bounded strcpy equivalent. Never calls strlen(src) - scans for a NUL only up to dest's capacity (REQ-...
sapi_status_t sapi_string_find_char(const sapi_string_t *str, char c, bool *out_found, size_t *out_index)
Bounded strchr equivalent. "Not found" is a normal outcome, not an error - see out_found.
sapi_status_t sapi_string_to_i64(const sapi_string_t *str, int64_t *out_value)
As sapi_string_to_i32(), for int64_t.
sapi_status_t sapi_string_append_u64(sapi_string_t *dest, uint64_t value)
Bounded base-10 append of a uint64_t. See sapi_string_append_u32().
sapi_status_t sapi_string_find_substr(const sapi_string_t *haystack, const sapi_string_t *needle, bool *out_found, size_t *out_index)
Bounded strstr equivalent. "Not found" is a normal outcome, not an error - see out_found.
sapi_status_t sapi_string_copy_n(sapi_string_t *dest, const char *src, size_t src_len)
Bounded copy of an exact-length, not-necessarily-NUL-terminated source (e.g. a length-prefixed field)...
sapi_status_t sapi_string_compare(const sapi_string_t *a, const sapi_string_t *b, int32_t *out_cmp)
Bounded strcmp equivalent. Compares up to the shorter string's length, then by length if that prefix ...
sapi_status_t sapi_string_to_u32(const sapi_string_t *str, uint32_t *out_value)
Bounded base-10 atoi equivalent for uint32_t.
sapi_status_t sapi_string_append_i32(sapi_string_t *dest, int32_t value)
Bounded base-10 append of an int32_t; a leading '-' is emitted for negative values....
sapi_status_t sapi_string_to_i32(const sapi_string_t *str, int32_t *out_value)
As sapi_string_to_u32(), for int32_t; a leading '-' is accepted.
sapi_status_t sapi_string_from_u32(sapi_string_t *dest, uint32_t value)
Bounded base-10 itoa equivalent for uint32_t. Replaces dest's content.
sapi_status_t sapi_string_to_u64(const sapi_string_t *str, uint64_t *out_value)
As sapi_string_to_u32(), for uint64_t.
Checked integer casting between all fixed-width types and size_t (ADR-003). Every conversion in the c...
static sapi_status_t sapi_string_append_bytes(sapi_string_t *dest, const char *src, size_t n)
Appends exactly n bytes of src to dest, no NUL scan, bounds-checked against dest's remaining capacity...
static void sapi_string_format_u64_digits(uint64_t value, char *out, size_t *out_len)
Fills out[0..*out_len) with value's base-10 digits, most-significant first, no leading zeros (except ...
Bounded, checked string manipulation (ADR-006). Replaces strcpy/strcat/sprintf/atoi/strtok-style unbo...
Read-only view of a buffer's currently valid bytes. Grants no write access to the underlying storage.
Bounded string: buf.length is the string length, not counting a NUL.