#ifndef OSGINTROSPECTION_REFLECTOR_ #define OSGINTROSPECTION_REFLECTOR_ #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())); } }; /// 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 { T &ctr = variant_cast(instance); return ctr.at(i); } virtual Value get(const Value &instance, int i) const { const T &ctr = variant_cast(instance); return ctr.at(i); } }; struct Setter: PropertySetter { virtual void set(Value &instance, int i, const Value &v) const { T &ctr = variant_cast(instance); ctr.at(i) = variant_cast(v); } }; struct Counter: PropertyCounter { virtual int count(const Value &instance) const { const T &ctr = variant_cast(instance); return static_cast(ctr.size()); } }; struct Adder: PropertyAdder { virtual void add(Value &instance, const Value &v) const { T &ctr = variant_cast(instance); ctr.push_back(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value &instance, int i) const { T &ctr = variant_cast(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.erase(j); } }; StdVectorReflector(const std::string &name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(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 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 = variant_cast(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 = variant_cast(instance); typename T::const_iterator j=ctr.begin(); std::advance(j, i); return *j; } }; struct Counter: PropertyCounter { virtual int count(const Value &instance) const { const T &ctr = variant_cast(instance); return static_cast(ctr.size()); } }; struct Adder: PropertyAdder { virtual void add(Value &instance, const Value &v) const { T &ctr = variant_cast(instance); ctr.insert(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value &instance, int i) const { T &ctr = variant_cast(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), "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 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 = variant_cast(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 = variant_cast(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 = variant_cast(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 { const T &ctr = variant_cast(instance); return static_cast(ctr.size()); } }; struct Adder: PropertyAdder { virtual void add(Value &instance, const Value &v) const { T &ctr = variant_cast(instance); ctr.push_back(variant_cast(v)); } }; struct Remover: PropertyRemover { virtual void remove(Value &instance, int i) const { T &ctr = variant_cast(instance); typename T::iterator j=ctr.begin(); std::advance(j, i); ctr.erase(j); } }; StdListReflector(const std::string &name): ValueReflector(name) { addConstructor(new TypedConstructorInfo0(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 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 = variant_cast(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 = variant_cast(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 { T &ctr = variant_cast(instance); ctr.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 = variant_cast(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(name) { addConstructor(new TypedConstructorInfo0(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 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 variant_cast(instance).first; case 1: return variant_cast(instance).second; default: return Value(); } } virtual Value get(Value &instance) const { switch (i_) { case 0: return variant_cast(instance).first; case 1: return variant_cast(instance).second; default: return Value(); } } virtual void set(const Value &instance, const Value &v) const { T &ctr = variant_cast(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