General refactoring

This commit is contained in:
Ivan Morozov
2022-09-23 21:59:32 +03:00
parent a0970d0963
commit 029908f8a1
17 changed files with 98 additions and 115 deletions

View File

@ -1,6 +1,5 @@
#pragma once
//#include "../../DocxFormat/Source/Base/Nullable.h"
#include <memory>
namespace RedBlackTree

View File

@ -91,8 +91,6 @@ void RBTree::Insert(PIRBNode newNode)
// NodeInserted(insertedNode);
// }
//Trace.WriteLine(" ");
//Print();
}
void RBTree::Delete(PIRBNode templ, PIRBNode &deletedAlt)
@ -169,9 +167,8 @@ PIRBNode RBTree::LookupNode(PIRBNode templ)
{
n = n->getLeft();
}
else
else // compResult > 0;
{
//assert compResult > 0;
n = n->getRight();
}
}
@ -283,7 +280,7 @@ void RBTree::InsertCase5(PIRBNode n)
}
else
{
//assert n == n->getParent().right && n->getParent() == n->grandparent().right;
// assert n == n->getParent()->getRight() && n->getParent() == n->Grandparent()->getRight();
RotateLeft(n->Grandparent());
}
}
@ -369,13 +366,13 @@ void RBTree::DeleteCase6(PIRBNode n)
n->getParent()->setColor(Color::BLACK);
if (n == n->getParent()->getLeft())
{
//assert nodeColor(n->sibling().right) == Color::RED;
//assert nodeColor(n->Sibling()->getRight()) == Color::RED;
n->Sibling()->getRight()->setColor(Color::BLACK);
RotateLeft(n->getParent());
}
else
{
//assert nodeColor(n->sibling().left) == Color::RED;
//assert nodeColor(n->Sibling()->getLeft()) == Color::RED;
n->Sibling()->getLeft()->setColor(Color::BLACK);
RotateRight(n->getParent());
}

View File

@ -70,7 +70,13 @@ DataTime CFItem::getDataTime() const
void CFItem::setDataTime(const DataTime &value)
{
if (!dirEntry.use_count())
return;
if (dirEntry.lock()->getStgType() != StgStream && dirEntry.lock()->getStgType() != StgRoot)
dirEntry.lock()->setModifyDate(value.getUINT64());
else
throw CFException(L"Modify Date can only be set on storage entries");
}
GUID CFItem::getStorageCLSID() const

View File

