Added: #1440 Max file utility library

--HG--
branch : build_pipeline_v3
hg/feature/build_pipeline_v3
kaetemi 12 years ago
parent 4e35b4f551
commit 4b1a310dfb

@ -1,4 +1,5 @@
SUBDIRS( SUBDIRS(
max
max_dump max_dump
plugin_library plugin_library
plugin_nel plugin_nel

@ -0,0 +1,39 @@
FIND_PACKAGE(LIBGSF)
IF (NOT (LIBGSF_INCLUDE_DIR AND LIBGSF_LIBRARIES))
MESSAGE(FATAL_ERROR "LIBGSF not found!")
ENDIF (NOT (LIBGSF_INCLUDE_DIR AND LIBGSF_LIBRARIES))
FIND_PACKAGE(GLIB2)
if (NOT GLIB2_FOUND)
MESSAGE(FATAL_ERROR "GLIB2 not found!")
ENDIF (NOT GLIB2_FOUND)
INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${LIBGSF_INCLUDE_DIR})
FILE(GLOB SRCS *.cpp)
FILE(GLOB HDRS *.h)
NL_TARGET_LIB(pipeline_max
${SRCS}
${HDRS}
)
TARGET_LINK_LIBRARIES(pipeline_max
${LIBGSF_LIBRARIES}
${GLIB2_LIBRARIES}
nelmisc
)
SET_TARGET_PROPERTIES(pipeline_max PROPERTIES LINK_INTERFACE_LIBRARIES "")
NL_DEFAULT_PROPS(pipeline_max "NeL, Tools, Pipeline: Max (Library)")
NL_ADD_LIB_SUFFIX(pipeline_max)
NL_ADD_RUNTIME_FLAGS(pipeline_max)
IF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC)
INSTALL(TARGETS pipeline_max LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
ENDIF((WITH_INSTALL_LIBRARIES AND WITH_STATIC) OR NOT WITH_STATIC)

@ -0,0 +1,236 @@
/**
* \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;
// #define NL_DEBUG_STORAGE_STREAM
namespace PIPELINE {
namespace MAX {
CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input), m_Output(NULL), m_Is64Bit(false)
{
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()
{
}
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)
{
#ifdef NL_DEBUG_STORAGE_STREAM
nldebug("Serial 0 size buffer");
#endif
return;
}
if (m_Input)
{
if (!gsf_input_read(m_Input, len, buf))
{
#ifdef NL_DEBUG_STORAGE_STREAM
nldebug("Cannot read from input, throw exception");
#endif
throw NLMISC::EStream();
}
}
else if (m_Output)
{
throw NLMISC::EStream(); // not yet implemented
}
else
{
#ifdef NL_DEBUG_STORAGE_STREAM
nldebug("No input or output, should not happen, throw exception");
#endif
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()
{
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;
}
else
{
#ifdef NL_DEBUG_STORAGE_STREAM
nldebug("No input, this function cannot output, throw exception");
#endif
throw NLMISC::EStream();
}
}
bool CStorageStream::enterChunk(uint16 id)
{
if (m_Output)
{
throw NLMISC::EStream(); // not yet implemented
}
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)
{
throw NLMISC::EStream(); // not yet implemented
}
else
{
#ifdef NL_DEBUG_STORAGE_STREAM
nldebug("No input or output, should not happen, throw exception");
#endif
throw NLMISC::EStream();
}
}
} /* namespace MAX */
} /* namespace PIPELINE */
/* end of file */

@ -0,0 +1,121 @@
/**
* \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 {
namespace MAX {
/**
* \brief CStorageStream
* \date 2012-08-16 22:06GMT
* \author Jan Boon (Kaetemi)
* CStorageStream
*/
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);
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();
// 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;
void *m_Output; // todo
std::vector<CChunk> 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);
*/
}; /* class CStorageStream */
} /* namespace MAX */
} /* namespace PIPELINE */
#endif /* #ifndef PIPELINE_STORAGE_STREAM_H */
/* end of file */

