| 195 | } |
| 196 | |
| 197 | int dictMerge(dict *dst, dict *src) |
| 198 | { |
| 199 | #define MERGE_BLOCK_SIZE 4 |
| 200 | dictEntry *rgdeT[MERGE_BLOCK_SIZE]; |
| 201 | |
| 202 | assert(dst != src); |
| 203 | if (dictSize(src) == 0) |
| 204 | return DICT_OK; |
| 205 | |
| 206 | if (dictSize(dst) == 0) |
| 207 | { |
| 208 | dict::swap(*dst, *src); |
| 209 | std::swap(dst->pauserehash, src->pauserehash); |
| 210 | return DICT_OK; |
| 211 | } |
| 212 | |
| 213 | size_t expectedSize = dictSize(src) + dictSize(dst); |
| 214 | if (dictSize(src) > dictSize(dst) && src->asyncdata == nullptr && dst->asyncdata == nullptr) |
| 215 | { |
| 216 | dict::swap(*dst, *src); |
| 217 | std::swap(dst->pauserehash, src->pauserehash); |
| 218 | } |
| 219 | |
| 220 | if (!dictIsRehashing(dst) && !dictIsRehashing(src)) |
| 221 | { |
| 222 | if (dst->ht[0].size >= src->ht[0].size) |
| 223 | { |
| 224 | dst->ht[1] = dst->ht[0]; |
| 225 | dst->ht[0] = src->ht[0]; |
| 226 | } |
| 227 | else |
| 228 | { |
| 229 | dst->ht[1] = src->ht[0]; |
| 230 | } |
| 231 | _dictReset(&src->ht[0]); |
| 232 | dst->rehashidx = 0; |
| 233 | assert(dictIsRehashing(dst)); |
| 234 | assert((dictSize(src)+dictSize(dst)) == expectedSize); |
| 235 | return DICT_OK; |
| 236 | } |
| 237 | |
| 238 | if (!dictIsRehashing(src) && dictSize(src) > 0 && |
| 239 | (src->ht[0].size == dst->ht[0].size || src->ht[0].size == dst->ht[1].size)) |
| 240 | { |
| 241 | auto &htDst = (src->ht[0].size == dst->ht[0].size) ? dst->ht[0] : dst->ht[1]; |
| 242 | |
| 243 | assert(src->ht[0].size == htDst.size); |
| 244 | for (size_t ide = 0; ide < src->ht[0].size; ide += MERGE_BLOCK_SIZE) |
| 245 | { |
| 246 | if (src->ht[0].used == 0) |
| 247 | break; |
| 248 | |
| 249 | for (int dde = 0; dde < MERGE_BLOCK_SIZE; ++dde) { |
| 250 | rgdeT[dde] = src->ht[0].table[ide + dde]; |
| 251 | src->ht[0].table[ide + dde] = nullptr; |
| 252 | } |
| 253 | |
| 254 | for (;;) { |
no test coverage detected