3ef0406105
1. type converters created automatically by the I_BaseType macro use static_cast<> even for base-to-derived conversions. dynamic_cast<> should be used instead. 2. as a consequence of the above fix, I_BaseType must now differentiate between polymorphic and non-polymorphic base classes, because the latter can't be dynamic_cast'd to derived classes. Some template magic (see is_polymorphic<> in ReflectionMacros) is used to detect polymorphism at compile time (I'm NOT sure it works on all platforms as it's partly implementation-dependent. Please test!). 3. predefined custom property getters/setters/counters/etc. (as those defined for STL containers) only work on Value objects that contain non-pointer instances. This was an unwanted restriction that no longer exists. Wrappers will need to be recompiled. This is a good time to give them a fresh update with genwrapper. NOTE: fix #1 should get rid of those crashes and strange behaviours that some users noticed while using osgIntrospection through osgTcl or in their own code."
850 lines
29 KiB
C++
850 lines
29 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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.
|
|
*/
|
|
//osgIntrospection - Copyright (C) 2005 Marco Jez
|
|
|
|
#ifndef OSGINTROSPECTION_REFLECTOR_
|
|
#define OSGINTROSPECTION_REFLECTOR_
|
|
|
|
#include <osgIntrospection/Reflection>
|
|
#include <osgIntrospection/Type>
|
|
#include <osgIntrospection/Value>
|
|
#include <osgIntrospection/PropertyInfo>
|
|
#include <osgIntrospection/MethodInfo>
|
|
#include <osgIntrospection/ConstructorInfo>
|
|
#include <osgIntrospection/InstanceCreator>
|
|
#include <osgIntrospection/ReaderWriter>
|
|
#include <osgIntrospection/TypedConstructorInfo>
|
|
#include <osgIntrospection/Comparator>
|
|
#include <osgIntrospection/Utility>
|
|
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <iterator>
|
|
|
|
namespace osgIntrospection
|
|
{
|
|
|
|
class CustomAttribute;
|
|
class ReaderWriter;
|
|
|
|
/// A Reflector is a proxy class that is used to create a new description
|
|
/// of a given type. If the type to be described is simple and doesn't
|
|
/// require additional details such as properties and methods, it can be
|
|
/// reflected by simply creating a global instance of one of the classes
|
|
/// derived from Reflector, for example ValueReflector. Other types may
|
|
/// need further information and therefore it could be necessary to create
|
|
/// a new subclass of Reflector or extend one of the existing subclasses.
|
|
/// The reflected type can be set by calling Reflector's protected
|
|
/// 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.
|
|
///
|
|
template<typename T>
|
|
class Reflector
|
|
{
|
|
public:
|
|
typedef T reflected_type;
|
|
typedef Reflector<T> inherited;
|
|
|
|
/// Virtual destructor.
|
|
virtual ~Reflector() {}
|
|
|
|
protected:
|
|
/// Direct initialization constructor. Parameter 'name' is the name
|
|
/// of the type being reflected and 'ns' is its namespace.
|
|
Reflector(const std::string& name, const std::string& ns, bool abstract = false);
|
|
|
|
/// Direct initialization constructor. Parameter 'qname' is the
|
|
/// fully-qualified name of the type being reflected, i.e. containing
|
|
/// both the namespace and the name (separated by "::").
|
|
Reflector(const std::string& qname, bool abstract = false);
|
|
|
|
protected:
|
|
|
|
/// Returns the Type object being described.
|
|
Type* getType() { return _type; }
|
|
|
|
/// Declares a new base type for the current type.
|
|
void addBaseType(const Type& type);
|
|
|
|
/// Sets the comparator object for the current type.
|
|
void setComparator(const Comparator* cmp);
|
|
|
|
/// Adds a property description to the current type.
|
|
PropertyInfo* addProperty(PropertyInfo* pi);
|
|
|
|
/// Adds a method description to the current type.
|
|
MethodInfo* addMethod(MethodInfo* mi);
|
|
|
|
/// Adds an enumeration label to the current type.
|
|
void addEnumLabel(int v, const std::string& label, bool strip_namespace = true);
|
|
|
|
/// Adds a constructor description to the current type.
|
|
/// As soon as a constructor is added through this method,
|
|
/// the automatically-generated default constructor is
|
|
/// removed.
|
|
ConstructorInfo* addConstructor(ConstructorInfo* ci);
|
|
|
|
/// Returns a string containing the qualified version of 'name'.
|
|
std::string qualifyName(const std::string& name) const;
|
|
|
|
/// Adds a custom attribute to the type being described.
|
|
CustomAttributeProvider *addAttribute(const CustomAttribute* attrib);
|
|
|
|
/// Sets the current type's ReaderWriter object.
|
|
void setReaderWriter(const ReaderWriter* rw);
|
|
|
|
private:
|
|
struct PtrConstructor: ConstructorInfo
|
|
{
|
|
PtrConstructor(const Type* pt)
|
|
: ConstructorInfo(*pt, ParameterInfoList())
|
|
{
|
|
}
|
|
|
|
Value createInstance(ValueList& ) const { T* x = 0; return x; }
|
|
};
|
|
|
|
struct ConstPtrConstructor: ConstructorInfo
|
|
{
|
|
ConstPtrConstructor(const Type* pt)
|
|
: ConstructorInfo(*pt, ParameterInfoList())
|
|
{
|
|
}
|
|
|
|
Value createInstance(ValueList& ) const { const T *x = 0; return x; }
|
|
};
|
|
|
|
void init();
|
|
static std::string purify(const std::string& s);
|
|
static void split_qualified_name(const std::string& q, std::string& n, std::string& ns);
|
|
|
|
typedef std::vector<MethodInfo* > TempMethodList;
|
|
TempMethodList _temp_methods;
|
|
Type* _type;
|
|
};
|
|
|
|
/// This reflector ought to be used to describe types that can be
|
|
/// created on the stack. Such types are for example int, double,
|
|
/// std::string, or other (possibly small) user-defined structs or
|
|
/// classes. The instance creator associated to types created through
|
|
/// this reflector will create Value objects whose internal type is T.
|
|
template<typename T>
|
|
struct ValueReflector: Reflector<T>
|
|
{
|
|
typedef ValueReflector<T> inherited;
|
|
typedef ValueInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
|
|
|
|
ValueReflector(const std::string& name, const std::string& ns)
|
|
: Reflector<T>(name, ns, false)
|
|
{
|
|
}
|
|
|
|
ValueReflector(const std::string& qname)
|
|
: Reflector<T>(qname, false)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// This reflector is to be used to describe abstract types that can't
|
|
/// be instantiated. For this reason a DummyInstanceCreator is used in
|
|
/// order to avoid compiler errors.
|
|
template<typename T>
|
|
struct AbstractObjectReflector: Reflector<T>
|
|
{
|
|
typedef AbstractObjectReflector<T> inherited;
|
|
typedef DummyInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
|
|
|
|
AbstractObjectReflector(const std::string& name, const std::string& ns)
|
|
: Reflector<T>(name, ns, true)
|
|
{
|
|
}
|
|
|
|
AbstractObjectReflector(const std::string& qname)
|
|
: Reflector<T>(qname, true)
|
|
{
|
|
}
|
|
};
|
|
|
|
/// This reflector is to be used to describe types that ought to be
|
|
/// created on the heap. Such types are for example all classes derived
|
|
/// from osg::Referenced. The instance creator associated to types
|
|
/// created through this reflector will create Value objects whose
|
|
/// internal type is T*.
|
|
template<typename T>
|
|
struct ObjectReflector: Reflector<T>
|
|
{
|
|
typedef ObjectReflector<T> inherited;
|
|
typedef ObjectInstanceCreator<typename Reflector<T>::reflected_type> instance_creator_type;
|
|
|
|
ObjectReflector(const std::string& name, const std::string& ns)
|
|
: Reflector<T>(name, ns, false)
|
|
{
|
|
}
|
|
|
|
ObjectReflector(const std::string& qname)
|
|
: Reflector<T>(qname, false)
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
/// This reflector is a ValueReflector that should be used to define
|
|
/// types that can be read and written from/to streams using the <<
|
|
/// and >> operators. A StdReaderWriter is assigned by default.
|
|
template<typename T>
|
|
struct AtomicValueReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
AtomicValueReflector(const std::string& name, const std::string& ns)
|
|
: ValueReflector<T>(name, ns)
|
|
{
|
|
setReaderWriter(new StdReaderWriter<T>);
|
|
setComparator(new PartialOrderComparator<T>);
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
}
|
|
|
|
AtomicValueReflector(const std::string& qname)
|
|
: ValueReflector<T>(qname)
|
|
{
|
|
setReaderWriter(new StdReaderWriter<T>);
|
|
setComparator(new PartialOrderComparator<T>);
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
}
|
|
};
|
|
|
|
|
|
/// This reflector is a ValueReflector that should be used to define
|
|
/// enumerations. It assigns an EnumReaderWriter by default.
|
|
template<typename T>
|
|
struct EnumReflector: ValueReflector<T>
|
|
{
|
|
typedef EnumReflector<T> inherited;
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
EnumReflector(const std::string& name, const std::string& ns)
|
|
: ValueReflector<T>(name, ns)
|
|
{
|
|
setReaderWriter(new EnumReaderWriter<T>);
|
|
setComparator(new TotalOrderComparator<T>);
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
}
|
|
|
|
EnumReflector(const std::string& qname)
|
|
: ValueReflector<T>(qname)
|
|
{
|
|
setReaderWriter(new EnumReaderWriter<T>);
|
|
setComparator(new TotalOrderComparator<T>);
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
}
|
|
};
|
|
|
|
|
|
/// This class allows to define the means for reflecting STL containers
|
|
/// such as std::deque and std::vector.
|
|
template<typename T, typename VT>
|
|
struct StdVectorReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
struct Getter: PropertyGetter
|
|
{
|
|
virtual Value get(Value& instance, int i) const
|
|
{
|
|
return getInstance<T>(instance).at(i);
|
|
}
|
|
|
|
virtual Value get(const Value& instance, int i) const
|
|
{
|
|
return getInstance<T>(instance).at(i);
|
|
}
|
|
};
|
|
|
|
struct Setter: PropertySetter
|
|
{
|
|
virtual void set(Value& instance, int i, const Value& v) const
|
|
{
|
|
getInstance<T>(instance).at(i) = variant_cast<const typename T::value_type& >(v);
|
|
}
|
|
};
|
|
|
|
struct Counter: PropertyCounter
|
|
{
|
|
virtual int count(const Value& instance) const
|
|
{
|
|
return static_cast<int>(getInstance<T>(instance).size());
|
|
}
|
|
};
|
|
|
|
struct Adder: PropertyAdder
|
|
{
|
|
virtual void add(Value& instance, const Value& v) const
|
|
{
|
|
getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
|
|
}
|
|
};
|
|
|
|
struct Remover: PropertyRemover
|
|
{
|
|
virtual void remove(Value& instance, int i) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
ctr.erase(j);
|
|
}
|
|
};
|
|
|
|
StdVectorReflector(const std::string& name): ValueReflector<T>(name)
|
|
{
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
|
|
PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
|
|
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
|
|
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
|
|
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
|
|
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
|
|
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
|
|
|
|
if (typeid(VT).before(typeid(typename T::value_type)) ||
|
|
typeid(typename T::value_type).before(typeid(VT)))
|
|
{
|
|
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
|
|
}
|
|
|
|
this->addProperty(pi);
|
|
}
|
|
};
|
|
|
|
/// This class allows to define the means for reflecting STL containers
|
|
/// such as std::set and std::multiset.
|
|
template<typename T, typename VT>
|
|
struct StdSetReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
struct Getter: PropertyGetter
|
|
{
|
|
virtual Value get(Value& instance, int i) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
return *j;
|
|
}
|
|
|
|
virtual Value get(const Value& instance, int i) const
|
|
{
|
|
const T& ctr = getInstance<T>(instance);
|
|
typename T::const_iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
return *j;
|
|
}
|
|
};
|
|
|
|
struct Counter: PropertyCounter
|
|
{
|
|
virtual int count(const Value& instance) const
|
|
{
|
|
return static_cast<int>(getInstance<T>(instance).size());
|
|
}
|
|
};
|
|
|
|
struct Adder: PropertyAdder
|
|
{
|
|
virtual void add(Value& instance, const Value& v) const
|
|
{
|
|
getInstance<T>(instance).insert(variant_cast<const typename T::value_type& >(v));
|
|
}
|
|
};
|
|
|
|
struct Remover: PropertyRemover
|
|
{
|
|
virtual void remove(Value& instance, int i) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
ctr.erase(j);
|
|
}
|
|
};
|
|
|
|
StdSetReflector(const std::string& name): ValueReflector<T>(name)
|
|
{
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
|
|
PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
|
|
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
|
|
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
|
|
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
|
|
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
|
|
|
|
if (typeid(VT).before(typeid(typename T::value_type)) ||
|
|
typeid(typename T::value_type).before(typeid(VT)))
|
|
{
|
|
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
|
|
}
|
|
|
|
this->addProperty(pi);
|
|
}
|
|
};
|
|
|
|
/// This class allows to define the means for reflecting STL containers
|
|
/// that cannot be indexed directly, such as std::list.
|
|
template<typename T, typename VT>
|
|
struct StdListReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
struct Getter: PropertyGetter
|
|
{
|
|
virtual Value get(Value& instance, int i) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
return *j;
|
|
}
|
|
|
|
virtual Value get(const Value& instance, int i) const
|
|
{
|
|
const T& ctr = getInstance<T>(instance);
|
|
typename T::const_iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
return *j;
|
|
}
|
|
};
|
|
|
|
struct Setter: PropertySetter
|
|
{
|
|
virtual void set(Value& instance, int i, const Value& v) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
*j = variant_cast<const typename T::value_type& >(v);
|
|
}
|
|
};
|
|
|
|
struct Counter: PropertyCounter
|
|
{
|
|
virtual int count(const Value& instance) const
|
|
{
|
|
return static_cast<int>(getInstance<T>(instance).size());
|
|
}
|
|
};
|
|
|
|
struct Adder: PropertyAdder
|
|
{
|
|
virtual void add(Value& instance, const Value& v) const
|
|
{
|
|
getInstance<T>(instance).push_back(variant_cast<const typename T::value_type& >(v));
|
|
}
|
|
};
|
|
|
|
struct Remover: PropertyRemover
|
|
{
|
|
virtual void remove(Value& instance, int i) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
typename T::iterator j=ctr.begin();
|
|
std::advance(j, i);
|
|
ctr.erase(j);
|
|
}
|
|
};
|
|
|
|
StdListReflector(const std::string& name): ValueReflector<T>(name)
|
|
{
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
|
|
PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Items", 0, 0, 0, 0, 0);
|
|
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
|
|
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
|
|
pi->addAttribute(new CustomPropertyCountAttribute(new Counter));
|
|
pi->addAttribute(new CustomPropertyAddAttribute(new Adder));
|
|
pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover));
|
|
|
|
if (typeid(VT).before(typeid(typename T::value_type)) ||
|
|
typeid(typename T::value_type).before(typeid(VT)))
|
|
{
|
|
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
|
|
}
|
|
|
|
this->addProperty(pi);
|
|
}
|
|
};
|
|
|
|
/// This class allows to define the means for reflecting STL associative
|
|
/// containers which hold pairs of key+value, such as std::map.
|
|
template<typename T, typename IT, typename VT>
|
|
struct StdMapReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
typedef typename T::iterator iterator;
|
|
typedef typename T::const_iterator const_iterator;
|
|
typedef typename T::key_type key_type;
|
|
typedef typename T::mapped_type mapped_type;
|
|
|
|
struct Getter: PropertyGetter
|
|
{
|
|
virtual Value get(Value& instance, const ValueList& indices) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
const key_type& key = variant_cast<const key_type& >(indices.front());
|
|
|
|
iterator i = ctr.find(key);
|
|
if (i == ctr.end()) return Value();
|
|
return i->second;
|
|
}
|
|
|
|
virtual Value get(const Value& instance, const ValueList& indices) const
|
|
{
|
|
const T& ctr = getInstance<T>(instance);
|
|
const key_type& key = variant_cast<const key_type& >(indices.front());
|
|
|
|
const_iterator i = ctr.find(key);
|
|
if (i == ctr.end()) return Value();
|
|
return i->second;
|
|
}
|
|
};
|
|
|
|
struct Setter: PropertySetter
|
|
{
|
|
virtual void set(Value& instance, const ValueList& indices, const Value& v) const
|
|
{
|
|
getInstance<T>(instance).insert(std::make_pair(variant_cast<const key_type& >(indices.front()),
|
|
variant_cast<const mapped_type& >(v)));
|
|
}
|
|
};
|
|
|
|
struct Indexer: IndexInfo
|
|
{
|
|
ParameterInfoList _params;
|
|
const Type& _itype;
|
|
|
|
Indexer()
|
|
: _itype(typeof(IT))
|
|
{
|
|
_params.push_back(new ParameterInfo("key", typeof(key_type), 0, ParameterInfo::IN));
|
|
}
|
|
|
|
virtual ~Indexer()
|
|
{
|
|
delete _params.front();
|
|
}
|
|
|
|
virtual const ParameterInfoList& getIndexParameters() const
|
|
{
|
|
return _params;
|
|
}
|
|
|
|
virtual void getIndexValueSet(int /*whichindex*/, const Value& instance, ValueList& values) const
|
|
{
|
|
const T& ctr = getInstance<T>(instance);
|
|
for (const_iterator i=ctr.begin();
|
|
i!=ctr.end();
|
|
++i)
|
|
{
|
|
values.push_back(Value(i->first).convertTo(_itype));
|
|
}
|
|
}
|
|
};
|
|
|
|
StdMapReflector(const std::string& name): ValueReflector<T>(name)
|
|
{
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
|
|
PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::mapped_type), "Items", 0, 0);
|
|
pi->addAttribute(new CustomPropertyGetAttribute(new Getter));
|
|
pi->addAttribute(new CustomPropertySetAttribute(new Setter));
|
|
pi->addAttribute(new CustomIndexAttribute(new Indexer));
|
|
|
|
if (typeid(VT).before(typeid(typename T::mapped_type)) ||
|
|
typeid(typename T::mapped_type).before(typeid(VT)))
|
|
{
|
|
pi->addAttribute(new PropertyTypeAttribute(typeof(VT)));
|
|
}
|
|
|
|
this->addProperty(pi);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename PT1, typename PT2>
|
|
struct StdPairReflector: ValueReflector<T>
|
|
{
|
|
typedef typename ValueReflector<T>::instance_creator_type instance_creator_type;
|
|
|
|
struct Accessor: PropertyGetter, PropertySetter
|
|
{
|
|
Accessor(int i): _i(i) {}
|
|
|
|
virtual Value get(const Value& instance) const
|
|
{
|
|
switch (_i)
|
|
{
|
|
case 0: return getInstance<T>(instance).first;
|
|
case 1: return getInstance<T>(instance).second;
|
|
default: return Value();
|
|
}
|
|
}
|
|
|
|
virtual Value get(Value& instance) const
|
|
{
|
|
switch (_i)
|
|
{
|
|
case 0: return getInstance<T>(instance).first;
|
|
case 1: return getInstance<T>(instance).second;
|
|
default: return Value();
|
|
}
|
|
}
|
|
|
|
virtual void set(Value& instance, const Value& v) const
|
|
{
|
|
T& ctr = getInstance<T>(instance);
|
|
|
|
switch (_i)
|
|
{
|
|
case 0: ctr.first = variant_cast<const typename T::first_type& >(v); break;
|
|
case 1: ctr.second = variant_cast<const typename T::second_type& >(v); break;
|
|
}
|
|
}
|
|
|
|
int _i;
|
|
};
|
|
|
|
StdPairReflector(const std::string& name): ValueReflector<T>(name)
|
|
{
|
|
addConstructor(new TypedConstructorInfo0<T, instance_creator_type>(ParameterInfoList()));
|
|
|
|
PropertyInfo* pi1 = new PropertyInfo(typeof(T), typeof(typename T::first_type), "first", 0, 0);
|
|
pi1->addAttribute(new CustomPropertyGetAttribute(new Accessor(0)));
|
|
pi1->addAttribute(new CustomPropertySetAttribute(new Accessor(0)));
|
|
|
|
if (typeid(PT1).before(typeid(typename T::first_type)) ||
|
|
typeid(typename T::first_type).before(typeid(PT1)))
|
|
pi1->addAttribute(new PropertyTypeAttribute(typeof(PT1)));
|
|
|
|
this->addProperty(pi1);
|
|
|
|
PropertyInfo* pi2 = new PropertyInfo(typeof(T), typeof(typename T::second_type), "second", 0, 0);
|
|
pi2->addAttribute(new CustomPropertyGetAttribute(new Accessor(1)));
|
|
pi2->addAttribute(new CustomPropertySetAttribute(new Accessor(1)));
|
|
|
|
if (typeid(PT2).before(typeid(typename T::second_type)) ||
|
|
typeid(typename T::second_type).before(typeid(PT2)))
|
|
pi2->addAttribute(new PropertyTypeAttribute(typeof(PT2)));
|
|
|
|
this->addProperty(pi2);
|
|
}
|
|
};
|
|
|
|
|
|
// TEMPLATE METHODS
|
|
|
|
template<typename T>
|
|
Reflector<T>::Reflector(const std::string& name, const std::string& ns, bool abstract)
|
|
: _type(Reflection::getOrRegisterType(typeid(T), true))
|
|
{
|
|
if (!_type->_name.empty())
|
|
_type->_aliases.push_back(ns.empty()? purify(name): purify(ns+"::"+name));
|
|
else
|
|
{
|
|
_type->_name = purify(name);
|
|
_type->_namespace = purify(ns);
|
|
}
|
|
_type->_is_abstract = abstract;
|
|
init();
|
|
}
|
|
|
|
template<typename T>
|
|
Reflector<T>::Reflector(const std::string& qname, bool abstract)
|
|
: _type(Reflection::getOrRegisterType(typeid(T), true))
|
|
{
|
|
if (!_type->_name.empty())
|
|
_type->_aliases.push_back(purify(qname));
|
|
else
|
|
{
|
|
split_qualified_name(purify(qname), _type->_name, _type->_namespace);
|
|
}
|
|
_type->_is_abstract = abstract;
|
|
init();
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::init()
|
|
{
|
|
// pointer type
|
|
if (!_type->_pointed_type)
|
|
{
|
|
Type* ptype = Reflection::getOrRegisterType(typeid(T*), true);
|
|
ptype->_name = _type->_name;
|
|
ptype->_namespace = _type->_namespace;
|
|
ptype->_pointed_type = _type;
|
|
ptype->_is_defined = true;
|
|
ptype->_cons.push_back(new PtrConstructor(ptype));
|
|
ptype->_rw = new PtrReaderWriter<T*>();
|
|
ptype->_cmp = new TotalOrderComparator<T*>();
|
|
}
|
|
|
|
// const pointer type
|
|
if (!_type->_pointed_type || !_type->_is_const)
|
|
{
|
|
Type* cptype = Reflection::getOrRegisterType(typeid(const T*), true);
|
|
cptype->_name = _type->_name;
|
|
cptype->_namespace = _type->_namespace;
|
|
cptype->_is_const = true;
|
|
cptype->_pointed_type = _type;
|
|
cptype->_is_defined = true;
|
|
cptype->_cons.push_back(new ConstPtrConstructor(cptype));
|
|
cptype->_rw = new PtrReaderWriter<const T*>();
|
|
cptype->_cmp = new TotalOrderComparator<const T*>();
|
|
}
|
|
|
|
_type->_is_defined = true;
|
|
}
|
|
|
|
template<typename T>
|
|
std::string Reflector<T>::purify(const std::string& s)
|
|
{
|
|
std::string r(s);
|
|
while (true)
|
|
{
|
|
std::string::size_type p = r.find(" COMMA ");
|
|
if (p == std::string::npos) break;
|
|
r.replace(p, 7, ", ");
|
|
};
|
|
return r;
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::split_qualified_name(const std::string& q, std::string& n, std::string& ns)
|
|
{
|
|
int templ = 0;
|
|
std::string::size_type split_point = std::string::npos;
|
|
std::string::size_type j = 0;
|
|
for (std::string::const_iterator i=q.begin(); i!=q.end(); ++i, ++j)
|
|
{
|
|
if (*i == '<') ++templ;
|
|
if (*i == '>') --templ;
|
|
if (templ == 0)
|
|
{
|
|
if (*i == ':' && (i+1)!=q.end() && *(i+1) == ':')
|
|
split_point = j;
|
|
}
|
|
}
|
|
if (split_point == std::string::npos)
|
|
{
|
|
ns.clear();
|
|
n = q;
|
|
}
|
|
else
|
|
{
|
|
n = q.substr(split_point+2);
|
|
ns = q.substr(0, split_point);
|
|
}
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::addBaseType(const Type& type)
|
|
{
|
|
_type->_base.push_back(&type);
|
|
}
|
|
|
|
template<typename T>
|
|
PropertyInfo* Reflector<T>::addProperty(PropertyInfo* pi)
|
|
{
|
|
_type->_props.push_back(pi);
|
|
return pi;
|
|
}
|
|
|
|
template<typename T>
|
|
MethodInfo* Reflector<T>::addMethod(MethodInfo* mi)
|
|
{
|
|
for (TempMethodList::iterator i=_temp_methods.begin(); i!=_temp_methods.end(); ++i)
|
|
{
|
|
if (mi->overrides(*i))
|
|
return *i;
|
|
}
|
|
|
|
_temp_methods.push_back(mi);
|
|
_type->_methods.push_back(mi);
|
|
return mi;
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::addEnumLabel(int v, const std::string& label, bool strip_namespace)
|
|
{
|
|
if (strip_namespace)
|
|
{
|
|
std::string::size_type p = label.rfind("::");
|
|
if (p != std::string::npos)
|
|
{
|
|
_type->_labels.insert(std::make_pair(v, label.substr(p+2)));
|
|
return;
|
|
}
|
|
}
|
|
_type->_labels.insert(std::make_pair(v, label));
|
|
}
|
|
|
|
template<typename T>
|
|
ConstructorInfo* Reflector<T>::addConstructor(ConstructorInfo* ci)
|
|
{
|
|
_type->_cons.push_back(ci);
|
|
return ci;
|
|
}
|
|
|
|
template<typename T>
|
|
std::string Reflector<T>::qualifyName(const std::string& name) const
|
|
{
|
|
std::string s;
|
|
if (!_type->_namespace.empty())
|
|
{
|
|
s.append(_type->_namespace);
|
|
s.append("::");
|
|
}
|
|
if (!_type->_name.empty())
|
|
{
|
|
s.append(_type->_name);
|
|
s.append("::");
|
|
}
|
|
s.append(name);
|
|
return s;
|
|
}
|
|
|
|
template<typename T>
|
|
CustomAttributeProvider *Reflector<T>::addAttribute(const CustomAttribute* attrib)
|
|
{
|
|
return _type->addAttribute(attrib);
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::setReaderWriter(const ReaderWriter* rw)
|
|
{
|
|
_type->_rw = rw;
|
|
}
|
|
|
|
template<typename T>
|
|
void Reflector<T>::setComparator(const Comparator* cmp)
|
|
{
|
|
_type->_cmp = cmp;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|