Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : : #include <string.h>
4 : :
5 : : /**
6 : : * @brief Append one string descriptor to another using cached string lengths
7 : : *
8 : : * This helper is the strict descriptor-to-descriptor string append counterpart
9 : : * of @ref mem_copy. Both operands must already be string descriptors that use
10 : : * the same non-zero element width. The source descriptor is treated as a
11 : : * fixed-string payload whose logical extent ends exactly at
12 : : * `source->string_length + 1`, so any reserved tail beyond the cached
13 : : * terminator is ignored instead of being rescanned or appended
14 : : *
15 : : * @par No terminator search needed
16 : : * Because both descriptors carry an authoritative cached `string_length`,
17 : : * this function performs **no terminator search at all** — it simply uses
18 : : * the cached visible length of the source. This is the fastest available
19 : : * path for appending one libmem string to another and should be preferred
20 : : * whenever both operands are already managed string descriptors.
21 : : *
22 : : * For appending raw C-string buffers, use @ref mem_concat_fixed_string,
23 : : * @ref mem_concat_bounded_string, or @ref mem_concat_unbounded_string
24 : : * depending on whether and how the source is terminated
25 : : *
26 : : * @param destination Pointer to the string descriptor that receives the append
27 : : * @param source Pointer to the string descriptor whose visible payload is appended
28 : : * @return `SUCCESS` on success; `FAILURE` otherwise
29 : : */
30 : 35 : Return mem_concat_strings(
31 : : memory *destination,
32 : : const memory *source)
33 : : {
34 : : /* Status returned by this function through provide()
35 : : Default value assumes successful completion */
36 : 35 : Return status = SUCCESS;
37 : :
38 : : /* Logical source element count used for fixed-string routing */
39 : 35 : size_t source_total_elements = 0;
40 : :
41 : : /* Total source byte count passed to the routed append helper */
42 : 35 : size_t source_size_bytes = 0;
43 : :
44 [ + - - + ]: 35 : if(destination == NULL || source == NULL)
45 : : {
46 : 0 : report("Memory management; mem_concat_strings arguments must be non-NULL");
47 : 0 : provide(FAILURE);
48 : : }
49 : :
50 [ + + - + ]: 35 : if(source->length > 0 && source->data == NULL)
51 : : {
52 : 0 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
53 : 0 : provide(FAILURE);
54 : : }
55 : :
56 [ + + + + ]: 35 : if(destination->is_string == false || source->is_string == false)
57 : : {
58 : 2 : report("Memory management; Source and destination must both be strings");
59 : 2 : provide(FAILURE);
60 : : }
61 : :
62 [ + + ]: 33 : if(destination->single_element_size != source->single_element_size)
63 : : {
64 : 1 : report("Memory management; Element size mismatch (%zu vs %zu)",
65 : : destination->single_element_size,
66 : : source->single_element_size);
67 : 1 : provide(FAILURE);
68 : : }
69 : :
70 [ + + + + ]: 32 : if((destination->length == 0 && destination->string_length != 0) ||
71 [ + + - + ]: 31 : (destination->length > 0 && destination->string_length >= destination->length))
72 : : {
73 : 1 : report("Memory management; Destination string descriptor is inconsistent");
74 : 1 : provide(FAILURE);
75 : : }
76 : :
77 [ + + - + ]: 31 : if((source->length == 0 && source->string_length != 0) ||
78 [ + - - + ]: 30 : (source->length > 0 && source->string_length >= source->length))
79 : : {
80 : 1 : report("Memory management; Source string descriptor is inconsistent");
81 : 1 : provide(FAILURE);
82 : : }
83 : :
84 : : /* In descriptor-to-descriptor string mode, the source contract already
85 : : guarantees a cached visible length and a terminator right after it.
86 : : Route the append through fixed-string semantics so only the visible prefix plus
87 : : one terminator participates in the concatenation, while any reserved tail
88 : : beyond that cached terminator remains ignored */
89 : 30 : run(mem_guarded_add(source->string_length,1,&source_total_elements));
90 : 30 : run(mem_guarded_byte_size(source,source_total_elements,&source_size_bytes));
91 : 30 : run(mem_core_string(
92 : : SOURCE_FIXED_STRING | TRANSFER_APPEND,
93 : : destination,
94 : : source_size_bytes,
95 : : source->data));
96 : :
97 : 30 : provide(status);
98 : : }
|