Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : :
4 : : /**
5 : : * @brief Compute the visible string length stored in a descriptor
6 : : *
7 : : * The library is being migrated to a unified string model where strings stored
8 : : * in @ref memory descriptors may use arbitrary non-zero element widths instead
9 : : * of being limited to byte-sized characters. Common representations include
10 : : * `char`, `signed char`, `unsigned char`, `char8_t`, `wchar_t`, `char16_t`,
11 : : * `char32_t`, and fixed-width code-unit storage such as `uint8_t`,
12 : : * `uint16_t`, and `uint32_t`. String algorithms are defined in whole
13 : : * elements, and a string terminator is an element whose bytes are all zero.
14 : : *
15 : : * The function accepts both cached string descriptors and generic data
16 : : * descriptors. When @ref memory::is_string is `true`, the cached
17 : : * @ref memory::string_length value is returned immediately without rescanning
18 : : * the payload and without additional integrity checks. The cache is expected
19 : : * to be computed and maintained by descriptor-mutating helpers, which carry
20 : : * responsibility for the correctness of @ref memory::string_length so repeated
21 : : * length queries stay cheap. When @ref memory::is_string is `false`, the
22 : : * descriptor is scanned element by element until the first zero-valued element
23 : : * or until @ref memory::length elements have been inspected. A zero-valued
24 : : * element means that every byte in that element is zero. The reported length
25 : : * is always measured in elements, not bytes
26 : : *
27 : : * Behavior details:
28 : : * - Invalid arguments (`memory_structure == NULL` or `length_out == NULL`)
29 : : * return `FAILURE`.
30 : : * - If @ref memory::single_element_size is 0, the function returns `FAILURE`.
31 : : * - If @ref memory::length is 0, `*length_out` is set to 0.
32 : : * - If @ref memory::data is `NULL` while @ref memory::length is also 0,
33 : : * `*length_out` is set to 0.
34 : : * - If @ref memory::data is `NULL` while @ref memory::length is non-zero,
35 : : * the function returns `FAILURE` because the descriptor is inconsistent.
36 : : * - When @ref memory::is_string is `true`, the cached
37 : : * @ref memory::string_length is returned immediately without extra integrity
38 : : * checks or recomputation.
39 : : * - In data mode, `*length_out` receives the visible prefix length measured by
40 : : * a bounded scan up to the first zero-valued element or @ref memory::length
41 : : *
42 : : * Return-path details:
43 : : * - The function returns via `provide(...)`.
44 : : * - If global status (`global_return_status`) is not `SUCCESS`, the returned
45 : : * value may be overridden by that global status.
46 : : * - For control-flow checks that treat graceful non-error statuses as
47 : : * acceptable, prefer `(status & TRIUMPH) != 0`
48 : : *
49 : : * @param memory_structure Descriptor whose contents are interpreted as a string
50 : : * @param length_out Output pointer that receives the computed length
51 : : * @return Local result is `SUCCESS`/`FAILURE`; final returned value is subject
52 : : * to `provide(...)` global-status propagation
53 : : */
54 : 42377 : Return mem_string_length(
55 : : const memory *memory_structure,
56 : : size_t *length_out)
57 : : {
58 : : /* Status returned by this function through provide()
59 : : Default value assumes successful completion */
60 : 42377 : Return status = SUCCESS;
61 : :
62 [ + + - + ]: 42377 : if(memory_structure == NULL || length_out == NULL)
63 : : {
64 : 1 : report("Memory management; Invalid arguments for string length helper");
65 : 1 : status = FAILURE;
66 : : }
67 : :
68 [ + + + + : 42377 : if((TRIUMPH & status) && memory_structure->length > 0 && memory_structure->data == NULL)
+ + ]
69 : : {
70 : 3 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
71 : 3 : status = FAILURE;
72 : : }
73 : :
74 [ + + + + ]: 42377 : if((TRIUMPH & status) && memory_structure->single_element_size == 0)
75 : : {
76 : 1 : report("Memory management; Descriptor element size is zero (uninitialized)");
77 : 1 : status = FAILURE;
78 : : }
79 : :
80 [ + + + + ]: 42377 : if((TRIUMPH & status) && memory_structure->is_string == true)
81 : : {
82 : 42367 : *length_out = memory_structure->string_length;
83 : : }
84 : :
85 [ + + + + ]: 42377 : if((TRIUMPH & status) && memory_structure->is_string == false)
86 : : {
87 : 5 : run(mem_find_zero_terminator(memory_structure,length_out));
88 : : }
89 : :
90 : 42377 : provide(status);
91 : : }
|