From 9beb31bac4da00e94ae856e68712897f52e605ae Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sat, 18 Aug 2012 10:57:09 +0200 Subject: [PATCH] Added: #1440 Write functionality for storage stream --HG-- branch : build_pipeline_v3 --- .../nel/tools/pipeline/max/storage_stream.cpp | 75 +++++++- code/nel/tools/pipeline/max/storage_stream.h | 4 +- .../pipeline/max_dump/storage_stream.cpp | 174 ------------------ .../tools/pipeline/max_dump/storage_stream.h | 122 ------------ 4 files changed, 74 insertions(+), 301 deletions(-) delete mode 100644 code/nel/tools/pipeline/max_dump/storage_stream.cpp delete mode 100644 code/nel/tools/pipeline/max_dump/storage_stream.h diff --git a/code/nel/tools/pipeline/max/storage_stream.cpp b/code/nel/tools/pipeline/max/storage_stream.cpp index 35ac771a8..cb6253e18 100644 --- a/code/nel/tools/pipeline/max/storage_stream.cpp +++ b/code/nel/tools/pipeline/max/storage_stream.cpp @@ -32,6 +32,7 @@ // 3rd Party includes #include +#include // NeL includes // #include @@ -55,6 +56,15 @@ CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input m_Chunks[0].Size = 0x80000000; } +CStorageStream::CStorageStream(GsfOutput *output) : NLMISC::IStream(true), m_Input(NULL), m_Output(output), m_Is64Bit(false) +{ + 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() { @@ -74,6 +84,18 @@ bool CStorageStream::seek(sint32 offset, NLMISC::IStream::TSeekOrigin origin) co return gsf_input_seek(m_Input, offset, G_SEEK_END); } } + else if (m_Output) + { + switch (origin) + { + case begin: + return gsf_output_seek(m_Output, offset, G_SEEK_SET); + case current: + return gsf_output_seek(m_Output, offset, G_SEEK_CUR); + case end: + return gsf_output_seek(m_Output, offset, G_SEEK_END); + } + } return NLMISC::IStream::seek(offset, origin); } @@ -85,6 +107,12 @@ sint32 CStorageStream::getPos() const if (res < 2147483647L) // exception when larger return (sint32)res; } + else if (m_Output) + { + gsf_off_t res = gsf_output_tell(m_Output); + if (res < 2147483647L) // exception when larger + return (sint32)res; + } return NLMISC::IStream::getPos(); } @@ -109,7 +137,13 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len) } else if (m_Output) { - throw NLMISC::EStream(); // not yet implemented + if (!gsf_output_write(m_Output, len, buf)) + { +#ifdef NL_DEBUG_STORAGE_STREAM + nldebug("Cannot write to output, throw exception"); +#endif + throw NLMISC::EStream(); + } } else { @@ -129,7 +163,17 @@ void CStorageStream::serialBit(bool &bit) bool CStorageStream::eof() { - return gsf_input_eof(m_Input); + if (m_Input) + { + return gsf_input_eof(m_Input); + } + else + { +#ifdef NL_DEBUG_STORAGE_STREAM + nldebug("No input, this function cannot output, throw exception"); +#endif + throw NLMISC::EStream(); + } } bool CStorageStream::enterChunk() @@ -187,7 +231,22 @@ bool CStorageStream::enterChunk(uint16 id) { if (m_Output) { - throw NLMISC::EStream(); // not yet implemented + 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 { @@ -219,7 +278,15 @@ sint32 CStorageStream::leaveChunk() } else if (m_Output) { - throw NLMISC::EStream(); // not yet implemented + 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 { diff --git a/code/nel/tools/pipeline/max/storage_stream.h b/code/nel/tools/pipeline/max/storage_stream.h index 46a342752..c1c0e41b0 100644 --- a/code/nel/tools/pipeline/max/storage_stream.h +++ b/code/nel/tools/pipeline/max/storage_stream.h @@ -34,6 +34,7 @@ // 3rd Party includes #include +#include // NeL includes #include @@ -73,6 +74,7 @@ private: public: CStorageStream(GsfInput *input); + CStorageStream(GsfOutput *output); virtual ~CStorageStream(); virtual bool seek(sint32 offset, TSeekOrigin origin) const; @@ -103,7 +105,7 @@ private: private: GsfInput *m_Input; - void *m_Output; // todo + GsfOutput *m_Output; std::vector m_Chunks; bool m_Is64Bit; diff --git a/code/nel/tools/pipeline/max_dump/storage_stream.cpp b/code/nel/tools/pipeline/max_dump/storage_stream.cpp deleted file mode 100644 index 3dbe005f8..000000000 --- a/code/nel/tools/pipeline/max_dump/storage_stream.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** - * \file storage_stream.cpp - * \brief CStorageStream - * \date 2012-08-16 22:06GMT - * \author Jan Boon (Kaetemi) - * CStorageStream - */ - -/* - * 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_stream.h" - -// STL includes - -// 3rd Party includes -#include - -// NeL includes -// #include - -// Project includes - -using namespace std; -// using namespace NLMISC; - -namespace PIPELINE { -#if 0 -CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input) -{ - m_RootChunk.OffsetBegin = -6; - m_RootChunk.Id = 0; - m_RootChunk.Size = 0x80000000; - m_CurrentChunk = &m_RootChunk; -} - -CStorageStream::~CStorageStream() -{ - -} - -bool CStorageStream::seek(sint32 offset, NLMISC::IStream::TSeekOrigin origin) const -{ - if (m_Input) - { - switch (origin) - { - case begin: - return gsf_input_seek(m_Input, offset, G_SEEK_SET); - case current: - return gsf_input_seek(m_Input, offset, G_SEEK_CUR); - case end: - return gsf_input_seek(m_Input, offset, G_SEEK_END); - } - } - return NLMISC::IStream::seek(offset, origin); -} - -sint32 CStorageStream::getPos() const -{ - if (m_Input) - { - gsf_off_t res = gsf_input_tell(m_Input); - if (res < 2147483647L) // exception when larger - return (sint32)res; - } - return NLMISC::IStream::getPos(); -} - -void CStorageStream::serialBuffer(uint8 *buf, uint len) -{ - if (!len) - return; - if (m_Input) - { - if (!gsf_input_read(m_Input, len, buf)) - throw NLMISC::EStream(); - } - else - { - throw NLMISC::EStream(); - } -} - -void CStorageStream::serialBit(bool &bit) -{ - uint8 var = (uint8)bit; - serial(var); - bit = (bool)var; -} - -bool CStorageStream::eof() -{ - return gsf_input_eof(m_Input); -} - -bool CStorageStream::enterChunk() -{ - // input logic - if (!isChunkContainer()) - return false; - if (endOfChunk()) - return false; - CChunk *chunk = new CChunk(); - 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; - } - chunk->Parent = m_CurrentChunk; - { - // temp memleak fix - std::map::iterator it = m_CurrentChunk->Children.find(chunk->Id); - if (it != m_CurrentChunk->Children.end()) - m_CurrentChunk->Children.erase(it); - } - m_CurrentChunk->Children[chunk->Id] = chunk; // assuming there's one child per id... - m_CurrentChunk = chunk; - return true; -} - -sint32 CStorageStream::leaveChunk() -{ - // input logic - sint32 skipped = m_CurrentChunk->endOfChunk() - CStorageStream::getPos(); - if (skipped) - CStorageStream::seek(m_CurrentChunk->endOfChunk(), begin); - m_CurrentChunk = m_CurrentChunk->Parent; - return skipped; -} - -void CStorageStream::buildChunkIndexById() -{ - -} - -void CStorageStream::findChunkById(uint16 id) -{ - -} -#endif -} /* namespace PIPELINE */ - -/* end of file */ diff --git a/code/nel/tools/pipeline/max_dump/storage_stream.h b/code/nel/tools/pipeline/max_dump/storage_stream.h deleted file mode 100644 index 0cb2807a5..000000000 --- a/code/nel/tools/pipeline/max_dump/storage_stream.h +++ /dev/null @@ -1,122 +0,0 @@ -/** - * \file storage_stream.h - * \brief CStorageStream - * \date 2012-08-16 22:06GMT - * \author Jan Boon (Kaetemi) - * CStorageStream - */ - -/* - * 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_STREAM_H -#define PIPELINE_STORAGE_STREAM_H -#include - -// STL includes -#include - -// 3rd Party includes -#include - -// NeL includes -#include - -// Project includes - -namespace PIPELINE { -#if 0 -struct CChunk -{ - CChunk() : Parent(NULL) { } - ~CChunk() - { - for (std::map::iterator it = Children.begin(), end = Children.end(); it != end; ++it) - delete it->second; - Children.clear(); - } - CChunk *Parent; - std::map Children; - - // 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; } -}; - -/** - * \brief CStorageStream - * \date 2012-08-16 22:06GMT - * \author Jan Boon (Kaetemi) - * CStorageStream - */ -class CStorageStream : public NLMISC::IStream -{ -public: - CStorageStream(GsfInput *input); - virtual ~CStorageStream(); - - virtual bool seek(sint32 offset, TSeekOrigin origin) const; - virtual sint32 getPos() const; - // virtual std::string getStreamName() const; // char const * gsf_input_name (GsfInput *input); - virtual void serialBuffer(uint8 *buf, uint len); - virtual void serialBit(bool &bit); - - 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(); - // Returns the number of skipped bytes - sint32 leaveChunk(); - - inline uint16 getChunkId() { return m_CurrentChunk->Id; } - inline sint32 getChunkSize() { return m_CurrentChunk->getSize(); } - inline bool isChunkContainer() { return m_CurrentChunk->isContainer(); } - inline bool endOfChunk() { return m_CurrentChunk == &m_RootChunk ? eof() : CStorageStream::getPos() >= m_CurrentChunk->endOfChunk(); } - - void buildChunkIndexById(); - void findChunkById(uint16 id); - -private: - GsfInput *m_Input; - CChunk m_RootChunk; - CChunk *m_CurrentChunk; - -/* there exist compressed max files, so maybe we will need this at some point -GsfInput * gsf_input_uncompress (GsfInput *src); -*/ - -}; /* class CStorageStream */ -#endif -} /* namespace PIPELINE */ - -#endif /* #ifndef PIPELINE_STORAGE_STREAM_H */ - -/* end of file */