diff --git a/code/nel/tools/pipeline/max/storage_chunks.cpp b/code/nel/tools/pipeline/max/storage_chunks.cpp
new file mode 100644
index 000000000..5edf1fdaa
--- /dev/null
+++ b/code/nel/tools/pipeline/max/storage_chunks.cpp
@@ -0,0 +1,189 @@
+/**
+ * \file storage_chunks.cpp
+ * \brief CStorageChunks
+ * \date 2012-08-18 09:20GMT
+ * \author Jan Boon (Kaetemi)
+ * CStorageChunks
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE PIPELINE.
+ * RYZOM CORE PIPELINE is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * RYZOM CORE PIPELINE is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with RYZOM CORE PIPELINE. If not, see
+ * .
+ */
+
+#include
+#include "storage_chunks.h"
+
+// STL includes
+
+// NeL includes
+#include
+
+// Project includes
+
+// using namespace std;
+// using namespace NLMISC;
+
+// #define NL_DEBUG_STORAGE
+
+namespace PIPELINE {
+namespace MAX {
+
+CStorageChunks::CStorageChunks(NLMISC::IStream &stream, sint64 size) : m_Stream(stream), m_Is64Bit(false)
+{
+ if (size >= 2147483647L)
+ throw NLMISC::EStream("64bit chunks not supported");
+ m_Chunks.reserve(64);
+ m_Chunks.resize(1);
+ m_Chunks[0].HeaderSize = 0;
+ m_Chunks[0].OffsetBegin = stream.getPos();
+ if (stream.isReading())
+ {
+ m_Chunks[0].Id = 0;
+ m_Chunks[0].Size = 0x80000000 | (uint32)(size);
+ }
+ else
+ {
+ m_Chunks[0].Id = 1;
+ m_Chunks[0].Size = 0;
+ }
+}
+
+CStorageChunks::~CStorageChunks()
+{
+#ifdef NL_DEBUG_STORAGE
+ if (m_Chunks.size() != 1)
+ nldebug("Not all chunks were closed");
+#endif
+}
+
+bool CStorageChunks::enterChunk()
+{
+ if (m_Stream.isReading())
+ {
+ // input logic
+ if (!isChunkContainer())
+ {
+#ifdef NL_DEBUG_STORAGE
+ nldebug("Current chunk is not a container, cannot enter");
+#endif
+ return false;
+ }
+ if (endOfChunk())
+ {
+#ifdef NL_DEBUG_STORAGE
+ nldebug("End of chunk, cannot enter");
+#endif
+ return false;
+ }
+ m_Chunks.resize(m_Chunks.size() + 1);
+ CChunk *chunk = currentChunk();
+ chunk->OffsetBegin = m_Stream.getPos();
+ m_Stream.serial(chunk->Id);
+ m_Stream.serial(chunk->Size);
+ chunk->HeaderSize = 6;
+ if (chunk->Size == 0)
+ {
+ // this is a 64bit chunk
+ uint64 size64;
+ m_Stream.serial(size64);
+ chunk->HeaderSize += 8;
+ bool iscont = (size64 & 0x8000000000000000) == 0x8000000000000000;
+ size64 &= 0x7FFFFFFFFFFFFFFF;
+ if (size64 >= 2147483647L)
+ throw NLMISC::EStream("64bit chunks not supported");
+ // downgrade to 32 bit chunk
+ chunk->Size = (uint32)size64;
+ if (iscont) chunk->Size |= 0x80000000;
+ m_Is64Bit = true; // it's true
+ }
+ return true;
+ }
+ else
+ {
+#ifdef NL_DEBUG_STORAGE
+ nldebug("No input, this function cannot output, throw exception");
+#endif
+ throw NLMISC::EStream();
+ }
+}
+
+bool CStorageChunks::enterChunk(uint16 id, bool container)
+{
+ if (!m_Stream.isReading())
+ {
+ if (m_Is64Bit)
+ throw NLMISC::EStream("64bit chunks not supported");
+
+ // enter the new chunk
+ m_Chunks.resize(m_Chunks.size() + 1);
+ CChunk *chunk = currentChunk();
+ uint32 sizeDummy = 0xFFFFFFFF;
+ chunk->Id = container ? 1 : 0;
+ chunk->OffsetBegin = m_Stream.getPos(); // store current pos
+
+ // write header
+ m_Stream.serial(id); // write the id
+ m_Stream.serial(sizeDummy); // write 32 bit size placeholder
+ return true;
+ }
+ else // input or exception
+ {
+ while (enterChunk())
+ {
+ if (getChunkId() == id)
+ return true;
+ leaveChunk(); // skip data
+ }
+ return false;
+ }
+}
+
+sint32 CStorageChunks::leaveChunk()
+{
+ if (m_Stream.isReading())
+ {
+ // input logic
+ sint32 skipped = currentChunk()->endOfChunk() - m_Stream.getPos();
+ if (skipped)
+ {
+ m_Stream.seek(currentChunk()->endOfChunk(), NLMISC::IStream::begin);
+#ifdef NL_DEBUG_STORAGE
+ nldebug("Skipped %i bytes in the current chunk", skipped);
+#endif
+ }
+ m_Chunks.resize(m_Chunks.size() - 1);
+ return skipped;
+ }
+ else
+ {
+ sint32 pos = m_Stream.getPos();
+ sint32 sizeWithHeader = pos - currentChunk()->OffsetBegin;
+ sint32 sizePos = currentChunk()->OffsetBegin + 2;
+ m_Stream.seek(sizePos, NLMISC::IStream::begin); // hopefully this correctly overwrites!!!
+ uint32 sizeField = (uint32)sizeWithHeader | (uint32)currentChunk()->Id << 31; // add container flag
+ m_Stream.serial(sizeField);
+ m_Stream.seek(pos, NLMISC::IStream::begin);
+ m_Chunks.resize(m_Chunks.size() - 1);
+ return sizeWithHeader;
+ }
+}
+
+} /* namespace MAX */
+} /* namespace PIPELINE */
+
+/* end of file */
diff --git a/code/nel/tools/pipeline/max/storage_chunks.h b/code/nel/tools/pipeline/max/storage_chunks.h
new file mode 100644
index 000000000..45d72fb87
--- /dev/null
+++ b/code/nel/tools/pipeline/max/storage_chunks.h
@@ -0,0 +1,107 @@
+/**
+ * \file storage_chunks.h
+ * \brief CStorageChunks
+ * \date 2012-08-18 09:20GMT
+ * \author Jan Boon (Kaetemi)
+ * CStorageChunks
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE PIPELINE.
+ * RYZOM CORE PIPELINE is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * RYZOM CORE PIPELINE is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with RYZOM CORE PIPELINE. If not, see
+ * .
+ */
+
+#ifndef PIPELINE_STORAGE_CHUNKS_H
+#define PIPELINE_STORAGE_CHUNKS_H
+#include
+
+// STL includes
+
+// NeL includes
+#include
+
+// Project includes
+
+namespace PIPELINE {
+namespace MAX {
+
+/**
+ * \brief CStorageChunks
+ * \date 2012-08-18 09:20GMT
+ * \author Jan Boon (Kaetemi)
+ * CStorageChunks
+ */
+class CStorageChunks
+{
+private:
+ struct CChunk
+ {
+ // Size of the chunk header, 6 for 32 bit, 14 for 64 bit
+ uint8 HeaderSize;
+ // Where the header starts
+ sint32 OffsetBegin;
+
+ // Identifier
+ uint16 Id;
+ // Size including header size
+ uint32 Size;
+
+ inline sint32 getSizeWithHeader() const { return (sint32)(Size & 0x7FFFFFFF); }
+ inline sint32 getSize() const { return getSizeWithHeader() - (sint32)HeaderSize; }
+ inline bool isContainer() const { return (Size & 0x80000000) == 0x80000000; }
+ inline sint32 endOfChunk() const { return OffsetBegin + getSizeWithHeader(); }
+ inline sint32 getDataBegin() const { return OffsetBegin + (sint32)HeaderSize; }
+ };
+
+public:
+ CStorageChunks(NLMISC::IStream &stream, sint64 size = 0);
+ virtual ~CStorageChunks();
+
+ // Returns true if there's another chunk, false if no more chunks in this container or if the current chunk is not a container
+ bool enterChunk();
+ // Reads and skips chunks until the one with given id is found, or writes a chunk with this id
+ bool enterChunk(uint16 id, bool container);
+ // Returns the number of skipped bytes in read more, returns chunk size including header in write mode
+ sint32 leaveChunk();
+
+ inline bool is64Bit() const { return m_Is64Bit; }
+ inline void set64Bit(bool enabled = true) { m_Is64Bit = enabled; }
+
+ inline uint16 getChunkId() const { return currentChunk()->Id; }
+ inline sint32 getChunkSize() const { return currentChunk()->getSize(); }
+ inline bool isChunkContainer() const { return currentChunk()->isContainer(); }
+ inline bool endOfChunk() const { return /*m_Chunks.size() == 1 ? eof() :*/ m_Stream.getPos() >= currentChunk()->endOfChunk(); }
+
+ inline NLMISC::IStream &stream() { return m_Stream; }
+
+private:
+ inline const CChunk *currentChunk() const { return &m_Chunks[m_Chunks.size() - 1]; }
+ inline CChunk *currentChunk() { return &m_Chunks[m_Chunks.size() - 1]; }
+
+private:
+ NLMISC::IStream &m_Stream;
+ std::vector m_Chunks;
+ bool m_Is64Bit;
+
+}; /* class CStorageChunks */
+
+} /* namespace MAX */
+} /* namespace PIPELINE */
+
+#endif /* #ifndef PIPELINE_STORAGE_CHUNKS_H */
+
+/* end of file */
diff --git a/code/nel/tools/pipeline/max/storage_object.cpp b/code/nel/tools/pipeline/max/storage_object.cpp
new file mode 100644
index 000000000..2de47052b
--- /dev/null
+++ b/code/nel/tools/pipeline/max/storage_object.cpp
@@ -0,0 +1,236 @@
+/**
+ * \file storage_object.cpp
+ * \brief CStorageObject
+ * \date 2012-08-18 09:02GMT
+ * \author Jan Boon (Kaetemi)
+ * CStorageObject
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE PIPELINE.
+ * RYZOM CORE PIPELINE is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * RYZOM CORE PIPELINE is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with RYZOM CORE PIPELINE. If not, see
+ * .
+ */
+
+#include
+#include "storage_object.h"
+
+// STL includes
+#include
+
+// NeL includes
+// #include
+
+// Project includes
+#include "storage_stream.h"
+#include "storage_chunks.h"
+
+// using namespace std;
+// using namespace NLMISC;
+
+#define NL_DEBUG_STORAGE
+
+namespace PIPELINE {
+namespace MAX {
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+std::string IStorageObject::toString()
+{
+ std::stringstream ss;
+ toString(ss);
+ return ss.str();
+}
+
+void IStorageObject::setSize(sint32 size)
+{
+ // ignore
+}
+
+bool IStorageObject::getSize(sint32 &size) const
+{
+ return false;
+}
+
+bool IStorageObject::isContainer() const
+{
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+std::string CStorageContainer::getClassName() // why is this not const in IClassable?
+{
+ return "StorageContainer";
+}
+
+void CStorageContainer::serial(NLMISC::IStream &stream)
+{
+ if (stream.getPos() == 0)
+ {
+ CStorageStream *storageStream = dynamic_cast(&stream);
+ if (storageStream)
+ {
+ // implicitly assume the entire stream is the container
+ CStorageChunks chunks(stream, stream.isReading() ? storageStream->size() : 0);
+ serial(chunks);
+ return;
+ }
+ }
+ // wrapping the container inside a stream with necessary size markers
+ {
+ const uint32 magic = 0xC0C01473;
+ stream.serialCheck(magic);
+ uint version = stream.serialVersion(1);
+ sint32 sizePos;
+ bool reading = stream.isReading();
+ if (!reading)
+ sizePos = stream.getPos();
+ sint64 size = 0;
+ stream.serial(size);
+ CStorageChunks chunks(stream, size);
+ serial(chunks);
+ if (!reading)
+ {
+ sint32 returnPos = stream.getPos();
+ stream.seek(sizePos, NLMISC::IStream::begin);
+ stream.serial(size);
+ stream.seek(returnPos, NLMISC::IStream::begin);
+ }
+ return;
+ }
+}
+
+void CStorageContainer::toString(std::ostream &ostream, const std::string &pad)
+{
+ // note: only use pad when multi-lining
+ // like Blah: (Something) "SingleValue"
+ // Blahblah: (Container) {
+ // Moo: (Foo) "What" }
+ // only increase pad when multi-lining sub-items
+ ostream << "(" << getClassName() << ") { ";
+ std::string padpad = pad + "\t";
+ for (TStorageObjectContainer::const_iterator it = Chunks.begin(), end = Chunks.end(); it != end; ++it)
+ {
+ 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);
+ }
+ ostream << "} ";
+}
+
+bool CStorageContainer::isContainer() const
+{
+ return true;
+}
+
+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();
+ while (chunks.enterChunk())
+ {
+ uint16 id = chunks.getChunkId();
+ IStorageObject *storageObject = createChunkById(id, chunks.isChunkContainer());
+ storageObject->setSize(chunks.getChunkSize());
+ if (storageObject->isContainer()) static_cast(storageObject)->serial(chunks);
+ else storageObject->serial(chunks.stream());
+ Chunks.push_back(TStorageObjectWithId(id, storageObject));
+ if (chunks.leaveChunk()) // bytes were skipped while reading
+ throw EStorage();
+ }
+ }
+ else
+ {
+ for (TStorageObjectContainer::iterator it = Chunks.begin(), end = Chunks.end(); it != end; ++it)
+ {
+ chunks.enterChunk(it->first, it->second->isContainer());
+ it->second->serial(chunks.stream());
+ chunks.leaveChunk();
+ }
+ }
+}
+
+IStorageObject *CStorageContainer::createChunkById(uint16 id, bool container)
+{
+ if (container)
+ {
+ return new CStorageContainer();
+ }
+ else
+ {
+ return new CStorageRaw();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+std::string CStorageRaw::getClassName()
+{
+ return "StorageRaw";
+}
+
+void CStorageRaw::serial(NLMISC::IStream &stream)
+{
+ stream.serialBuffer(&Value[0], Value.size());
+}
+
+void CStorageRaw::toString(std::ostream &ostream, const std::string &pad)
+{
+ // note: only use pad when multi-lining
+ // like Blah: (Something) "SingleValue"
+ // Blahblah: (Container) {
+ // Moo: (Foo) "What" }
+ // only increase pad when multi-lining sub-items
+ ostream << "(" << getClassName() << ") { ";
+
+ ostream << "} ";
+}
+
+void CStorageRaw::setSize(sint32 size)
+{
+ Value.resize(size);
+}
+
+bool CStorageRaw::getSize(sint32 &size) const
+{
+ size = Value.size();
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+
+} /* namespace MAX */
+} /* namespace PIPELINE */
+
+/* end of file */
diff --git a/code/nel/tools/pipeline/max/storage_object.h b/code/nel/tools/pipeline/max/storage_object.h
new file mode 100644
index 000000000..d6a141964
--- /dev/null
+++ b/code/nel/tools/pipeline/max/storage_object.h
@@ -0,0 +1,143 @@
+/**
+ * \file storage_object.h
+ * \brief CStorageObject
+ * \date 2012-08-18 09:02GMT
+ * \author Jan Boon (Kaetemi)
+ * CStorageObject
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE PIPELINE.
+ * RYZOM CORE PIPELINE is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Affero General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * RYZOM CORE PIPELINE is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with RYZOM CORE PIPELINE. If not, see
+ * .
+ */
+
+#ifndef PIPELINE_STORAGE_OBJECT_H
+#define PIPELINE_STORAGE_OBJECT_H
+#include
+
+// STL includes
+#include
+
+// NeL includes
+#include
+
+// Project includes
+
+namespace PIPELINE {
+namespace MAX {
+ class CStorageChunks;
+
+struct EStorage : public NLMISC::Exception
+{
+ EStorage() : NLMISC::Exception("PIPELINE::MAX::EStorage") { }
+ virtual ~EStorage() throw() { }
+};
+
+// IStorageObject : exposes serial(CStorageStream &stream) and dump(const std::string &pad)
+class IStorageObject : public NLMISC::IStreamable
+{
+public:
+ // 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();
+ virtual void toString(std::ostream &ostream, const std::string &pad = "") = 0;
+
+public: // should be protected but that doesn't compile, nice c++!
+ // Sets size when reading
+ virtual void setSize(sint32 size);
+ // Gets the size when writing, return false if unknown
+ virtual bool getSize(sint32 &size) const;
+ // Only true when inherting from CStorageContainer
+ virtual bool isContainer() const;
+};
+
+// CStorageContainer : serializes a container chunk
+class CStorageContainer : public IStorageObject
+{
+public:
+ // public data
+ typedef std::pair TStorageObjectWithId;
+ typedef std::vector TStorageObjectContainer;
+ TStorageObjectContainer Chunks;
+
+ // inherited
+ virtual std::string getClassName();
+ virtual void serial(NLMISC::IStream &stream); // only used to wrap a container inside another stream
+ virtual void toString(std::ostream &ostream, const std::string &pad = "");
+
+public: // should be protected but that doesn't compile, nice c++!
+ // inherited
+ virtual bool isContainer() const;
+
+protected:
+ // override in subclasses, default to parent if not handled
+ virtual void serial(CStorageChunks &chunks);
+ virtual IStorageObject *createChunkById(uint16 id, bool container);
+};
+
+// CStorageRaw : serializes raw data, use for unknown data
+class CStorageRaw : public IStorageObject
+{
+public:
+ // public data
+ typedef std::vector TType;
+ TType Value;
+
+ // inherited
+ virtual std::string getClassName();
+ virtual void serial(NLMISC::IStream &stream);
+ virtual void toString(std::ostream &ostream, const std::string &pad = "");
+
+public: // should be protected but that doesn't compile, nice c++!
+ // Sets size when reading
+ virtual void setSize(sint32 size);
+ // Gets the size when writing, return false if unknown
+ virtual bool getSize(sint32 &size) const;
+};
+/*
+// CStorageUCString : serializes an ucstring chunk
+class CStorageUCString : public ucstring, public IStorageObject
+{
+public:
+ virtual void serial(CStorageStream *stream);
+ virtual void dump(const std::string &pad);
+};
+
+// CStorageString : serializes a string chunk
+class CStorageString : public std::string, public IStorageObject
+{
+public:
+ virtual void serial(CStorageStream *stream);
+ virtual void dump(const std::string &pad);
+};
+
+template
+class CStorageValue : public IStorageObject
+{
+public:
+ T Value;
+ virtual void serial(CStorageStream *stream);
+ virtual void dump(const std::string &pad);
+};
+*/
+
+} /* namespace MAX */
+} /* namespace PIPELINE */
+
+#endif /* #ifndef PIPELINE_STORAGE_OBJECT_H */
+
+/* end of file */
diff --git a/code/nel/tools/pipeline/max/storage_stream.cpp b/code/nel/tools/pipeline/max/storage_stream.cpp
index cb6253e18..e0651d826 100644
--- a/code/nel/tools/pipeline/max/storage_stream.cpp
+++ b/code/nel/tools/pipeline/max/storage_stream.cpp
@@ -39,30 +39,22 @@
// Project includes
-using namespace std;
+// using namespace std;
// using namespace NLMISC;
-// #define NL_DEBUG_STORAGE_STREAM
+// #define NL_DEBUG_STORAGE
namespace PIPELINE {
namespace MAX {
-CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input), m_Output(NULL), m_Is64Bit(false)
+CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input), m_Output(NULL)
{
- m_Chunks.reserve(64);
- m_Chunks.resize(1);
- m_Chunks[0].OffsetBegin = -6;
- m_Chunks[0].Id = 0;
- m_Chunks[0].Size = 0x80000000;
+
}
-CStorageStream::CStorageStream(GsfOutput *output) : NLMISC::IStream(true), m_Input(NULL), m_Output(output), m_Is64Bit(false)
+CStorageStream::CStorageStream(GsfOutput *output) : NLMISC::IStream(false), m_Input(NULL), m_Output(output)
{
- m_Chunks.reserve(64);
- m_Chunks.resize(1);
- m_Chunks[0].OffsetBegin = -6;
- m_Chunks[0].Id = 1; // in write mode, id flags a container
- m_Chunks[0].Size = 0;
+
}
CStorageStream::~CStorageStream()
@@ -120,7 +112,7 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len)
{
if (!len)
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("Serial 0 size buffer");
#endif
return;
@@ -129,7 +121,7 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len)
{
if (!gsf_input_read(m_Input, len, buf))
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("Cannot read from input, throw exception");
#endif
throw NLMISC::EStream();
@@ -139,7 +131,7 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len)
{
if (!gsf_output_write(m_Output, len, buf))
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("Cannot write to output, throw exception");
#endif
throw NLMISC::EStream();
@@ -147,7 +139,7 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len)
}
else
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("No input or output, should not happen, throw exception");
#endif
throw NLMISC::EStream();
@@ -169,132 +161,29 @@ bool CStorageStream::eof()
}
else
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("No input, this function cannot output, throw exception");
#endif
throw NLMISC::EStream();
}
}
-bool CStorageStream::enterChunk()
+sint32 CStorageStream::size()
{
if (m_Input)
{
- // input logic
- if (!isChunkContainer())
- {
-#ifdef NL_DEBUG_STORAGE_STREAM
- nldebug("Current chunk is not a container, cannot enter");
-#endif
- return false;
- }
- if (endOfChunk())
- {
-#ifdef NL_DEBUG_STORAGE_STREAM
- nldebug("End of chunk, cannot enter");
-#endif
- return false;
- }
- m_Chunks.resize(m_Chunks.size() + 1);
- CChunk *chunk = currentChunk();
- chunk->OffsetBegin = CStorageStream::getPos();
- serial(chunk->Id);
- serial(chunk->Size);
- chunk->HeaderSize = 6;
- if (chunk->Size == 0)
- {
- // this is a 64bit chunk
- uint64 size64;
- serial(size64);
- chunk->HeaderSize += 8;
- bool iscont = (size64 & 0x8000000000000000) == 0x8000000000000000;
- size64 &= 0x7FFFFFFFFFFFFFFF;
- if (size64 >= 2147483647L)
- throw NLMISC::EStream("64bit chunks not supported");
- // downgrade to 32 bit chunk
- chunk->Size = (uint32)size64;
- if (iscont) chunk->Size |= 0x80000000;
- m_Is64Bit = true; // it's true
- }
- return true;
+ gsf_off_t res = gsf_input_size(m_Input);
+ if (res < 2147483647L) // exception when larger
+ return (sint32)res;
}
else
{
-#ifdef NL_DEBUG_STORAGE_STREAM
+#ifdef NL_DEBUG_STORAGE
nldebug("No input, this function cannot output, throw exception");
#endif
throw NLMISC::EStream();
}
-}
-
-bool CStorageStream::enterChunk(uint16 id)
-{
- if (m_Output)
- {
- if (m_Is64Bit)
- throw NLMISC::EStream("64bit chunks not supported");
-
- // current chunk is a container
- currentChunk()->Id = 1; // in write mode, id flags a container
-
- // enter the new chunk
- m_Chunks.resize(m_Chunks.size() + 1);
- CChunk *chunk = currentChunk();
- chunk->Id = 0; // don't know if it's a container
- uint32 sizeDummy = 0xFFFFFFFF;
- chunk->OffsetBegin = getPos(); // store current pos
-
- // write header
- serial(id); // write the id
- serial(sizeDummy); // write 32 bit size placeholder
- }
- else // input or exception
- {
- while (enterChunk())
- {
- if (getChunkId() == id)
- return true;
- leaveChunk(); // skip data
- }
- return false;
- }
-}
-
-sint32 CStorageStream::leaveChunk()
-{
- if (m_Input)
- {
- // input logic
- sint32 skipped = currentChunk()->endOfChunk() - CStorageStream::getPos();
- if (skipped)
- {
- CStorageStream::seek(currentChunk()->endOfChunk(), begin);
-#ifdef NL_DEBUG_STORAGE_STREAM
- nldebug("Skipped %i bytes in the current chunk", skipped);
-#endif
- }
- m_Chunks.resize(m_Chunks.size() - 1);
- return skipped;
- }
- else if (m_Output)
- {
- sint32 pos = getPos();
- sint32 sizeWithHeader = pos - currentChunk()->OffsetBegin;
- sint32 sizePos = currentChunk()->OffsetBegin + 2;
- seek(sizePos, begin); // hopefully this correctly overwrites!!!
- uint32 sizeField = (uint32)sizeWithHeader | (uint32)currentChunk()->Id << 31; // add container flag
- serial(sizeField);
- seek(pos, begin);
- m_Chunks.resize(m_Chunks.size() - 1);
- return sizeWithHeader;
- }
- else
- {
-#ifdef NL_DEBUG_STORAGE_STREAM
- nldebug("No input or output, should not happen, throw exception");
-#endif
- throw NLMISC::EStream();
- }
+ throw NLMISC::EStream();
}
} /* namespace MAX */
diff --git a/code/nel/tools/pipeline/max/storage_stream.h b/code/nel/tools/pipeline/max/storage_stream.h
index c1c0e41b0..e50a611d0 100644
--- a/code/nel/tools/pipeline/max/storage_stream.h
+++ b/code/nel/tools/pipeline/max/storage_stream.h
@@ -52,26 +52,6 @@ namespace MAX {
*/
class CStorageStream : public NLMISC::IStream
{
-private:
- struct CChunk
- {
- // Size of the chunk header, 6 for 32 bit, 14 for 64 bit
- uint8 HeaderSize;
- // Where the header starts
- sint32 OffsetBegin;
-
- // Identifier
- uint16 Id;
- // Size including header size
- uint32 Size;
-
- inline sint32 getSizeWithHeader() { return (sint32)(Size & 0x7FFFFFFF); }
- inline sint32 getSize() { return getSizeWithHeader() - (sint32)HeaderSize; }
- inline bool isContainer() { return (Size & 0x80000000) == 0x80000000; }
- inline sint32 endOfChunk() { return OffsetBegin + getSizeWithHeader(); }
- inline sint32 getDataBegin() { return OffsetBegin + (sint32)HeaderSize; }
- };
-
public:
CStorageStream(GsfInput *input);
CStorageStream(GsfOutput *output);
@@ -83,31 +63,12 @@ public:
virtual void serialBuffer(uint8 *buf, uint len);
virtual void serialBit(bool &bit);
+ sint32 size();
bool eof();
- // Returns true if there's another chunk, false if no more chunks in this container or if the current chunk is not a container
- bool enterChunk();
- // Reads and skips chunks until the one with given id is found, or writes a chunk with this id
- bool enterChunk(uint16 id);
- // Returns the number of skipped bytes in read more, returns chunk size including header in write mode
- sint32 leaveChunk();
-
- inline bool is64Bit() const { return m_Is64Bit; }
- inline void set64Bit(bool enabled = true) { m_Is64Bit = enabled; }
-
- inline uint16 getChunkId() { return currentChunk()->Id; }
- inline sint32 getChunkSize() { return currentChunk()->getSize(); }
- inline bool isChunkContainer() { return currentChunk()->isContainer(); }
- inline bool endOfChunk() { return m_Chunks.size() == 1 ? eof() : CStorageStream::getPos() >= currentChunk()->endOfChunk(); }
-
-private:
- inline CChunk *currentChunk() { return &m_Chunks[m_Chunks.size() - 1]; }
-
private:
GsfInput *m_Input;
GsfOutput *m_Output;
- std::vector m_Chunks;
- bool m_Is64Bit;
/* there exist compressed max files, so maybe we will need this at some point
GsfInput * gsf_input_uncompress (GsfInput *src);
diff --git a/code/nel/tools/pipeline/max_dump/main.cpp b/code/nel/tools/pipeline/max_dump/main.cpp
index 7ffe984dd..e7669306f 100644
--- a/code/nel/tools/pipeline/max_dump/main.cpp
+++ b/code/nel/tools/pipeline/max_dump/main.cpp
@@ -11,11 +11,13 @@
#include
#include
#include
+#include
#include
#include
#include "../max/storage_stream.h"
+#include "../max/storage_object.h"
//static const char *filename = "/srv/work/database/interfaces/anims_max/cp_fy_hof_species.max";
static const char *filename = "/home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max";
@@ -32,75 +34,7 @@ inline uint8 cleanChar(uint8 c)
namespace PIPELINE {
namespace MAX {
-struct EStorage : public NLMISC::Exception
-{
- EStorage() : NLMISC::Exception("PIPELINE::MAX::EStorage") { }
- virtual ~EStorage() throw() { }
-};
-
-// IStorageObject : exposes serial(CStorageStream *stream) and dump(const std::string &pad)
-class IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream) = 0;
- virtual void dump(const std::string &pad) = 0;
-};
-
-class IStorageStreamable : public NLMISC::IStreamable, public IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream);
- virtual void serial(NLMISC::IStream &stream) = 0;
-};
-void IStorageStreamable::serial(CStorageStream *stream)
-{
- serial(*((NLMISC::IStream *)stream));
-}
-
-// CStorageContainer : serializes a container chunk
-class CStorageContainer : public std::vector >, public IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream);
- virtual void dump(const std::string &pad);
-
- // override in subclasses, call parent if not handled
- virtual IStorageObject *serialChunk(CStorageStream *stream);
-};
-
-// CStorageRaw : serializes raw data, use for unknown data
-class CStorageRaw : public std::vector, public IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream);
- virtual void dump(const std::string &pad);
-};
-
-// CStorageUCString : serializes an ucstring chunk
-class CStorageUCString : public ucstring, public IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream);
- virtual void dump(const std::string &pad);
-};
-
-// CStorageString : serializes a string chunk
-class CStorageString : public std::string, public IStorageObject
-{
-public:
- virtual void serial(CStorageStream *stream);
- virtual void dump(const std::string &pad);
-};
-
-template
-class CStorageValue : public IStorageObject
-{
-public:
- T Value;
- virtual void serial(CStorageStream *stream);
- virtual void dump(const std::string &pad);
-};
-
+/*
struct CClass_ID : public NLMISC::IStreamable
{
uint32 A;
@@ -145,21 +79,7 @@ std::string CClassDirectoryHeader::getClassName()
void CStorageContainer::serial(CStorageStream *stream)
{
- if (stream->isReading())
- {
- while (stream->enterChunk())
- {
- uint16 id = stream->getChunkId();
- IStorageObject *storageObject = serialChunk(stream);
- push_back(std::pair(id, storageObject));
- if (stream->leaveChunk()) // bytes were skipped while reading
- throw EStorage();
- }
- }
- else
- {
- throw EStorage();
- }
+
}
IStorageObject *CStorageContainer::serialChunk(CStorageStream *stream)
{
@@ -291,10 +211,10 @@ void CStorageValue::dump(const std::string &pad)
std::string valstr = NLMISC::toString(Value);
printf("%s%s\n", pad.c_str(), valstr.c_str());
}
-
+*/
}
}
-
+/*
static void dumpData(PIPELINE::MAX::CStorageStream *in, const std::string &pad)
{
sint32 size = in->getChunkSize();
@@ -336,7 +256,7 @@ static void dumpContainer(PIPELINE::MAX::CStorageStream *in, const std::string &
printf("%sSKIPPED: %i\n", pad.c_str(), skipped);
}
}
-
+*/
// int __stdcall WinMain(void *, void *, void *, int)
int main(int argc, char **argv)
{
@@ -382,13 +302,16 @@ int main(int argc, char **argv)
g_print("%s\n", streamname);
GsfInput *input = gsf_infile_child_by_name(infile, streamname);
- //gsf_input_dump(input, 1); // just a regular hex dump of this input stream
- PIPELINE::MAX::CStorageStream *instream = new PIPELINE::MAX::CStorageStream(input);
- dumpContainer(instream, "");
- //PIPELINE::MAX::CStorageContainer ctr;
- //ctr.serial(instream);
- //ctr.dump("");
- delete instream;
+
+ {
+ //gsf_input_dump(input, 1); // just a regular hex dump of this input stream
+ PIPELINE::MAX::CStorageStream instream(input);
+ //dumpContainer(instream, "");
+ PIPELINE::MAX::CStorageContainer ctr;
+ ctr.serial(instream);
+ ctr.toString(std::cout);
+ //ctr.dump("");
+ }
g_object_unref(input);
g_object_unref(infile);