Added: #1440 Implementation for CSceneClass

--HG--
branch : build_pipeline_v3
hg/feature/build_pipeline_v3
kaetemi 12 years ago
parent 2cf7892854
commit 96ebef489d

@ -151,6 +151,9 @@ void CAppData::parse(uint16 version, TParseLevel level)
{
if (level & PARSE_BUILTIN)
{
// Cannot be parsed yet
if (!m_ChunksOwnsPointers) { nlerror("Already parsed"); return; }
// First parse all the child nodes
CStorageContainer::parse(version, level);
@ -183,8 +186,8 @@ void CAppData::parse(uint16 version, TParseLevel level)
void CAppData::clean()
{
if (m_ChunksOwnsPointers) { nldebug("Not parsed"); return; } // Must have local ownership
if (m_Chunks.size() == 0) { nlwarning("Bad container size"); return; } // Already cleaned
if (m_ChunksOwnsPointers) { nldebug("Not parsed, or disowned"); return; } // Must have local ownership
if (m_Chunks.size() == 0) { nlwarning("Already cleaned (or did not build due to coding error)"); return; } // Already cleaned
if (m_Chunks.begin()->first != NLMAXFILE_APP_DATA_HEADER_CHUNK_ID) { nlerror("Bad id %x, expected %x", (uint32)m_Chunks.begin()->first, NLMAXFILE_APP_DATA_HEADER_CHUNK_ID); return; } // Cannot happen, because we won't have local ownership if parsing failed
delete m_Chunks.begin()->second; // Delete the header chunk, since we own it
m_Chunks.clear(); // Clear the remaining chunks
@ -194,7 +197,7 @@ void CAppData::build(uint16 version)
{
// Must be clean first
if (!m_ChunksOwnsPointers && m_Chunks.size() != 0) { nlerror("Not cleaned"); return; }
if (m_Chunks.size() != 0) { nldebug("Not parsed"); return; }
if (m_Chunks.size() != 0) { nldebug("Not parsed, or disowned"); return; }
// Set up the header in the chunks container
CStorageValue<uint32> *headerSize = new CStorageValue<uint32>(); // Owned locally, not by m_Chunks
@ -211,12 +214,15 @@ void CAppData::disown()
if (m_ChunksOwnsPointers) { nldebug("Not parsed"); }
if (!m_ChunksOwnsPointers && (m_Chunks.size() != (m_Entries.size() + 1))) { nlerror("Not built"); return; } // If chunks is not the owner, built chunks must match the parsed data
// NOTE: m_Chunks must be valid at this point!
// Disown all the child chunks
CStorageContainer::disown();
// Disown locally
m_Entries.clear();
// Give ownership back
m_ChunksOwnsPointers = true;
// Disown all the child chunks
CStorageContainer::disown();
}
void CAppData::init()

@ -29,6 +29,7 @@
#include "scene_class.h"
// STL includes
#include <iomanip>
// NeL includes
// #include <nel/misc/debug.h>
@ -65,29 +66,96 @@ std::string CSceneClass::getClassName()
void CSceneClass::toString(std::ostream &ostream, const std::string &pad)
{
CStorageContainer::toString(ostream, pad);
if (m_ChunksOwnsPointers)
{
CStorageContainer::toString(ostream, pad);
}
else
{
ostream << "(" << getClassName() << ": " << ucstring(getClassDesc()->displayName()).toUtf8() << ", " << getClassDesc()->classId().toString() << ", " << ucstring(getClassDesc()->dllPluginDesc()->internalName()).toUtf8() << ") [" << m_Chunks.size() << "] { ";
toStringLocal(ostream, pad);
ostream << "} ";
}
}
void CSceneClass::parse(uint16 version, TParseLevel level)
{
// Cannot be parsed yet
if (!m_ChunksOwnsPointers) { nlerror("Already parsed"); return; } // Already parsed, illegal to call twice
// Parse all child chunks
CStorageContainer::parse(version, level);
// Orphanize all child chunk
m_OrphanedChunks.insert(m_OrphanedChunks.end(), m_Chunks.begin(), m_Chunks.end());
// Take ownership
m_ChunksOwnsPointers = false;
// Inheriting classes take control from here on, they should check
// m_ChunksOwnsPointers to be false before taking action, in case
// a subclass called disown due to failure.
}
void CSceneClass::clean()
{
CStorageContainer::clean();
if (m_ChunksOwnsPointers) { nldebug("Not parsed, or disowned"); return; } // Must have local ownership, parsing may have failed
if (m_Chunks.size() == 0 && m_OrphanedChunks.size() != 0) { nlwarning("Already cleaned"); return; } // Already cleaned, should not call twice, not reliable because not all chunks have child chunks
// Clear unneeded references from the parent
m_Chunks.clear();
// Clean owned child chunks
for (TStorageObjectContainer::const_iterator it = m_OrphanedChunks.begin(), end = m_OrphanedChunks.end(); it != end; ++it)
{
if (it->second->isContainer())
{
nldebug("Cleaning orphan child");
static_cast<CStorageContainer *>(it->second)->clean();
}
}
}
void CSceneClass::build(uint16 version)
{
// Must be clean first
if (!m_ChunksOwnsPointers && m_Chunks.size() != 0) { nlerror("Not cleaned"); return; } // Cannot call twice, illegal call
if (m_Chunks.size() != 0) { nldebug("Not parsed, or disowned"); return; } // Don't have local ownership, parsing may have failed, the built version is implicitly up to date
// Store orphan chunks
m_Chunks.insert(m_Chunks.end(), m_OrphanedChunks.begin(), m_OrphanedChunks.end());
// Build the orphan chunks (this is a little trick to do it this
// way here, don't do this from subclasses)
CStorageContainer::build(version);
// Set the insertion pointer before the orphans
m_PutChunkInsert = m_Chunks.begin();
// Inheriting classes take control from here on, so the build is
// called to owned subclasses from the putChunk function.
}
void CSceneClass::disown()
{
if (m_ChunksOwnsPointers) { nldebug("Not parsed"); }
if (!m_ChunksOwnsPointers && (m_Chunks.size() < m_OrphanedChunks.size())) { nlerror("Not built"); return; } // If chunks is not the owner, built chunks must match the parsed data. This check is not fully reliable
// Clear local references
m_OrphanedChunks.clear();
// Return ownership
m_ChunksOwnsPointers = true;
// Disown children
CStorageContainer::disown();
}
void CSceneClass::init()
{
// Nothing to do here!
}
IStorageObject *CSceneClass::createChunkById(uint16 id, bool container)
{
// Temporary
@ -113,6 +181,26 @@ const ISceneClassDesc *CSceneClass::getClassDesc()
return static_cast<const ISceneClassDesc *>(&SceneClassDesc);
}
void CSceneClass::toStringLocal(std::ostream &ostream, const std::string &pad) const
{
std::string padpad = pad + "\t";
sint i = 0;
for (TStorageObjectContainer::const_iterator it = m_OrphanedChunks.begin(), end = m_OrphanedChunks.end(); it != end; ++it)
{
std::stringstream ss;
ss << std::hex << std::setfill('0');
ss << std::setw(4) << it->first;
ostream << "\n" << pad << i << " 0x" << ss.str() << ": ";
it->second->toString(ostream, padpad);
++i;
}
}
IStorageObject *CSceneClass::getChunk(uint16 id)
{
return NULL;
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

@ -90,7 +90,7 @@ public:
/// Return the class description of the inheriting class
virtual const ISceneClassDesc *getClassDesc();
/// Create a readable representation of this class
virtual void toStringLocal(std::ostream &ostream, const std::string &pad = "");
virtual void toStringLocal(std::ostream &ostream, const std::string &pad = "") const;
//@}
public:
@ -105,7 +105,7 @@ protected:
/// Use during parsing. Gets the chunk with specified id. Warnings when chunks are skipped may be elevated to errors. Remaining orphaned chunks will be appended after chunks that are written by the classes. Returns NULL when the chunk does not exist. Empty chunks are often not written by classes. You have ownership over the chunk until it is disowned. In case that the chunk cannot be parsed, call disown and abort parsing. If this function returns NULL it is also possible that the parsing has been aborted when m_ChunksOwnsPointers is true
IStorageObject *getChunk(uint16 id);
/// Use during file build. Adds a chunk to the chunks that will be written to the file. Build is called when a chunk is passed through
void putChunk(uint16 id, IStorageObject *storageObject)
void putChunk(uint16 id, IStorageObject *storageObject);
//@}
protected:

@ -29,7 +29,6 @@
#include "scene_class_unknown.h"
// STL includes
#include <iomanip>
// NeL includes
// #include <nel/misc/debug.h>
@ -121,7 +120,7 @@ CSceneClassUnknown::~CSceneClassUnknown()
void CSceneClassUnknown::toString(std::ostream &ostream, const std::string &pad)
{
nlassert(m_ChunksOwnsPointers);
/*nlassert(m_ChunksOwnsPointers);
ostream << "(" << getClassName() << ": " << ucstring(getClassDesc()->displayName()).toUtf8() << ", " << getClassDesc()->classId().toString() << ", " << ucstring(getClassDesc()->dllPluginDesc()->internalName()).toUtf8() << ") [" << m_Chunks.size() << "] { ";
std::string padpad = pad + "\t";
sint i = 0;
@ -134,7 +133,8 @@ void CSceneClassUnknown::toString(std::ostream &ostream, const std::string &pad)
it->second->toString(ostream, padpad);
++i;
}
ostream << "} ";
ostream << "} ";*/
CSceneClass::toString(ostream, pad);
}
void CSceneClassUnknown::parse(uint16 version, TParseLevel level)

@ -196,6 +196,7 @@ void CStorageContainer::toString(std::ostream &ostream, const std::string &pad)
void CStorageContainer::parse(uint16 version, TParseLevel level)
{
nlassert(m_ChunksOwnsPointers); // Can only use this when m_Chunks still has ownership.
for (TStorageObjectContainer::const_iterator it = m_Chunks.begin(), end = m_Chunks.end(); it != end; ++it)
{
if (it->second->isContainer())
@ -230,6 +231,7 @@ void CStorageContainer::build(uint16 version)
void CStorageContainer::disown()
{
nlassert(m_ChunksOwnsPointers); // Can only use this when m_Chunks has been given ownership.
for (TStorageObjectContainer::const_iterator it = m_Chunks.begin(), end = m_Chunks.end(); it != end; ++it)
{
if (it->second->isContainer())

Loading…
Cancel
Save