#pragma once #include "tl/result.h" #include "tl/string.h" #include "tl/vector_map.h" #include "fs/IStreamSource.h" #include "fs/IPack.h" #include "fs/AbsPath.h" #include "fs/Api.h" struct zip; struct zip_source; struct zip_file; namespace tl { template<> struct ptr_traits { static constexpr inline bool custom_deleter = true; static constexpr inline bool requires_virtual_destructor_check = false; }; //template<> struct ptr_traits //{ // static constexpr inline bool custom_deleter = true; // static constexpr inline bool requires_virtual_destructor_check = false; //}; template<> struct ptr_traits { static constexpr inline bool custom_deleter = true; static constexpr inline bool requires_virtual_destructor_check = false; }; } namespace fs { class MapSourceView; class FS_API ZipPack final : public IPack { public: ZipPack() = default; ~ZipPack() override = default; typedef tl::result, Error> CreateResult; static CreateResult create(tl::unique_ref source); static CreateResult create(tl::lent_ref filesystem, AbsPathView path); void setEncryptionData(const tl::string& key, uint32_t rounds); OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; IsFileResult isFile(AbsPathView path) const override; IsFolderResult isFolder(AbsPathView path) const override; ExistsResult exists(AbsPathView path) const override; GetStatResult getStat(AbsPathView path) const override; cppcoro::generator enumerate(AbsPath path) const override; cppcoro::generator enumerateRecursively(AbsPath path) const override; tl::result convertToNativePath(AbsPathView path) const override; struct ZipData { tl::unique_ptr fsMapSource; tl::lent_ptr filesystem; AbsPath path; tl::unique_ptr fsSource; uint64_t cachedSize = uint64_t(-1); //tl::unique_ptr zipSource; tl::unique_ptr zipArchive; }; protected: struct File; struct Folder; struct EntryIndex; ZipPack(tl::shared_ptr data); //OpenMapSourceResult openRawMapSource(const File& file, MapView mapView) const; //OpenSourceResult openRawSource(const File& file) const; OpenSourceResult _openSource(const File& file) const; OpenMapSourceResult _openMapSource(const File& file) const; OpenStreamSourceResult _openStreamSource(const File& file) const; uint16_t getOrAddFolder(AbsPathView folderPath, tl::vector>& io_childrenIndices); void createEntries(zip& archive); struct File { uint16_t zipIndex = 0; //index inside the zip archive tl::string name; uint16_t parentIndex = 0; }; static_assert(sizeof(File) <= sizeof(tl::string) + 40, "Check your sizes!!!"); struct Folder { uint16_t zipIndex = 0; //index inside the zip archive tl::string name; uint16_t parentIndex = 0; uint16_t childrenStartIndex = 0; // this is an index inside m_childrenIndices uint16_t childrenCount = 0; }; static_assert(sizeof(Folder) <= sizeof(tl::string) + 20, "Check your sizes!!!"); struct EntryIndex { EntryIndex() = default; EntryIndex(bool isFolder, uint16_t index) : isFolder(isFolder) , index(index) { } uint32_t isFolder : 1; uint32_t index : 16; }; static_assert(sizeof(EntryIndex) == 4, "Check your sizes!!!"); private: mutable std::mutex m_zipMapSourceLock; tl::shared_ptr m_zipData; tl::string m_encryptionKey; uint32_t m_encryptionRounds = 32; tl::vector_map m_pathToIndex; tl::vector m_files; tl::vector m_folders; tl::vector m_childrenIndices; // these are indices inside the m_files or m_folders void buildUpPath(RelPath& path, const Folder& folder, uint32_t toIndex) const; void buildUpPath(RelPath& path, const File& file, uint32_t toIndex) const; }; }