#pragma once #include "sectorcollection.h" #include "cfstorage.h" #include "slist.h" #include #include "RBTree/rbtree.h" #include "idirectoryentry.h" #include #include "header.h" namespace CFCPP { class DirectoryEntry; enum CFSConfiguration { Default = 1, SectorRecycle = 2, EraseFreeSectors = 4, NoValidationException = 8, LeaveOpen = 16 }; enum CFSUpdateMode { /// ReadOnly update mode prevents overwriting /// of the opened file. /// Data changes are allowed but they have to be /// persisted on a different file when required ReadOnly, /// Update mode allows subsequent data changing operations /// to be persisted directly on the opened file or stream /// method when required. Warning: this option may cause existing data loss if misused. Update }; class CompoundFile { public: CompoundFile(const std::wstring &fileName, CFSUpdateMode updateMode, CFSConfiguration configParameters = Default); CompoundFile(CFSVersion cfsVersion, CFSConfiguration configFlags); CompoundFile(const std::wstring &fileName); CompoundFile(Stream stream); CompoundFile(); void Commit(bool releaseMemory = false); inline bool HasSourceStream() {return sourceStream != nullptr;} void Close(); static std::shared_ptr CreateNewTree(); std::shared_ptr GetChildrenTree(int sid); std::shared_ptr RootStorage(); bool IsClosed()const; SVector &GetDirectories(); void ResetDirectoryEntry(int sid); void InvalidateDirectoryEntry(int sid); void FreeAssociatedData(int sid); void FreeData(CFStream* stream); void WriteData(std::shared_ptr cfItem, const std::vector& buffer, std::streamsize position, int offset, int count); void WriteData(std::shared_ptr cfItem, std::streamsize position, const std::vector& buffer); void WriteData(std::shared_ptr cfItem, const std::vector& buffer); void AppendData(std::shared_ptr cfItem, const std::vector& buffer); void SetStreamLength(std::shared_ptr cfItem, std::streamsize length); SList FindFreeSectors(SectorType sType); std::vector GetData(const CFStream *cFStream); int ReadData(CFStream* cFStream, std::streamsize position, std::vector& buffer, int count); int ReadData(CFStream* cFStream, std::streamsize position, std::vector& buffer, int offset, int count); std::vector GetDataBySID(int sid); GUID getGuidBySID(int sid); GUID getGuidForStream(int sid); void Save(std::wstring wFileName); void Save(Stream stream); protected: int GetSectorSize(); void Dispose(bool disposing); private: void CheckForLockSector(); void OnSizeLimitReached(); void LoadFile(std::wstring fileName); void SetFileName(std::wstring fileName); void LoadStream(Stream stream); void Load(Stream stream); SVector GetFatSectorChain(); SVector GetDifatSectorChain(); SVector GetNormalSectorChain(int secID); SVector GetMiniSectorChain(int secID); SVector GetSectorChain(int secID, SectorType chainType); void EnsureUniqueSectorIndex(int nextSecID, std::unordered_set &processedSectors); void CommitDirectory(); void Close(bool closeStream); std::shared_ptr RootEntry(); SVector FindDirectoryEntries(std::wstring entryName); std::shared_ptr DoLoadChildrenTrusted(std::shared_ptr de); void DoLoadChildren(std::shared_ptr bst, std::shared_ptr de); void NullifyChildNodes(std::shared_ptr de); void LoadSiblings(std::shared_ptr bst, std::shared_ptr de); void DoLoadSiblings(std::shared_ptr bst, std::shared_ptr de); bool ValidateSibling(int sid); void LoadDirectories(); void FreeMiniChain(SVector& sectorChain, bool zeroSector); void FreeMiniChain(SVector& sectorChain, int nth_sector_to_remove, bool zeroSector); void FreeChain(SVector& sectorChain, int nth_sector_to_remove, bool zeroSector); void FreeChain(SVector& sectorChain, bool zeroSector); void AllocateSectorChain(SVector& sectorChain); void AllocateFATSectorChain(SVector& sectorChain); void AllocateDIFATSectorChain(SVector& FATsectorChain); void AllocateMiniSectorChain(SVector& sectorChain); void PersistMiniStreamToStream(const SVector& miniSectorChain); static int LowSaturation(int i); void SetSectorChain(SVector sectorChain); CFSVersion getVersion() const; public: CFSConfiguration configuration = Default; std::unique_ptr
header; Stream sourceStream; private: const int HEADER_DIFAT_ENTRIES_COUNT = 109; int DIFAT_SECTOR_FAT_ENTRIES_COUNT = 127; int FAT_SECTOR_ENTRIES_COUNT = 128; const int SIZE_OF_SID = 4; bool sectorRecycle = false; bool eraseFreeSectors = false; static constexpr int FLUSHING_QUEUE_SIZE = 6000; static constexpr int FLUSHING_BUFFER_MAX_SIZE = 1024 * 1024 * 16; SectorCollection sectors; std::fstream stream; std::string fileName; std::shared_ptr rootStorage; bool closeStream = true; bool _transactionLockAdded = false; int _lockSectorId = -1; bool _transactionLockAllocated = false; bool validationExceptionEnabled = true; bool _disposed;//false CFSUpdateMode updateMode; SVector directoryEntries; std::list levelSIDs; std::mutex lockObject; }; }