| 441 | } |
| 442 | |
| 443 | size_t DObject::PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail) |
| 444 | { |
| 445 | const PClass *info = GetClass(); |
| 446 | size_t changed = 0; |
| 447 | if (info->FlatPointers == nullptr) |
| 448 | { |
| 449 | info->BuildFlatPointers(); |
| 450 | assert(info->FlatPointers); |
| 451 | } |
| 452 | |
| 453 | for(size_t i = 0; i < info->FlatPointersSize; i++) |
| 454 | { |
| 455 | size_t offset = info->FlatPointers[i].first; |
| 456 | auto& obj = *(DObject**)((uint8_t*)this + offset); |
| 457 | |
| 458 | if (obj == old) |
| 459 | { |
| 460 | // If a pointer's type is null, that means it's native and anything native is safe to swap |
| 461 | // around due to its inherit type expansiveness. |
| 462 | if (info->FlatPointers[i].second == nullptr || notOld->IsKindOf(info->FlatPointers[i].second->PointedClass())) |
| 463 | { |
| 464 | obj = notOld; |
| 465 | changed++; |
| 466 | } |
| 467 | else if (nullOnFail && obj != nullptr) |
| 468 | { |
| 469 | obj = nullptr; |
| 470 | changed++; |
| 471 | } |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | if (info->ArrayPointers == nullptr) |
| 476 | { |
| 477 | info->BuildArrayPointers(); |
| 478 | assert(info->ArrayPointers); |
| 479 | } |
| 480 | |
| 481 | for(size_t i = 0; i < info->ArrayPointersSize; i++) |
| 482 | { |
| 483 | const bool isType = notOld->IsKindOf(static_cast<PObjectPointer*>(info->ArrayPointers[i].second->ElementType)->PointedClass()); |
| 484 | |
| 485 | if (!isType && !nullOnFail) |
| 486 | continue; |
| 487 | |
| 488 | auto aray = (TArray<DObject*>*)((uint8_t*)this + info->ArrayPointers[i].first); |
| 489 | for (auto &p : *aray) |
| 490 | { |
| 491 | if (p == old) |
| 492 | { |
| 493 | if (isType) |
| 494 | { |
| 495 | p = notOld; |
| 496 | changed++; |
| 497 | } |
| 498 | else if (p != nullptr) |
| 499 | { |
| 500 | p = nullptr; |
nothing calls this directly
no test coverage detected