OpenSceneGraph/include/osgDB/StreamOperator
Robert Osfield 4044fd5a74 From Wang Rui, "The file attached includes two new features for the serialization IO functionality. First, custom serializer version control should work now, just by defining a new REGISTER_CUSTOM_OBJECT_WRAPPER macro. For example:
// A custom class
namespace CustomDomain {

class MyGroup : public osg::Group
{
public:
    META_Node( CustomDomain, MyGroup );

    void setMyName( const std::string& n );
    const std::string& getMyName() const;

    void setMyID( int id );
    int getMyID() const;

    ...
};

}

// The serialization wrapper using a custom domain name
REGISTER_CUSTOM_OBJECT_WRAPPER( MyDomain,
                                CustomDomain_MyGroup,
                                new CustomDomain::MyGroup,
                                CustomDomain::MyGroup,
                                "osg::Object osg::Node osg::Group CustomDomain::MyGroup" )
{
    ADD_STRING_SERIALIZER( MyName, std::string() );
    {
        UPDATE_TO_VERSION_SCOPED( 1 );  // Updated for a new domain version
        ADD_INT_SERIALIZER( MyID, 0 );
    }
}

Save the class instance as follows:
osgDB::writeNodeFile( *myGroup, "serializer_test.osgt", new osgDB::Options("CustomDomains=MyDomain:1") );

The output file will include the domain version definition and all the class data, and can be read back. We can also force setting the domain version by the CustomDomains option while reading the saved files. If we save the class instance without any options, MyID will be ignored because the default domain version is 0.

This may help third-party libraries like osgEarth to maintain their own serializers without regarding to the OSG soversion changes.

Another feature added is a more robust binary format, which in fact adds a size-offset at each block's beginning. When there are problems or unsupported data types while reading, we can now directly jump to the block end indicated by the offset value. So a .osgb file will automatically ignore bad data and read remains as normal (at present it will fail at all). This feature will not break the backward compatibility, and can be disabled by setting "RobustBinaryFormat=false" while writing out.

Hope these changes can work smoothly with present and future community projects. Maybe we should also consider have an osgserializer example to test and demonstrate all things we can do now."
2013-06-24 08:48:55 +00:00

138 lines
4.8 KiB
Plaintext

#ifndef OSGDB_STREAMOPERATOR
#define OSGDB_STREAMOPERATOR
#include <iostream>
#include <sstream>
#include <osg/Referenced>
#include <osgDB/Export>
#include <osgDB/DataTypes>
namespace osgDB
{
// forward declare
class InputStream;
class OSGDB_EXPORT OutputIterator : public osg::Referenced
{
public:
OutputIterator() : _out(0), _supportBinaryBrackets(false) {}
virtual ~OutputIterator() {}
void setStream( std::ostream* ostream ) { _out = ostream; }
std::ostream* getStream() { return _out; }
const std::ostream* getStream() const { return _out; }
void setSupportBinaryBrackets( bool b ) { _supportBinaryBrackets = b; }
bool getSupportBinaryBrackets() const { return _supportBinaryBrackets; }
virtual bool isBinary() const = 0;
virtual void writeBool( bool b ) = 0;
virtual void writeChar( char c ) = 0;
virtual void writeUChar( unsigned char c ) = 0;
virtual void writeShort( short s ) = 0;
virtual void writeUShort( unsigned short s ) = 0;
virtual void writeInt( int i ) = 0;
virtual void writeUInt( unsigned int i ) = 0;
virtual void writeLong( long l ) = 0;
virtual void writeULong( unsigned long l ) = 0;
virtual void writeFloat( float f ) = 0;
virtual void writeDouble( double d ) = 0;
virtual void writeString( const std::string& s ) = 0;
virtual void writeStream( std::ostream& (*fn)(std::ostream&) ) = 0;
virtual void writeBase( std::ios_base& (*fn)(std::ios_base&) ) = 0;
virtual void writeGLenum( const ObjectGLenum& value ) = 0;
virtual void writeProperty( const ObjectProperty& prop ) = 0;
virtual void writeMark( const ObjectMark& mark ) = 0;
virtual void writeCharArray( const char* s, unsigned int size ) = 0;
virtual void writeWrappedString( const std::string& str ) = 0;
virtual void flush() { _out->flush(); }
protected:
// Return true if the manipulator is std::endl
bool isEndl( std::ostream& (*fn)(std::ostream&) )
{
#ifdef __sun
// What a mess, but solaris does not like taking the address below
std::stringstream ss;
ss << fn;
std::string s = ss.str();
return !s.empty() && s[0] == '\n';
#else
return fn==static_cast<std::ostream& (*)(std::ostream&)>(std::endl);
#endif
}
std::ostream* _out;
bool _supportBinaryBrackets;
};
class OSGDB_EXPORT InputIterator : public osg::Referenced
{
public:
InputIterator() : _in(0), _inputStream(0), _byteSwap(0), _supportBinaryBrackets(false), _failed(false) {}
virtual ~InputIterator() {}
void setStream( std::istream* istream ) { _in = istream; }
std::istream* getStream() { return _in; }
const std::istream* getStream() const { return _in; }
void setInputStream( InputStream* inputStream) { _inputStream = inputStream; }
InputStream* getInputStream() { return _inputStream; }
const InputStream* getInputStream() const { return _inputStream; }
void setByteSwap(int byteSwap) { _byteSwap = byteSwap; }
int getByteSwap() const { return _byteSwap; }
void setSupportBinaryBrackets( bool b ) { _supportBinaryBrackets = b; }
bool getSupportBinaryBrackets() const { return _supportBinaryBrackets; }
void checkStream() const { if (_in->rdstate()&_in->failbit) _failed = true; }
bool isFailed() const { return _failed; }
virtual bool isBinary() const = 0;
virtual void readBool( bool& b ) = 0;
virtual void readChar( char& c ) = 0;
virtual void readSChar( signed char& c ) = 0;
virtual void readUChar( unsigned char& c ) = 0;
virtual void readShort( short& s ) = 0;
virtual void readUShort( unsigned short& s ) = 0;
virtual void readInt( int& i ) = 0;
virtual void readUInt( unsigned int& i ) = 0;
virtual void readLong( long& l ) = 0;
virtual void readULong( unsigned long& l ) = 0;
virtual void readFloat( float& f ) = 0;
virtual void readDouble( double& d ) = 0;
virtual void readString( std::string& s ) = 0;
virtual void readStream( std::istream& (*fn)(std::istream&) ) = 0;
virtual void readBase( std::ios_base& (*fn)(std::ios_base&) ) = 0;
virtual void readGLenum( ObjectGLenum& value ) = 0;
virtual void readProperty( ObjectProperty& prop ) = 0;
virtual void readMark( ObjectMark& mark ) = 0;
virtual void readCharArray( char* s, unsigned int size ) = 0;
virtual void readWrappedString( std::string& str ) = 0;
virtual bool matchString( const std::string& /*str*/ ) { return false; }
virtual void advanceToCurrentEndBracket() {}
void throwException( const std::string& msg );
void readComponentArray( char* s, unsigned int numElements, unsigned int numComponentsPerElements, unsigned int componentSizeInBytes);
protected:
std::istream* _in;
osgDB::InputStream* _inputStream;
int _byteSwap;
bool _supportBinaryBrackets;
mutable bool _failed;
};
}
#endif