Make an SIValue that creates its own copies of the original's allocations, if any. * This is not a deep clone: if the inner value holds its own references, * such as the Entity pointer to the properties of a Node or Edge, those are unmodified. */
| 132 | * This is not a deep clone: if the inner value holds its own references, |
| 133 | * such as the Entity pointer to the properties of a Node or Edge, those are unmodified. */ |
| 134 | SIValue SI_CloneValue(const SIValue v) { |
| 135 | if(v.allocation == M_NONE) return v; // Stack value; no allocation necessary. |
| 136 | |
| 137 | if(v.type == T_STRING) { |
| 138 | // Allocate a new copy of the input's string value. |
| 139 | return SI_DuplicateStringVal(v.stringval); |
| 140 | } |
| 141 | |
| 142 | if(v.type == T_ARRAY) { |
| 143 | return SIArray_Clone(v); |
| 144 | } |
| 145 | |
| 146 | if(v.type == T_PATH) { |
| 147 | return SIPath_Clone(v); |
| 148 | } |
| 149 | |
| 150 | if(v.type == T_MAP) { |
| 151 | return Map_Clone(v); |
| 152 | } |
| 153 | |
| 154 | // Copy the memory region for Node and Edge values. This does not modify the |
| 155 | // inner Entity pointer to the value's properties. |
| 156 | SIValue clone; |
| 157 | clone.type = v.type; |
| 158 | clone.allocation = M_SELF; |
| 159 | |
| 160 | size_t size = 0; |
| 161 | if(v.type == T_NODE) { |
| 162 | size = sizeof(Node); |
| 163 | } else if(v.type == T_EDGE) { |
| 164 | size = sizeof(Edge); |
| 165 | } else { |
| 166 | ASSERT(false && "Encountered heap-allocated SIValue of unhandled type"); |
| 167 | } |
| 168 | |
| 169 | clone.ptrval = rm_malloc(size); |
| 170 | memcpy(clone.ptrval, v.ptrval, size); |
| 171 | return clone; |
| 172 | } |
| 173 | |
| 174 | SIValue SI_ShallowCloneValue(const SIValue v) { |
| 175 | if(v.allocation == M_CONST || v.allocation == M_NONE) return v; |
no test coverage detected