| 658 | struct PFVfsList { std::vector<std::string> paths; }; |
| 659 | |
| 660 | PF_API PF_HANDLE pf_vfs_find(const char* extension) { |
| 661 | ClearError(); |
| 662 | if (!g_vfsMounted) { SetError("VFS not mounted"); return nullptr; } |
| 663 | try { |
| 664 | auto* list = new PFVfsList(); |
| 665 | std::string ext(extension ? extension : ""); |
| 666 | std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); |
| 667 | |
| 668 | for (int i = 0; i < GFileBanks.Size(); i++) { |
| 669 | QFBank& bank = GFileBanks[i]; |
| 670 | bank.Lock(); |
| 671 | std::string prefix((const char*)bank.GetPrefix()); |
| 672 | struct Ctx { PFVfsList* list; std::string* ext; std::string* prefix; }; |
| 673 | Ctx ctx{list, &ext, &prefix}; |
| 674 | bank.ForEach([](const FileInfoO& fi, const FileBankType*, void* c) { |
| 675 | auto* x = static_cast<Ctx*>(c); |
| 676 | std::string name((const char*)fi.name); |
| 677 | std::string lower = name; |
| 678 | std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); |
| 679 | if (x->ext->empty() || (lower.size() >= x->ext->size() && |
| 680 | lower.substr(lower.size() - x->ext->size()) == *x->ext)) |
| 681 | x->list->paths.push_back(*x->prefix + name); |
| 682 | }, &ctx); |
| 683 | bank.Unlock(); |
| 684 | } |
| 685 | std::sort(list->paths.begin(), list->paths.end()); |
| 686 | return list; |
| 687 | } catch (const std::exception& e) { |
| 688 | SetError(e.what()); |
| 689 | return nullptr; |
| 690 | } |
| 691 | } |
| 692 | |
| 693 | PF_API int pf_vfs_find_count(PF_HANDLE list) { |
| 694 | if (!list) return 0; |