Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : :
4 : : /**
5 : : * @brief Zero-filled fallback storage for soft read-only string access
6 : : *
7 : : * `mem_string(...)` must be able to return an empty string even for string
8 : : * descriptors whose elements are wider than one byte. A plain
9 : : * `static char empty_string[] = ""` is only guaranteed to describe a byte
10 : : * string, so it is not a good universal fallback for `wchar_t`, `char16_t`,
11 : : * `char32_t`, or other descriptor element widths
12 : : *
13 : : * The `empty` field provides a block of zero-filled storage whose size matches
14 : : * `sizeof(max_align_t)`. The `align` field is not used as data. It exists so
15 : : * the whole object inherits the strongest standard alignment that the platform
16 : : * normally provides for fundamental scalar types. That way callers can safely
17 : : * interpret the returned address as a pointer to a zero-valued string element
18 : : * of the descriptor's width instead of only as a `char *`
19 : : *
20 : : * Using a file-scope union also solves the lifetime problem. A stack buffer
21 : : * would become invalid as soon as `mem_string(...)` returned, while this object
22 : : * lives for the whole program and needs no heap allocation or cleanup logic.
23 : : * The exact byte size stays platform-dependent because `sizeof(max_align_t)` is
24 : : * ABI-dependent, but that is still preferable here to introducing a separate
25 : : * hard-coded magic limit
26 : : */
27 : : static const union
28 : : {
29 : : max_align_t align;
30 : : unsigned char empty[sizeof(max_align_t)];
31 : : } empty_string = {0};
32 : :
33 : : /**
34 : : * @brief Return a soft read-only string view without modifying descriptor state
35 : : *
36 : : * This helper is meant for callers that already trust string mode and only need
37 : : * a readable pointer. It does not rescan the buffer for a terminator, does not
38 : : * recalculate the visible length, and never rewrites descriptor state. The
39 : : * function performs only the most basic descriptor checks and otherwise fully
40 : : * trusts the cached `string_length`
41 : : *
42 : : * When the descriptor is logically empty, the function returns a zero-filled
43 : : * fallback string instead of NULL. Gross descriptor contract violations such
44 : : * as a NULL descriptor, a zero element size, calling the helper on a data
45 : : * descriptor, a non-zero logical length with a NULL data pointer, or a cached
46 : : * string length that is not strictly smaller than `length` are reported and
47 : : * also fall back to the same empty string storage
48 : : *
49 : : * @param memory_object Descriptor interpreted as a read-only string descriptor
50 : : * @return Read-only pointer to descriptor-backed string data or to shared empty
51 : : * fallback storage when no valid string view can be exposed
52 : : */
53 : 109249 : const void *mem_string(const memory *memory_object)
54 : : {
55 [ + + ]: 109249 : if(memory_object == NULL)
56 : : {
57 : 1 : report("Memory management; Soft string view requires a non-NULL descriptor");
58 : 1 : return(empty_string.empty);
59 : : }
60 : :
61 [ + + ]: 109248 : if(memory_object->single_element_size == 0)
62 : : {
63 : 1 : report("Memory management; Soft string view requires a non-zero element size");
64 : 1 : return(empty_string.empty);
65 : : }
66 : :
67 [ + + ]: 109247 : if(memory_object->is_string == false)
68 : : {
69 : 1 : report("Memory management; Soft string view requires a string descriptor");
70 : 1 : return(empty_string.empty);
71 : : }
72 : :
73 [ + + + + ]: 109246 : if(memory_object->length > 0 && memory_object->data == NULL)
74 : : {
75 : 2 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
76 : 2 : return(empty_string.empty);
77 : : }
78 : :
79 [ + + + + ]: 109244 : if(memory_object->data == NULL || memory_object->length == 0)
80 : : {
81 : 1082 : return(empty_string.empty);
82 : : }
83 : :
84 [ + + ]: 108162 : if(memory_object->string_length >= memory_object->length)
85 : : {
86 : 1 : report("Memory management; Soft string view requires string_length to stay below length");
87 : 1 : return(empty_string.empty);
88 : : }
89 : :
90 : 108161 : return(memory_object->data);
91 : : }
|