From Mike Wittman, "These changes add support for reflection of reference and const reference type representations via osgIntrospection::Type. This covers just the static type information; the dynamic behavior via Type::createInstance/Type::InvokeMethod should not be affected."

This commit is contained in:
Robert Osfield
2007-02-12 17:14:46 +00:00
parent 4ed84daf2f
commit a725e0af7d
15 changed files with 970 additions and 887 deletions

View File

@@ -119,6 +119,10 @@ SOURCE=..\..\src\osgIntrospection\Reflection.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgIntrospection\Reflector.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgIntrospection\Type.cpp
# End Source File
# Begin Source File

View File

@@ -66,7 +66,7 @@ void print_types()
for (TypeList::const_iterator i=types.begin(); i!=types.end(); ++i)
{
// ignore pointer types and undefined types
if (!(*i)->isDefined() || (*i)->isPointer())
if (!(*i)->isDefined() || (*i)->isPointer() || (*i)->isReference())
continue;
// print the type name

View File

@@ -56,7 +56,7 @@ namespace osgIntrospection
virtual bool isLessThanOrEqualTo(const Value& , const Value& ) const
{
throw ComparisonOperatorNotSupportedException(typeid(T), "less than or equal to");
throw ComparisonOperatorNotSupportedException(extended_typeid<T>(), "less than or equal to");
}
virtual ~PartialOrderComparator() {}

View File

@@ -16,7 +16,7 @@
#define OSGINTROSPECTION_EXCEPTIONS_
#include <string>
#include <typeinfo>
#include <osgIntrospection/ExtendedTypeInfo>
namespace osgIntrospection
{
@@ -38,7 +38,7 @@ namespace osgIntrospection
struct TypeNotDefinedException: public ReflectionException
{
TypeNotDefinedException(const std::type_info& ti)
TypeNotDefinedException(const ExtendedTypeInfo &ti)
: ReflectionException("type `" + std::string(ti.name()) + "' is declared but not defined")
{
}
@@ -46,7 +46,7 @@ namespace osgIntrospection
struct TypeIsAbstractException: public ReflectionException
{
TypeIsAbstractException(const std::type_info& ti)
TypeIsAbstractException(const ExtendedTypeInfo &ti)
: ReflectionException("cannot create instances of abstract type `" + std::string(ti.name()) + "'")
{
}
@@ -54,7 +54,7 @@ namespace osgIntrospection
struct ConstructorNotFoundException: public ReflectionException
{
ConstructorNotFoundException(const std::type_info& ti)
ConstructorNotFoundException(const ExtendedTypeInfo &ti)
: ReflectionException("could not find a suitable constructor in type `" + std::string(ti.name()) + "'")
{
}
@@ -136,13 +136,13 @@ namespace osgIntrospection
BINARY_READ
};
StreamingNotSupportedException(OperationType op, const std::type_info& type)
StreamingNotSupportedException(OperationType op, const ExtendedTypeInfo &type)
: ReflectionException(build_msg(op, type))
{
}
private:
std::string build_msg(OperationType op, const std::type_info& type)
std::string build_msg(OperationType op, const ExtendedTypeInfo &type)
{
std::string opstr;
switch (op)
@@ -160,7 +160,7 @@ namespace osgIntrospection
struct TypeConversionException: public ReflectionException
{
TypeConversionException(const std::type_info& type1, const std::type_info& type2)
TypeConversionException(const ExtendedTypeInfo &type1, const ExtendedTypeInfo &type2)
: ReflectionException("cannot convert from type `" + std::string(type1.name()) + "' to type `" + std::string(type2.name()) + "'")
{
}
@@ -220,7 +220,7 @@ namespace osgIntrospection
struct ComparisonNotPermittedException: ReflectionException
{
ComparisonNotPermittedException(const std::type_info& ti)
ComparisonNotPermittedException(const ExtendedTypeInfo &ti)
: ReflectionException("comparison not permitted on type `" + std::string(ti.name()) + "'")
{
}
@@ -228,7 +228,7 @@ namespace osgIntrospection
struct ComparisonOperatorNotSupportedException: ReflectionException
{
ComparisonOperatorNotSupportedException(const std::type_info& ti, const std::string& op)
ComparisonOperatorNotSupportedException(const ExtendedTypeInfo &ti, const std::string& op)
: ReflectionException("comparison operator `" + op + "' is not supported on type `" + std::string(ti.name()) + "'")
{
}

View File

@@ -57,22 +57,22 @@ namespace osgIntrospection
};
/// Writes a textual representation of the value's content to a stream.
virtual std::ostream &writeTextValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_WRITE, v.getType().getStdTypeInfo()); }
virtual std::ostream &writeTextValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_WRITE, v.getType().getExtendedTypeInfo()); }
/// Reads a textual representation of the value's content from a stream.
virtual std::istream &readTextValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getStdTypeInfo()); }
virtual std::istream &readTextValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getExtendedTypeInfo()); }
/// 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.
virtual std::wistream &readTextValue(std::wistream& , Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getStdTypeInfo()); }
virtual std::wistream &readTextValue(std::wistream& , Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::TEXT_READ, v.getType().getExtendedTypeInfo()); }
/// Writes a binary representation of the value's content to a stream.
virtual std::ostream &writeBinaryValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_WRITE, v.getType().getStdTypeInfo()); }
virtual std::ostream &writeBinaryValue(std::ostream &, const Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_WRITE, v.getType().getExtendedTypeInfo()); }
/// Reads a binary representation of the value's content from a stream.
virtual std::istream &readBinaryValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_READ, v.getType().getStdTypeInfo()); }
virtual std::istream &readBinaryValue(std::istream &, Value& v, const Options* = 0) const { throw StreamingNotSupportedException(StreamingNotSupportedException::BINARY_READ, v.getType().getExtendedTypeInfo()); }
/// Virtual destructor.
virtual ~ReaderWriter() {}

