| 73 | |
| 74 | template <typename F> |
| 75 | bool enumerateFilePaths(F&& callback) { |
| 76 | if (!fileStatSlimCache.empty()) { |
| 77 | for (const auto& entry : fileStatSlimCache) { |
| 78 | callback(std::string_view{entry.first}); |
| 79 | } |
| 80 | return true; |
| 81 | } |
| 82 | |
| 83 | const bool wasOpen = isOpen(); |
| 84 | if (!wasOpen && !open()) { |
| 85 | return false; |
| 86 | } |
| 87 | |
| 88 | if (!loadZipDetails()) { |
| 89 | if (!wasOpen) { |
| 90 | close(); |
| 91 | } |
| 92 | return false; |
| 93 | } |
| 94 | |
| 95 | file.seek(zipDetails.centralDirOffset); |
| 96 | |
| 97 | uint32_t sig; |
| 98 | char itemName[256]; |
| 99 | |
| 100 | while (file.available()) { |
| 101 | file.read(&sig, 4); |
| 102 | if (sig != 0x02014b50) { |
| 103 | break; |
| 104 | } |
| 105 | |
| 106 | file.seekCur(24); |
| 107 | uint16_t nameLen, m, k; |
| 108 | file.read(&nameLen, 2); |
| 109 | file.read(&m, 2); |
| 110 | file.read(&k, 2); |
| 111 | file.seekCur(12); |
| 112 | |
| 113 | if (nameLen < sizeof(itemName)) { |
| 114 | file.read(itemName, nameLen); |
| 115 | itemName[nameLen] = '\0'; |
| 116 | callback(std::string_view{itemName, nameLen}); |
| 117 | } else { |
| 118 | file.seekCur(nameLen); |
| 119 | } |
| 120 | |
| 121 | file.seekCur(m + k); |
| 122 | } |
| 123 | |
| 124 | if (!wasOpen) { |
| 125 | close(); |
| 126 | } |
| 127 | return true; |
| 128 | } |
| 129 | }; |