Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : : #include <string.h>
4 : :
5 : : /**
6 : : * @brief Copy one descriptor into another when both descriptors use the same mode
7 : : *
8 : : * This helper copies one descriptor into another when both descriptors already
9 : : * use the same semantic mode.
10 : : * When both operands are treated as strings, the copy trusts the cached
11 : : * `source->string_length`, treats the source as a fixed-string payload that
12 : : * ends exactly at that cached visible length plus one terminator element, and
13 : : * delegates the replacement to @ref mem_copy_fixed_string. When both
14 : : * operands are already in data mode, the raw descriptor transfer is delegated
15 : : * to @ref mem_copy_data
16 : : *
17 : : * Mixed string/data copies are rejected on purpose. This helper does not perform
18 : : * implicit mode conversion because that would hide a change in the semantic kind
19 : : * of the payload behind a plain copy call. In string mode the source and
20 : : * destination must also use the same element size, and a string source must
21 : : * provide consistent cached string metadata
22 : : *
23 : : * @param destination Pointer to the destination descriptor that receives the copy
24 : : * @param source Pointer to the source descriptor to copy from
25 : : * @return `SUCCESS` on success; `FAILURE` otherwise
26 : : */
27 : 647 : Return mem_copy(
28 : : memory *destination,
29 : : const memory *source)
30 : : {
31 : : /* Status returned by this function through provide()
32 : : Default value assumes successful completion */
33 : 647 : Return status = SUCCESS;
34 : :
35 : : /* Total source byte count passed to the routed copy helper */
36 : 647 : size_t source_size_bytes = 0;
37 : :
38 : : /* Logical source element count used for fixed-string routing */
39 : 647 : size_t source_total_elements = 0;
40 : :
41 [ + - - + ]: 647 : if(destination == NULL || source == NULL)
42 : : {
43 : 0 : report("Memory management; copy arguments must be non-NULL");
44 : 0 : provide(FAILURE);
45 : : }
46 : :
47 [ + + + + ]: 647 : if(destination->length > 0 && destination->data == NULL)
48 : : {
49 : 1 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
50 : 1 : provide(FAILURE);
51 : : }
52 : :
53 [ + + + + ]: 646 : if(source->length > 0 && source->data == NULL)
54 : : {
55 : 2 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
56 : 2 : provide(FAILURE);
57 : : }
58 : :
59 [ + + ]: 644 : if(destination->single_element_size == 0)
60 : : {
61 : 1 : report("Memory management; Destination element size is zero (uninitialized)");
62 : 1 : provide(FAILURE);
63 : : }
64 : :
65 [ + + ]: 643 : if(source->single_element_size == 0)
66 : : {
67 : 1 : report("Memory management; Source element size is zero (uninitialized)");
68 : 1 : provide(FAILURE);
69 : : }
70 : :
71 [ + + ]: 642 : if(destination->is_string != source->is_string)
72 : : {
73 : 2 : report("Memory management; Source and destination must both be strings or both be data");
74 : 2 : provide(FAILURE);
75 : : }
76 : :
77 [ + + ]: 640 : if(destination->is_string == true)
78 : : {
79 [ + + ]: 635 : if(destination->single_element_size != source->single_element_size)
80 : : {
81 : 1 : report("Memory management; Element size mismatch (%zu vs %zu)",
82 : : destination->single_element_size,
83 : : source->single_element_size);
84 : 1 : provide(FAILURE);
85 : : }
86 : :
87 [ + + - + ]: 634 : if((source->length == 0 && source->string_length != 0) ||
88 [ + - - + ]: 633 : (source->length > 0 && source->string_length >= source->length))
89 : : {
90 : 1 : report("Memory management; Source string descriptor is inconsistent");
91 : 1 : provide(FAILURE);
92 : : }
93 : :
94 : : /* In descriptor-to-descriptor string mode, the source contract already
95 : : guarantees a cached visible length and a terminator right after it.
96 : : Route the copy through fixed-string semantics so the transfer uses exactly
97 : : that visible prefix plus one terminator element, instead of rescanning
98 : : the whole logical span in search of zero */
99 : 633 : run(mem_guarded_add(source->string_length,1,&source_total_elements));
100 : 633 : run(mem_guarded_byte_size(source,source_total_elements,&source_size_bytes));
101 : 633 : run(mem_copy_fixed_string(destination,source_size_bytes,source->data));
102 : : } else {
103 : 5 : run(mem_copy_data(destination,source));
104 : : }
105 : :
106 : 638 : provide(status);
107 : : }
|