| 354 | |
| 355 | template <class Item> |
| 356 | Item TopDUContextDynamicData::DUChainItemStorage<Item>::itemForIndex(uint index) const |
| 357 | { |
| 358 | if (index >= (0x0fffffff / 2)) { |
| 359 | index = 0x0fffffff - index; //We always keep the highest bit at zero |
| 360 | if (index == 0 || index > uint(temporaryItems.size())) |
| 361 | return {}; |
| 362 | else |
| 363 | return temporaryItems.at(index - 1); |
| 364 | } |
| 365 | |
| 366 | if (index == 0 || index > static_cast<uint>(items.size())) { |
| 367 | qCWarning(LANGUAGE) << "item index out of bounds:" << index << "count:" << items.size(); |
| 368 | return {}; |
| 369 | } |
| 370 | const uint realIndex = index - 1; |
| 371 | const auto& item = items.at(realIndex); |
| 372 | if (item) { |
| 373 | //Shortcut, because this is the most common case |
| 374 | return item; |
| 375 | } |
| 376 | |
| 377 | if (realIndex < ( uint )offsets.size() && offsets[realIndex].dataOffset) { |
| 378 | Q_ASSERT(!data->m_itemRetrievalForbidden); |
| 379 | |
| 380 | //Construct the context, and eventually its parent first |
| 381 | ///TODO: ugly, remove need for const_cast |
| 382 | auto itemData = const_cast<DUChainBaseData*>( |
| 383 | reinterpret_cast<const DUChainBaseData*>(data->pointerInData(offsets[realIndex].dataOffset)) |
| 384 | ); |
| 385 | |
| 386 | auto& item = items[realIndex]; |
| 387 | item = dynamic_cast<typename PtrType<Item>::value>(DUChainItemSystem::self().create(itemData)); |
| 388 | if (!item) { |
| 389 | //When this happens, the item has not been registered correctly. |
| 390 | //We can stop here, because else we will get crashes later. |
| 391 | qCritical() << "Failed to load item with identity" << itemData->classId; |
| 392 | return {}; |
| 393 | } |
| 394 | |
| 395 | if (isSharedDataItem<Item>()) { |
| 396 | // NOTE: shared data must never point to mmapped data regions as otherwise we might end up with |
| 397 | // use-after-free or double-deletions etc. pp. |
| 398 | // thus, make the item always dynamic after deserialization |
| 399 | item->makeDynamic(); |
| 400 | } |
| 401 | |
| 402 | auto parent = data->contextForIndex(offsets[realIndex].parentContext); |
| 403 | Q_ASSERT_X(parent, Q_FUNC_INFO, "Could not find parent context for loaded item.\n" |
| 404 | "Potentially, the context has been deleted without deleting its children."); |
| 405 | item->rebuildDynamicData(parent, index); |
| 406 | } else { |
| 407 | qCWarning(LANGUAGE) << "invalid item for index" << index << offsets.size() << |
| 408 | offsets.value(realIndex).dataOffset; |
| 409 | } |
| 410 | |
| 411 | return item; |
| 412 | } |
| 413 |
no test coverage detected