@ -9,14 +9,15 @@ namespace CFCPP
class CompoundFile;
class IDirectoryEntry;
struct DataTime
{
DataTime(unsigned long long time);
unsigned long long getUINT64()const;
char data[8] = {0,0,0,0,0,0,0,0};
};
class CFItem : public std::enable_shared_from_this<CFItem>
{
public:
@ -43,6 +44,7 @@ public:
std::shared_ptr<IDirectoryEntry> getDirEntry() const;
friend class CompoundFile;
protected:
std::weak_ptr<IDirectoryEntry> dirEntry;
CompoundFile* compoundFile;

View File

@ -177,8 +177,6 @@ std::shared_ptr<CFStorage> CFStorage::AddStorage(const std::wstring &storageName
std::shared_ptr<IDirectoryEntry> cfo
= DirectoryEntry::New(storageName, StgType::StgStorage, compoundFile->GetDirectories());
//this.CompoundFile.InsertNewDirectoryEntry(cfo);
try
{
// Add object to Siblings tree

View File

@ -17,14 +17,18 @@ public:
std::shared_ptr<CFStream> AddStream(const std::wstring& streamName);
std::shared_ptr<CFStream> GetStream(const std::wstring& streamName);
bool TryGetStream(const std::wstring& streamName, std::shared_ptr<CFStream> &cfStream);
std::shared_ptr<CFStorage> AddStorage(const std::wstring& storageName);
std::shared_ptr<CFStorage> GetStorage(const std::wstring& storageName);
bool TryGetStream(const std::wstring& streamName, std::shared_ptr<CFStream> &cfStream);
std::shared_ptr<CFStorage> TryGetStorage(const std::wstring& storageName);
bool TryGetStorage(const std::wstring& storageName, std::shared_ptr<CFStorage> &cfStorage);
std::shared_ptr<CFStorage> AddStorage(const std::wstring& storageName);
void VisitEntries(RedBlackTree::Action<std::shared_ptr<CFItem>> action, bool recursive);
void Delete(const std::wstring& entryName);
void RenameItem(const std::wstring& oldItemName, const std::wstring& newItemName);
std::streamsize size() const {return CFItem::size();}
private:

View File

@ -71,7 +71,7 @@ void CFStream::CopyFrom(const Stream &input)
std::vector<BYTE> buffer(Length(input));
// if (input.CanSeek)
// if (CanSeek? )
{
input->seek(0, std::ios::beg);
}

View File

@ -11,15 +11,19 @@ class CFStream : public CFItem
public:
CFStream(CompoundFile* compFile, std::weak_ptr<IDirectoryEntry> dirEntry);
void SetData(const std::vector<BYTE>& data);
void Append(const std::vector<BYTE>& data);
void Write(const std::vector<BYTE>& data, std::streamsize position);
void Write(const std::vector<BYTE>& data, std::streamsize position, int offset, int count);
void Append(const std::vector<BYTE>& data);
std::vector<BYTE> getData() const;
int Read(std::vector<BYTE>& buffer, std::streamsize position, int count);
int Read(std::vector<BYTE>& buffer, std::streamsize position, int offset, int count);
void SetData(const std::vector<BYTE>& data); // set hard
std::vector<BYTE> getData() const;
void CopyFrom(const Stream& input);
void Resize(std::streamsize length);
std::streamsize size() const {return CFItem::size();}
};
}

View File

@ -47,10 +47,9 @@ CompoundFile::CompoundFile(CFSVersion cfsVersion, CFSConfiguration configFlags)
DIFAT_SECTOR_FAT_ENTRIES_COUNT = (GetSectorSize() / 4) - 1;
FAT_SECTOR_ENTRIES_COUNT = (GetSectorSize() / 4);
//Root --
// Root
std::shared_ptr<IDirectoryEntry> rootDir = DirectoryEntry::New(L"Root Entry", StgType::StgRoot, directoryEntries);
rootDir->setStgColor(StgColor::Black);
//InsertNewDirectoryEntry(rootDir);
rootStorage.reset(new CFStorage(this, rootDir));
}
@ -113,9 +112,9 @@ void CompoundFile::Commit(bool releaseMemory)
for (int i = 0; i < (int)sectors.largeArraySlices.size(); i++)
{
//Note:
//Here sectors should not be loaded dynamically because
//if they are null it means that no change has involved them;
// Note:
// Here sectors should not be loaded dynamically because
// if they are null it means that no change has involved them;
std::shared_ptr<Sector> s = sectors[i];
@ -149,17 +148,17 @@ void CompoundFile::Commit(bool releaseMemory)
sourceStream->seek(0, std::ios::beg);
header->Write(sourceStream);
// sourceStream-> SetLength((long)(sectors.Count + 1) * sSize);
sourceStream->flush();
}
// if (releaseMemory)
// GC.Collect();
bool CompoundFile::HasSourceStream() const
{
return sourceStream != nullptr;
}
//}
//catch (Exception ex)
//{
// throw CFException("Internal error while committing data", ex);
//}
bool CompoundFile::ValidationExceptionEnabled() const
{
return validationExceptionEnabled;
}
void CompoundFile::Close()
@ -186,10 +185,6 @@ bool CompoundFile::IsClosed() const
return _disposed;
}
/// <summary>
/// Load compound file from an existing stream.
/// </summary>
/// <param name="stream">Stream to load compound file from</param>
void CompoundFile::Load(Stream stream)
{
try
@ -208,7 +203,7 @@ void CompoundFile::Load(Stream stream)
sectors.Clear();
//sectors = new ArrayList();
for (int i = 0; i < n_sector; i++)
{
sectors.Add({});
@ -261,8 +256,7 @@ void CompoundFile::Save(Stream stream)
if (_disposed)
throw CFDisposedException("Compound File closed: cannot save data");
// if (!stream.CanSeek)
// throw CFException("Cannot save on a non-seekable stream");
// Check seekable
CheckForLockSector();
int sSize = GetSectorSize();
@ -376,16 +370,12 @@ SVector<Sector> CompoundFile::GetFatSectorChain()
s.reset(new Sector(GetSectorSize(), sourceStream));
s->type = SectorType::FAT;
s->id = nextSecID;
sectors[nextSecID] = s;//UUU
sectors[nextSecID] = s;
}
result.push_back(s);
//difatStream.Read(nextDIFATSectorBuffer, 4);
//nextSecID = BitConverter.ToInt32(nextDIFATSectorBuffer, 0);
if (difatStream->position == ((GetSectorSize() - 4) + i * GetSectorSize()))
if (difatStream->getPosition() == ((GetSectorSize() - 4) + i * GetSectorSize()))
{
// Skip DIFAT chain fields considering the possibility that the last FAT entry has been already read
difatStream->read(nextDIFATSectorBuffer, 4);
@ -665,7 +655,7 @@ SVector<IDirectoryEntry> CompoundFile::FindDirectoryEntries(std::wstring entryNa
{
SVector<IDirectoryEntry> result;
for (auto d : *directoryEntries)
for (auto& d : *directoryEntries)
{
if (d->GetEntryName() == entryName && d->getStgType() != StgType::StgInvalid)
result.push_back(d);
@ -673,6 +663,7 @@ SVector<IDirectoryEntry> CompoundFile::FindDirectoryEntries(std::wstring entryNa
return result;
}
std::shared_ptr<RedBlackTree::RBTree> CompoundFile::DoLoadChildrenTrusted(std::shared_ptr<IDirectoryEntry> de)
{
std::shared_ptr<RedBlackTree::RBTree> bst;
@ -712,7 +703,6 @@ void CompoundFile::LoadSiblings(std::shared_ptr<RedBlackTree::RBTree> bst, std::
{
// If there're more left siblings load them...
DoLoadSiblings(bst, directoryEntries[de->getLeftSibling()]);
//NullifyChildNodes(directoryEntries[de.LeftSibling]);
}
if (de->getRightSibling() != DirectoryEntry::NOSTREAM)
@ -721,7 +711,6 @@ void CompoundFile::LoadSiblings(std::shared_ptr<RedBlackTree::RBTree> bst, std::
// If there're more right siblings load them...
DoLoadSiblings(bst, directoryEntries[de->getRightSibling()]);
//NullifyChildNodes(directoryEntries[de.RightSibling]);
}
}
@ -869,10 +858,6 @@ void CompoundFile::FreeMiniChain(SVector<Sector> &sectorChain, int nth_sector_to
miniFATView.write(reinterpret_cast<const char*>(&freesec), 4);
}
// Write End of Chain in MiniFAT ---------------------------------------
//miniFATView.Seek(sectorChain[(sectorChain.Count - 1) - nth_sector_to_remove].Id * SIZE_OF_SID, SeekOrigin.Begin);
//miniFATView.Write(BitConverter.GetBytes(Sector.ENDOFCHAIN), 4);
// Write End of Chain in MiniFAT ---------------------------------------
if (nth_sector_to_remove > 0 && sectorChain.size() > 0)
{
@ -992,7 +977,7 @@ void CompoundFile::AllocateDIFATSectorChain(SVector<Sector> &FATsectorChain)
header->fatSectorsNumber = FATsectorChain.size();
// Allocate Sectors
for (auto s : *FATsectorChain)
for (auto& s : *FATsectorChain)
{
if (s->id == -1)
{
@ -1054,7 +1039,7 @@ void CompoundFile::AllocateDIFATSectorChain(SVector<Sector> &FATsectorChain)
{
if (i < HEADER_DIFAT_ENTRIES_COUNT)
{
header->difat[i] = FATsectorChain[i]->id; // int to byte
header->difat[i] = FATsectorChain[i]->id;
}
else
{
@ -1127,9 +1112,6 @@ void CompoundFile::AllocateDIFATSectorChain(SVector<Sector> &FATsectorChain)
fatSv.write(reinterpret_cast<const char*>(&fatsect), 4);
}
//fatSv.Seek(fatSv.BaseSectorChain[fatSv.BaseSectorChain.Count - 1].Id * 4, SeekOrigin.Begin);
//fatSv.Write(BitConverter.GetBytes(Sector.ENDOFCHAIN), 4);
header->fatSectorsNumber = fatSv.BaseSectorChain().size();
}
@ -1172,7 +1154,7 @@ void CompoundFile::AllocateMiniSectorChain(SVector<Sector> &sectorChain)
miniStreamView.seek(rootStorage->size() + Sector::MINISECTOR_SIZE, std::ios::beg);
//miniStreamView.Write(s.GetData(), 0, Sector.MINISECTOR_SIZE);
s->id = (int)(miniStreamView.position - Sector::MINISECTOR_SIZE) / Sector::MINISECTOR_SIZE;
s->id = (int)(miniStreamView.getPosition() - Sector::MINISECTOR_SIZE) / Sector::MINISECTOR_SIZE;
rootStorage->getDirEntry()->setSize(miniStreamView.getLength());
}
@ -1257,7 +1239,7 @@ CFSVersion CompoundFile::getVersion() const
return (CFSVersion)header->majorVersion;
}
SVector<IDirectoryEntry>& CompoundFile::GetDirectories()
SVector<IDirectoryEntry> &CompoundFile::GetDirectories()
{
return directoryEntries;
}
@ -1400,7 +1382,6 @@ void CompoundFile::SetStreamLength(std::shared_ptr<CFItem> cfItem, std::streamsi
}
// No transition caused by size change
}
}
@ -1532,7 +1513,6 @@ void CompoundFile::SetStreamLength(std::shared_ptr<CFItem> cfItem, std::streamsi
destSv.write(buf.data(), (int)toRead);
//Free old mini chain
int oldChainCount = oldChain.size();
FreeMiniChain(oldChain, eraseFreeSectors);
//Set up normal destination chain
@ -1602,14 +1582,11 @@ SList<Sector> CompoundFile::FindFreeSectors(SectorType sType)
while (idx < nMinisectors)
{
//AssureLength(miniStreamView, (int)miniFATView.Length);
int nextId = miniFATView.ReadInt32();
if (nextId == Sector::FREESECT)
{
std::shared_ptr<Sector> ms(new Sector(Sector::MINISECTOR_SIZE, sourceStream));
// byte[] temp = new byte[Sector.MINISECTOR_SIZE];
ms->id = idx;
ms->type = SectorType::Mini;
@ -1636,8 +1613,6 @@ std::vector<BYTE> CompoundFile::GetData(const CFStream *cFStream)
auto de = cFStream->dirEntry;
//IDirectoryEntry root = directoryEntries[0];
SList<Sector> zeroQueue;
if (de.lock()->getSize() < header->minSizeStandardStream)
{
@ -1683,7 +1658,6 @@ int CompoundFile::ReadData(CFStream *cFStream, std::streamsize position, std::ve
}
else
{
sView.reset(new StreamView(GetSectorChain(de->getStartSetc(), SectorType::Normal), GetSectorSize(), de->getSize(), zeroQueue, sourceStream));
}
@ -1811,7 +1785,6 @@ void CompoundFile::WriteData(std::shared_ptr<CFItem> cfItem, const std::vector<B
if (cfItem->size() < header->minSizeStandardStream)
{
PersistMiniStreamToStream(sv.BaseSectorChain());
//SetSectorChain(sv.BaseSectorChain);
}
}
@ -1905,9 +1878,7 @@ void CompoundFile::LoadStream(Stream stream)
if (stream.get() == nullptr)
throw CFException("Stream parameter cannot be null");
if (/*!stream.CanSeek*/false)
throw CFException("Cannot load a non-seekable Stream");
// Check seekable
stream->seek(0, std::ios::beg);

View File

@ -15,25 +15,16 @@ class DirectoryEntry;
enum CFSConfiguration
{
Default = 1,
SectorRecycle = 2,
EraseFreeSectors = 4,
NoValidationException = 8,
LeaveOpen = 16
Default = 1, // No other flags
SectorRecycle = 2, // Rewrite unused sectors
EraseFreeSectors = 4, // Free sectors are erased to avoid information leakage
NoValidationException = 8, // Ignore some file reading errors to read broken files
LeaveOpen = 16 // file will not be closed
};
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
};
@ -45,15 +36,28 @@ public:
CompoundFile(const std::wstring &fileName);
CompoundFile(Stream stream);
CompoundFile();
void Commit(bool releaseMemory = false);
inline bool HasSourceStream() {return sourceStream != nullptr;}
// Main methods
std::shared_ptr<CFStorage> RootStorage();
void Save(std::wstring wFileName);
void Save(Stream stream);
void Commit(bool releaseMemory = false);
bool HasSourceStream() const;
bool ValidationExceptionEnabled() const;
bool IsClosed()const;
void Close();
std::vector<BYTE> GetDataBySID(int sid);
GUID getGuidBySID(int sid);
GUID getGuidForStream(int sid);
// internal methods
static std::shared_ptr<RedBlackTree::RBTree> CreateNewTree();
std::shared_ptr<RedBlackTree::RBTree> GetChildrenTree(int sid);
std::shared_ptr<CFStorage> RootStorage();
bool IsClosed()const;
SVector<IDirectoryEntry> &GetDirectories();
void ResetDirectoryEntry(int sid);
void InvalidateDirectoryEntry(int sid);
@ -69,13 +73,6 @@ public:
int ReadData(CFStream* cFStream, std::streamsize position, std::vector<BYTE>& buffer, int count);
int ReadData(CFStream* cFStream, std::streamsize position, std::vector<BYTE>& buffer, int offset, int count);
std::vector<BYTE> 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);
@ -137,6 +134,8 @@ private:
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;
@ -148,10 +147,10 @@ private:
bool _transactionLockAllocated = false;
bool validationExceptionEnabled = true;
bool _disposed = false;
CFSUpdateMode updateMode;
SVector<IDirectoryEntry> directoryEntries;
std::list<int> levelSIDs;
std::mutex lockObject;
};
}

View File

@ -297,7 +297,7 @@ ULONG64 DirectoryEntry::fnv_hash(const char *buffer, int lenght)
std::shared_ptr<IDirectoryEntry> DirectoryEntry::New(std::wstring name, StgType stgType, SVector<IDirectoryEntry>& dirRepository)
{
std::shared_ptr<IDirectoryEntry> de;
if (/*dirRepository != null*/true)
if (dirRepository)
{
de.reset(new DirectoryEntry(name, stgType, dirRepository));
// No invalid directory entry found

View File

@ -102,7 +102,6 @@ private:
SVector<IDirectoryEntry>& dirRepository;
std::weak_ptr<RedBlackTree::IRBNode> parent;
GUID storageCLSID;
};
}

View File

@ -52,7 +52,7 @@ private:
Stream stream;
std::vector<BYTE> data;
std::mutex lockObject;
bool _disposed;//false
bool _disposed = false;
};
}

View File

@ -23,16 +23,6 @@ void SectorCollection::Clear()
std::shared_ptr<Sector>& SectorCollection::operator[](size_t index)
{
// size_t globalPos = 0;
// for (size_t i = 0; i < largeArraySlices.size(); i ++)
// {
// size_t sliceSize = largeArraySlices[i].size();
// globalPos += sliceSize;
// if (globalPos < index)
// return largeArraySlices[i][i % sliceSize];
// }
// return {};
int itemIndex = index / SLICE_SIZE;
int itemOffset = index % SLICE_SIZE;
@ -59,8 +49,7 @@ int SectorCollection::add(std::shared_ptr<Sector> item)
}
else
{
// std::unique_ptr<std::vector<Sector>> ar(new std::vector<Sector>(SLICE_SIZE));
SVector<Sector> ar;
SVector<Sector> ar/*(SLICE_SIZE)*/;
ar.push_back(item);
largeArraySlices.push_back(ar);
count++;

View File

@ -12,6 +12,8 @@ class StreamRW
{
public:
StreamRW(Stream stream);
T_LONG64 Seek(T_LONG64 offset);
T_LONG64 Tell();

View File

@ -7,8 +7,8 @@ using namespace CFCPP;
StreamView::StreamView(const SVector<Sector> &sectorChain, int sectorSize, Stream stream)
: sectorSize(sectorSize), sectorChain(sectorChain), stream(stream)
{
// if (sectorChain == null)
// throw CFException("Sector Chain cannot be null");
if (sectorChain == nullptr)
throw CFException("Sector Chain cannot be null");
if (sectorSize <= 0)
throw CFException("Sector size must be greater than zero");
@ -238,7 +238,17 @@ void StreamView::adjustLength(std::streamsize value, SList<Sector> &availableSec
}
}
std::streamsize StreamView::getPosition() const
{
return position;
}
std::streamsize StreamView::getLength() const
{
return length;
}
SVector<Sector> &StreamView::BaseSectorChain()
{
return sectorChain;
}

View File

@ -15,6 +15,7 @@ public:
StreamView(const SVector<Sector> &sectorChain, int sectorSize, std::streamsize length,
SList<Sector> &availableSectors, Stream stream, bool isFatStream = false);
std::streamsize tell() override;
std::streamsize seek(std::streamsize offset, std::ios_base::seekdir mode = std::ios::beg) override;
std::streamsize read(char *buffer, std::streamsize count) override;
@ -22,9 +23,11 @@ public:
void flush() override {}
void close() override;
std::streamsize getPosition() const;
void SetLength(std::streamsize value);
std::streamsize getLength() const;
inline SVector<Sector>& BaseSectorChain() {return sectorChain;}
SVector<Sector>& BaseSectorChain();
int ReadInt32();
void WriteInt32(int val);
@ -32,6 +35,7 @@ public:
private:
void adjustLength(std::streamsize value);
void adjustLength(std::streamsize value, SList<Sector> &availableSectors);
private:
int sectorSize;
std::streamsize length;
@ -40,9 +44,8 @@ private:
bool isFatStream = false;
int buf = 0;
public:
Stream stream;
SList<Sector> freeSectors;
std::streamsize position = 0;
SList<Sector> freeSectors;
};
}