Ticket #8912: kyra_resource_parent_cache_v7.diff
File kyra_resource_parent_cache_v7.diff, 10.4 KB (added by , 17 years ago) |
---|
-
resource.h
43 43 44 44 struct ResFileEntry { 45 45 Common::String parent; 46 mutable ResFileEntry *parentEntry; // Cache to avoid lookup by string in the map 47 // No smart invalidation is needed because the map is cleared globally 48 // or expanded but no element is ever removed 46 49 uint32 size; 47 50 48 51 bool preload; … … 128 131 bool loadFileToBuf(const char *file, void *buf, uint32 maxSize); 129 132 protected: 130 133 void checkFile(const Common::String &file); 131 bool isAccessable(const Common::String &file); 134 bool isAccessible(const Common::String &file); 135 bool isAccessible(const ResFileEntry *fileEntry); 132 136 133 137 void detectFileTypes(); 138 void detectFileType(const Common::String &filename, ResFileEntry *fileEntry); 134 139 135 140 void initializeLoaders(); 136 141 const ResArchiveLoader *getLoader(ResFileEntry::kType type) const; … … 140 145 LoaderList _loaders; 141 146 ResFileMap _map; 142 147 148 ResFileEntry *getParentEntry(const ResFileEntry *entry) const; 149 ResFileEntry *getParentEntry(const Common::String &filename) const; 150 143 151 typedef Common::List<Common::SharedPtr<CompArchiveLoader> > CompLoaderList; 144 152 typedef CompLoaderList::iterator CompLoaderIterator; 145 153 typedef CompLoaderList::const_iterator CCompLoaderIterator; -
resource.cpp
150 150 } 151 151 152 152 bool Resource::loadPakFile(const Common::String &filename) { 153 if (!isAccess able(filename))153 if (!isAccessible(filename)) 154 154 return false; 155 155 156 156 ResFileMap::iterator iter = _map.find(filename); … … 201 201 // If the old parent is not protected we mark it as not preload anymore, 202 202 // since now no longer all of its embedded files are in the filemap. 203 203 oldParent->_value.preload = false; 204 _map[i->filename]= i->entry;204 iter->_value = i->entry; 205 205 } 206 206 } else { 207 207 // Old parent not found? That's strange... But we just overwrite the old 208 208 // entry. 209 _map[i->filename]= i->entry;209 iter->_value = i->entry; 210 210 } 211 211 } else { 212 212 // The old parent has the same filenames as the new archive, we are sure and overwrite the 213 213 // old file entry, could be afterall that the preload flag of the new archive was 214 214 // just unflagged. 215 _map[i->filename]= i->entry;215 iter->_value = i->entry; 216 216 } 217 217 } 218 218 // 'else' case would mean here overwriting an existing file entry in the map without parent. … … 244 244 filename.toUppercase(); 245 245 246 246 if (filename.hasSuffix(".PAK")) { 247 if (!isAccess able(filename) && _vm->gameFlags().isDemo) {247 if (!isAccessible(filename) && _vm->gameFlags().isDemo) { 248 248 // the demo version supplied with Kyra3 does not 249 249 // contain all pak files listed in filedata.fdt 250 250 // so we don't do anything here if they are non … … 289 289 } 290 290 291 291 bool Resource::isInPakList(const Common::String &filename) { 292 if (!isAccess able(filename))292 if (!isAccessible(filename)) 293 293 return false; 294 294 ResFileMap::iterator iter = _map.find(filename); 295 295 if (iter == _map.end()) … … 320 320 bool Resource::exists(const char *file, bool errorOutOnFail) { 321 321 if (Common::File::exists(file)) 322 322 return true; 323 else if (isAccess able(file))323 else if (isAccessible(file)) 324 324 return true; 325 325 else if (errorOutOnFail) 326 326 error("File '%s' can't be found", file); … … 335 335 if (f.open(file)) 336 336 return f.size(); 337 337 } else { 338 if (!isAccess able(file))338 if (!isAccessible(file)) 339 339 return 0; 340 340 341 341 ResFileMap::const_iterator iter = _map.find(file); … … 362 362 if ((compEntry = _compFiles.find(file)) != _compFiles.end()) 363 363 return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false); 364 364 365 if (!isAccess able(file))365 if (!isAccessible(file)) 366 366 return 0; 367 367 368 368 ResFileMap::const_iterator iter = _map.find(file); … … 381 381 Common::SeekableReadStream *parent = getFileStream(iter->_value.parent); 382 382 assert(parent); 383 383 384 ResFile Map::const_iterator parentIter = _map.find(iter->_value.parent);385 const ResArchiveLoader *loader = getLoader(parent Iter->_value.type);384 ResFileEntry* parentEntry = getParentEntry(&iter->_value); 385 const ResArchiveLoader *loader = getLoader(parentEntry->type); 386 386 assert(loader); 387 387 388 388 return loader->loadFileFromArchive(file, parent, iter->_value); … … 391 391 return 0; 392 392 } 393 393 394 bool Resource::isAccess able(const Common::String &file) {394 bool Resource::isAccessible(const Common::String &file) { 395 395 checkFile(file); 396 396 397 397 ResFileMap::const_iterator iter = _map.find(file); 398 while (iter != _map.end()) { 399 if (!iter->_value.parent.empty()) { 400 iter = _map.find(iter->_value.parent); 401 if (iter != _map.end()) { 402 // parent can never be a non archive file 403 if (iter->_value.type == ResFileEntry::kRaw) 404 return false; 405 // not mounted parent means not accessable 406 else if (!iter->_value.mounted) 407 return false; 408 } 398 if (iter == _map.end()) 399 return false; 400 401 return isAccessible(&iter->_value); 402 } 403 404 bool Resource::isAccessible(const ResFileEntry *fileEntry) { 405 assert(fileEntry); 406 407 const ResFileEntry* currentEntry = fileEntry; 408 while (not currentEntry->parent.empty()) { 409 if (currentEntry->parentEntry) { 410 currentEntry = currentEntry->parentEntry; 409 411 } else { 410 return true; 412 ResFileMap::iterator it = _map.find(currentEntry->parent); 413 if (it == _map.end()) 414 return false; 415 else 416 currentEntry->parentEntry = &it->_value; 411 417 } 418 // parent can never be a non archive file 419 if (currentEntry->type == ResFileEntry::kRaw) 420 return false; 421 // not mounted parent means not accessable 422 else if (!currentEntry->mounted) 423 return false; 412 424 } 413 return false; 425 426 return true; 414 427 } 415 428 429 ResFileEntry *Resource::getParentEntry(const ResFileEntry *entry) const { 430 assert(entry); 431 if (entry->parent.empty()) 432 return 0; 433 else if (entry->parentEntry) { 434 assert(_map.find(entry->parent) != _map.end()); // If some day the hash map implementations changes and moves nodes around, 435 // this assumption would fail and the whole system would need a refactoring 436 assert(entry->parentEntry == &_map.find(entry->parent)->_value); 437 return entry->parentEntry; 438 } else { 439 ResFileMap::iterator it = _map.find(entry->parent); 440 if (it == _map.end()) 441 return 0; // If it happens often, the structure maybe deserves a flag to avoid rechecking the map 442 else { 443 entry->parentEntry = &it->_value; 444 return entry->parentEntry; 445 } 446 } 447 } 448 449 ResFileEntry *Resource::getParentEntry(const Common::String &filename) const { 450 ResFileMap::iterator it = _map.find(filename); 451 assert(it != _map.end()); 452 return getParentEntry(&it->_value); 453 } 454 416 455 void Resource::checkFile(const Common::String &file) { 417 456 if (_map.find(file) == _map.end()) { 418 457 CompFileMap::const_iterator iter; 419 458 420 459 if ((iter = _compFiles.find(file)) != _compFiles.end()) { 421 ResFileEntry entry;460 ResFileEntry& entry = _map[file]; 422 461 entry.parent = ""; 462 entry.parentEntry = 0; 423 463 entry.size = iter->_value.size; 424 464 entry.mounted = false; 425 465 entry.preload = false; 426 466 entry.prot = false; 427 467 entry.type = ResFileEntry::kAutoDetect; 428 468 entry.offset = 0; 429 _map[file] = entry; 430 431 detectFileTypes(); 469 470 detectFileType(file, &entry); 432 471 } else if (Common::File::exists(file)) { 433 472 Common::File temp; 434 473 if (temp.open(file)) { 435 ResFileEntry entry;474 ResFileEntry& entry = _map[file]; 436 475 entry.parent = ""; 476 entry.parentEntry = 0; 437 477 entry.size = temp.size(); 438 478 entry.mounted = file.compareToIgnoreCase(StaticResource::staticDataFilename()) != 0; 439 479 entry.preload = false; 440 480 entry.prot = false; 441 481 entry.type = ResFileEntry::kAutoDetect; 442 482 entry.offset = 0; 443 _map[file] = entry;444 483 temp.close(); 445 484 446 detectFileType s();485 detectFileType(file, &entry); 447 486 } 448 487 } 449 488 } 450 489 } 451 490 452 void Resource::detectFileTypes() { 453 for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) { 454 if (!isAccessable(i->_key)) 455 continue; 491 void Resource::detectFileType(const Common::String &filename, ResFileEntry *fileEntry) { 492 assert(fileEntry); 493 494 if (!isAccessible(fileEntry)) 495 return; 456 496 457 if (i->_value.type == ResFileEntry::kAutoDetect) {458 459 460 if (!(*l)->checkFilename(i->_key))461 462 463 464 stream = getFileStream(i->_key);497 if (fileEntry->type == ResFileEntry::kAutoDetect) { 498 Common::SeekableReadStream *stream = 0; 499 for (LoaderIterator l = _loaders.begin(); l != _loaders.end(); ++l) { 500 if (!(*l)->checkFilename(filename)) 501 continue; 502 503 if (!stream) 504 stream = getFileStream(filename); 465 505 466 if ((*l)->isLoadable(i->_key, *stream)) { 467 i->_value.type = (*l)->getType(); 468 i->_value.mounted = false; 469 i->_value.preload = false; 470 break; 471 } 506 if ((*l)->isLoadable(filename, *stream)) { 507 fileEntry->type = (*l)->getType(); 508 fileEntry->mounted = false; 509 fileEntry->preload = false; 510 break; 472 511 } 473 delete stream; 474 stream = 0; 512 } 513 delete stream; 514 stream = 0; 475 515 476 if (i->_value.type == ResFileEntry::kAutoDetect) 477 i->_value.type = ResFileEntry::kRaw; 478 } 516 if (fileEntry->type == ResFileEntry::kAutoDetect) 517 fileEntry->type = ResFileEntry::kRaw; 479 518 } 480 519 } 481 520 521 void Resource::detectFileTypes() { 522 for (ResFileMap::iterator i = _map.begin(); i != _map.end(); ++i) 523 detectFileType(i->_key, &i->_value); 524 } 525 482 526 void Resource::tryLoadCompFiles() { 483 527 for (CCompLoaderIterator i = _compLoaders.begin(); i != _compLoaders.end(); ++i) { 484 528 if ((*i)->checkForFiles()) … … 620 664 entry.size = endoffset - startoffset; 621 665 entry.offset = startoffset; 622 666 entry.parent = filename; 667 entry.parentEntry = 0; 623 668 entry.type = ResFileEntry::kAutoDetect; 624 669 entry.mounted = false; 625 670 entry.prot = false; … … 738 783 for (Common::List<Common::String>::iterator file = filenames.begin(); file != filenames.end(); ++file) { 739 784 ResFileEntry entry; 740 785 entry.parent = filename; 786 entry.parentEntry = 0; 741 787 entry.type = ResFileEntry::kAutoDetect; 742 788 entry.mounted = false; 743 789 entry.preload = false; … … 807 853 for (uint i = 0; i < entries; ++i) { 808 854 ResFileEntry entry; 809 855 entry.parent = filename; 856 entry.parentEntry = 0; 810 857 entry.type = ResFileEntry::kAutoDetect; 811 858 entry.mounted = false; 812 859 entry.preload = false;