/* -*-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_TYPE #define OSGINTROSPECTION_TYPE #include #include #include #include #include #include #include #include #include namespace osgIntrospection { // forward declarations class MethodInfo; class PropertyInfo; class ParameterInfo; class ReaderWriter; class ConstructorInfo; struct Comparator; // typedefs for member info lists typedef std::vector MethodInfoList; typedef std::vector PropertyInfoList; typedef std::vector ParameterInfoList; typedef std::vector ConstructorInfoList; // typedefs for member info map typedef std::map PropertyInfoMap; typedef std::map MethodInfoMap; // typedef for enum label map typedef std::map EnumLabelMap; // typedef for base type typedef std::vector TypeList; /// Objects of class Type are used to maintain information about /// reflected types. They also provide a number of services, like /// instance creation and dynamic calling of methods. /// All details about the data type being described are available /// at runtime, provided that the type was defined (and not just /// declared) through a Reflector class. /// It is not possible to modify a Type object once it has been /// created, unless you are a class derived from Reflector (which /// has firm friendship with this class). class OSGINTROSPECTION_EXPORT Type: public CustomAttributeProvider { public: /// Destructor. Note that this class is not meant to be subclassed. ~Type(); /// Returns a reference to the std::type_info instance associated /// to this Type. inline const std::type_info& getStdTypeInfo() 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; /// Returns the name of the reflected type. inline const std::string& getName() const; /// Returns the namespace of the reflected type. inline const std::string& getNamespace() const; /// Returns the qualified name of the reflected type. The qualified /// name is formed by the namespace, if present, plus other modifiers /// like 'const' and/or '*' (pointer) where applicable. inline std::string getQualifiedName() const; /// Returns true if either the fully-qualified name or one of the /// name aliases match the given argument inline bool matchesName(const std::string& name) const; /// Returns the number of base types. /// This number is zero if the type is not derived from any other /// type. inline int getNumBaseTypes() const; /// Returns the i-th base type. inline const Type& getBaseType(int i) const; /// Returns the base type list. inline const TypeList& getBaseTypeList() const; /// Returns the number of type name aliases. inline int getNumAliases() const; /// Returns the i-th name alias const std::string& getAlias(int i) const; /// Returns whether the reflected type is abstract. inline bool isAbstract() const; /// Returns whether the reflected type is "atomic", that is /// it can be rendered to and decoded from a stream directly. inline bool isAtomic() const; /// Returns whether the reflected type is an enumeration. inline bool isEnum() const; /// Returns whether the reflected type is the type void. inline bool isVoid() const; /// Returns true if the reflected type is a pointer, false otherwise. inline bool isPointer() const; /// Returns true if the reflected type is a pointer AND it is const, /// false otherwise. inline bool isConstPointer() const; /// Returns true if the reflected type is a pointer AND it is not /// const, false otherwise. inline bool isNonConstPointer() const; /// Returns the pointed type. If the reflected type is not a pointer, /// the object returned is typeof(void). inline const Type& getPointedType() 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; /// Fills a list of properties that are either defined in this Type /// or in inherited types. void getAllProperties(PropertyInfoList& props) const; /// Fills a map of "type <-> propertyInfoList" that are either defined in this Type /// or in inherited types. void getPropertiesMap(PropertyInfoMap& props) const; /// Returns the list of constructors defined for this type. inline const ConstructorInfoList& getConstructors() const; /// Returns the list of methods defined for this type. The list /// does not include methods inherited from base types. inline const MethodInfoList& getMethods() const; /// Fills a list of methods that are either defined in this Type /// or in inherited types. void getAllMethods(MethodInfoList& methods) const; /// Fills a map of "type <-> MethodInfoList" that are either defined in this Type /// or in inherited types. void getMethodsMap(MethodInfoMap& methods) const; /// Returns the map of enumeration labels. If the type is not an /// enumeration, an empty map is returned. inline const EnumLabelMap& getEnumLabels() const; /// Searches for a constructor that can be called with the given list /// of arguments without raising type conversion errors. If more than /// one constructors are suitable for calling, the best match is /// returned. const ConstructorInfo* getCompatibleConstructor(const ValueList& values) const; /// Searches for a constructor whose parameters match exactly the given /// list of parameter descriptions. const ConstructorInfo* getConstructor(const ParameterInfoList& params) const; /// Searches for a method that can be called with the given list of /// arguments without raising type conversion errors. If more than /// one method are suitable for calling, the best match is returned. const MethodInfo* getCompatibleMethod(const std::string& name, const ValueList& values, bool inherit) const; /// Searches for a method whose parameters match exactly the given /// list of parameter descriptions. const MethodInfo* getMethod(const std::string& name, const ParameterInfoList& params, bool inherit) const; /// Searches for a property given its name, type and list of indices. /// Only exact matches are returned. const PropertyInfo* getProperty(const std::string& name, const Type& ptype, const ParameterInfoList& indices, bool inherit) const; /// Searches for a suitable method and invokes it with the given list /// of arguments (const instance). Value invokeMethod(const std::string& name, const Value& instance, ValueList& args, bool inherit) const; /// Searches for a suitable method and invokes it with the given list /// of arguments. Value invokeMethod(const std::string& name, Value& instance, ValueList& args, bool inherit) const; /// Returns whether the reflected type is derived from another type. bool isSubclassOf(const Type& type) const; /// Returns the instance of the reader/writer object assigned to /// this type, if any. Otherwise it returns the null pointer. inline const ReaderWriter* getReaderWriter() const; /// Returns the instance of the comparator object assigned to /// this type, if any. Otherwise it returns the null pointer. inline const Comparator* getComparator() const; /// Creates an instance of the reflected type. The returned Value /// can be casted to T*, where T is the reflected type. If the type /// is abstract, an exception is thrown. Value createInstance(ValueList& args) const; inline Value createInstance() const; protected: Type(const std::type_info& ti) : _ti(ti), _is_const(false), _is_abstract(false), _pointed_type(0), _is_defined(false), _rw(0), _cmp(0) { } // throws an exception if the type is not defined. void check_defined() const; virtual void getInheritedProviders(CustomAttributeProviderList& providers) const; private: template friend class Reflector; template friend struct TypeNameAliasProxy; friend class Reflection; Type(const Type& copy): CustomAttributeProvider(copy), _ti(copy._ti) {} const std::type_info& _ti; std::string _name; std::string _namespace; TypeList _base; bool _is_const; bool _is_abstract; const Type* _pointed_type; ConstructorInfoList _cons; PropertyInfoList _props; MethodInfoList _methods; EnumLabelMap _labels; bool _is_defined; const ReaderWriter* _rw; const Comparator* _cmp; typedef std::vector AliasList; AliasList _aliases; }; // OPERATORS /// Equality test operator. Returns true if the two instances of Type /// describe the same type, false otherwise. inline bool operator==(const Type& t1, const Type& t2) { return (t1.getStdTypeInfo() == t2.getStdTypeInfo()) != 0; } /// Inequality test operator. Returns false if the two instances of Type /// describe the same type, true otherwise. inline bool operator!=(const Type& t1, const Type& t2) { return (t1.getStdTypeInfo() != t2.getStdTypeInfo()) != 0; } /// Less than operator. Returns true if the first type comes before the /// second one. The actual ordering is implementation-dependent. inline bool operator<(const Type& t1, const Type& t2) { return (t1.getStdTypeInfo().before(t2.getStdTypeInfo())) != 0; } /// Greater than or equal to operator. Returns !operator<(). inline bool operator>=(const Type& t1, const Type& t2) { return !operator<(t1, t2); } // INLINE METHODS inline void Type::check_defined() const { if (!_is_defined) throw TypeNotDefinedException(_ti); } inline const std::type_info& Type::getStdTypeInfo() const { return _ti; } inline const std::string& Type::getName() const { check_defined(); return _name; } inline const std::string& Type::getNamespace() const { check_defined(); return _namespace; } inline std::string Type::getQualifiedName() const { check_defined(); std::string qname; if (_is_const) qname = "const "; if (!_namespace.empty()) { qname.append(_namespace); qname.append("::"); } qname.append(_name); if (_pointed_type) qname.append(" *"); return qname; } inline int Type::getNumBaseTypes() const { check_defined(); return static_cast(_base.size()); } inline bool Type::isConstPointer() const { check_defined(); return _is_const && _pointed_type; } inline bool Type::isNonConstPointer() const { check_defined(); return !_is_const && _pointed_type; } inline bool Type::isAbstract() const { check_defined(); return _is_abstract; } inline bool Type::isAtomic() const { check_defined(); return _rw != 0; } inline const PropertyInfoList& Type::getProperties() const { check_defined(); return _props; } inline const ConstructorInfoList& Type::getConstructors() const { check_defined(); return _cons; } inline const MethodInfoList& Type::getMethods() const { check_defined(); return _methods; } inline bool Type::isPointer() const { check_defined(); return _pointed_type != 0; } inline bool Type::isVoid() const { return (_ti == typeid(void)) != 0; } inline const Type& Type::getPointedType() const { check_defined(); if (_pointed_type) return *_pointed_type; return Reflection::type_void(); } inline bool Type::isEnum() const { check_defined(); return !_labels.empty(); } inline const EnumLabelMap& Type::getEnumLabels() const { check_defined(); return _labels; } inline bool Type::isDefined() const { return _is_defined; } inline const ReaderWriter* Type::getReaderWriter() const { check_defined(); return _rw; } inline const Comparator* Type::getComparator() const { check_defined(); return _cmp; } inline const Type& Type::getBaseType(int i) const { check_defined(); return *_base.at(i); } inline const TypeList& Type::getBaseTypeList() const { check_defined(); return _base; } inline Value Type::createInstance() const { ValueList args; return createInstance(args); } inline int Type::getNumAliases() const { return static_cast(_aliases.size()); } inline const std::string& Type::getAlias(int i) const { return _aliases[i]; } inline bool Type::matchesName(const std::string& name) const { if (getQualifiedName() == name) return true; if (std::find(_aliases.begin(), _aliases.end(), name) != _aliases.end()) return true; return false; } } #endif