2006-07-18 23:21:48 +08:00
|
|
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
2005-04-29 18:06:50 +08:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
//osgIntrospection - Copyright (C) 2005 Marco Jez
|
|
|
|
|
2004-12-09 13:28:20 +08:00
|
|
|
#ifndef OSGINTROSPECTION_READERWRITER_
|
|
|
|
#define OSGINTROSPECTION_READERWRITER_
|
|
|
|
|
|
|
|
#include <osgIntrospection/Value>
|
|
|
|
#include <osgIntrospection/Type>
|
|
|
|
#include <osgIntrospection/Exceptions>
|
|
|
|
#include <osgIntrospection/variant_cast>
|
|
|
|
|
|
|
|
#include <osg/Vec2>
|
|
|
|
#include <osg/Vec3>
|
|
|
|
#include <osg/Vec4>
|
|
|
|
#include <osg/ref_ptr>
|
|
|
|
|
|
|
|
#include <iostream>
|
2006-09-01 20:52:15 +08:00
|
|
|
#include <sstream>
|
2004-12-09 13:28:20 +08:00
|
|
|
|
|
|
|
|
|
|
|
namespace osgIntrospection
|
|
|
|
{
|
|
|
|
|
2005-03-14 17:28:31 +08:00
|
|
|
/// This is the base class for reader/writer objects. A ReaderWriter's
|
|
|
|
/// purpose is to provide the means for writing the content of a Value
|
|
|
|
/// object to a stream and for reading it back. Descendants can either
|
|
|
|
/// be specialized for just one data type or they can handle several
|
|
|
|
/// types, that's up to the implementor. A derived class is not required
|
|
|
|
/// to support all streaming operations (text write, text read, bin write
|
|
|
|
/// and bin read), it can implement just some of them, although full
|
|
|
|
/// support is strongly encouraged.
|
|
|
|
class ReaderWriter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
class Options
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Options(): fno_(false) {}
|
|
|
|
virtual ~Options() {}
|
|
|
|
|
|
|
|
bool getForceNumericOutput() const { return fno_; }
|
|
|
|
void setForceNumericOutput(bool fno) { fno_ = fno; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool fno_;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Writes a textual representation of the value's content to a stream.
|
2007-02-13 01:14:46 +08:00
|
|
|
virtual std::ostream &writeTextValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_WRITE, v.getType().getExtendedTypeInfo()); }
|
2005-03-14 17:28:31 +08:00
|
|
|
|
|
|
|
/// Reads a textual representation of the value's content from a stream.
|
2007-02-13 01:14:46 +08:00
|
|
|
virtual std::istream &readTextValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getExtendedTypeInfo()); }
|
2005-03-14 17:28:31 +08:00
|
|
|
|
2006-09-01 20:52:15 +08:00
|
|
|
/// Writes a textual representation of the value's content to a stream.
|
|
|
|
virtual std::wostream &writeTextValue(std::wostream & wos, const Value& v, const Options* op = 0) const { std::ostringstream os; writeTextValue(os, v, op); wos << os; return (wos);}
|
|
|
|
|
|
|
|
/// Reads a textual representation of the value's content from a stream.
|
2007-02-13 01:14:46 +08:00
|
|
|
virtual std::wistream &readTextValue(std::wistream& , Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getExtendedTypeInfo()); }
|
2006-09-01 20:52:15 +08:00
|
|
|
|
2005-03-14 17:28:31 +08:00
|
|
|
/// Writes a binary representation of the value's content to a stream.
|
2007-02-13 01:14:46 +08:00
|
|
|
virtual std::ostream &writeBinaryValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_WRITE, v.getType().getExtendedTypeInfo()); }
|
2005-03-14 17:28:31 +08:00
|
|
|
|
|
|
|
/// Reads a binary representation of the value's content from a stream.
|
2007-02-13 01:14:46 +08:00
|
|
|
virtual std::istream &readBinaryValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_READ, v.getType().getExtendedTypeInfo()); }
|
2005-03-14 17:28:31 +08:00
|
|
|
|
|
|
|
/// Virtual destructor.
|
|
|
|
virtual ~ReaderWriter() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// This class template provides basic default streaming capabilities
|
|
|
|
/// for all types that define streaming operators (<< and >>). Most of
|
|
|
|
/// the standard types are able to be read and written this way, so the
|
|
|
|
/// StdReaderWriter template can be a convenient default for several
|
|
|
|
/// types. The binary representation is a raw copy of the memory content.
|
|
|
|
///
|
|
|
|
/// TO-DO: improve binary streaming and avoid arch dependency.
|
|
|
|
///
|
|
|
|
template<typename T>
|
|
|
|
class StdReaderWriter: public ReaderWriter
|
|
|
|
{
|
|
|
|
public:
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeTextValue(std::ostream &os, const Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
return (os << variant_cast<T>(v));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readTextValue(std::istream &is, Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
if (v.isEmpty()) v = Value(T());
|
|
|
|
return (is >> variant_cast<T &>(v));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readBinaryValue(std::istream &is, Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
if (v.isEmpty()) v = Value(T());
|
|
|
|
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2006-09-01 20:52:15 +08:00
|
|
|
template<typename T>
|
|
|
|
class StdWReaderWriter: public ReaderWriter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual std::wostream &writeTextValue(std::wostream &wos, const Value& v, const Options * = 0) const
|
|
|
|
{
|
|
|
|
return (wos << variant_cast<T>(v));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::wistream &readTextValue(std::wistream &wis, Value& v, const Options * = 0) const
|
|
|
|
{
|
|
|
|
if (v.isEmpty()) v = Value(T());
|
|
|
|
return (wis >> variant_cast<T &>(v));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value& v, const Options * = 0) const
|
|
|
|
{
|
|
|
|
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual std::istream &readBinaryValue(std::istream &is, Value& v, const Options * = 0) const
|
|
|
|
{
|
|
|
|
if (v.isEmpty()) v = Value(T());
|
|
|
|
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2005-03-14 17:28:31 +08:00
|
|
|
/// This ReaderWriter can be used to read and write enumeration values.
|
|
|
|
/// The textual representation will be the enum label, if found, or the
|
|
|
|
/// numerical value. The binary representation doesn't take label names
|
|
|
|
/// into account.
|
|
|
|
template<typename T>
|
|
|
|
class EnumReaderWriter: public ReaderWriter
|
|
|
|
{
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeTextValue(std::ostream &os, const Value& v, const Options *options = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
int numeric = static_cast<int>(variant_cast<T>(v));
|
|
|
|
|
|
|
|
if (!options || !options->getForceNumericOutput())
|
|
|
|
{
|
2005-04-29 19:19:58 +08:00
|
|
|
const Type& type = v.getType();
|
|
|
|
const EnumLabelMap& elm = type.getEnumLabels();
|
2005-03-14 17:28:31 +08:00
|
|
|
EnumLabelMap::const_iterator i = elm.find(numeric);
|
|
|
|
if (i != elm.end())
|
|
|
|
{
|
|
|
|
os << i->second;
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::vector<std::string> labels;
|
|
|
|
|
|
|
|
// it could be a bitmask
|
|
|
|
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
|
|
|
{
|
|
|
|
if (i->first != 0 && ((i->first & numeric) == i->first))
|
|
|
|
{
|
|
|
|
numeric ^= i->first;
|
|
|
|
labels.push_back(i->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check whether all bits were discovered
|
|
|
|
if (numeric == 0)
|
|
|
|
{
|
|
|
|
for (std::vector<std::string>::const_iterator i=labels.begin(); i!=labels.end(); ++i)
|
|
|
|
{
|
|
|
|
os << *i;
|
|
|
|
if ((i+1) != labels.end()) os << " | ";
|
|
|
|
}
|
|
|
|
return os;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return os << numeric;
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readTextValue(std::istream &is, Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
if (v.isEmpty()) v = Value(T());
|
|
|
|
|
|
|
|
int i;
|
|
|
|
if (is >> i)
|
|
|
|
{
|
|
|
|
variant_cast<T &>(v) = static_cast<T>(i);
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
|
|
|
|
is.clear();
|
|
|
|
|
|
|
|
std::string s;
|
|
|
|
if (is >> s)
|
|
|
|
{
|
2005-04-29 19:19:58 +08:00
|
|
|
const Type& type = v.getType();
|
|
|
|
const EnumLabelMap& elm = type.getEnumLabels();
|
2005-03-14 17:28:31 +08:00
|
|
|
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
|
|
|
{
|
|
|
|
if (i->second.compare(s) == 0)
|
|
|
|
{
|
|
|
|
variant_cast<T &>(v) = static_cast<T>(i->first);
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readBinaryValue(std::istream &is, Value& v, const Options * = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
if (v.isEmpty())
|
|
|
|
v = Value(T());
|
|
|
|
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/// This is a ReaderWriter class that can be used to read and write
|
|
|
|
/// pointer values. Note: template parameter T must be a pointer!
|
|
|
|
template<typename T>
|
|
|
|
class PtrReaderWriter: public ReaderWriter
|
|
|
|
{
|
|
|
|
public:
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeTextValue(std::ostream &os, const Value& v, const Options* = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
return (os << (void*)variant_cast<T>(v));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readTextValue(std::istream &is, Value& v, const Options* = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
void *ptr;
|
|
|
|
is >> ptr;
|
|
|
|
v = Value(T(ptr));
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value& v, const Options* = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
|
|
|
}
|
|
|
|
|
2005-04-29 19:19:58 +08:00
|
|
|
virtual std::istream &readBinaryValue(std::istream &is, Value& v, const Options* = 0) const
|
2005-03-14 17:28:31 +08:00
|
|
|
{
|
|
|
|
T ptr;
|
|
|
|
is.read(reinterpret_cast<char *>(&ptr), sizeof(T));
|
|
|
|
v = Value(ptr);
|
|
|
|
return is;
|
|
|
|
}
|
|
|
|
};
|
2004-12-09 13:28:20 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|