Added: #1440 Write functionality for storage stream

--HG--
branch : build_pipeline_v3
hg/feature/build_pipeline_v3
kaetemi 12 years ago
parent a90d76361c
commit 9beb31bac4

@ -32,6 +32,7 @@
// 3rd Party includes // 3rd Party includes
#include <gsf/gsf-input-stdio.h> #include <gsf/gsf-input-stdio.h>
#include <gsf/gsf-output-stdio.h>
// NeL includes // NeL includes
// #include <nel/misc/debug.h> // #include <nel/misc/debug.h>
@ -55,6 +56,15 @@ CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input
m_Chunks[0].Size = 0x80000000; 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() 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); 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); return NLMISC::IStream::seek(offset, origin);
} }
@ -85,6 +107,12 @@ sint32 CStorageStream::getPos() const
if (res < 2147483647L) // exception when larger if (res < 2147483647L) // exception when larger
return (sint32)res; 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(); return NLMISC::IStream::getPos();
} }
@ -109,7 +137,13 @@ void CStorageStream::serialBuffer(uint8 *buf, uint len)
} }
else if (m_Output) 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 else
{ {
@ -129,7 +163,17 @@ void CStorageStream::serialBit(bool &bit)
bool CStorageStream::eof() 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() bool CStorageStream::enterChunk()
@ -187,7 +231,22 @@ bool CStorageStream::enterChunk(uint16 id)
{ {
if (m_Output) 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 else // input or exception
{ {
@ -219,7 +278,15 @@ sint32 CStorageStream::leaveChunk()
} }
else if (m_Output) 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 else
{ {

@ -34,6 +34,7 @@
// 3rd Party includes // 3rd Party includes
#include <gsf/gsf-infile.h> #include <gsf/gsf-infile.h>
#include <gsf/gsf-outfile.h>
// NeL includes // NeL includes
#include <nel/misc/stream.h> #include <nel/misc/stream.h>
@ -73,6 +74,7 @@ private:
public: public:
CStorageStream(GsfInput *input); CStorageStream(GsfInput *input);
CStorageStream(GsfOutput *output);
virtual ~CStorageStream(); virtual ~CStorageStream();
virtual bool seek(sint32 offset, TSeekOrigin origin) const; virtual bool seek(sint32 offset, TSeekOrigin origin) const;
@ -103,7 +105,7 @@ private:
private: private:
GsfInput *m_Input; GsfInput *m_Input;
void *m_Output; // todo GsfOutput *m_Output;
std::vector<CChunk> m_Chunks; std::vector<CChunk> m_Chunks;
bool m_Is64Bit; bool m_Is64Bit;

@ -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
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include "storage_stream.h"
// STL includes
// 3rd Party includes
#include <gsf/gsf-input-stdio.h>
// NeL includes
// #include <nel/misc/debug.h>
// 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<uint16, CChunk *>::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 */

@ -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
* <http://www.gnu.org/licenses/>.
*/
#ifndef PIPELINE_STORAGE_STREAM_H
#define PIPELINE_STORAGE_STREAM_H
#include <nel/misc/types_nl.h>
// STL includes
#include <map>
// 3rd Party includes
#include <gsf/gsf-infile.h>
// NeL includes
#include <nel/misc/stream.h>
// Project includes
namespace PIPELINE {
#if 0
struct CChunk
{
CChunk() : Parent(NULL) { }
~CChunk()
{
for (std::map<uint16, CChunk *>::iterator it = Children.begin(), end = Children.end(); it != end; ++it)
delete it->second;
Children.clear();
}
CChunk *Parent;
std::map<uint16, CChunk *> 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 */
Loading…
Cancel
Save