@ -25,6 +25,7 @@ ADD_EXECUTABLE(pipeline_max_dump
TARGET_LINK_LIBRARIES(pipeline_max_dump TARGET_LINK_LIBRARIES(pipeline_max_dump
${LIBGSF_LIBRARIES} ${LIBGSF_LIBRARIES}
${GLIB2_LIBRARIES} ${GLIB2_LIBRARIES}
pipeline_max
nelmisc nelmisc
) )

@ -37,17 +37,17 @@ f 2320 DocumentSummaryInformation
kaetemi@benzaiten ~/source/minimax/build $ gsf dump /home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max VideoPostQueue kaetemi@benzaiten ~/source/minimax/build $ gsf dump /home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max VideoPostQueue
VideoPostQueue VideoPostQueue
[ [
50 00 (id: 80) 50 00 (id: 0x0050)
0a 00 00 00 (size: 10 - 6 = 4) 0a 00 00 00 (size: 10 - 6 = 4)
[ [
01 00 00 00 (value: 1) 01 00 00 00 (value: 1)
] ]
] ]
[ [
60 00 (id: 96) 60 00 (id: 0x0060)
2a 00 00 80 (size: 42 - 6 = 36) (note: negative bit = container) 2a 00 00 80 (size: 42 - 6 = 36) (note: negative bit = container)
[ [
10 00 (id: 16) 10 00 (id: 0x0010)
1e 00 00 00 (size: 30 - 6 = 24) 1e 00 00 00 (size: 30 - 6 = 24)
[ [
07 00 00 00 (value: 7) 07 00 00 00 (value: 7)
@ -57,7 +57,7 @@ VideoPostQueue
20 12 00 00 (value: 4610) 20 12 00 00 (value: 4610)
00 00 00 00 00 00 00 00
] ]
20 00 (id: 32) 20 00 (id: 0x0020)
06 00 00 00 (size: 6 - 6 = 0) 06 00 00 00 (size: 6 - 6 = 0)
] ]
] ]

@ -15,13 +15,13 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include "storage_stream.h" #include "../max/storage_stream.h"
//static const char *filename = "/srv/work/database/interfaces/anims_max/cp_fy_hof_species.max"; //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"; static const char *filename = "/home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max";
static const char *filename = "/home/kaetemi/3dsMax/scenes/test2008.max"; //static const char *filename = "/home/kaetemi/3dsMax/scenes/test2008.max";
//static const char *filename = "/home/kaetemi/3dsMax/scenes/teapot_test_scene.max"; //static const char *filename = "/home/kaetemi/3dsMax/scenes/teapot_test_scene.max";
static const char *streamname = "Scene"; static const char *streamname = "DllDirectory";
inline uint8 cleanChar(uint8 c) inline uint8 cleanChar(uint8 c)
{ {
@ -295,7 +295,7 @@ void CStorageValue<T>::dump(const std::string &pad)
} }
} }
static void dumpData(PIPELINE::CStorageStream *in, const std::string &pad) static void dumpData(PIPELINE::MAX::CStorageStream *in, const std::string &pad)
{ {
sint32 size = in->getChunkSize(); sint32 size = in->getChunkSize();
std::vector<uint8> buffer; std::vector<uint8> buffer;
@ -319,7 +319,7 @@ static void dumpData(PIPELINE::CStorageStream *in, const std::string &pad)
} }
} }
static void dumpContainer(PIPELINE::CStorageStream *in, const std::string &pad) static void dumpContainer(PIPELINE::MAX::CStorageStream *in, const std::string &pad)
{ {
while (in->enterChunk()) while (in->enterChunk())
{ {
@ -383,7 +383,7 @@ int main(int argc, char **argv)
GsfInput *input = gsf_infile_child_by_name(infile, streamname); GsfInput *input = gsf_infile_child_by_name(infile, streamname);
//gsf_input_dump(input, 1); // just a regular hex dump of this input stream //gsf_input_dump(input, 1); // just a regular hex dump of this input stream
PIPELINE::CStorageStream *instream = new PIPELINE::CStorageStream(input); PIPELINE::MAX::CStorageStream *instream = new PIPELINE::MAX::CStorageStream(input);
dumpContainer(instream, ""); dumpContainer(instream, "");
//PIPELINE::MAX::CStorageContainer ctr; //PIPELINE::MAX::CStorageContainer ctr;
//ctr.serial(instream); //ctr.serial(instream);

@ -42,7 +42,7 @@ using namespace std;
// using namespace NLMISC; // using namespace NLMISC;
namespace PIPELINE { namespace PIPELINE {
#if 0
CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input) CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input)
{ {
m_RootChunk.OffsetBegin = -6; m_RootChunk.OffsetBegin = -6;
@ -168,7 +168,7 @@ void CStorageStream::findChunkById(uint16 id)
{ {
} }
#endif
} /* namespace PIPELINE */ } /* namespace PIPELINE */
/* end of file */ /* end of file */

@ -41,7 +41,7 @@
// Project includes // Project includes
namespace PIPELINE { namespace PIPELINE {
#if 0
struct CChunk struct CChunk
{ {
CChunk() : Parent(NULL) { } CChunk() : Parent(NULL) { }
@ -114,7 +114,7 @@ GsfInput * gsf_input_uncompress (GsfInput *src);
*/ */
}; /* class CStorageStream */ }; /* class CStorageStream */
#endif
} /* namespace PIPELINE */ } /* namespace PIPELINE */
#endif /* #ifndef PIPELINE_STORAGE_STREAM_H */ #endif /* #ifndef PIPELINE_STORAGE_STREAM_H */

Loading…
Cancel
Save