Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : :
4 : : /**
5 : : * @brief Shared internal append core for arrays of inline string descriptors
6 : : *
7 : : * This helper keeps all descriptor-array management in one place. Public
8 : : * wrappers only decide whether the source should be copied through the bounded
9 : : * or unbounded string backend. The core then validates the root descriptor,
10 : : * grows it by one `memory` element, initializes the new slot as a string
11 : : * descriptor, routes the actual copy to the matching backend, and rolls the
12 : : * array back if any later step fails
13 : : *
14 : : * The root descriptor must stay in data mode and must store elements of type
15 : : * `memory`. The appended child descriptor always starts as an empty string
16 : : * descriptor created by @ref m_init
17 : : *
18 : : * @param source_mode Either `SOURCE_UNBOUNDED_STRING` or `SOURCE_BOUNDED_STRING`
19 : : * @param descriptor_array Root data-mode descriptor that stores `memory` elements
20 : : * @param single_element_size Element width in bytes for the appended child string descriptor
21 : : * @param source_limit_bytes Maximum byte count used only for bounded source mode
22 : : * @param source_string Source string passed to the selected copy backend
23 : : * @return `SUCCESS` on success; `FAILURE` otherwise
24 : : */
25 : 665 : Return mem_string_array_core(
26 : : MEM_CORE_MODE source_mode,
27 : : memory *descriptor_array,
28 : : size_t single_element_size,
29 : : size_t source_limit_bytes,
30 : : const void *const source_string)
31 : : {
32 : : /* Status returned by this function through provide()
33 : : Default value assumes successful completion */
34 : 665 : Return status = SUCCESS;
35 : :
36 : 665 : memory *inline_descriptors_data_rewritable = NULL;
37 : 665 : size_t next_index = 0;
38 : :
39 [ - + ]: 665 : if(descriptor_array == NULL)
40 : : {
41 : 0 : report("Memory management; String-array append descriptor is NULL");
42 : 0 : provide(FAILURE);
43 : : }
44 : :
45 [ + + - + ]: 665 : if(descriptor_array->length > 0 && descriptor_array->data == NULL)
46 : : {
47 : 0 : report("Memory management; String-array append descriptor has non-zero length with NULL data pointer");
48 : 0 : provide(FAILURE);
49 : : }
50 : :
51 [ - + ]: 665 : if(descriptor_array->single_element_size != sizeof(memory))
52 : : {
53 : 0 : report("Memory management; String-array append requires a root descriptor with memory-sized elements");
54 : 0 : provide(FAILURE);
55 : : }
56 : :
57 [ - + ]: 665 : if(descriptor_array->is_string == true)
58 : : {
59 : 0 : report("Memory management; String-array append requires a data-mode root descriptor");
60 : 0 : provide(FAILURE);
61 : : }
62 : :
63 [ - + ]: 665 : if(descriptor_array->string_length != 0)
64 : : {
65 : 0 : report("Memory management; Data-mode root descriptor has stale string metadata during string-array append");
66 : 0 : provide(FAILURE);
67 : : }
68 : :
69 [ - + ]: 665 : if(single_element_size == 0)
70 : : {
71 : 0 : report("Memory management; String-array append requires a non-zero string element size");
72 : 0 : provide(FAILURE);
73 : : }
74 : :
75 [ + + - + ]: 665 : if(source_mode != SOURCE_UNBOUNDED_STRING &&
76 : : source_mode != SOURCE_BOUNDED_STRING)
77 : : {
78 : 0 : report("Memory management; String-array append received unsupported source mode");
79 : 0 : provide(FAILURE);
80 : : }
81 : :
82 : : /* Save the old logical length as the insertion index. After growth, the new
83 : : inline string descriptor belongs exactly at this saved slot */
84 : 665 : next_index = descriptor_array->length;
85 : :
86 : 665 : run(m_resize(descriptor_array,next_index + 1,ZERO_NEW_MEMORY));
87 : :
88 [ + - + - ]: 665 : if((TRIUMPH & status) && descriptor_array->length > next_index)
89 : : {
90 : 665 : inline_descriptors_data_rewritable = m_data(memory,descriptor_array);
91 : :
92 [ - + ]: 665 : if(inline_descriptors_data_rewritable == NULL)
93 : : {
94 : 0 : report("Memory management; String-array append could not map the grown root descriptor");
95 : 0 : status = FAILURE;
96 : : }
97 : : }
98 : :
99 [ + - + - ]: 665 : if((TRIUMPH & status) && inline_descriptors_data_rewritable != NULL)
100 : : {
101 : : /* Use the low-level constructor here because the element width is a runtime value.
102 : : m_init(T,...) requires a compile-time type, so it cannot express descriptors whose string element size is provided by the caller */
103 : 665 : inline_descriptors_data_rewritable[next_index] = mem_init(single_element_size,MEMORY_STRING);
104 : :
105 [ + + ]: 665 : if(source_mode == SOURCE_UNBOUNDED_STRING)
106 : : {
107 : 663 : run(mem_copy_unbounded_string(&inline_descriptors_data_rewritable[next_index],source_string));
108 : : }
109 : :
110 [ + + ]: 665 : if(source_mode == SOURCE_BOUNDED_STRING)
111 : : {
112 : 2 : run(mem_copy_bounded_string(&inline_descriptors_data_rewritable[next_index],source_limit_bytes,source_string));
113 : : }
114 : : }
115 : :
116 [ - + - - ]: 665 : if((TRIUMPH & status) == 0 && descriptor_array->length > next_index)
117 : : {
118 : 0 : inline_descriptors_data_rewritable = m_data(memory,descriptor_array);
119 : :
120 [ # # ]: 0 : if(inline_descriptors_data_rewritable != NULL)
121 : : {
122 : 0 : call(m_del(&inline_descriptors_data_rewritable[next_index]));
123 : : }
124 : :
125 : 0 : call(m_resize(descriptor_array,next_index));
126 : : }
127 : :
128 : 665 : provide(status);
129 : : }
|