From 33f548341a1c2791c4699b0ea93c0b13077998c3 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 20 Aug 2012 01:18:32 +0200 Subject: [PATCH] Added: #1440 Extended parser for DllDirectory --HG-- branch : build_pipeline_v3 --- code/nel/tools/pipeline/max/dll_directory.cpp | 119 ++++++++++++++++-- code/nel/tools/pipeline/max/dll_directory.h | 16 +++ .../nel/tools/pipeline/max/storage_object.cpp | 48 +++++-- code/nel/tools/pipeline/max/storage_object.h | 23 ++++ code/nel/tools/pipeline/max_dump/main.cpp | 20 +++ 5 files changed, 212 insertions(+), 14 deletions(-) diff --git a/code/nel/tools/pipeline/max/dll_directory.cpp b/code/nel/tools/pipeline/max/dll_directory.cpp index 4c403460f..ea962dcd0 100644 --- a/code/nel/tools/pipeline/max/dll_directory.cpp +++ b/code/nel/tools/pipeline/max/dll_directory.cpp @@ -48,7 +48,7 @@ CDllDirectory::CDllDirectory() CDllDirectory::~CDllDirectory() { - + // TODO: Delete m_ChunkCache and m_Entries when !ChunksOwnsPointers } std::string CDllDirectory::getClassName() @@ -58,17 +58,102 @@ std::string CDllDirectory::getClassName() void CDllDirectory::toString(std::ostream &ostream, const std::string &pad) { - CStorageContainer::toString(ostream, pad); + if (ChunksOwnsPointers) + { + CStorageContainer::toString(ostream, pad); + } + else + { + ostream << "(" << getClassName() << ") [" << Chunks.size() << "] PARSED { "; + std::string padpad = pad + "\t"; + sint i = 0; + for (TStorageObjectContainer::const_iterator it = m_ChunkCache.begin(), end = m_ChunkCache.end(); it != end; ++it) + { + uint16 id = it->first; + switch (id) + { + case 0x2038: + { + uint subi = 0; + for (std::vector::iterator subit = m_Entries.begin(), subend = m_Entries.end(); subit != subend; ++subit) + { + ostream << "\n" << pad << "Entries[" << subi << "]: "; + (*subit)->toString(ostream, padpad); + ++subi; + } + } + break; + default: + std::stringstream ss; + ss << std::hex << std::setfill('0'); + ss << std::setw(4) << it->first; + ostream << "\n" << pad << "0x" << ss.str() << ": "; + it->second->toString(ostream, padpad); + ++i; + break; + } + } + ostream << "} "; + } } void CDllDirectory::parse(uint16 version, TParseLevel level) { - CStorageContainer::parse(version, level); + if (level & PARSE_INTERNAL) + { + // Ensure not yet parsed + nlassert(m_ChunkCache.empty()); + nlassert(m_Entries.empty()); + + // Parse entries first + CStorageContainer::parse(version, level); + + // Initialize + m_ParseVersion = version; + uint16 lastCached = 0xFFFF; + bool parsedDllEntry = false; + + // Parse chunks + for (TStorageObjectContainer::iterator it = Chunks.begin(), end = Chunks.end(); it != end; ++it) + { + uint16 id = it->first; + switch (id) + { + case 0x2038: // DllEntry + if (parsedDllEntry && (lastCached != id)) + throw EStorageParse(); // There were chunks inbetween + if (!parsedDllEntry) + { + m_ChunkCache.push_back(TStorageObjectWithId(id, NULL)); // Dummy entry to know the location + lastCached = id; + parsedDllEntry = true; + } + m_Entries.push_back(static_cast(it->second)); + break; + default: + m_ChunkCache.push_back(*it); // Dummy entry to know the location + lastCached = id; + break; + } + } + + // Now ownership of the pointers lies in m_ChunkCache and m_Entries + ChunksOwnsPointers = false; + } } void CDllDirectory::build(uint16 version) { + // TODO: Set up the Chunks list, when (CDllEntry::ID, NULL) is found write out all of the entries. + // Build the entries last CStorageContainer::build(version); + + // NOTE: Ownership remains with m_ChunkCache and m_Entries +} + +const CDllEntry *CDllDirectory::get(std::vector::size_type idx) const +{ + return m_Entries[idx]; } IStorageObject *CDllDirectory::createChunkById(uint16 id, bool container) @@ -92,7 +177,7 @@ IStorageObject *CDllDirectory::createChunkById(uint16 id, bool container) return CStorageContainer::createChunkById(id, container); } -CDllEntry::CDllEntry() +CDllEntry::CDllEntry() : m_DllDescription(NULL), m_DllFilename(NULL) { } @@ -109,17 +194,37 @@ std::string CDllEntry::getClassName() void CDllEntry::toString(std::ostream &ostream, const std::string &pad) { - CStorageContainer::toString(ostream, pad); + if (m_DllDescription && m_DllFilename) + { + ostream << "(" << getClassName() << ") [" << Chunks.size() << "] PARSED { "; + std::string padpad = pad + "\t"; + ostream << "\n" << pad << "DllDescription: " << m_DllDescription->Value.toUtf8(); + ostream << "\n" << pad << "DllFilename: " << m_DllFilename->Value.toUtf8(); + ostream << "} "; + } + else + { + CStorageContainer::toString(ostream, pad); + } } void CDllEntry::parse(uint16 version, TParseLevel level) { - CStorageContainer::parse(version, level); + // CStorageContainer::parse(version, level); + nlassert(Chunks.size() == 2); + TStorageObjectContainer::iterator it = Chunks.begin(); + nlassert(it->first == 0x2039); // DllDescription + m_DllDescription = static_cast *>(it->second); + ++it; + nlassert(it->first == 0x2037); // DllFilename + m_DllFilename = static_cast *>(it->second); + // ++it; } void CDllEntry::build(uint16 version) { - CStorageContainer::build(version); + // Nothing to do here! + // CStorageContainer::build(version); } IStorageObject *CDllEntry::createChunkById(uint16 id, bool container) diff --git a/code/nel/tools/pipeline/max/dll_directory.h b/code/nel/tools/pipeline/max/dll_directory.h index e8ffc4500..3cce7619c 100644 --- a/code/nel/tools/pipeline/max/dll_directory.h +++ b/code/nel/tools/pipeline/max/dll_directory.h @@ -32,6 +32,7 @@ // STL includes // NeL includes +#include // Project includes #include "storage_object.h" @@ -40,6 +41,8 @@ namespace PIPELINE { namespace MAX { +class CDllEntry; + /** * \brief CDllDirectory * \date 2012-08-18 09:01GMT @@ -58,9 +61,17 @@ public: virtual void parse(uint16 version, TParseLevel level); virtual void build(uint16 version); + // public + const CDllEntry *get(std::vector::size_type idx) const; + protected: virtual IStorageObject *createChunkById(uint16 id, bool container); +private: + uint16 m_ParseVersion; + TStorageObjectContainer m_ChunkCache; + std::vector m_Entries; + }; /* class CDllDirectory */ /** @@ -81,8 +92,13 @@ public: virtual void parse(uint16 version, TParseLevel level); virtual void build(uint16 version); + const ucstring &dllDescription() { return m_DllDescription->Value; } + const ucstring &dllFilename() { return m_DllFilename->Value; } + protected: virtual IStorageObject *createChunkById(uint16 id, bool container); + CStorageValue *m_DllDescription; + CStorageValue *m_DllFilename; }; /* class CDllDirectory */ diff --git a/code/nel/tools/pipeline/max/storage_object.cpp b/code/nel/tools/pipeline/max/storage_object.cpp index c623d47dd..a133b7262 100644 --- a/code/nel/tools/pipeline/max/storage_object.cpp +++ b/code/nel/tools/pipeline/max/storage_object.cpp @@ -50,6 +50,16 @@ namespace MAX { //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// +IStorageObject::IStorageObject() +{ + +} + +IStorageObject::~IStorageObject() +{ + +} + std::string IStorageObject::toString() { std::stringstream ss; @@ -76,6 +86,19 @@ bool IStorageObject::isContainer() const //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// +CStorageContainer::CStorageContainer() : ChunksOwnsPointers(true) +{ + +} + +CStorageContainer::~CStorageContainer() +{ + if (ChunksOwnsPointers) + { + + } +} + std::string CStorageContainer::getClassName() // why is this not const in IClassable? { return "StorageContainer"; @@ -83,6 +106,11 @@ std::string CStorageContainer::getClassName() // why is this not const in IClass void CStorageContainer::serial(NLMISC::IStream &stream) { + if (stream.isReading()) + { + nlassert(ChunksOwnsPointers); + nlassert(Chunks.empty()); + } if (stream.getPos() == 0) { CStorageStream *storageStream = dynamic_cast(&stream); @@ -125,6 +153,7 @@ void CStorageContainer::toString(std::ostream &ostream, const std::string &pad) // Blahblah: (Container) { // Moo: (Foo) "What" } // only increase pad when multi-lining sub-items + nlassert(ChunksOwnsPointers); ostream << "(" << getClassName() << ") [" << Chunks.size() << "] { "; std::string padpad = pad + "\t"; sint i = 0; @@ -171,13 +200,8 @@ void CStorageContainer::serial(CStorageChunks &chunks) { if (chunks.stream().isReading()) { -#ifdef NL_DEBUG_STORAGE - if (Chunks.size()) - { - nldebug("Storage container not empty, clearing"); - } -#endif - Chunks.clear(); + nlassert(ChunksOwnsPointers); + nlassert(Chunks.empty()); while (chunks.enterChunk()) { uint16 id = chunks.getChunkId(); @@ -221,6 +245,16 @@ IStorageObject *CStorageContainer::createChunkById(uint16 id, bool container) //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// +CStorageRaw::CStorageRaw() +{ + +} + +CStorageRaw::~CStorageRaw() +{ + +} + std::string CStorageRaw::getClassName() { return "StorageRaw"; diff --git a/code/nel/tools/pipeline/max/storage_object.h b/code/nel/tools/pipeline/max/storage_object.h index 44adad187..5e9d25b08 100644 --- a/code/nel/tools/pipeline/max/storage_object.h +++ b/code/nel/tools/pipeline/max/storage_object.h @@ -44,9 +44,17 @@ namespace MAX { struct EStorage : public NLMISC::Exception { EStorage() : NLMISC::Exception("PIPELINE::MAX::EStorage") { } + EStorage(const char *msg) : NLMISC::Exception(msg) { } virtual ~EStorage() throw() { } }; +struct EStorageParse : public EStorage +{ + EStorageParse() : EStorage("PIPELINE::MAX::EStorageParse") { } + EStorageParse(const char *msg) : EStorage(msg) { } + virtual ~EStorageParse() throw() { } +}; + enum TParseLevel { PARSE_INTERNAL = 0x00000001, // Directly parse basic class formats @@ -70,6 +78,9 @@ const uint16 Version2010 = 0x2012; class IStorageObject : public NLMISC::IStreamable { public: + IStorageObject(); + virtual ~IStorageObject(); + // virtual std::string getClassName() = 0; // inherited from NLMISC::IClassable through NLMISC::IStreamable // virtual void serial(NLMISC::IStream &stream); // inherited from NLMISC::IStreamable std::string toString(); @@ -93,6 +104,14 @@ public: typedef std::list TStorageObjectContainer; TStorageObjectContainer Chunks; +protected: + // protected data + bool ChunksOwnsPointers; + +public: + CStorageContainer(); + virtual ~CStorageContainer(); + // inherited virtual std::string getClassName(); virtual void serial(NLMISC::IStream &stream); // only used to wrap a container inside another stream @@ -123,6 +142,10 @@ public: typedef std::vector TType; TType Value; +public: + CStorageRaw(); + virtual ~CStorageRaw(); + // inherited virtual std::string getClassName(); virtual void serial(NLMISC::IStream &stream); diff --git a/code/nel/tools/pipeline/max_dump/main.cpp b/code/nel/tools/pipeline/max_dump/main.cpp index 0250bd330..1edac2b17 100644 --- a/code/nel/tools/pipeline/max_dump/main.cpp +++ b/code/nel/tools/pipeline/max_dump/main.cpp @@ -74,6 +74,23 @@ int main(int argc, char **argv) g_free(display_name); g_print("%s\n", streamname); + GsfInput *input = NULL; + + PIPELINE::MAX::CDllDirectory dllDirectory; + input = gsf_infile_child_by_name(infile, "DllDirectory"); + { + PIPELINE::MAX::CStorageStream instream(input); + dllDirectory.serial(instream); + } + g_object_unref(input); + dllDirectory.toString(std::cout); + std::cout << "\n"; + dllDirectory.parse(PIPELINE::MAX::VersionUnknown, PIPELINE::MAX::PARSE_INTERNAL); + dllDirectory.toString(std::cout); + std::cout << "\n"; + + +/* GsfInput *input = gsf_infile_child_by_name(infile, streamname); { @@ -88,6 +105,9 @@ int main(int argc, char **argv) } g_object_unref(input); + */ + + g_object_unref(infile); return 0;