/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 #include #include #include #include #include #include #include #include #include #include #include #include #include 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 class Reflector { public: typedef T reflected_type; typedef Reflector 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 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 struct ValueReflector: Reflector { typedef ValueReflector inherited; typedef ValueInstanceCreator::reflected_type> instance_creator_type; ValueReflector(const std::string& name, const std::string& ns) : Reflector(name, ns, false) { } ValueReflector(const std::string& qname) : Reflector(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 struct AbstractObjectReflector: Reflector { typedef AbstractObjectReflector inherited; typedef DummyInstanceCreator::reflected_type> instance_creator_type; AbstractObjectReflector(const std::string& name, const std::string& ns) : Reflector(name, ns, true) { } AbstractObjectReflector(const std::string& qname) : Reflector(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 struct ObjectReflector: Reflector { typedef ObjectReflector inherited; typedef ObjectInstanceCreator::reflected_type> instance_creator_type; ObjectReflector(const std::string& name, const std::string& ns) : Reflector(name, ns, false) { } ObjectReflector(const std::string& qname) : Reflector(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 struct AtomicValueReflector: ValueReflector { typedef typename ValueReflector::instance_creator_type instance_creator_type; AtomicValueReflector(const std::string& name, const std::string& ns) : ValueReflector(name, ns) { setReaderWriter(new StdReaderWriter); setComparator(new PartialOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } AtomicValueReflector(const std::string& qname) : ValueReflector(qname) { setReaderWriter(new StdReaderWriter); setComparator(new PartialOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } }; template struct WAtomicValueReflector: ValueReflector { typedef typename ValueReflector::instance_creator_type instance_creator_type; WAtomicValueReflector(const std::string& name, const std::string& ns) : ValueReflector(name, ns) { setReaderWriter(new StdWReaderWriter); setComparator(new PartialOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } WAtomicValueReflector(const std::string& qname) : ValueReflector(qname) { setReaderWriter(new StdWReaderWriter); setComparator(new PartialOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } }; /// This reflector is a ValueReflector that should be used to define /// enumerations. It assigns an EnumReaderWriter by default. template struct EnumReflector: ValueReflector { typedef EnumReflector inherited; typedef typename ValueReflector::instance_creator_type instance_creator_type; EnumReflector(const std::string& name, const std::string& ns) : ValueReflector(name, ns) { setReaderWriter(new EnumReaderWriter); setComparator(new TotalOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } EnumReflector(const std::string& qname) : ValueReflector(qname) { setReaderWriter(new EnumReaderWriter); setComparator(new TotalOrderComparator); addConstructor(new TypedConstructorInfo0(ParameterInfoList())); } }; /// This class allows to define the means for reflecting STL containers /// such as std::deque and std::vector. template struct StdVectorReflector: ValueReflector { typedef typename ValueReflector::instance_creator_type instance_creator_type; struct Getter: PropertyGetter { virtual Value get(Value& instance, int i) const { return getInstance(instance).at(i); } virtual Value get(const Value& instance, int i) const { return getInstance(instance).at(i); } }; struct Setter: PropertySetter { virtual void set(Value& instance, int i, const Value& v) const { getInstance(instance).at(i) = variant_cast(v); } }; struct Counter: PropertyCounter { virtual int count(const Value& instance) const { return static_cast(getInstance(instance).size()); } }; struct Adder: PropertyAdder { virtual void add(Value& instance, const Value& v) const { getInstance(instance).push_back(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value& instance, int i) const { T& ctr = getInstance(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.erase(j); } }; struct Inserter: PropertyInserter { virtual void insert(Value& instance, int i, const Value& v) const { T& ctr = getInstance(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.insert(j, variant_cast(v)); } }; StdVectorReflector(const std::string& name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(ParameterInfoList())); PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Item", 0, 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)); pi->addAttribute(new CustomPropertyInsertAttribute(new Inserter)); 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 struct StdSetReflector: ValueReflector { typedef typename ValueReflector::instance_creator_type instance_creator_type; struct Getter: PropertyGetter { virtual Value get(Value& instance, int i) const { T& ctr = getInstance(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(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(getInstance(instance).size()); } }; struct Adder: PropertyAdder { virtual void add(Value& instance, const Value& v) const { getInstance(instance).insert(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value& instance, int i) const { T& ctr = getInstance(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.erase(j); } }; StdSetReflector(const std::string& name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(ParameterInfoList())); PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Item", 0, 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 struct StdListReflector: ValueReflector { typedef typename ValueReflector::instance_creator_type instance_creator_type; struct Getter: PropertyGetter { virtual Value get(Value& instance, int i) const { T& ctr = getInstance(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(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(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); *j = variant_cast(v); } }; struct Counter: PropertyCounter { virtual int count(const Value& instance) const { return static_cast(getInstance(instance).size()); } }; struct Adder: PropertyAdder { virtual void add(Value& instance, const Value& v) const { getInstance(instance).push_back(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value& instance, int i) const { T& ctr = getInstance(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.erase(j); } }; struct Inserter: PropertyInserter { virtual void insert(Value& instance, int i, const Value& v) const { T& ctr = getInstance(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.insert(j, variant_cast(v)); } }; StdListReflector(const std::string& name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(ParameterInfoList())); PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::value_type), "Item", 0, 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)); pi->addAttribute(new CustomPropertyInsertAttribute(new Inserter)); 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 struct StdMapReflector: ValueReflector { typedef typename ValueReflector::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(instance); const key_type& key = variant_cast(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(instance); const key_type& key = variant_cast(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(instance).insert(std::make_pair(variant_cast(indices.front()), variant_cast(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(instance); for (const_iterator i=ctr.begin(); i!=ctr.end(); ++i) { values.push_back(Value(i->first).convertTo(_itype)); } } }; struct Remover: PropertyRemover { virtual void remove(Value& instance, ValueList& values) const { getInstance(instance).erase(getInstance(values.front())); } }; StdMapReflector(const std::string& name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(ParameterInfoList())); PropertyInfo* pi = new PropertyInfo(typeof(T), typeof(typename T::mapped_type), "Item", 0, 0, 0); pi->addAttribute(new CustomPropertyGetAttribute(new Getter)); pi->addAttribute(new CustomPropertySetAttribute(new Setter)); pi->addAttribute(new CustomIndexAttribute(new Indexer)); pi->addAttribute(new CustomPropertyRemoveAttribute(new Remover)); 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 struct StdPairReflector: ValueReflector { typedef typename ValueReflector::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(instance).first; case 1: return getInstance(instance).second; default: return Value(); } } virtual Value get(Value& instance) const { switch (_i) { case 0: return getInstance(instance).first; case 1: return getInstance(instance).second; default: return Value(); } } virtual void set(Value& instance, const Value& v) const { T& ctr = getInstance(instance); switch (_i) { case 0: ctr.first = variant_cast(v); break; case 1: ctr.second = variant_cast(v); break; } } int _i; }; StdPairReflector(const std::string& name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(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 Reflector::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 Reflector::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 void Reflector::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(); ptype->_cmp = new TotalOrderComparator(); } // 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(); cptype->_cmp = new TotalOrderComparator(); } _type->_is_defined = true; } template std::string Reflector::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 void Reflector::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 void Reflector::addBaseType(const Type& type) { _type->_base.push_back(&type); } template PropertyInfo* Reflector::addProperty(PropertyInfo* pi) { _type->_props.push_back(pi); return pi; } template MethodInfo* Reflector::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 void Reflector::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 ConstructorInfo* Reflector::addConstructor(ConstructorInfo* ci) { _type->_cons.push_back(ci); return ci; } template std::string Reflector::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 CustomAttributeProvider *Reflector::addAttribute(const CustomAttribute* attrib) { return _type->addAttribute(attrib); } template void Reflector::setReaderWriter(const ReaderWriter* rw) { _type->_rw = rw; } template void Reflector::setComparator(const Comparator* cmp) { _type->_cmp = cmp; } } #endif