| 310 | } |
| 311 | |
| 312 | static void vMemMgrInsertNode(VMemMgr* self, MemNode* node) noexcept { |
| 313 | if (!self->_root) { |
| 314 | // Empty tree case. |
| 315 | self->_root = node; |
| 316 | } |
| 317 | else { |
| 318 | // False tree root. |
| 319 | RbNode head = { { nullptr, nullptr }, 0, 0 }; |
| 320 | |
| 321 | // Grandparent & parent. |
| 322 | RbNode* g = nullptr; |
| 323 | RbNode* t = &head; |
| 324 | |
| 325 | // Iterator & parent. |
| 326 | RbNode* p = nullptr; |
| 327 | RbNode* q = t->node[1] = self->_root; |
| 328 | |
| 329 | int dir = 0; |
| 330 | int last = 0; // Not needed to initialize, but makes some tools happy. |
| 331 | |
| 332 | // Search down the tree. |
| 333 | for (;;) { |
| 334 | if (!q) { |
| 335 | // Insert new node at the bottom. |
| 336 | q = node; |
| 337 | p->node[dir] = node; |
| 338 | } |
| 339 | else if (rbIsRed(q->node[0]) && rbIsRed(q->node[1])) { |
| 340 | // Color flip. |
| 341 | q->red = 1; |
| 342 | q->node[0]->red = 0; |
| 343 | q->node[1]->red = 0; |
| 344 | } |
| 345 | |
| 346 | // Fix red violation. |
| 347 | if (rbIsRed(q) && rbIsRed(p)) { |
| 348 | int dir2 = t->node[1] == g; |
| 349 | t->node[dir2] = q == p->node[last] ? rbRotateSingle(g, !last) : rbRotateDouble(g, !last); |
| 350 | } |
| 351 | |
| 352 | // Stop if found. |
| 353 | if (q == node) |
| 354 | break; |
| 355 | |
| 356 | last = dir; |
| 357 | dir = q->mem < node->mem; |
| 358 | |
| 359 | // Update helpers. |
| 360 | if (g) t = g; |
| 361 | |
| 362 | g = p; |
| 363 | p = q; |
| 364 | q = q->node[dir]; |
| 365 | } |
| 366 | |
| 367 | // Update root. |
| 368 | self->_root = static_cast<MemNode*>(head.node[1]); |
| 369 | } |
no test coverage detected