View File

@@ -16,6 +16,7 @@
#define OSGINTROSPECTION_REFLECTION_
#include <osgIntrospection/Export>
#include <osgIntrospection/ExtendedTypeInfo>
#include <typeinfo>
#include <map>
@@ -24,7 +25,7 @@
/// This macro emulates the behavior of the standard typeid operator,
/// returning the Type object associated to the type of the given
/// expression.
#define typeof(expr) osgIntrospection::Reflection::getType(typeid(expr))
#define typeof(type) osgIntrospection::Reflection::getType(extended_typeid<type>())
namespace osgIntrospection
{
@@ -34,20 +35,9 @@ namespace osgIntrospection
typedef std::vector<const Converter* > ConverterList;
/// This predicate compares two instances of std::type_info for equality.
/// Note that we can't rely on default pointer comparison because it is
/// not guaranteed that &typeid(T) always returns the same pointer for a
/// given T (thanks Andrew Koenig).
struct TypeInfoCmp
{
bool operator()(const std::type_info* t1, const std::type_info* t2) const
{
return t1->before(*t2) != 0;
}
};
/// A map of types, indexed by their associated type_info structure.
typedef std::map<const std::type_info* , Type* , TypeInfoCmp> TypeMap;
/// A map of types, indexed by their associated ExtendedTypeInfo
/// structure.
typedef std::map<ExtendedTypeInfo, Type*> TypeMap;
/// This class provides basic reflection services such as registration
@@ -55,13 +45,13 @@ namespace osgIntrospection
class OSGINTROSPECTION_EXPORT Reflection
{
public:
/// Returns the Type object associated to the given type_info
/// structure. If the type hasn't been created yet it is
/// automatically created and added to the global type map.
/// Please note that such type will have the status of
/// Returns the Type object associated to the given
/// ExtendedTypeInfo structure. If the type hasn't been created
/// yet it is automatically created and added to the global type
/// map. Please note that such type will have the status of
/// "declared", you still need to give details about it through
/// a Reflector class before you can query it.
static const Type& getType(const std::type_info& ti);
static const Type& getType(const ExtendedTypeInfo &ti);
/// Finds a Type object given its qualified name, which must
/// be identical to the qualified name returned by that Type's
@@ -98,8 +88,8 @@ namespace osgIntrospection
};
static StaticData& getOrCreateStaticData();
static Type* registerType(const std::type_info& ti);
static Type* getOrRegisterType(const std::type_info& ti, bool replace_if_defined = false);
static Type* registerType(const ExtendedTypeInfo &ti);
static Type* getOrRegisterType(const ExtendedTypeInfo &ti, bool replace_if_defined = false);
static void registerConverter(const Type& source, const Type& dest, const Converter* cvt);
private:

File diff suppressed because it is too large Load Diff

View File

@@ -48,8 +48,9 @@ namespace osgIntrospection
/// methods.
///
/// NOTE: when you create a Reflector for type T, it will automatically
/// create descriptions for types T* and const T*. You should NEVER
/// create reflectors for pointer types explicitely.
/// create descriptions for types T*, const T*, T&, and const T&. You
/// should NEVER create reflectors for pointer or reference types
/// explicitly.
///
template<typename T>
class Reflector
@@ -128,6 +129,7 @@ namespace osgIntrospection
};
void init();
void init_reference_types();
static std::string purify(const std::string& s);
static void split_qualified_name(const std::string& q, std::string& n, std::string& ns);
@@ -712,7 +714,7 @@ namespace osgIntrospection
template<typename T>
Reflector<T>::Reflector(const std::string& name, const std::string& ns, bool abstract)
: _type(Reflection::getOrRegisterType(typeid(T), true))
: _type(Reflection::getOrRegisterType(extended_typeid<T>(), true))
{
if (!_type->_name.empty())
_type->_aliases.push_back(ns.empty()? purify(name): purify(ns+"::"+name));
@@ -727,7 +729,7 @@ namespace osgIntrospection
template<typename T>
Reflector<T>::Reflector(const std::string& qname, bool abstract)
: _type(Reflection::getOrRegisterType(typeid(T), true))
: _type(Reflection::getOrRegisterType(extended_typeid<T>(), true))
{
if (!_type->_name.empty())
_type->_aliases.push_back(purify(qname));
@@ -745,7 +747,7 @@ namespace osgIntrospection
// pointer type
if (!_type->_pointed_type)
{
Type* ptype = Reflection::getOrRegisterType(typeid(T*), true);
Type* ptype = Reflection::getOrRegisterType(extended_typeid<T*>(), true);
ptype->_name = _type->_name;
ptype->_namespace = _type->_namespace;
ptype->_pointed_type = _type;
@@ -758,7 +760,7 @@ namespace osgIntrospection
// const pointer type
if (!_type->_pointed_type || !_type->_is_const)
{
Type* cptype = Reflection::getOrRegisterType(typeid(const T*), true);
Type* cptype = Reflection::getOrRegisterType(extended_typeid<const T*>(), true);
cptype->_name = _type->_name;
cptype->_namespace = _type->_namespace;
cptype->_is_const = true;
@@ -769,9 +771,39 @@ namespace osgIntrospection
cptype->_cmp = new TotalOrderComparator<const T*>();
}
init_reference_types();
_type->_is_defined = true;
}
template<typename T>
void Reflector<T>::init_reference_types()
{
// reference type
if (!_type->_referenced_type)
{
Type* ptype = Reflection::getOrRegisterType(extended_typeid<T&>(), true);
ptype->_name = _type->_name;
ptype->_namespace = _type->_namespace;
ptype->_referenced_type = _type;
ptype->_is_defined = true;
}
// const reference type
if (!_type->_referenced_type || !_type->_is_const)
{
Type* cptype = Reflection::getOrRegisterType(extended_typeid<const T&>(), true);
cptype->_name = _type->_name;
cptype->_namespace = _type->_namespace;
cptype->_is_const = true;
cptype->_referenced_type = _type;
cptype->_is_defined = true;
}
}
template<>
void Reflector<void>::init_reference_types();
template<typename T>
std::string Reflector<T>::purify(const std::string& s)
{

View File

@@ -18,6 +18,7 @@
#include <osgIntrospection/Exceptions>
#include <osgIntrospection/Value>
#include <osgIntrospection/CustomAttributeProvider>
#include <osgIntrospection/ExtendedTypeInfo>
#include <string>
#include <typeinfo>
@@ -71,6 +72,10 @@ namespace osgIntrospection
/// to this Type.
inline const std::type_info& getStdTypeInfo() const;
/// Returns a reference to the ExtendedTypeInfo associated
/// to this Type.
inline ExtendedTypeInfo getExtendedTypeInfo() const;
/// Returns true if this Type is defined, false if it's just
/// declared. See class Reflector if you want to create a new Type.
inline bool isDefined() const;
@@ -141,6 +146,21 @@ namespace osgIntrospection
/// the object returned is typeof(void).
inline const Type& getPointedType() const;
/// Returns true if the reflected type is a reference, false otherwise.
inline bool isReference() const;
/// Returns true if the reflected type is a reference AND it is const,
/// false otherwise.
inline bool isConstReference() const;
/// Returns true if the reflected type is a reference AND it is not
/// const, false otherwise.
inline bool isNonConstReference() const;
/// Returns the referenced type. If the reflected type is not a reference,
/// the object returned is typeof(void).
inline const Type& getReferencedType() const;
/// Returns the list of properties defined for this type. The list
/// does not include properties inherited from base types.
inline const PropertyInfoList& getProperties() const;
@@ -221,11 +241,12 @@ namespace osgIntrospection
inline Value createInstance() const;
protected:
Type(const std::type_info& ti)
Type(const ExtendedTypeInfo &ti)
: _ti(ti),
_is_const(false),
_is_abstract(false),
_pointed_type(0),
_referenced_type(0),
_is_defined(false),
_rw(0),
_cmp(0)
@@ -244,7 +265,7 @@ namespace osgIntrospection
Type(const Type& copy): CustomAttributeProvider(copy), _ti(copy._ti) {}
const std::type_info& _ti;
ExtendedTypeInfo _ti;
std::string _name;
std::string _namespace;
@@ -254,6 +275,7 @@ namespace osgIntrospection
bool _is_const;
bool _is_abstract;
const Type* _pointed_type;
const Type* _referenced_type;
ConstructorInfoList _cons;
PropertyInfoList _props;
@@ -310,6 +332,11 @@ namespace osgIntrospection
}
inline const std::type_info& Type::getStdTypeInfo() const
{
return _ti.getStdTypeInfo();
}
inline ExtendedTypeInfo Type::getExtendedTypeInfo() const
{
return _ti;
}
@@ -339,6 +366,8 @@ namespace osgIntrospection
qname.append(_name);
if (_pointed_type)
qname.append(" *");
else if (_referenced_type)
qname.append(" &");
return qname;
}
@@ -370,6 +399,18 @@ namespace osgIntrospection
return !_is_const && _pointed_type;
}
inline bool Type::isConstReference() const
{
check_defined();
return _is_const && _referenced_type;
}
inline bool Type::isNonConstReference() const
{
check_defined();
return !_is_const && _referenced_type;
}
inline bool Type::isAbstract() const
{
check_defined();
@@ -406,9 +447,15 @@ namespace osgIntrospection
return _pointed_type != 0;
}
inline bool Type::isReference() const
{
check_defined();
return _referenced_type != 0;
}
inline bool Type::isVoid() const
{
return (_ti == typeid(void)) != 0;
return (_ti == extended_typeid<void>()) != 0;
}
inline const Type& Type::getPointedType() const
@@ -419,6 +466,14 @@ namespace osgIntrospection
return Reflection::type_void();
}
inline const Type& Type::getReferencedType() const
{
check_defined();
if (_referenced_type)
return *_referenced_type;
return Reflection::type_void();
}
inline bool Type::isEnum() const
{
check_defined();

View File

@@ -29,7 +29,7 @@ namespace osgIntrospection
{
TypeNameAliasProxy(const std::string& name)
{
Type* type = Reflection::getOrRegisterType(typeid(C));
Type* type = Reflection::getOrRegisterType(extended_typeid<C>());
if (std::find(type->_aliases.begin(), type->_aliases.end(), name) == type->_aliases.end())
type->_aliases.push_back(name);
}

View File

@@ -17,6 +17,7 @@
#include <osgIntrospection/Export>
#include <osgIntrospection/Reflection>
#include <osgIntrospection/type_traits>
#include <vector>
#include <memory>
@@ -250,7 +251,7 @@ namespace osgIntrospection
virtual const Type* type() const
{
return &typeof(static_cast<Instance<T> *>(inst_)->_data);
return &typeof(T);
}
virtual bool nullptr() const
@@ -296,13 +297,13 @@ namespace osgIntrospection
virtual const Type* type() const
{
return &typeof(static_cast<Instance<T> *>(inst_)->_data);
return &typeof(T);
}
virtual const Type* ptype() const
{
if (!static_cast<Instance<T> *>(inst_)->_data) return 0;
return &typeof(*static_cast<Instance<T> *>(inst_)->_data);
return &typeof(typename remove_pointer<T>::type);
}
virtual bool nullptr() const

View File

@@ -8,6 +8,7 @@ CXXFILES =\
MethodInfo.cpp\
PropertyInfo.cpp\
Reflection.cpp\
Reflector.cpp\
Type.cpp\
Utility.cpp\
Value.cpp\

View File

@@ -39,18 +39,18 @@ Reflection::StaticData& Reflection::getOrCreateStaticData()
if (!_static_data)
{
_static_data = new StaticData;
std::auto_ptr<Type> tvoid(new Type(typeid(void)));
_static_data->typemap.insert(std::make_pair(&typeid(void), tvoid.get()));
std::auto_ptr<Type> tvoid(new Type(extended_typeid<void>()));
_static_data->typemap.insert(std::make_pair(extended_typeid<void>(), tvoid.get()));
_static_data->type_void = tvoid.release();
}
return *_static_data;
}
const Type& Reflection::getType(const std::type_info& ti)
const Type& Reflection::getType(const ExtendedTypeInfo &ti)
{
const TypeMap& types = getTypes();
TypeMap::const_iterator i = types.find(&ti);
TypeMap::const_iterator i = types.find(ti);
if (i == types.end())
{
return *registerType(ti);
@@ -79,17 +79,17 @@ const Type& Reflection::type_void()
return *getOrCreateStaticData().type_void;
}
Type* Reflection::registerType(const std::type_info& ti)
Type* Reflection::registerType(const ExtendedTypeInfo &ti)
{
std::auto_ptr<Type> type(new Type(ti));
getOrCreateStaticData().typemap.insert(std::make_pair(&ti, type.get()));
getOrCreateStaticData().typemap.insert(std::make_pair(ti, type.get()));
return type.release();
}
Type* Reflection::getOrRegisterType(const std::type_info& ti, bool replace_if_defined)
Type* Reflection::getOrRegisterType(const ExtendedTypeInfo &ti, bool replace_if_defined)
{
TypeMap& tm = getOrCreateStaticData().typemap;
TypeMap::iterator i = tm.find(&ti);
TypeMap::iterator i = tm.find(ti);
if (i != tm.end())
{

View File

@@ -69,7 +69,7 @@ bool Type::isSubclassOf(const Type& type) const
check_defined();
for (TypeList::const_iterator i=_base.begin(); i!=_base.end(); ++i)
{
if (**i == type.getStdTypeInfo())
if ((*i)->getExtendedTypeInfo() == type.getExtendedTypeInfo())
return true;
if ((*i)->isSubclassOf(type))
return true;

View File

@@ -29,7 +29,7 @@ Value Value::convertTo(const Type& outtype) const
{
Value v = tryConvertTo(outtype);
if (v.isEmpty())
throw TypeConversionException(_type->getStdTypeInfo(), outtype.getStdTypeInfo());
throw TypeConversionException(_type->getExtendedTypeInfo(), outtype.getExtendedTypeInfo());
return v;
}
@@ -92,7 +92,7 @@ std::string Value::toString() const
throw StreamWriteErrorException();
return oss.str();
}
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, _type->getStdTypeInfo());
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, _type->getExtendedTypeInfo());
}
std::wstring Value::toWString() const
@@ -107,7 +107,7 @@ std::wstring Value::toWString() const
throw StreamWriteErrorException();
return woss.str();
}
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, _type->getStdTypeInfo());
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, _type->getExtendedTypeInfo());
}
void Value::check_empty() const
@@ -137,7 +137,7 @@ bool Value::operator ==(const Value& other) const
const Comparator* cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(_type->getStdTypeInfo());
throw ComparisonNotPermittedException(_type->getExtendedTypeInfo());
if (cmp1 == cmp2)
return cmp->isEqualTo(*this, other);
@@ -156,7 +156,7 @@ bool Value::operator <=(const Value& other) const
const Comparator* cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(_type->getStdTypeInfo());
throw ComparisonNotPermittedException(_type->getExtendedTypeInfo());
if (cmp1 == cmp2)
return cmp->isLessThanOrEqualTo(*this, other);
@@ -185,7 +185,7 @@ bool Value::operator <(const Value& other) const
const Comparator* cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(_type->getStdTypeInfo());
throw ComparisonNotPermittedException(_type->getExtendedTypeInfo());
if (cmp1 == cmp2)
return cmp->isLessThanOrEqualTo(*this, other) && !cmp->isEqualTo(*this, other);
@@ -208,7 +208,7 @@ bool Value::operator >=(const Value& other) const
const Comparator* cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(_type->getStdTypeInfo());
throw ComparisonNotPermittedException(_type->getExtendedTypeInfo());
if (cmp1 == cmp2)
return !cmp->isLessThanOrEqualTo(*this, other) || cmp->isEqualTo(*this, other);