/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library 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 * OpenSceneGraph Public License for more details. */ // Written by Wang Rui, (C) 2010 #ifndef OSGDB__SERIALIZER #define OSGDB__SERIALIZER #include #include #include #include #include #include #include namespace osgDB { #ifndef OBJECT_CAST #define OBJECT_CAST static_cast #endif class IntLookup { public: typedef int Value; typedef std::map StringToValue; typedef std::map ValueToString; IntLookup() {} unsigned int size() const { return _stringToValue.size(); } void add( const char* str, Value value ) { if ( _valueToString.find(value)!=_valueToString.end() ) { osg::notify(osg::WARN) << "Duplicate enum value " << value << " with old string: " << _valueToString[value] << " and new string: " << str << std::endl; } _valueToString[value] = str; _stringToValue[str] = value; } Value getValue( const char* str ) { StringToValue::iterator itr = _stringToValue.find(str); if ( itr==_stringToValue.end() ) { Value value; std::stringstream stream; stream << str; stream >> value; _stringToValue[str] = value; return value; } return itr->second; } const std::string& getString( Value value ) { ValueToString::iterator itr = _valueToString.find(value); if ( itr==_valueToString.end() ) { std::string str; std::stringstream stream; stream << value; stream >> str; _valueToString[value] = str; return _valueToString[value]; } return itr->second; } protected: StringToValue _stringToValue; ValueToString _valueToString; }; class UserLookupTableProxy { public: typedef void (*AddValueFunc)( IntLookup* lookup ); UserLookupTableProxy( AddValueFunc func ) { if ( func ) (*func)(&_lookup); } IntLookup _lookup; }; #define BEGIN_USER_TABLE(NAME, CLASS) \ static void add_user_value_func_##NAME(osgDB::IntLookup*); \ static osgDB::UserLookupTableProxy s_user_lookup_table_##NAME(&add_user_value_func_##NAME); \ static void add_user_value_func_##NAME(osgDB::IntLookup* lookup) { typedef CLASS MyClass #define ADD_USER_VALUE(VALUE) lookup->add(#VALUE, MyClass::VALUE) #define END_USER_TABLE() } #define USER_READ_FUNC(NAME, FUNCNAME) \ static int FUNCNAME(osgDB::InputStream& is) { \ int value; if (is.isBinary()) is >> value; \ else { std::string str; is >> str; \ value = (s_user_lookup_table_##NAME)._lookup.getValue(str.c_str()); } \ return value; } #define USER_WRITE_FUNC(NAME, FUNCNAME) \ static void FUNCNAME(osgDB::OutputStream& os, int value) { \ if (os.isBinary()) os << value; \ else os << (s_user_lookup_table_##NAME)._lookup.getString(value); } \ class BaseSerializer : public osg::Referenced { public: BaseSerializer() {} virtual bool read( InputStream&, osg::Object& ) = 0; virtual bool write( OutputStream&, const osg::Object& ) = 0; virtual const std::string& getName() const = 0; }; template class UserSerializer : public BaseSerializer { public: typedef bool (*Checker)( const C& ); typedef bool (*Reader)( InputStream&, C& ); typedef bool (*Writer)( OutputStream&, const C& ); UserSerializer( const char* name, Checker cf, Reader rf, Writer wf ) : _name(name), _checker(cf), _reader(rf), _writer(wf) {} virtual bool read( InputStream& is, osg::Object& obj ) { C& object = OBJECT_CAST(obj); if ( is.isBinary() ) { bool ok = false; is >> ok; if ( !ok ) return true; } else { if ( !is.matchString(_name) ) return true; } return (*_reader)(is, object); } virtual bool write( OutputStream& os, const osg::Object& obj ) { const C& object = OBJECT_CAST(obj); bool ok = (*_checker)(object); if ( os.isBinary() ) { os << ok; if ( !ok ) return true; } else { if ( !ok ) return true; os << PROPERTY(_name.c_str()); } return (*_writer)(os, object); } virtual const std::string& getName() const { return _name; } protected: std::string _name; Checker _checker; public: Reader _reader; Writer _writer; }; template class TemplateSerializer : public BaseSerializer { public: TemplateSerializer( const char* name ) : _name(name) {} virtual bool read( InputStream& is, osg::Object& obj ) = 0; virtual bool write( OutputStream& os, const osg::Object& obj ) = 0; virtual const std::string& getName() const { return _name; } protected: std::string _name; P _defaultValue; }; template class PropByValSerializer : public TemplateSerializer

