Branch data Line data Source code
1 : : #include "mem.h"
2 : : #include "mem_internal.h"
3 : :
4 : : /**
5 : : * @brief Shared internal data-descriptor core for append and copy entry points
6 : : *
7 : : * This helper is the descriptor-to-descriptor raw-data counterpart of
8 : : * @ref mem_core_string. Both operands must be in data mode, and the transfer
9 : : * is always performed byte for byte without any string interpretation
10 : : *
11 : : * Source and destination may use different element sizes. The only size-compatibility
12 : : * rule is that the full source payload, measured in bytes, must be divisible by
13 : : * the destination element size. That rule prevents the result from ending with
14 : : * a partial destination element whose ownership would be unclear
15 : : *
16 : : * Self-aliasing is supported because the actual byte transfer is delegated to
17 : : * @ref mem_core_buffer. If the source descriptor points into the destination
18 : : * allocation, the raw-pointer core saves the source offset before resizing and
19 : : * rebuilds the source pointer afterwards before calling `memmove(...)`
20 : : *
21 : : * Example:
22 : : * @code
23 : : * m_create(unsigned short,destination);
24 : : * m_create(unsigned char,source);
25 : : *
26 : : * const unsigned char bytes[] = {'a','b','c','d'};
27 : : *
28 : : * if((TRIUMPH & mem_copy_buffer(source,sizeof(bytes),bytes)) == 0) { return FAILURE; }
29 : : * if((TRIUMPH & mem_core_data(TRANSFER_REPLACE,destination,source)) == 0) { return FAILURE; }
30 : : * // destination now stores two elements whose raw byte view is "abcd"
31 : : * @endcode
32 : : *
33 : : * @param mode Binary mode flags. Data-descriptor cores only use transfer flags
34 : : * @param destination Pointer to the destination descriptor in data mode
35 : : * @param source Pointer to the source descriptor in data mode
36 : : * @return `SUCCESS` on success; `FAILURE` otherwise
37 : : */
38 : 35 : Return mem_core_data(
39 : : const MEM_CORE_MODE mode,
40 : : memory *destination,
41 : : const memory *source)
42 : : {
43 : : /* Status returned by this function through provide()
44 : : Default value assumes successful completion */
45 : 35 : Return status = SUCCESS;
46 : :
47 : : /* Transfer-mode subset extracted from the combined mode flags */
48 : 35 : const MEM_CORE_MODE transfer_mode = mode & TRANSFER_MASK;
49 : :
50 : : /* Exact source payload size expressed in bytes */
51 : 35 : size_t source_bytes = 0;
52 : :
53 [ + - - + ]: 35 : if(destination == NULL || source == NULL)
54 : : {
55 : 0 : report("Memory management; Arguments must be non-NULL");
56 : 0 : provide(FAILURE);
57 : : }
58 : :
59 [ + + - + ]: 35 : if(destination->length > 0 && destination->data == NULL)
60 : : {
61 : 0 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
62 : 0 : provide(FAILURE);
63 : : }
64 : :
65 [ + + + + ]: 35 : if(source->length > 0 && source->data == NULL)
66 : : {
67 : 1 : report("Memory management; Descriptor has non-zero length with NULL data pointer");
68 : 1 : provide(FAILURE);
69 : : }
70 : :
71 [ + + ]: 34 : if(destination->is_string == true)
72 : : {
73 : 2 : report("Memory management; Destination must be in data mode, but it is a string");
74 : 2 : provide(FAILURE);
75 : : }
76 : :
77 [ - + ]: 32 : if(source->is_string == true)
78 : : {
79 : 0 : report("Memory management; Source must be in data mode, but it is a string");
80 : 0 : provide(FAILURE);
81 : : }
82 : :
83 [ - + ]: 32 : if(destination->single_element_size == 0)
84 : : {
85 : 0 : report("Memory management; Destination element size is zero (uninitialized)");
86 : 0 : provide(FAILURE);
87 : : }
88 : :
89 [ - + ]: 32 : if(source->single_element_size == 0)
90 : : {
91 : 0 : report("Memory management; Source element size is zero (uninitialized)");
92 : 0 : provide(FAILURE);
93 : : }
94 : :
95 : 32 : run(mem_guarded_byte_size(source,source->length,&source_bytes));
96 : :
97 [ - + ]: 32 : if(CRITICAL & status)
98 : : {
99 : 0 : report("Memory management; Source byte count overflows");
100 : 0 : provide(status);
101 : : }
102 : :
103 [ + + ]: 32 : if((source_bytes % destination->single_element_size) != 0)
104 : : {
105 : 11 : report(
106 : : "Memory management; Source byte count %zu is not divisible by destination element size %zu",
107 : : source_bytes,
108 : : destination->single_element_size);
109 : 11 : provide(FAILURE);
110 : : }
111 : :
112 : 21 : provide(mem_core_buffer(transfer_mode,destination,source_bytes,source->data));
113 : : }
|