{ public: typedef TemplateSerializer

ParentType; typedef P (C::*Getter)() const; typedef void (C::*Setter)( P ); PropByValSerializer( const char* name, P def, Getter gf, Setter sf, bool useHex=false ) : ParentType(name), _getter(gf), _setter(sf), _useHex(useHex) { ParentType::_defaultValue = def; } virtual bool read( InputStream& is, osg::Object& obj ) { C& object = OBJECT_CAST(obj); P value; if ( is.isBinary() ) { is >> value; if ( ParentType::_defaultValue!=value ) (object.*_setter)( value ); } else if ( is.matchString(ParentType::_name) ) { if ( _useHex ) is >> std::hex; is >> value; if ( _useHex ) is >> std::dec; (object.*_setter)( value ); } return true; } virtual bool write( OutputStream& os, const osg::Object& obj ) { const C& object = OBJECT_CAST(obj); P value = (object.*_getter)(); if ( os.isBinary() ) { os << value; } else if ( ParentType::_defaultValue!=value ) { os << PROPERTY((ParentType::_name).c_str()); if ( _useHex ) os << std::hex; os << value; if ( _useHex ) os << std::dec; os << std::endl; } return true; } public: Getter _getter; Setter _setter; protected: bool _useHex; }; template class PropByRefSerializer : public TemplateSerializer

{ public: typedef TemplateSerializer

ParentType; typedef const P& CP; typedef CP (C::*Getter)() const; typedef void (C::*Setter)( CP ); PropByRefSerializer( const char* name, CP def, Getter gf, Setter sf ) : ParentType(name), _getter(gf), _setter(sf) { ParentType::_defaultValue = def; } virtual bool read( InputStream& is, osg::Object& obj ) { C& object = OBJECT_CAST(obj); P value; if ( is.isBinary() ) { is >> value; if ( ParentType::_defaultValue!=value ) (object.*_setter)( value ); } else if ( is.matchString(ParentType::_name) ) { is >> value; (object.*_setter)( value ); } return true; } virtual bool write( OutputStream& os, const osg::Object& obj ) { const C& object = OBJECT_CAST(obj); CP value = (object.*_getter)(); if ( os.isBinary() ) { os << value; } else if ( ParentType::_defaultValue!=value ) { os << PROPERTY((ParentType::_name).c_str()) << value << std::endl; } return true; } public: Getter _getter; Setter _setter; }; template class MatrixSerializer : public TemplateSerializer { public: typedef TemplateSerializer ParentType; typedef const osg::Matrix& (C::*Getter)() const; typedef void (C::*Setter)( const osg::Matrix& ); MatrixSerializer( const char* name, const osg::Matrix& def, Getter gf, Setter sf ) : ParentType(name), _getter(gf), _setter(sf) { ParentType::_defaultValue = def; } virtual bool read( InputStream& is, osg::Object& obj ) { C& object = OBJECT_CAST(obj); osg::Matrix value; if ( is.isBinary() ) { readMatrixImplementation( is, value ); if ( ParentType::_defaultValue!=value ) (object.*_setter)( value ); } else if ( is.matchString(ParentType::_name) ) { readMatrixImplementation( is, value ); (object.*_setter)( value ); } return true; } virtual bool write( OutputStream& os, const osg::Object& obj ) { const C& object = OBJECT_CAST(obj); const osg::Matrix& value = (object.*_getter)(); if ( os.isBinary() ) { OSG_NOTICE<<"MatrixSerializer::write() binary"<