Changed tabs to four spaces
This commit is contained in:
parent
21ae4c6c65
commit
4beb385d2d
@ -8,238 +8,238 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// By adding this attribute to a PropertyInfo you specify that there
|
||||
/// is no default value for that property.
|
||||
class NoDefaultValueAttribute: public CustomAttribute {};
|
||||
/// By adding this attribute to a PropertyInfo you specify that there
|
||||
/// is no default value for that property.
|
||||
class NoDefaultValueAttribute: public CustomAttribute {};
|
||||
|
||||
|
||||
/// By adding this attribute to a PropertyInfo you specify a custom
|
||||
/// default value for that property.
|
||||
class DefaultValueAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
DefaultValueAttribute(const Value &v): v_(v) {}
|
||||
const Value &getDefaultValue() const { return v_; }
|
||||
private:
|
||||
Value v_;
|
||||
};
|
||||
/// By adding this attribute to a PropertyInfo you specify a custom
|
||||
/// default value for that property.
|
||||
class DefaultValueAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
DefaultValueAttribute(const Value &v): v_(v) {}
|
||||
const Value &getDefaultValue() const { return v_; }
|
||||
private:
|
||||
Value v_;
|
||||
};
|
||||
|
||||
/// Base struct for custom property getters. Descendants may override
|
||||
/// one or more of the get() methods to provide the means for retrieving
|
||||
/// the value of a property. The first version of get() is used with
|
||||
/// indexed properties, the second one serves simple properties and the
|
||||
/// last one is used with array properties.
|
||||
struct PropertyGetter
|
||||
{
|
||||
virtual Value get(const Value &instance, const ValueList &indices) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::IGET); }
|
||||
virtual Value get(const Value &instance) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::GET); }
|
||||
virtual Value get(const Value &instance, int i) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::AGET); }
|
||||
virtual ~PropertyGetter() {}
|
||||
};
|
||||
/// Base struct for custom property getters. Descendants may override
|
||||
/// one or more of the get() methods to provide the means for retrieving
|
||||
/// the value of a property. The first version of get() is used with
|
||||
/// indexed properties, the second one serves simple properties and the
|
||||
/// last one is used with array properties.
|
||||
struct PropertyGetter
|
||||
{
|
||||
virtual Value get(const Value &instance, const ValueList &indices) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::IGET); }
|
||||
virtual Value get(const Value &instance) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::GET); }
|
||||
virtual Value get(const Value &instance, int i) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::AGET); }
|
||||
virtual ~PropertyGetter() {}
|
||||
};
|
||||
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to retrieve the value of a property instead of the
|
||||
/// default getter method.
|
||||
class CustomPropertyGetAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyGetAttribute(const PropertyGetter *getter)
|
||||
: CustomAttribute(), getter_(getter) {}
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to retrieve the value of a property instead of the
|
||||
/// default getter method.
|
||||
class CustomPropertyGetAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyGetAttribute(const PropertyGetter *getter)
|
||||
: CustomAttribute(), getter_(getter) {}
|
||||
|
||||
const PropertyGetter *getGetter() const { return getter_; }
|
||||
const PropertyGetter *getGetter() const { return getter_; }
|
||||
|
||||
~CustomPropertyGetAttribute()
|
||||
{
|
||||
delete getter_;
|
||||
}
|
||||
~CustomPropertyGetAttribute()
|
||||
{
|
||||
delete getter_;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyGetter *getter_;
|
||||
};
|
||||
private:
|
||||
const PropertyGetter *getter_;
|
||||
};
|
||||
|
||||
/// Base struct for custom property setters. Descendants may override
|
||||
/// one or more of the set() methods to provide the means for setting
|
||||
/// the value of a property. The first version of set() is used with
|
||||
/// indexed properties, the second one serves simple properties and the
|
||||
/// last one is used with array properties.
|
||||
struct PropertySetter
|
||||
{
|
||||
virtual void set(Value &instance, ValueList &indices, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ISET); }
|
||||
virtual void set(Value &instance, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::SET); }
|
||||
virtual void set(Value &instance, int i, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ASET); }
|
||||
virtual ~PropertySetter() {}
|
||||
};
|
||||
/// Base struct for custom property setters. Descendants may override
|
||||
/// one or more of the set() methods to provide the means for setting
|
||||
/// the value of a property. The first version of set() is used with
|
||||
/// indexed properties, the second one serves simple properties and the
|
||||
/// last one is used with array properties.
|
||||
struct PropertySetter
|
||||
{
|
||||
virtual void set(Value &instance, ValueList &indices, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ISET); }
|
||||
virtual void set(Value &instance, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::SET); }
|
||||
virtual void set(Value &instance, int i, const Value &value) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ASET); }
|
||||
virtual ~PropertySetter() {}
|
||||
};
|
||||
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to set the value of a property instead of the
|
||||
/// default setter method.
|
||||
class CustomPropertySetAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertySetAttribute(const PropertySetter *setter)
|
||||
: CustomAttribute(), setter_(setter) {}
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to set the value of a property instead of the
|
||||
/// default setter method.
|
||||
class CustomPropertySetAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertySetAttribute(const PropertySetter *setter)
|
||||
: CustomAttribute(), setter_(setter) {}
|
||||
|
||||
const PropertySetter *getSetter() const { return setter_; }
|
||||
const PropertySetter *getSetter() const { return setter_; }
|
||||
|
||||
~CustomPropertySetAttribute()
|
||||
{
|
||||
delete setter_;
|
||||
}
|
||||
~CustomPropertySetAttribute()
|
||||
{
|
||||
delete setter_;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertySetter *setter_;
|
||||
};
|
||||
private:
|
||||
const PropertySetter *setter_;
|
||||
};
|
||||
|
||||
/// Base struct for custom array property counters. Descendants should
|
||||
/// override the count() method which must return the number of items
|
||||
/// in a chosen array property for the given instance.
|
||||
struct PropertyCounter
|
||||
{
|
||||
virtual int count(const Value &instance) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::COUNT); }
|
||||
virtual ~PropertyCounter() {}
|
||||
};
|
||||
/// Base struct for custom array property counters. Descendants should
|
||||
/// override the count() method which must return the number of items
|
||||
/// in a chosen array property for the given instance.
|
||||
struct PropertyCounter
|
||||
{
|
||||
virtual int count(const Value &instance) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::COUNT); }
|
||||
virtual ~PropertyCounter() {}
|
||||
};
|
||||
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to count the number of items in an array property.
|
||||
class CustomPropertyCountAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyCountAttribute(const PropertyCounter *counter)
|
||||
: CustomAttribute(), counter_(counter) {}
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to count the number of items in an array property.
|
||||
class CustomPropertyCountAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyCountAttribute(const PropertyCounter *counter)
|
||||
: CustomAttribute(), counter_(counter) {}
|
||||
|
||||
const PropertyCounter *getCounter() const { return counter_; }
|
||||
const PropertyCounter *getCounter() const { return counter_; }
|
||||
|
||||
~CustomPropertyCountAttribute()
|
||||
{
|
||||
delete counter_;
|
||||
}
|
||||
~CustomPropertyCountAttribute()
|
||||
{
|
||||
delete counter_;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyCounter *counter_;
|
||||
};
|
||||
private:
|
||||
const PropertyCounter *counter_;
|
||||
};
|
||||
|
||||
/// Base struct for custom array property adders. Descendants should
|
||||
/// override the add() method whose purpose is to add a new item to
|
||||
/// an array property.
|
||||
struct PropertyAdder
|
||||
{
|
||||
virtual void add(Value&, const Value&) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ADD); }
|
||||
virtual ~PropertyAdder() {}
|
||||
};
|
||||
/// Base struct for custom array property adders. Descendants should
|
||||
/// override the add() method whose purpose is to add a new item to
|
||||
/// an array property.
|
||||
struct PropertyAdder
|
||||
{
|
||||
virtual void add(Value&, const Value&) const { throw PropertyAccessException("[n/a inside a custom accessor]", PropertyAccessException::ADD); }
|
||||
virtual ~PropertyAdder() {}
|
||||
};
|
||||
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to add a new item to an array property.
|
||||
class CustomPropertyAddAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyAddAttribute(const PropertyAdder *adder)
|
||||
: CustomAttribute(), adder_(adder) {}
|
||||
/// By setting an attribute of this class you can specify a custom object
|
||||
/// that will be used to add a new item to an array property.
|
||||
class CustomPropertyAddAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomPropertyAddAttribute(const PropertyAdder *adder)
|
||||
: CustomAttribute(), adder_(adder) {}
|
||||
|
||||
const PropertyAdder *getAdder() const { return adder_; }
|
||||
const PropertyAdder *getAdder() const { return adder_; }
|
||||
|
||||
~CustomPropertyAddAttribute()
|
||||
{
|
||||
delete adder_;
|
||||
}
|
||||
~CustomPropertyAddAttribute()
|
||||
{
|
||||
delete adder_;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyAdder *adder_;
|
||||
};
|
||||
private:
|
||||
const PropertyAdder *adder_;
|
||||
};
|
||||
|
||||
|
||||
/// This struct allows customization of an indexed property's index set.
|
||||
/// You must derive from this struct and provide a concrete implementation
|
||||
/// of getIndexValueSet(), which must return (in parameter values) a list
|
||||
/// of valid values to be used as indices. The whichindex parameter
|
||||
/// specifies which index is being queried (0 = first index, 1 = second
|
||||
/// index, ...).
|
||||
/// See CustomIndexAttribute for details.
|
||||
struct IndexInfo
|
||||
{
|
||||
virtual const ParameterInfoList &getIndexParameters() const = 0;
|
||||
virtual void getIndexValueSet(int whichindex, const Value &instance, ValueList &values) const = 0;
|
||||
virtual ~IndexInfo() {}
|
||||
};
|
||||
/// This struct allows customization of an indexed property's index set.
|
||||
/// You must derive from this struct and provide a concrete implementation
|
||||
/// of getIndexValueSet(), which must return (in parameter values) a list
|
||||
/// of valid values to be used as indices. The whichindex parameter
|
||||
/// specifies which index is being queried (0 = first index, 1 = second
|
||||
/// index, ...).
|
||||
/// See CustomIndexAttribute for details.
|
||||
struct IndexInfo
|
||||
{
|
||||
virtual const ParameterInfoList &getIndexParameters() const = 0;
|
||||
virtual void getIndexValueSet(int whichindex, const Value &instance, ValueList &values) const = 0;
|
||||
virtual ~IndexInfo() {}
|
||||
};
|
||||
|
||||
|
||||
/// By default each index in an indexed property is assumed to be an
|
||||
/// enumeration. When serialization is performed, indices are chosen
|
||||
/// from the set of enum labels that were defined for the index type.
|
||||
/// With this attribute you can provide custom code to determine the
|
||||
/// set of values to be used as indices, instead of the default enum
|
||||
/// values. This attribute is required, for example, when the number
|
||||
/// and/or value of indices is not constant over time (such as in
|
||||
/// associative containers).
|
||||
class CustomIndexAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomIndexAttribute(const IndexInfo *ii)
|
||||
: CustomAttribute(), ii_(ii) {}
|
||||
/// By default each index in an indexed property is assumed to be an
|
||||
/// enumeration. When serialization is performed, indices are chosen
|
||||
/// from the set of enum labels that were defined for the index type.
|
||||
/// With this attribute you can provide custom code to determine the
|
||||
/// set of values to be used as indices, instead of the default enum
|
||||
/// values. This attribute is required, for example, when the number
|
||||
/// and/or value of indices is not constant over time (such as in
|
||||
/// associative containers).
|
||||
class CustomIndexAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
CustomIndexAttribute(const IndexInfo *ii)
|
||||
: CustomAttribute(), ii_(ii) {}
|
||||
|
||||
const IndexInfo *getIndexInfo() const
|
||||
{
|
||||
return ii_;
|
||||
}
|
||||
const IndexInfo *getIndexInfo() const
|
||||
{
|
||||
return ii_;
|
||||
}
|
||||
|
||||
~CustomIndexAttribute()
|
||||
{
|
||||
delete ii_;
|
||||
}
|
||||
~CustomIndexAttribute()
|
||||
{
|
||||
delete ii_;
|
||||
}
|
||||
|
||||
private:
|
||||
const IndexInfo *ii_;
|
||||
};
|
||||
private:
|
||||
const IndexInfo *ii_;
|
||||
};
|
||||
|
||||
/// Attribute for overriding the type of a property with a custom
|
||||
/// type. If you add this attribute to a PropertyInfo object, then
|
||||
/// all subsequent calls to getValue()/getArrayItem()/getIndexedValue()
|
||||
/// will perform a conversion from the actual property's type to
|
||||
/// the custom type specified through this attribute. Similarly, all
|
||||
/// methods in PropertyInfo that alter the property's value will accept
|
||||
/// a value of the custom type instead of the actual type. In this
|
||||
/// case the conversion is implicit and occurs later within the accessor
|
||||
/// methods.
|
||||
class PropertyTypeAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
PropertyTypeAttribute(const Type &type)
|
||||
: CustomAttribute(), type_(type) {}
|
||||
/// Attribute for overriding the type of a property with a custom
|
||||
/// type. If you add this attribute to a PropertyInfo object, then
|
||||
/// all subsequent calls to getValue()/getArrayItem()/getIndexedValue()
|
||||
/// will perform a conversion from the actual property's type to
|
||||
/// the custom type specified through this attribute. Similarly, all
|
||||
/// methods in PropertyInfo that alter the property's value will accept
|
||||
/// a value of the custom type instead of the actual type. In this
|
||||
/// case the conversion is implicit and occurs later within the accessor
|
||||
/// methods.
|
||||
class PropertyTypeAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
PropertyTypeAttribute(const Type &type)
|
||||
: CustomAttribute(), type_(type) {}
|
||||
|
||||
const Type &getPropertyType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
const Type &getPropertyType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
const Type &type_;
|
||||
};
|
||||
private:
|
||||
const Type &type_;
|
||||
};
|
||||
|
||||
/// Attribute for overriding the type of an index (of an indexed
|
||||
/// property) with a custom type. Behaves like PropertyTypeAttribute,
|
||||
/// but it affects the value of an index instead of the property's
|
||||
/// value itself.
|
||||
/// NOTE: property with custom indexing attributes are not affected
|
||||
/// by this attribute!
|
||||
class IndexTypeAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
IndexTypeAttribute(int whichindex, const Type &type)
|
||||
: CustomAttribute(), wi_(whichindex), type_(type) {}
|
||||
/// Attribute for overriding the type of an index (of an indexed
|
||||
/// property) with a custom type. Behaves like PropertyTypeAttribute,
|
||||
/// but it affects the value of an index instead of the property's
|
||||
/// value itself.
|
||||
/// NOTE: property with custom indexing attributes are not affected
|
||||
/// by this attribute!
|
||||
class IndexTypeAttribute: public CustomAttribute
|
||||
{
|
||||
public:
|
||||
IndexTypeAttribute(int whichindex, const Type &type)
|
||||
: CustomAttribute(), wi_(whichindex), type_(type) {}
|
||||
|
||||
int getWhichIndex() const
|
||||
{
|
||||
return wi_;
|
||||
}
|
||||
int getWhichIndex() const
|
||||
{
|
||||
return wi_;
|
||||
}
|
||||
|
||||
const Type &getIndexType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
const Type &getIndexType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
private:
|
||||
int wi_;
|
||||
const Type &type_;
|
||||
};
|
||||
private:
|
||||
int wi_;
|
||||
const Type &type_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,13 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// The base class for custom attributes. This is an empty class
|
||||
/// for now.
|
||||
class CustomAttribute
|
||||
{
|
||||
public:
|
||||
virtual ~CustomAttribute() {}
|
||||
};
|
||||
/// The base class for custom attributes. This is an empty class
|
||||
/// for now.
|
||||
class CustomAttribute
|
||||
{
|
||||
public:
|
||||
virtual ~CustomAttribute() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -10,102 +10,102 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
// forward declarations
|
||||
class Type;
|
||||
class CustomAttribute;
|
||||
class CustomAttributeProvider;
|
||||
// forward declarations
|
||||
class Type;
|
||||
class CustomAttribute;
|
||||
class CustomAttributeProvider;
|
||||
|
||||
// vector of attributes
|
||||
typedef std::vector<const CustomAttribute *> CustomAttributeList;
|
||||
// vector of attributes
|
||||
typedef std::vector<const CustomAttribute *> CustomAttributeList;
|
||||
|
||||
// vector of attribute providers
|
||||
typedef std::vector<const CustomAttributeProvider *> CustomAttributeProviderList;
|
||||
// vector of attribute providers
|
||||
typedef std::vector<const CustomAttributeProvider *> CustomAttributeProviderList;
|
||||
|
||||
|
||||
/// This is the base class for custom attribute providers, that is objects
|
||||
/// that can be assigned a list of custom attributes. Methods defined in
|
||||
/// this class provide the means for adding, retrieving and searching for
|
||||
/// attributes.
|
||||
class OSGINTROSPECTION_EXPORT CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Returns the const list of custom attributes.
|
||||
inline const CustomAttributeList &getCustomAttributes() const
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
/// This is the base class for custom attribute providers, that is objects
|
||||
/// that can be assigned a list of custom attributes. Methods defined in
|
||||
/// this class provide the means for adding, retrieving and searching for
|
||||
/// attributes.
|
||||
class OSGINTROSPECTION_EXPORT CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Returns the const list of custom attributes.
|
||||
inline const CustomAttributeList &getCustomAttributes() const
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
|
||||
/// Returns the list of custom attributes.
|
||||
inline CustomAttributeList &getCustomAttributes()
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
/// Returns the list of custom attributes.
|
||||
inline CustomAttributeList &getCustomAttributes()
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
|
||||
/// Adds a new attribute to the list.
|
||||
inline CustomAttributeProvider *addAttribute(const CustomAttribute *attr)
|
||||
{
|
||||
attribs_.push_back(attr);
|
||||
return this;
|
||||
}
|
||||
/// Adds a new attribute to the list.
|
||||
inline CustomAttributeProvider *addAttribute(const CustomAttribute *attr)
|
||||
{
|
||||
attribs_.push_back(attr);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// Returns whether at least one attribute of the given type is
|
||||
/// present in the attribute list. If the inherit parameter is
|
||||
/// set to true, the search is forwarded to base types.
|
||||
bool isDefined(const Type &type, bool inherit) const;
|
||||
/// Returns whether at least one attribute of the given type is
|
||||
/// present in the attribute list. If the inherit parameter is
|
||||
/// set to true, the search is forwarded to base types.
|
||||
bool isDefined(const Type &type, bool inherit) const;
|
||||
|
||||
/// Returns whether at least one attribute of the given type is
|
||||
/// present in the attribute list. If the inherit parameter is
|
||||
/// set to true, the search is forwarded to base types.
|
||||
/// [template version]
|
||||
template<typename T> inline bool isDefined(bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == typeid(T)) return true;
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
if ((*i)->isDefined<T>(true)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// Returns whether at least one attribute of the given type is
|
||||
/// present in the attribute list. If the inherit parameter is
|
||||
/// set to true, the search is forwarded to base types.
|
||||
/// [template version]
|
||||
template<typename T> inline bool isDefined(bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == typeid(T)) return true;
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
if ((*i)->isDefined<T>(true)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Searchs for an attribute of the given type and returns a pointer
|
||||
/// to it if found, a null pointer otherwise. If the inherit parameter
|
||||
/// is set to true, the search is forwarded to base types.
|
||||
const CustomAttribute *getAttribute(const Type &type, bool inherit) const;
|
||||
/// Searchs for an attribute of the given type and returns a pointer
|
||||
/// to it if found, a null pointer otherwise. If the inherit parameter
|
||||
/// is set to true, the search is forwarded to base types.
|
||||
const CustomAttribute *getAttribute(const Type &type, bool inherit) const;
|
||||
|
||||
/// Searchs for an attribute of the given type and returns a pointer
|
||||
/// to it if found, a null pointer otherwise. If the inherit parameter
|
||||
/// is set to true, the search is forwarded to base types.
|
||||
/// [template version]
|
||||
template<typename T> inline const T *getAttribute(bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == typeid(T)) return static_cast<const T *>(*i);
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
const T *ca = (*i)->getAttribute<T>(true);
|
||||
if (ca) return ca;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/// Searchs for an attribute of the given type and returns a pointer
|
||||
/// to it if found, a null pointer otherwise. If the inherit parameter
|
||||
/// is set to true, the search is forwarded to base types.
|
||||
/// [template version]
|
||||
template<typename T> inline const T *getAttribute(bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == typeid(T)) return static_cast<const T *>(*i);
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
const T *ca = (*i)->getAttribute<T>(true);
|
||||
if (ca) return ca;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const = 0;
|
||||
virtual ~CustomAttributeProvider() {}
|
||||
protected:
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const = 0;
|
||||
virtual ~CustomAttributeProvider() {}
|
||||
|
||||
private:
|
||||
CustomAttributeList attribs_;
|
||||
};
|
||||
private:
|
||||
CustomAttributeList attribs_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,182 +7,182 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
class Exception
|
||||
{
|
||||
public:
|
||||
Exception(const std::string &msg): msg_(msg) {}
|
||||
const std::string &what() const throw() { return msg_; }
|
||||
class Exception
|
||||
{
|
||||
public:
|
||||
Exception(const std::string &msg): msg_(msg) {}
|
||||
const std::string &what() const throw() { return msg_; }
|
||||
|
||||
private:
|
||||
std::string msg_;
|
||||
};
|
||||
private:
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
struct ReflectionException: public Exception
|
||||
{
|
||||
ReflectionException(const std::string &msg): Exception(msg) {}
|
||||
};
|
||||
struct ReflectionException: public Exception
|
||||
{
|
||||
ReflectionException(const std::string &msg): Exception(msg) {}
|
||||
};
|
||||
|
||||
struct TypeNotDefinedException: public ReflectionException
|
||||
{
|
||||
TypeNotDefinedException(const std::type_info &ti)
|
||||
: ReflectionException("type `" + std::string(ti.name()) + "' is declared but not defined")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct TypeNotDefinedException: public ReflectionException
|
||||
{
|
||||
TypeNotDefinedException(const std::type_info &ti)
|
||||
: ReflectionException("type `" + std::string(ti.name()) + "' is declared but not defined")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeIsAbstractException: public ReflectionException
|
||||
{
|
||||
TypeIsAbstractException(const std::type_info &ti)
|
||||
: ReflectionException("cannot create instances of abstract type `" + std::string(ti.name()) + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct TypeIsAbstractException: public ReflectionException
|
||||
{
|
||||
TypeIsAbstractException(const std::type_info &ti)
|
||||
: ReflectionException("cannot create instances of abstract type `" + std::string(ti.name()) + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct InvalidFunctionPointerException: public ReflectionException
|
||||
{
|
||||
InvalidFunctionPointerException()
|
||||
: ReflectionException("invalid function pointer during invoke()")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct InvalidFunctionPointerException: public ReflectionException
|
||||
{
|
||||
InvalidFunctionPointerException()
|
||||
: ReflectionException("invalid function pointer during invoke()")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstIsConstException: public ReflectionException
|
||||
{
|
||||
ConstIsConstException()
|
||||
: ReflectionException("cannot modify a const value")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct ConstIsConstException: public ReflectionException
|
||||
{
|
||||
ConstIsConstException()
|
||||
: ReflectionException("cannot modify a const value")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct EmptyValueException: public ReflectionException
|
||||
{
|
||||
EmptyValueException()
|
||||
: ReflectionException("cannot retrieve an empty value")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeNotFoundException: public ReflectionException
|
||||
{
|
||||
TypeNotFoundException(const std::string &qname)
|
||||
: ReflectionException("type `" + qname + "' not found")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct EmptyValueException: public ReflectionException
|
||||
{
|
||||
EmptyValueException()
|
||||
: ReflectionException("cannot retrieve an empty value")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeNotFoundException: public ReflectionException
|
||||
{
|
||||
TypeNotFoundException(const std::string &qname)
|
||||
: ReflectionException("type `" + qname + "' not found")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct MethodNotFoundException: public ReflectionException
|
||||
{
|
||||
MethodNotFoundException(const std::string &name, const std::string &cname)
|
||||
: ReflectionException("could not find a suitable method of name `" + name + "' in class `" + cname + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct MethodNotFoundException: public ReflectionException
|
||||
{
|
||||
MethodNotFoundException(const std::string &name, const std::string &cname)
|
||||
: ReflectionException("could not find a suitable method of name `" + name + "' in class `" + cname + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct StreamWriteErrorException: public ReflectionException
|
||||
{
|
||||
StreamWriteErrorException()
|
||||
: ReflectionException("an error occured while trying to write to a stream")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct StreamWriteErrorException: public ReflectionException
|
||||
{
|
||||
StreamWriteErrorException()
|
||||
: ReflectionException("an error occured while trying to write to a stream")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct StreamReadErrorException: public ReflectionException
|
||||
{
|
||||
StreamReadErrorException()
|
||||
: ReflectionException("an error occured while trying to read from a stream")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct StreamReadErrorException: public ReflectionException
|
||||
{
|
||||
StreamReadErrorException()
|
||||
: ReflectionException("an error occured while trying to read from a stream")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class StreamingNotSupportedException: public ReflectionException
|
||||
{
|
||||
public:
|
||||
enum OperationType
|
||||
{
|
||||
ANY,
|
||||
TEXT_WRITE,
|
||||
TEXT_READ,
|
||||
BINARY_WRITE,
|
||||
BINARY_READ
|
||||
};
|
||||
class StreamingNotSupportedException: public ReflectionException
|
||||
{
|
||||
public:
|
||||
enum OperationType
|
||||
{
|
||||
ANY,
|
||||
TEXT_WRITE,
|
||||
TEXT_READ,
|
||||
BINARY_WRITE,
|
||||
BINARY_READ
|
||||
};
|
||||
|
||||
StreamingNotSupportedException(OperationType op, const std::type_info &type)
|
||||
: ReflectionException(build_msg(op, type))
|
||||
{
|
||||
}
|
||||
StreamingNotSupportedException(OperationType op, const std::type_info &type)
|
||||
: ReflectionException(build_msg(op, type))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::string build_msg(OperationType op, const std::type_info &type)
|
||||
{
|
||||
std::string opstr;
|
||||
switch (op)
|
||||
{
|
||||
case TEXT_WRITE: opstr = "writing to text stream"; break;
|
||||
case TEXT_READ: opstr = "reading from text stream"; break;
|
||||
case BINARY_WRITE: opstr = "writing to binary stream"; break;
|
||||
case BINARY_READ: opstr = "reading from binary stream"; break;
|
||||
case ANY:
|
||||
default: opstr = "streaming";
|
||||
}
|
||||
return opstr + std::string(" is not supported on type `" + std::string(type.name()) + "'");
|
||||
}
|
||||
};
|
||||
private:
|
||||
std::string build_msg(OperationType op, const std::type_info &type)
|
||||
{
|
||||
std::string opstr;
|
||||
switch (op)
|
||||
{
|
||||
case TEXT_WRITE: opstr = "writing to text stream"; break;
|
||||
case TEXT_READ: opstr = "reading from text stream"; break;
|
||||
case BINARY_WRITE: opstr = "writing to binary stream"; break;
|
||||
case BINARY_READ: opstr = "reading from binary stream"; break;
|
||||
case ANY:
|
||||
default: opstr = "streaming";
|
||||
}
|
||||
return opstr + std::string(" is not supported on type `" + std::string(type.name()) + "'");
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeConversionException: public ReflectionException
|
||||
{
|
||||
TypeConversionException(const std::type_info &type1, const std::type_info &type2)
|
||||
: ReflectionException("cannot convert from type `" + std::string(type1.name()) + "' to type `" + std::string(type2.name()) + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct TypeConversionException: public ReflectionException
|
||||
{
|
||||
TypeConversionException(const std::type_info &type1, const std::type_info &type2)
|
||||
: ReflectionException("cannot convert from type `" + std::string(type1.name()) + "' to type `" + std::string(type2.name()) + "'")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class PropertyAccessException: public ReflectionException
|
||||
{
|
||||
public:
|
||||
enum AccessType
|
||||
{
|
||||
GET,
|
||||
SET,
|
||||
IGET,
|
||||
ISET,
|
||||
AGET,
|
||||
ASET,
|
||||
ADD,
|
||||
COUNT
|
||||
};
|
||||
class PropertyAccessException: public ReflectionException
|
||||
{
|
||||
public:
|
||||
enum AccessType
|
||||
{
|
||||
GET,
|
||||
SET,
|
||||
IGET,
|
||||
ISET,
|
||||
AGET,
|
||||
ASET,
|
||||
ADD,
|
||||
COUNT
|
||||
};
|
||||
|
||||
PropertyAccessException(const std::string &pname, AccessType denied)
|
||||
: ReflectionException(build_msg(pname, denied))
|
||||
{
|
||||
}
|
||||
PropertyAccessException(const std::string &pname, AccessType denied)
|
||||
: ReflectionException(build_msg(pname, denied))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
std::string build_msg(const std::string &pname, AccessType denied) const
|
||||
{
|
||||
std::string msg;
|
||||
switch (denied)
|
||||
{
|
||||
case GET: msg = "retrieved"; break;
|
||||
case SET: msg = "set"; break;
|
||||
case IGET: msg = "retrieved with indices"; break;
|
||||
case ISET: msg = "set with indices"; break;
|
||||
case AGET: msg = "retrieved with array index"; break;
|
||||
case ASET: msg = "set with array index"; break;
|
||||
case ADD: msg = "added"; break;
|
||||
case COUNT: msg = "counted"; break;
|
||||
default: msg = "?";
|
||||
}
|
||||
return std::string("value for property `" + pname + "' cannot be " + msg);
|
||||
}
|
||||
};
|
||||
private:
|
||||
std::string build_msg(const std::string &pname, AccessType denied) const
|
||||
{
|
||||
std::string msg;
|
||||
switch (denied)
|
||||
{
|
||||
case GET: msg = "retrieved"; break;
|
||||
case SET: msg = "set"; break;
|
||||
case IGET: msg = "retrieved with indices"; break;
|
||||
case ISET: msg = "set with indices"; break;
|
||||
case AGET: msg = "retrieved with array index"; break;
|
||||
case ASET: msg = "set with array index"; break;
|
||||
case ADD: msg = "added"; break;
|
||||
case COUNT: msg = "counted"; break;
|
||||
default: msg = "?";
|
||||
}
|
||||
return std::string("value for property `" + pname + "' cannot be " + msg);
|
||||
}
|
||||
};
|
||||
|
||||
struct IndexValuesNotDefinedException: ReflectionException
|
||||
{
|
||||
IndexValuesNotDefinedException(const std::string &name, const std::string &iname)
|
||||
: ReflectionException("couldn't determine a finite set of values for index `" + iname + "' of property `" + name + "'. Make sure that either: 1) the index is an enumeration, or 2) a valid custom indexing attribute was assigned to the property.")
|
||||
{
|
||||
}
|
||||
};
|
||||
struct IndexValuesNotDefinedException: ReflectionException
|
||||
{
|
||||
IndexValuesNotDefinedException(const std::string &name, const std::string &iname)
|
||||
: ReflectionException("couldn't determine a finite set of values for index `" + iname + "' of property `" + name + "'. Make sure that either: 1) the index is an enumeration, or 2) a valid custom indexing attribute was assigned to the property.")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,13 +24,13 @@
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
|
||||
# ifdef OSGINTROSPECTION_LIBRARY
|
||||
# define OSGINTROSPECTION_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OSGINTROSPECTION_EXPORT __declspec(dllimport)
|
||||
# endif /* OSGINTROSPECTION_LIBRARY */
|
||||
# ifdef OSGINTROSPECTION_LIBRARY
|
||||
# define OSGINTROSPECTION_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define OSGINTROSPECTION_EXPORT __declspec(dllimport)
|
||||
# endif /* OSGINTROSPECTION_LIBRARY */
|
||||
#else
|
||||
# define OSGINTROSPECTION_EXPORT
|
||||
# define OSGINTROSPECTION_EXPORT
|
||||
#endif
|
||||
|
||||
// set up define for whether member templates are supported by VisualStudio compilers.
|
||||
|
@ -14,112 +14,112 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
class Type;
|
||||
class Type;
|
||||
|
||||
/// Class MethodInfo stores information about a class method. It is an
|
||||
/// abstract class, so it must be derived to provide the actual
|
||||
/// implementation of isConst() and invoke(). Instances of this class
|
||||
/// can't be modified after their creation.
|
||||
class OSGINTROSPECTION_EXPORT MethodInfo: public CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Direct initialization constructor.
|
||||
inline MethodInfo(const std::string &qname, const Type &decltype, const Type &rtype, const ParameterInfoList &plist);
|
||||
/// Class MethodInfo stores information about a class method. It is an
|
||||
/// abstract class, so it must be derived to provide the actual
|
||||
/// implementation of isConst() and invoke(). Instances of this class
|
||||
/// can't be modified after their creation.
|
||||
class OSGINTROSPECTION_EXPORT MethodInfo: public CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Direct initialization constructor.
|
||||
inline MethodInfo(const std::string &qname, const Type &decltype, const Type &rtype, const ParameterInfoList &plist);
|
||||
|
||||
/// Returns the Type object associated to the type that
|
||||
/// declares the reflected method.
|
||||
inline virtual const Type &getDeclaringType() const;
|
||||
/// Returns the Type object associated to the type that
|
||||
/// declares the reflected method.
|
||||
inline virtual const Type &getDeclaringType() const;
|
||||
|
||||
/// Returns the name of the reflected method.
|
||||
inline virtual const std::string &getName() const;
|
||||
/// Returns the name of the reflected method.
|
||||
inline virtual const std::string &getName() const;
|
||||
|
||||
/// Returns the return type of the reflected method.
|
||||
inline const Type &getReturnType() const;
|
||||
/// Returns the return type of the reflected method.
|
||||
inline const Type &getReturnType() const;
|
||||
|
||||
/// Returns a list of objects that describe the reflected
|
||||
/// method's parameters.
|
||||
inline const ParameterInfoList &getParameters() const;
|
||||
/// Returns a list of objects that describe the reflected
|
||||
/// method's parameters.
|
||||
inline const ParameterInfoList &getParameters() const;
|
||||
|
||||
/// Returns whether the reflected method is const or not.
|
||||
virtual bool isConst() const = 0;
|
||||
/// Returns whether the reflected method is const or not.
|
||||
virtual bool isConst() const = 0;
|
||||
|
||||
/// Invokes the reflected method dynamically on the given const
|
||||
/// instance, passing it the arguments as a list of Value objects.
|
||||
virtual Value invoke(const Value &instance, ValueList &args) const = 0;
|
||||
/// Invokes the reflected method dynamically on the given const
|
||||
/// instance, passing it the arguments as a list of Value objects.
|
||||
virtual Value invoke(const Value &instance, ValueList &args) const = 0;
|
||||
|
||||
/// Invokes the reflected method dynamically on the given instance,
|
||||
/// passing it the arguments as a list of Value objects.
|
||||
virtual Value invoke(Value &instance, ValueList &args) const = 0;
|
||||
/// Invokes the reflected method dynamically on the given instance,
|
||||
/// passing it the arguments as a list of Value objects.
|
||||
virtual Value invoke(Value &instance, ValueList &args) const = 0;
|
||||
|
||||
/// Invokes the reflected method dynamically on the given const
|
||||
/// instance, without arguments.
|
||||
inline Value invoke(const Value &instance) const;
|
||||
/// Invokes the reflected method dynamically on the given const
|
||||
/// instance, without arguments.
|
||||
inline Value invoke(const Value &instance) const;
|
||||
|
||||
/// Invokes the reflected method dynamically on the given
|
||||
/// instance, without arguments.
|
||||
inline Value invoke(Value &instance) const;
|
||||
/// Invokes the reflected method dynamically on the given
|
||||
/// instance, without arguments.
|
||||
inline Value invoke(Value &instance) const;
|
||||
|
||||
private:
|
||||
inline std::string strip_namespace(const std::string &s) const;
|
||||
private:
|
||||
inline std::string strip_namespace(const std::string &s) const;
|
||||
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
|
||||
std::string name_;
|
||||
const Type &decltype_;
|
||||
const Type &rtype_;
|
||||
ParameterInfoList params_;
|
||||
};
|
||||
std::string name_;
|
||||
const Type &decltype_;
|
||||
const Type &rtype_;
|
||||
ParameterInfoList params_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline MethodInfo::MethodInfo(const std::string &qname, const Type &decltype, const Type &rtype, const ParameterInfoList &plist)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
rtype_(rtype),
|
||||
params_(plist)
|
||||
{
|
||||
name_ = strip_namespace(qname);
|
||||
}
|
||||
// INLINE METHODS
|
||||
|
||||
inline MethodInfo::MethodInfo(const std::string &qname, const Type &decltype, const Type &rtype, const ParameterInfoList &plist)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
rtype_(rtype),
|
||||
params_(plist)
|
||||
{
|
||||
name_ = strip_namespace(qname);
|
||||
}
|
||||
|
||||
inline std::string MethodInfo::strip_namespace(const std::string &s) const
|
||||
{
|
||||
std::string::size_type p = s.rfind("::");
|
||||
if (p != std::string::npos)
|
||||
return s.substr(p+2);
|
||||
return s;
|
||||
}
|
||||
inline std::string MethodInfo::strip_namespace(const std::string &s) const
|
||||
{
|
||||
std::string::size_type p = s.rfind("::");
|
||||
if (p != std::string::npos)
|
||||
return s.substr(p+2);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline const std::string &MethodInfo::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
inline const std::string &MethodInfo::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline const Type &MethodInfo::getDeclaringType() const
|
||||
{
|
||||
return decltype_;
|
||||
}
|
||||
inline const Type &MethodInfo::getDeclaringType() const
|
||||
{
|
||||
return decltype_;
|
||||
}
|
||||
|
||||
inline const Type &MethodInfo::getReturnType() const
|
||||
{
|
||||
return rtype_;
|
||||
}
|
||||
inline const Type &MethodInfo::getReturnType() const
|
||||
{
|
||||
return rtype_;
|
||||
}
|
||||
|
||||
inline const ParameterInfoList &MethodInfo::getParameters() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
inline const ParameterInfoList &MethodInfo::getParameters() const
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
inline Value MethodInfo::invoke(const Value &instance) const
|
||||
{
|
||||
ValueList args;
|
||||
return invoke(instance, args);
|
||||
}
|
||||
inline Value MethodInfo::invoke(const Value &instance) const
|
||||
{
|
||||
ValueList args;
|
||||
return invoke(instance, args);
|
||||
}
|
||||
|
||||
inline Value MethodInfo::invoke(Value &instance) const
|
||||
{
|
||||
ValueList args;
|
||||
return invoke(instance, args);
|
||||
}
|
||||
inline Value MethodInfo::invoke(Value &instance) const
|
||||
{
|
||||
ValueList args;
|
||||
return invoke(instance, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -10,86 +10,86 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// This class stores information about a function parameter. A parameter
|
||||
/// is defined by its name, its type, its position within the parameter
|
||||
/// list, and zero or more attributes. Attributes describe how the
|
||||
/// parameter behave, for example whether it is an input or an output
|
||||
/// parameter.
|
||||
class ParameterInfo
|
||||
{
|
||||
public:
|
||||
enum ParameterAttributes
|
||||
{
|
||||
NONE = 0,
|
||||
/// This class stores information about a function parameter. A parameter
|
||||
/// is defined by its name, its type, its position within the parameter
|
||||
/// list, and zero or more attributes. Attributes describe how the
|
||||
/// parameter behave, for example whether it is an input or an output
|
||||
/// parameter.
|
||||
class ParameterInfo
|
||||
{
|
||||
public:
|
||||
enum ParameterAttributes
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
IN = 1, // parameter is used to pass data to the function
|
||||
OUT = 2, // parameter is used to return data from the function
|
||||
IN = 1, // parameter is used to pass data to the function
|
||||
OUT = 2, // parameter is used to return data from the function
|
||||
|
||||
INOUT = IN | OUT
|
||||
};
|
||||
INOUT = IN | OUT
|
||||
};
|
||||
|
||||
/// Direct initialization constructor.
|
||||
inline ParameterInfo(const std::string &name, const Type &type, int position, int attribs);
|
||||
/// Direct initialization constructor.
|
||||
inline ParameterInfo(const std::string &name, const Type &type, int position, int attribs);
|
||||
|
||||
/// Returns the parameter's name.
|
||||
inline const std::string &getName() const;
|
||||
/// Returns the parameter's name.
|
||||
inline const std::string &getName() const;
|
||||
|
||||
/// Return the parameter's position within the function's parameter
|
||||
/// list. This position is zero-based.
|
||||
inline int getPosition() const;
|
||||
/// Return the parameter's position within the function's parameter
|
||||
/// list. This position is zero-based.
|
||||
inline int getPosition() const;
|
||||
|
||||
/// Returns the parameter's type.
|
||||
inline const Type &getParameterType() const;
|
||||
/// Returns the parameter's type.
|
||||
inline const Type &getParameterType() const;
|
||||
|
||||
/// Returns the parameter's attributes.
|
||||
inline int getAttributes() const;
|
||||
/// Returns the parameter's attributes.
|
||||
inline int getAttributes() const;
|
||||
|
||||
/// Returns whether the parameter has the IN attribute.
|
||||
inline bool isIn() const { return (attribs_ & IN) != 0; }
|
||||
/// Returns whether the parameter has the IN attribute.
|
||||
inline bool isIn() const { return (attribs_ & IN) != 0; }
|
||||
|
||||
/// Returns whether the parameter has the OUT attribute.
|
||||
inline bool isOut() const { return (attribs_ & OUT) != 0; }
|
||||
/// Returns whether the parameter has the OUT attribute.
|
||||
inline bool isOut() const { return (attribs_ & OUT) != 0; }
|
||||
|
||||
/// Returns whether the parameter has both the IN and the
|
||||
/// OUT attribute.
|
||||
inline bool isInOut() const { return isIn() && isOut(); }
|
||||
/// Returns whether the parameter has both the IN and the
|
||||
/// OUT attribute.
|
||||
inline bool isInOut() const { return isIn() && isOut(); }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
const Type &type_;
|
||||
int position_;
|
||||
int attribs_;
|
||||
};
|
||||
private:
|
||||
std::string name_;
|
||||
const Type &type_;
|
||||
int position_;
|
||||
int attribs_;
|
||||
};
|
||||
|
||||
// INLINE METHODS
|
||||
// INLINE METHODS
|
||||
|
||||
inline ParameterInfo::ParameterInfo(const std::string &name, const Type &type, int position, int attribs)
|
||||
: name_(name),
|
||||
type_(type),
|
||||
position_(position),
|
||||
attribs_(attribs)
|
||||
{
|
||||
}
|
||||
inline ParameterInfo::ParameterInfo(const std::string &name, const Type &type, int position, int attribs)
|
||||
: name_(name),
|
||||
type_(type),
|
||||
position_(position),
|
||||
attribs_(attribs)
|
||||
{
|
||||
}
|
||||
|
||||
inline const std::string &ParameterInfo::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
inline const std::string &ParameterInfo::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline int ParameterInfo::getPosition() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
inline int ParameterInfo::getPosition() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
inline const Type &ParameterInfo::getParameterType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
inline const Type &ParameterInfo::getParameterType() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
inline int ParameterInfo::getAttributes() const
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
inline int ParameterInfo::getAttributes() const
|
||||
{
|
||||
return attribs_;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -14,248 +14,248 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// This class keeps information about a class' property. A property is
|
||||
/// defined by a name and a set of methods that store and retrieve
|
||||
/// values. When the user wants to "get" the value of a property, the
|
||||
/// getter method will be invoked and its value returned. When the user
|
||||
/// wants to "set" the value of a property, the setter method will be
|
||||
/// called. There are three kinds of property: simple (get/set), indexed
|
||||
/// (get[i1, i2, ...]/set[i1, i2, ...]), and array (count/add/get[i]/
|
||||
/// set[i]).
|
||||
/// Objects of class PropertyInfo can't be modified once they have been
|
||||
/// created, but they can be queried without restrictions. You can either
|
||||
/// retrieve the accessor methods and invoke them manually, or you can
|
||||
/// call getValue() / setValue() etc. methods to perform direct operations
|
||||
/// on the property, given an instance of the declaring type to work on.
|
||||
/// The latter technique is preferred because it checks for custom
|
||||
/// attributes associated to the PropertyInfo object and passes control
|
||||
/// to them when needed.
|
||||
///
|
||||
class OSGINTROSPECTION_EXPORT PropertyInfo: public CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Direct initialization constructor for simple and indexed
|
||||
/// properties.
|
||||
/// You must pass the Type object associated to the class that
|
||||
/// declares the property, the Type object that describes the
|
||||
/// type of the property's value, the property name and the
|
||||
/// getter/setter methods. Either the setter or the getter can
|
||||
/// be null, meaning a restricted access. If both are null, the
|
||||
/// user is expected to add a custom accessor attribute to this
|
||||
/// PropertyInfo object.
|
||||
/// If the getter method has parameters, the property is considered
|
||||
/// to be indexed. The same is true if the getter is null and the
|
||||
/// setter has more than one parameter.
|
||||
PropertyInfo(const Type &decltype, const Type &ptype, const std::string &name, const MethodInfo *getm, const MethodInfo *setm)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
ptype_(ptype),
|
||||
name_(name),
|
||||
getm_(getm),
|
||||
setm_(setm),
|
||||
numm_(0),
|
||||
addm_(0),
|
||||
is_array_(false)
|
||||
{
|
||||
if (getm_)
|
||||
{
|
||||
for (ParameterInfoList::size_type i=0; i<getm_->getParameters().size(); ++i)
|
||||
indices_.push_back(getm_->getParameters().at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setm_)
|
||||
{
|
||||
for (ParameterInfoList::size_type i=0; i<(setm_->getParameters().size()-1); ++i)
|
||||
indices_.push_back(setm_->getParameters().at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// This class keeps information about a class' property. A property is
|
||||
/// defined by a name and a set of methods that store and retrieve
|
||||
/// values. When the user wants to "get" the value of a property, the
|
||||
/// getter method will be invoked and its value returned. When the user
|
||||
/// wants to "set" the value of a property, the setter method will be
|
||||
/// called. There are three kinds of property: simple (get/set), indexed
|
||||
/// (get[i1, i2, ...]/set[i1, i2, ...]), and array (count/add/get[i]/
|
||||
/// set[i]).
|
||||
/// Objects of class PropertyInfo can't be modified once they have been
|
||||
/// created, but they can be queried without restrictions. You can either
|
||||
/// retrieve the accessor methods and invoke them manually, or you can
|
||||
/// call getValue() / setValue() etc. methods to perform direct operations
|
||||
/// on the property, given an instance of the declaring type to work on.
|
||||
/// The latter technique is preferred because it checks for custom
|
||||
/// attributes associated to the PropertyInfo object and passes control
|
||||
/// to them when needed.
|
||||
///
|
||||
class OSGINTROSPECTION_EXPORT PropertyInfo: public CustomAttributeProvider
|
||||
{
|
||||
public:
|
||||
/// Direct initialization constructor for simple and indexed
|
||||
/// properties.
|
||||
/// You must pass the Type object associated to the class that
|
||||
/// declares the property, the Type object that describes the
|
||||
/// type of the property's value, the property name and the
|
||||
/// getter/setter methods. Either the setter or the getter can
|
||||
/// be null, meaning a restricted access. If both are null, the
|
||||
/// user is expected to add a custom accessor attribute to this
|
||||
/// PropertyInfo object.
|
||||
/// If the getter method has parameters, the property is considered
|
||||
/// to be indexed. The same is true if the getter is null and the
|
||||
/// setter has more than one parameter.
|
||||
PropertyInfo(const Type &decltype, const Type &ptype, const std::string &name, const MethodInfo *getm, const MethodInfo *setm)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
ptype_(ptype),
|
||||
name_(name),
|
||||
getm_(getm),
|
||||
setm_(setm),
|
||||
numm_(0),
|
||||
addm_(0),
|
||||
is_array_(false)
|
||||
{
|
||||
if (getm_)
|
||||
{
|
||||
for (ParameterInfoList::size_type i=0; i<getm_->getParameters().size(); ++i)
|
||||
indices_.push_back(getm_->getParameters().at(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setm_)
|
||||
{
|
||||
for (ParameterInfoList::size_type i=0; i<(setm_->getParameters().size()-1); ++i)
|
||||
indices_.push_back(setm_->getParameters().at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Direct initialization constructor for "array" properties.
|
||||
/// You must pass the Type object associated to the type that
|
||||
/// declares the property, the Type object that describes the
|
||||
/// type of the property's value, the property name and the
|
||||
/// getter/setter/counter/adder methods.
|
||||
PropertyInfo(const Type &decltype, const Type &ptype, const std::string &name, const MethodInfo *getm, const MethodInfo *setm, const MethodInfo *numm, const MethodInfo *addm)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
ptype_(ptype),
|
||||
name_(name),
|
||||
getm_(getm),
|
||||
setm_(setm),
|
||||
numm_(numm),
|
||||
addm_(addm),
|
||||
is_array_(true)
|
||||
{
|
||||
}
|
||||
/// Direct initialization constructor for "array" properties.
|
||||
/// You must pass the Type object associated to the type that
|
||||
/// declares the property, the Type object that describes the
|
||||
/// type of the property's value, the property name and the
|
||||
/// getter/setter/counter/adder methods.
|
||||
PropertyInfo(const Type &decltype, const Type &ptype, const std::string &name, const MethodInfo *getm, const MethodInfo *setm, const MethodInfo *numm, const MethodInfo *addm)
|
||||
: CustomAttributeProvider(),
|
||||
decltype_(decltype),
|
||||
ptype_(ptype),
|
||||
name_(name),
|
||||
getm_(getm),
|
||||
setm_(setm),
|
||||
numm_(numm),
|
||||
addm_(addm),
|
||||
is_array_(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the number of indices
|
||||
inline int getNumIndices() const
|
||||
{
|
||||
return static_cast<int>(getIndexParameters().size());
|
||||
}
|
||||
/// Returns the number of indices
|
||||
inline int getNumIndices() const
|
||||
{
|
||||
return static_cast<int>(getIndexParameters().size());
|
||||
}
|
||||
|
||||
/// Returns the name of the property being described.
|
||||
inline virtual const std::string &getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
/// Returns the name of the property being described.
|
||||
inline virtual const std::string &getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
/// Returns the type that declares the property.
|
||||
inline virtual const Type &getDeclaringType() const
|
||||
{
|
||||
return decltype_;
|
||||
}
|
||||
/// Returns the type that declares the property.
|
||||
inline virtual const Type &getDeclaringType() const
|
||||
{
|
||||
return decltype_;
|
||||
}
|
||||
|
||||
/// Returns the type of the reflected property.
|
||||
inline const Type &getPropertyType() const
|
||||
{
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
if (pta) return pta->getPropertyType();
|
||||
return ptype_;
|
||||
}
|
||||
/// Returns the type of the reflected property.
|
||||
inline const Type &getPropertyType() const
|
||||
{
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
if (pta) return pta->getPropertyType();
|
||||
return ptype_;
|
||||
}
|
||||
|
||||
/// Returns the getter method.
|
||||
inline const MethodInfo *getGetMethod() const
|
||||
{
|
||||
return getm_;
|
||||
}
|
||||
/// Returns the getter method.
|
||||
inline const MethodInfo *getGetMethod() const
|
||||
{
|
||||
return getm_;
|
||||
}
|
||||
|
||||
/// Returns the setter method.
|
||||
inline const MethodInfo *getSetMethod() const
|
||||
{
|
||||
return setm_;
|
||||
}
|
||||
/// Returns the setter method.
|
||||
inline const MethodInfo *getSetMethod() const
|
||||
{
|
||||
return setm_;
|
||||
}
|
||||
|
||||
/// Returns the counter method.
|
||||
inline const MethodInfo *getCountMethod() const
|
||||
{
|
||||
return numm_;
|
||||
}
|
||||
/// Returns the counter method.
|
||||
inline const MethodInfo *getCountMethod() const
|
||||
{
|
||||
return numm_;
|
||||
}
|
||||
|
||||
/// Returns the adder method.
|
||||
inline const MethodInfo *getAddMethod() const
|
||||
{
|
||||
return addm_;
|
||||
}
|
||||
/// Returns the adder method.
|
||||
inline const MethodInfo *getAddMethod() const
|
||||
{
|
||||
return addm_;
|
||||
}
|
||||
|
||||
/// Returns whether the property's value can be retrieved.
|
||||
inline bool canGet() const
|
||||
{
|
||||
return (getm_ != 0) || isDefined<CustomPropertyGetAttribute>(false);
|
||||
}
|
||||
/// Returns whether the property's value can be retrieved.
|
||||
inline bool canGet() const
|
||||
{
|
||||
return (getm_ != 0) || isDefined<CustomPropertyGetAttribute>(false);
|
||||
}
|
||||
|
||||
/// Returns whether the property's value can be set.
|
||||
inline bool canSet() const
|
||||
{
|
||||
return setm_ != 0 || isDefined<CustomPropertySetAttribute>(false);
|
||||
}
|
||||
/// Returns whether the property's value can be set.
|
||||
inline bool canSet() const
|
||||
{
|
||||
return setm_ != 0 || isDefined<CustomPropertySetAttribute>(false);
|
||||
}
|
||||
|
||||
/// Returns whether the property's array of values can be counted.
|
||||
inline bool canCount() const
|
||||
{
|
||||
return numm_ != 0 || isDefined<CustomPropertyCountAttribute>(false);
|
||||
}
|
||||
/// Returns whether the property's array of values can be counted.
|
||||
inline bool canCount() const
|
||||
{
|
||||
return numm_ != 0 || isDefined<CustomPropertyCountAttribute>(false);
|
||||
}
|
||||
|
||||
/// Returns whether items can be added to the array property.
|
||||
inline bool canAdd() const
|
||||
{
|
||||
return addm_ != 0 || isDefined<CustomPropertyAddAttribute>(false);
|
||||
}
|
||||
/// Returns whether items can be added to the array property.
|
||||
inline bool canAdd() const
|
||||
{
|
||||
return addm_ != 0 || isDefined<CustomPropertyAddAttribute>(false);
|
||||
}
|
||||
|
||||
/// Returns whether the property is simple.
|
||||
inline bool isSimple() const
|
||||
{
|
||||
return !isIndexed() && !isArray();
|
||||
}
|
||||
/// Returns whether the property is simple.
|
||||
inline bool isSimple() const
|
||||
{
|
||||
return !isIndexed() && !isArray();
|
||||
}
|
||||
|
||||
/// Returns whether the property is indexed.
|
||||
inline bool isIndexed() const
|
||||
{
|
||||
return getNumIndices() > 0;
|
||||
}
|
||||
/// Returns whether the property is indexed.
|
||||
inline bool isIndexed() const
|
||||
{
|
||||
return getNumIndices() > 0;
|
||||
}
|
||||
|
||||
/// Returns whether the property is an array.
|
||||
inline bool isArray() const
|
||||
{
|
||||
return is_array_;
|
||||
}
|
||||
/// Returns whether the property is an array.
|
||||
inline bool isArray() const
|
||||
{
|
||||
return is_array_;
|
||||
}
|
||||
|
||||
/// Returns the list of index parameters.
|
||||
/// If the property is not indexed, this list is empty. If neither
|
||||
/// the get method nor the set method are defined, this list is
|
||||
/// empty unless a custom indexing attribute is defined.
|
||||
const ParameterInfoList &getIndexParameters() const;
|
||||
/// Returns the list of index parameters.
|
||||
/// If the property is not indexed, this list is empty. If neither
|
||||
/// the get method nor the set method are defined, this list is
|
||||
/// empty unless a custom indexing attribute is defined.
|
||||
const ParameterInfoList &getIndexParameters() const;
|
||||
|
||||
/// Returns a list of valid values that can be used for the specified
|
||||
/// index. If a custom indexing attribute is defined for this property,
|
||||
/// then it will be queried for the index set, otherwise the index
|
||||
/// will be treated as an enumeration and the set of enumeration
|
||||
/// values will be returned.
|
||||
void getIndexValueSet(int whichindex, const Value &instance, ValueList &values) const;
|
||||
/// Returns a list of valid values that can be used for the specified
|
||||
/// index. If a custom indexing attribute is defined for this property,
|
||||
/// then it will be queried for the index set, otherwise the index
|
||||
/// will be treated as an enumeration and the set of enumeration
|
||||
/// values will be returned.
|
||||
void getIndexValueSet(int whichindex, const Value &instance, ValueList &values) const;
|
||||
|
||||
/// Invokes the getter method on the given instance and
|
||||
/// returns the property's value. If a custom getter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
Value getValue(const Value &instance) const;
|
||||
/// Invokes the getter method on the given instance and
|
||||
/// returns the property's value. If a custom getter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
Value getValue(const Value &instance) const;
|
||||
|
||||
/// Invokes the setter method on the given instance and
|
||||
/// sets the property's value. If a custom setter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
void setValue(Value &instance, const Value &value) const;
|
||||
/// Invokes the setter method on the given instance and
|
||||
/// sets the property's value. If a custom setter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
void setValue(Value &instance, const Value &value) const;
|
||||
|
||||
/// Invokes the getter method on the given instance passing a list
|
||||
/// of indices and returns the indexed property's value. If a custom
|
||||
/// getter attribute is defined, it will be invoked instead.
|
||||
Value getIndexedValue(const Value &instance, ValueList &indices) const;
|
||||
/// Invokes the getter method on the given instance passing a list
|
||||
/// of indices and returns the indexed property's value. If a custom
|
||||
/// getter attribute is defined, it will be invoked instead.
|
||||
Value getIndexedValue(const Value &instance, ValueList &indices) const;
|
||||
|
||||
/// Invokes the setter method on the given instance passing a list
|
||||
/// of indices and sets the indexed property's value. If a custom
|
||||
/// setter attribute is defined, it will be invoked instead.
|
||||
void setIndexedValue(Value &instance, ValueList &indices, const Value &value) const;
|
||||
/// Invokes the setter method on the given instance passing a list
|
||||
/// of indices and sets the indexed property's value. If a custom
|
||||
/// setter attribute is defined, it will be invoked instead.
|
||||
void setIndexedValue(Value &instance, ValueList &indices, const Value &value) const;
|
||||
|
||||
/// Invokes the counter method on the given instance and returns
|
||||
/// the number of items of the array property. If a custom counter
|
||||
/// attribute is defined, it will be invoked instead.
|
||||
int getNumArrayItems(const Value &instance) const;
|
||||
/// Invokes the counter method on the given instance and returns
|
||||
/// the number of items of the array property. If a custom counter
|
||||
/// attribute is defined, it will be invoked instead.
|
||||
int getNumArrayItems(const Value &instance) const;
|
||||
|
||||
/// Invokes the getter method on the given instance and returns
|
||||
/// the i-th item of the array property. If a custom getter attribute
|
||||
/// us defined, it will be invoked instead.
|
||||
Value getArrayItem(const Value &instance, int i) const;
|
||||
/// Invokes the getter method on the given instance and returns
|
||||
/// the i-th item of the array property. If a custom getter attribute
|
||||
/// us defined, it will be invoked instead.
|
||||
Value getArrayItem(const Value &instance, int i) const;
|
||||
|
||||
/// Invokes the setter method on the given instance and sets
|
||||
/// the i-th item of the array property. If a custom setter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
void setArrayItem(Value &instance, int i, const Value &value) const;
|
||||
/// Invokes the setter method on the given instance and sets
|
||||
/// the i-th item of the array property. If a custom setter attribute
|
||||
/// is defined, it will be invoked instead.
|
||||
void setArrayItem(Value &instance, int i, const Value &value) const;
|
||||
|
||||
/// Invokes the adder method on the given instance and adds
|
||||
/// an item to the array property. If a custom adder attribute is
|
||||
/// defined, it will be invoked instead.
|
||||
void addArrayItem(Value &instance, const Value &value) const;
|
||||
/// Invokes the adder method on the given instance and adds
|
||||
/// an item to the array property. If a custom adder attribute is
|
||||
/// defined, it will be invoked instead.
|
||||
void addArrayItem(Value &instance, const Value &value) const;
|
||||
|
||||
/// Returns the default value associated to the reflected property.
|
||||
/// If no default value has been specified, this method tries to
|
||||
/// create an instance of the property type and then returns its
|
||||
/// value. There are some attributes that change the behavior of
|
||||
/// this method, for example NoDefaultValueAttribute.
|
||||
Value getDefaultValue() const;
|
||||
/// Returns the default value associated to the reflected property.
|
||||
/// If no default value has been specified, this method tries to
|
||||
/// create an instance of the property type and then returns its
|
||||
/// value. There are some attributes that change the behavior of
|
||||
/// this method, for example NoDefaultValueAttribute.
|
||||
Value getDefaultValue() const;
|
||||
|
||||
protected:
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
protected:
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
|
||||
private:
|
||||
const Type &decltype_;
|
||||
const Type &ptype_;
|
||||
std::string name_;
|
||||
const MethodInfo *getm_;
|
||||
const MethodInfo *setm_;
|
||||
const MethodInfo *numm_;
|
||||
const MethodInfo *addm_;
|
||||
ParameterInfoList indices_;
|
||||
bool is_array_;
|
||||
};
|
||||
private:
|
||||
const Type &decltype_;
|
||||
const Type &ptype_;
|
||||
std::string name_;
|
||||
const MethodInfo *getm_;
|
||||
const MethodInfo *setm_;
|
||||
const MethodInfo *numm_;
|
||||
const MethodInfo *addm_;
|
||||
ParameterInfoList indices_;
|
||||
bool is_array_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,255 +16,255 @@
|
||||
namespace osg
|
||||
{
|
||||
|
||||
/// ----------------------------------------------------------------------
|
||||
/// TEMPORARY FIX
|
||||
/// (currently osg::Vec? classes don't support input streaming)
|
||||
/// (currently osg::ref_ptr<> class doesn't support I/O streaming)
|
||||
inline std::istream& operator >> (std::istream& input, Vec2f& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1];
|
||||
return input;
|
||||
}
|
||||
/// ----------------------------------------------------------------------
|
||||
/// TEMPORARY FIX
|
||||
/// (currently osg::Vec? classes don't support input streaming)
|
||||
/// (currently osg::ref_ptr<> class doesn't support I/O streaming)
|
||||
inline std::istream& operator >> (std::istream& input, Vec2f& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1];
|
||||
return input;
|
||||
}
|
||||
|
||||
inline std::istream& operator >> (std::istream& input, Vec3f& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1] >> vec._v[2];
|
||||
return input;
|
||||
}
|
||||
inline std::istream& operator >> (std::istream& input, Vec3f& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1] >> vec._v[2];
|
||||
return input;
|
||||
}
|
||||
|
||||
inline std::istream& operator >> (std::istream& input, Vec4& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1] >> vec._v[2] >> vec._v[3];
|
||||
return input;
|
||||
}
|
||||
inline std::istream& operator >> (std::istream& input, Vec4& vec)
|
||||
{
|
||||
input >> vec._v[0] >> vec._v[1] >> vec._v[2] >> vec._v[3];
|
||||
return input;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream &operator << (std::ostream &s, const osg::ref_ptr<T> &r)
|
||||
{
|
||||
return s << r.get();
|
||||
}
|
||||
template<typename T>
|
||||
std::ostream &operator << (std::ostream &s, const osg::ref_ptr<T> &r)
|
||||
{
|
||||
return s << r.get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::istream &operator >> (std::istream &s, osg::ref_ptr<T> &r)
|
||||
{
|
||||
void *ptr;
|
||||
s >> ptr;
|
||||
r = (T *)ptr;
|
||||
return s;
|
||||
}
|
||||
template<typename T>
|
||||
std::istream &operator >> (std::istream &s, osg::ref_ptr<T> &r)
|
||||
{
|
||||
void *ptr;
|
||||
s >> ptr;
|
||||
r = (T *)ptr;
|
||||
return s;
|
||||
}
|
||||
|
||||
///
|
||||
/// END OF TEMPORARY FIX
|
||||
/// ----------------------------------------------------------------------
|
||||
///
|
||||
/// END OF TEMPORARY FIX
|
||||
/// ----------------------------------------------------------------------
|
||||
}
|
||||
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// This is the base class for reader/writer objects. A ReaderWriter's
|
||||
/// purpose is to provide the means for writing the content of a Value
|
||||
/// object to a stream and for reading it back. Descendants can either
|
||||
/// be specialized for just one data type or they can handle several
|
||||
/// types, that's up to the implementor. A derived class is not required
|
||||
/// to support all streaming operations (text write, text read, bin write
|
||||
/// and bin read), it can implement just some of them, although full
|
||||
/// support is strongly encouraged.
|
||||
class ReaderWriter
|
||||
{
|
||||
public:
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options(): fno_(false) {}
|
||||
virtual ~Options() {}
|
||||
/// This is the base class for reader/writer objects. A ReaderWriter's
|
||||
/// purpose is to provide the means for writing the content of a Value
|
||||
/// object to a stream and for reading it back. Descendants can either
|
||||
/// be specialized for just one data type or they can handle several
|
||||
/// types, that's up to the implementor. A derived class is not required
|
||||
/// to support all streaming operations (text write, text read, bin write
|
||||
/// and bin read), it can implement just some of them, although full
|
||||
/// support is strongly encouraged.
|
||||
class ReaderWriter
|
||||
{
|
||||
public:
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
Options(): fno_(false) {}
|
||||
virtual ~Options() {}
|
||||
|
||||
bool getForceNumericOutput() const { return fno_; }
|
||||
void setForceNumericOutput(bool fno) { fno_ = fno; }
|
||||
bool getForceNumericOutput() const { return fno_; }
|
||||
void setForceNumericOutput(bool fno) { fno_ = fno; }
|
||||
|
||||
private:
|
||||
bool fno_;
|
||||
};
|
||||
private:
|
||||
bool fno_;
|
||||
};
|
||||
|
||||
/// 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()); }
|
||||
/// 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()); }
|
||||
|
||||
/// 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()); }
|
||||
/// 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()); }
|
||||
|
||||
/// 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()); }
|
||||
/// 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()); }
|
||||
|
||||
/// 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()); }
|
||||
/// 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 destructor.
|
||||
virtual ~ReaderWriter() {}
|
||||
};
|
||||
/// Virtual destructor.
|
||||
virtual ~ReaderWriter() {}
|
||||
};
|
||||
|
||||
/// This class template provides basic default streaming capabilities
|
||||
/// for all types that define streaming operators (<< and >>). Most of
|
||||
/// the standard types are able to be read and written this way, so the
|
||||
/// StdReaderWriter template can be a convenient default for several
|
||||
/// types. The binary representation is a raw copy of the memory content.
|
||||
///
|
||||
/// TO-DO: improve binary streaming and avoid arch dependency.
|
||||
///
|
||||
template<typename T>
|
||||
class StdReaderWriter: public ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options * = 0) const
|
||||
{
|
||||
return (os << variant_cast<T>(v));
|
||||
}
|
||||
/// This class template provides basic default streaming capabilities
|
||||
/// for all types that define streaming operators (<< and >>). Most of
|
||||
/// the standard types are able to be read and written this way, so the
|
||||
/// StdReaderWriter template can be a convenient default for several
|
||||
/// types. The binary representation is a raw copy of the memory content.
|
||||
///
|
||||
/// TO-DO: improve binary streaming and avoid arch dependency.
|
||||
///
|
||||
template<typename T>
|
||||
class StdReaderWriter: public ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options * = 0) const
|
||||
{
|
||||
return (os << variant_cast<T>(v));
|
||||
}
|
||||
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
return (is >> variant_cast<T &>(v));
|
||||
}
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
return (is >> variant_cast<T &>(v));
|
||||
}
|
||||
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options * = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options * = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/// This ReaderWriter can be used to read and write enumeration values.
|
||||
/// The textual representation will be the enum label, if found, or the
|
||||
/// numerical value. The binary representation doesn't take label names
|
||||
/// into account.
|
||||
template<typename T>
|
||||
class EnumReaderWriter: public ReaderWriter
|
||||
{
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options *options = 0) const
|
||||
{
|
||||
int numeric = static_cast<int>(variant_cast<T>(v));
|
||||
/// This ReaderWriter can be used to read and write enumeration values.
|
||||
/// The textual representation will be the enum label, if found, or the
|
||||
/// numerical value. The binary representation doesn't take label names
|
||||
/// into account.
|
||||
template<typename T>
|
||||
class EnumReaderWriter: public ReaderWriter
|
||||
{
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options *options = 0) const
|
||||
{
|
||||
int numeric = static_cast<int>(variant_cast<T>(v));
|
||||
|
||||
if (!options || !options->getForceNumericOutput())
|
||||
{
|
||||
const Type &type = v.getType();
|
||||
const EnumLabelMap &elm = type.getEnumLabels();
|
||||
EnumLabelMap::const_iterator i = elm.find(numeric);
|
||||
if (i != elm.end())
|
||||
{
|
||||
os << i->second;
|
||||
return os;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> labels;
|
||||
if (!options || !options->getForceNumericOutput())
|
||||
{
|
||||
const Type &type = v.getType();
|
||||
const EnumLabelMap &elm = type.getEnumLabels();
|
||||
EnumLabelMap::const_iterator i = elm.find(numeric);
|
||||
if (i != elm.end())
|
||||
{
|
||||
os << i->second;
|
||||
return os;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> labels;
|
||||
|
||||
// it could be a bitmask
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (i->first != 0 && ((i->first & numeric) == i->first))
|
||||
{
|
||||
numeric ^= i->first;
|
||||
labels.push_back(i->second);
|
||||
}
|
||||
}
|
||||
// it could be a bitmask
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (i->first != 0 && ((i->first & numeric) == i->first))
|
||||
{
|
||||
numeric ^= i->first;
|
||||
labels.push_back(i->second);
|
||||
}
|
||||
}
|
||||
|
||||
// check whether all bits were discovered
|
||||
if (numeric == 0)
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator i=labels.begin(); i!=labels.end(); ++i)
|
||||
{
|
||||
os << *i;
|
||||
if ((i+1) != labels.end()) os << " | ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check whether all bits were discovered
|
||||
if (numeric == 0)
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator i=labels.begin(); i!=labels.end(); ++i)
|
||||
{
|
||||
os << *i;
|
||||
if ((i+1) != labels.end()) os << " | ";
|
||||
}
|
||||
return os;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return os << numeric;
|
||||
}
|
||||
return os << numeric;
|
||||
}
|
||||
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options * = 0) const
|
||||
{
|
||||
if (v.isEmpty()) v = Value(T());
|
||||
|
||||
int i;
|
||||
if (is >> i)
|
||||
{
|
||||
variant_cast<T &>(v) = static_cast<T>(i);
|
||||
return is;
|
||||
}
|
||||
int i;
|
||||
if (is >> i)
|
||||
{
|
||||
variant_cast<T &>(v) = static_cast<T>(i);
|
||||
return is;
|
||||
}
|
||||
|
||||
is.clear();
|
||||
is.clear();
|
||||
|
||||
std::string s;
|
||||
if (is >> s)
|
||||
{
|
||||
const Type &type = v.getType();
|
||||
const EnumLabelMap &elm = type.getEnumLabels();
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (i->second.compare(s) == 0)
|
||||
{
|
||||
variant_cast<T &>(v) = static_cast<T>(i->first);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string s;
|
||||
if (is >> s)
|
||||
{
|
||||
const Type &type = v.getType();
|
||||
const EnumLabelMap &elm = type.getEnumLabels();
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (i->second.compare(s) == 0)
|
||||
{
|
||||
variant_cast<T &>(v) = static_cast<T>(i->first);
|
||||
return is;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options *options = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options *options = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options *options = 0) const
|
||||
{
|
||||
if (v.isEmpty())
|
||||
v = Value(T());
|
||||
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options *options = 0) const
|
||||
{
|
||||
if (v.isEmpty())
|
||||
v = Value(T());
|
||||
return is.read(reinterpret_cast<char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/// This is a ReaderWriter class that can be used to read and write
|
||||
/// pointer values. Note: template parameter T must be a pointer!
|
||||
template<typename T>
|
||||
class PtrReaderWriter: public ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options* = 0) const
|
||||
{
|
||||
return (os << (void*)variant_cast<T>(v));
|
||||
}
|
||||
/// This is a ReaderWriter class that can be used to read and write
|
||||
/// pointer values. Note: template parameter T must be a pointer!
|
||||
template<typename T>
|
||||
class PtrReaderWriter: public ReaderWriter
|
||||
{
|
||||
public:
|
||||
virtual std::ostream &writeTextValue(std::ostream &os, const Value &v, const Options* = 0) const
|
||||
{
|
||||
return (os << (void*)variant_cast<T>(v));
|
||||
}
|
||||
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options* = 0) const
|
||||
{
|
||||
void *ptr;
|
||||
is >> ptr;
|
||||
v = Value(T(ptr));
|
||||
return is;
|
||||
}
|
||||
virtual std::istream &readTextValue(std::istream &is, Value &v, const Options* = 0) const
|
||||
{
|
||||
void *ptr;
|
||||
is >> ptr;
|
||||
v = Value(T(ptr));
|
||||
return is;
|
||||
}
|
||||
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options* = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
virtual std::ostream &writeBinaryValue(std::ostream &os, const Value &v, const Options* = 0) const
|
||||
{
|
||||
return os.write(reinterpret_cast<const char *>(extract_raw_data<T>(v)), sizeof(T));
|
||||
}
|
||||
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options* = 0) const
|
||||
{
|
||||
T ptr;
|
||||
is.read(reinterpret_cast<char *>(&ptr), sizeof(T));
|
||||
v = Value(ptr);
|
||||
return is;
|
||||
}
|
||||
};
|
||||
virtual std::istream &readBinaryValue(std::istream &is, Value &v, const Options* = 0) const
|
||||
{
|
||||
T ptr;
|
||||
is.read(reinterpret_cast<char *>(&ptr), sizeof(T));
|
||||
v = Value(ptr);
|
||||
return is;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -14,67 +14,67 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
class Type;
|
||||
class Type;
|
||||
|
||||
/// 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;
|
||||
}
|
||||
};
|
||||
/// 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 type_info structure.
|
||||
typedef std::map<const std::type_info *, Type *, TypeInfoCmp> TypeMap;
|
||||
|
||||
|
||||
/// This class provides basic reflection services such as registration
|
||||
/// of new types and queries on the global type map.
|
||||
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
|
||||
/// "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);
|
||||
/// This class provides basic reflection services such as registration
|
||||
/// of new types and queries on the global type map.
|
||||
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
|
||||
/// "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);
|
||||
|
||||
/// Finds a Type object given its qualified name, which must
|
||||
/// be identical to the qualified name returned by that Type's
|
||||
/// getQualifiedName() method. If the type hasn't been created
|
||||
/// yet, an exception is thrown.
|
||||
static const Type &getType(const std::string &qname);
|
||||
/// Finds a Type object given its qualified name, which must
|
||||
/// be identical to the qualified name returned by that Type's
|
||||
/// getQualifiedName() method. If the type hasn't been created
|
||||
/// yet, an exception is thrown.
|
||||
static const Type &getType(const std::string &qname);
|
||||
|
||||
/// Returns the global map of types.
|
||||
static const TypeMap &getTypes();
|
||||
/// Returns the global map of types.
|
||||
static const TypeMap &getTypes();
|
||||
|
||||
/// Return the Type object associated to the C++ type 'void'.
|
||||
/// This is a shortcut for typeof(void), which may be slow if
|
||||
/// the type map is large.
|
||||
static const Type &type_void();
|
||||
|
||||
private:
|
||||
template<typename C> friend class Reflector;
|
||||
/// Return the Type object associated to the C++ type 'void'.
|
||||
/// This is a shortcut for typeof(void), which may be slow if
|
||||
/// the type map is large.
|
||||
static const Type &type_void();
|
||||
|
||||
private:
|
||||
template<typename C> friend class Reflector;
|
||||
|
||||
struct StaticData
|
||||
{
|
||||
TypeMap typemap;
|
||||
const Type *type_void;
|
||||
};
|
||||
struct StaticData
|
||||
{
|
||||
TypeMap typemap;
|
||||
const Type *type_void;
|
||||
};
|
||||
|
||||
static StaticData &getOrCreateStaticData();
|
||||
static Type *registerType(const std::type_info &ti);
|
||||
static Type *registerOrReplaceType(const std::type_info &ti);
|
||||
static StaticData &getOrCreateStaticData();
|
||||
static Type *registerType(const std::type_info &ti);
|
||||
static Type *registerOrReplaceType(const std::type_info &ti);
|
||||
|
||||
private:
|
||||
static StaticData *staticdata__;
|
||||
};
|
||||
private:
|
||||
static StaticData *staticdata__;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -32,19 +32,19 @@
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define BEGIN_ENUM_REFLECTOR(c) \
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::EnumReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::EnumReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
|
||||
#define BEGIN_VALUE_REFLECTOR(c) \
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::ValueReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c, 0) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::ValueReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c, 0) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
|
||||
#define BEGIN_OBJECT_REFLECTOR(c) \
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::ObjectReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::ObjectReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
|
||||
#define BEGIN_ABSTRACT_OBJECT_REFLECTOR(c) \
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::AbstractObjectReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
namespace { struct OSG_RM_LINEID(reflector): public osgIntrospection::AbstractObjectReflector<c > { OSG_RM_LINEID(reflector)(): inherited(#c) { osgIntrospection::ParameterInfoList params; osgIntrospection::CustomAttributeProvider *cap = getType();
|
||||
|
||||
#define END_REFLECTOR \
|
||||
} } OSG_RM_LINEID(reflector_instance); }
|
||||
} } OSG_RM_LINEID(reflector_instance); }
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -66,62 +66,62 @@
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define Property(t, n) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method0(t, get##n), \
|
||||
Method1(void, set##n, IN, t, value)))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method0(t, get##n), \
|
||||
Method1(void, set##n, IN, t, value)))
|
||||
|
||||
#define ReadOnlyProperty(t, n) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method0(t, get##n), \
|
||||
0))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method0(t, get##n), \
|
||||
0))
|
||||
|
||||
#define WriteOnlyProperty(t, n) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
0, \
|
||||
Method1(void, set##n, IN, t, value)))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
0, \
|
||||
Method1(void, set##n, IN, t, value)))
|
||||
|
||||
#define PropertyWithCustomAccessors(t, n) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
0, \
|
||||
0))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
0, \
|
||||
0))
|
||||
|
||||
#define ArrayProperty(t, n, np) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #np, \
|
||||
Method1(t, get##n, IN, unsigned int, index), \
|
||||
Method2(void, set##n, IN, unsigned int, index, IN, t, value), \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #np, \
|
||||
Method1(t, get##n, IN, unsigned int, index), \
|
||||
Method2(void, set##n, IN, unsigned int, index, IN, t, value), \
|
||||
Method0(unsigned int, getNum##np), \
|
||||
Method1(void, add##n, IN, t, value)))
|
||||
Method1(void, add##n, IN, t, value)))
|
||||
|
||||
#define ArrayPropertyWithCustomAccessors(t, n, np) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #np, \
|
||||
0, \
|
||||
0, \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #np, \
|
||||
0, \
|
||||
0))
|
||||
0, \
|
||||
0, \
|
||||
0))
|
||||
|
||||
#define ArrayPropertyWithReturnType(t, n, np, r) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method1(t, get##n, IN, unsigned int, index), \
|
||||
Method2(r, set##n, IN, unsigned int, index, IN, t, value), \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method1(t, get##n, IN, unsigned int, index), \
|
||||
Method2(r, set##n, IN, unsigned int, index, IN, t, value), \
|
||||
Method0(unsigned int, getNum##np), \
|
||||
Method1(r, add##n, IN, t, value)))
|
||||
Method1(r, add##n, IN, t, value)))
|
||||
|
||||
#define IndexedProperty IndexedProperty1
|
||||
|
||||
#define IndexedProperty1(t, n, i0, n0) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method1(t, get##n, IN, i0, n0), \
|
||||
Method2(void, set##n, IN, i0, n0, IN, t, value)))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method1(t, get##n, IN, i0, n0), \
|
||||
Method2(void, set##n, IN, i0, n0, IN, t, value)))
|
||||
|
||||
#define IndexedProperty2(t, n, i0, n0, i1, n1) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method2(t, get##n, IN, i0, n0, IN, i1, n1), \
|
||||
Method3(void, set##n, IN, i0, n0, IN i1, n1, IN, t, value)))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method2(t, get##n, IN, i0, n0, IN, i1, n1), \
|
||||
Method3(void, set##n, IN, i0, n0, IN i1, n1, IN, t, value)))
|
||||
|
||||
#define IndexedProperty3(t, n, i0, n0, i1, n1, i2, n2) \
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method3(t, get##n, IN, i0, n0, IN, i1, n1, IN, i2, n2), \
|
||||
Method4(void, set##n, IN, i0, n0, IN i1, n1, IN, i2, n2, IN, t, value)))
|
||||
cap=addProperty(new osgIntrospection::PropertyInfo(osgIntrospection::Reflection::getType(typeid(reflected_type)), osgIntrospection::Reflection::getType(typeid(t)), #n, \
|
||||
Method3(t, get##n, IN, i0, n0, IN, i1, n1, IN, i2, n2), \
|
||||
Method4(void, set##n, IN, i0, n0, IN i1, n1, IN, i2, n2, IN, t, value)))
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ENUM LABELS
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,394 +14,394 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
// forward declarations
|
||||
class MethodInfo;
|
||||
class PropertyInfo;
|
||||
class ParameterInfo;
|
||||
class ReaderWriter;
|
||||
|
||||
// typedefs for member info lists
|
||||
typedef std::vector<const MethodInfo *> MethodInfoList;
|
||||
typedef std::vector<const PropertyInfo *> PropertyInfoList;
|
||||
typedef std::vector<const ParameterInfo *> ParameterInfoList;
|
||||
|
||||
// typedef for enum label map
|
||||
typedef std::map<int, std::string> EnumLabelMap;
|
||||
|
||||
/// Base class for instance creators. An instance creator is
|
||||
/// a lightweight object that creates a Value containing an
|
||||
/// instance of some type. Every non-abstract Type object has
|
||||
/// an instance creator that creates instances of that type.
|
||||
/// This is an abstract interface, it must be derived to
|
||||
/// provide the actual implementation of createInstance().
|
||||
struct InstanceCreatorBase
|
||||
{
|
||||
virtual Value createInstance() const = 0;
|
||||
};
|
||||
|
||||
/// This is an instance creator to be used with types that ought to
|
||||
/// be created on the heap, for example all classes derived from
|
||||
/// osg::Referenced.
|
||||
template<typename T>
|
||||
struct InstanceCreator: public InstanceCreatorBase
|
||||
{
|
||||
Value createInstance() const
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
};
|
||||
|
||||
/// This is an instance creator to be used with types that can be
|
||||
/// created on the stack (for example: int, std::string, or other
|
||||
/// possibly small user-defined structs or classes).
|
||||
template<typename T>
|
||||
struct ValueInstanceCreator: public InstanceCreatorBase
|
||||
{
|
||||
Value createInstance() const
|
||||
{
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
/// 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 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 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;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// 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 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 ¶ms, 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;
|
||||
// forward declarations
|
||||
class MethodInfo;
|
||||
class PropertyInfo;
|
||||
class ParameterInfo;
|
||||
class ReaderWriter;
|
||||
|
||||
// typedefs for member info lists
|
||||
typedef std::vector<const MethodInfo *> MethodInfoList;
|
||||
typedef std::vector<const PropertyInfo *> PropertyInfoList;
|
||||
typedef std::vector<const ParameterInfo *> ParameterInfoList;
|
||||
|
||||
// typedef for enum label map
|
||||
typedef std::map<int, std::string> EnumLabelMap;
|
||||
|
||||
/// Base class for instance creators. An instance creator is
|
||||
/// a lightweight object that creates a Value containing an
|
||||
/// instance of some type. Every non-abstract Type object has
|
||||
/// an instance creator that creates instances of that type.
|
||||
/// This is an abstract interface, it must be derived to
|
||||
/// provide the actual implementation of createInstance().
|
||||
struct InstanceCreatorBase
|
||||
{
|
||||
virtual Value createInstance() const = 0;
|
||||
};
|
||||
|
||||
/// This is an instance creator to be used with types that ought to
|
||||
/// be created on the heap, for example all classes derived from
|
||||
/// osg::Referenced.
|
||||
template<typename T>
|
||||
struct InstanceCreator: public InstanceCreatorBase
|
||||
{
|
||||
Value createInstance() const
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
};
|
||||
|
||||
/// This is an instance creator to be used with types that can be
|
||||
/// created on the stack (for example: int, std::string, or other
|
||||
/// possibly small user-defined structs or classes).
|
||||
template<typename T>
|
||||
struct ValueInstanceCreator: public InstanceCreatorBase
|
||||
{
|
||||
Value createInstance() const
|
||||
{
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
/// 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 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 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;
|
||||
|
||||
/// 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;
|
||||
|
||||
/// 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 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 ¶ms, 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;
|
||||
|
||||
/// 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.
|
||||
inline Value createInstance() const;
|
||||
|
||||
protected:
|
||||
Type(const std::type_info &ti)
|
||||
: ti_(ti),
|
||||
is_const_(false),
|
||||
pointed_type_(0),
|
||||
is_defined_(false),
|
||||
icb_(0),
|
||||
rw_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// throws an exception if the type is not defined.
|
||||
void check_defined() const;
|
||||
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
|
||||
void set_instance_creator(const InstanceCreatorBase *icb)
|
||||
{
|
||||
delete icb_;
|
||||
icb_ = icb;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename C> friend class Reflector;
|
||||
friend class Reflection;
|
||||
|
||||
Type(const Type ©): CustomAttributeProvider(copy), ti_(copy.ti_) {}
|
||||
|
||||
const std::type_info &ti_;
|
||||
|
||||
std::string name_;
|
||||
std::string namespace_;
|
||||
|
||||
typedef std::vector<const Type *> TypeList;
|
||||
TypeList base_;
|
||||
|
||||
bool is_const_;
|
||||
const Type *pointed_type_;
|
||||
|
||||
PropertyInfoList props_;
|
||||
MethodInfoList methods_;
|
||||
|
||||
EnumLabelMap labels_;
|
||||
bool is_defined_;
|
||||
|
||||
const InstanceCreatorBase *icb_;
|
||||
const ReaderWriter *rw_;
|
||||
};
|
||||
|
||||
// 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<int>(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 icb_ == 0;
|
||||
}
|
||||
|
||||
inline bool Type::isAtomic() const
|
||||
{
|
||||
check_defined();
|
||||
return rw_ != 0;
|
||||
}
|
||||
|
||||
inline const PropertyInfoList &Type::getProperties() const
|
||||
{
|
||||
check_defined();
|
||||
return props_;
|
||||
}
|
||||
|
||||
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 Type &Type::getBaseType(int i) const
|
||||
{
|
||||
check_defined();
|
||||
return *base_.at(i);
|
||||
}
|
||||
|
||||
inline Value Type::createInstance() const
|
||||
{
|
||||
check_defined();
|
||||
if (!icb_)
|
||||
throw TypeIsAbstractException(ti_);
|
||||
return icb_->createInstance();
|
||||
}
|
||||
/// 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;
|
||||
|
||||
/// 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.
|
||||
inline Value createInstance() const;
|
||||
|
||||
protected:
|
||||
Type(const std::type_info &ti)
|
||||
: ti_(ti),
|
||||
is_const_(false),
|
||||
pointed_type_(0),
|
||||
is_defined_(false),
|
||||
icb_(0),
|
||||
rw_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// throws an exception if the type is not defined.
|
||||
void check_defined() const;
|
||||
|
||||
virtual void getInheritedProviders(CustomAttributeProviderList &providers) const;
|
||||
|
||||
void set_instance_creator(const InstanceCreatorBase *icb)
|
||||
{
|
||||
delete icb_;
|
||||
icb_ = icb;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename C> friend class Reflector;
|
||||
friend class Reflection;
|
||||
|
||||
Type(const Type ©): CustomAttributeProvider(copy), ti_(copy.ti_) {}
|
||||
|
||||
const std::type_info &ti_;
|
||||
|
||||
std::string name_;
|
||||
std::string namespace_;
|
||||
|
||||
typedef std::vector<const Type *> TypeList;
|
||||
TypeList base_;
|
||||
|
||||
bool is_const_;
|
||||
const Type *pointed_type_;
|
||||
|
||||
PropertyInfoList props_;
|
||||
MethodInfoList methods_;
|
||||
|
||||
EnumLabelMap labels_;
|
||||
bool is_defined_;
|
||||
|
||||
const InstanceCreatorBase *icb_;
|
||||
const ReaderWriter *rw_;
|
||||
};
|
||||
|
||||
// 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<int>(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 icb_ == 0;
|
||||
}
|
||||
|
||||
inline bool Type::isAtomic() const
|
||||
{
|
||||
check_defined();
|
||||
return rw_ != 0;
|
||||
}
|
||||
|
||||
inline const PropertyInfoList &Type::getProperties() const
|
||||
{
|
||||
check_defined();
|
||||
return props_;
|
||||
}
|
||||
|
||||
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 Type &Type::getBaseType(int i) const
|
||||
{
|
||||
check_defined();
|
||||
return *base_.at(i);
|
||||
}
|
||||
|
||||
inline Value Type::createInstance() const
|
||||
{
|
||||
check_defined();
|
||||
if (!icb_)
|
||||
throw TypeIsAbstractException(ti_);
|
||||
return icb_->createInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,416 +11,416 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
class Type;
|
||||
|
||||
class OSGINTROSPECTION_EXPORT Value
|
||||
{
|
||||
public:
|
||||
/// Default constructor. Initializes internal structures
|
||||
/// so that the Type returned by getType() is typeof(void),
|
||||
/// and the value is empty so that isEmpty() returns true.
|
||||
/// Be careful when using empty values, as some operations
|
||||
/// on them may throw an exception.
|
||||
inline Value();
|
||||
|
||||
/// Direct initialization constructor for void pointers.
|
||||
/// Although one of the constructor templates below could
|
||||
/// certainly handle void pointers as well, we need to treat
|
||||
/// them separately because void* can't be dereferenced.
|
||||
inline Value(void *v);
|
||||
|
||||
/// Direct initialization constructor for const void pointers.
|
||||
/// Although one of the constructor templates below could
|
||||
/// certainly handle void pointers as well, we need to treat
|
||||
/// them separately because void* can't be dereferenced.
|
||||
inline Value(const void *v);
|
||||
|
||||
/// Direct initialization constructor template for non-const
|
||||
/// pointers. By initializing an instance of Value through
|
||||
/// this constructor, internal structures will be configured
|
||||
/// to handle polymorphic types. This means you'll be able to
|
||||
/// call getInstanceType() to get the actual type of the
|
||||
/// dereferenced value.
|
||||
template<typename T> Value(T *v);
|
||||
|
||||
/// Direct initialization constructor template for non-const
|
||||
/// pointers. By initializing an instance of Value through
|
||||
/// this constructor, internal structures will be configured
|
||||
/// to handle polymorphic types. This means you'll be able to
|
||||
/// call getInstanceType() to get the actual type of the
|
||||
/// dereferenced value.
|
||||
template<typename T> Value(const T *v);
|
||||
|
||||
/// Direct initialization constructor template for all types
|
||||
/// that are not handled by any of the constructors above.
|
||||
/// Calling getInstanceType() on an instance constructed
|
||||
/// this way returns the same as getType().
|
||||
template<typename T> Value(const T &v);
|
||||
|
||||
/// Copy constructor. The underlying value's type must have
|
||||
/// consistent copy semantics.
|
||||
inline Value(const Value ©);
|
||||
|
||||
/// Destructor. Frees internal resources but it does NOT delete
|
||||
/// the value held. For example, this function will produce a
|
||||
/// memory leak: void f() { Value v(new int); }
|
||||
inline ~Value();
|
||||
|
||||
/// Assignment operator. Behaves like the copy constructor.
|
||||
inline Value &operator=(const Value ©);
|
||||
|
||||
/// Returns whether the value is a pointer and it points to
|
||||
/// something whose type is different than void.
|
||||
inline bool isTypedPointer() const;
|
||||
|
||||
/// Returns whether this Value is empty.
|
||||
inline bool isEmpty() const;
|
||||
|
||||
/// Returns whether the value is a null pointer.
|
||||
inline bool isNullPointer() const;
|
||||
|
||||
/// Returns the exact type of the value held.
|
||||
inline const Type &getType() const;
|
||||
|
||||
/// If the value is a pointer to a non-void type, this method
|
||||
/// returns the actual type of the dereferenced pointer. Please
|
||||
/// note it is not the same as getType().getPointedType(),
|
||||
/// because the latter would return the non-polymorphic type.
|
||||
/// If the value is not a pointer, this method behaves like
|
||||
/// getType().
|
||||
inline const Type &getInstanceType() const;
|
||||
|
||||
/// Equality test operator. Returns true if the value passed
|
||||
/// as parameter is equal to this instance. The compare() method
|
||||
/// is used to perform the actual comparison.
|
||||
inline bool operator==(const Value &other) const;
|
||||
|
||||
/// Inequality test operator. Returns !operator==(other).
|
||||
inline bool operator!=(const Value &other) const;
|
||||
|
||||
/// Conversion to bool operator. Returns true if the value is
|
||||
/// not empty, false otherwise.
|
||||
inline operator bool() const;
|
||||
|
||||
/// Tries to convert this instance to a Value of the given type.
|
||||
/// The conversion is performed by rendering to a temporary stream
|
||||
/// in the source format and trying to read back from the stream
|
||||
/// in the destination format. If either the source or destination
|
||||
/// types, or both, don't have a ReaderWriter object, the conversion
|
||||
/// fails and an exception is thrown. If the conversion can't be
|
||||
/// completed for other reasons, other exceptions may be thrown.
|
||||
Value convertTo(const Type &outtype) const;
|
||||
|
||||
/// Tries to convert this instance to a Value of the given type.
|
||||
/// The conversion is performed by rendering to a temporary stream
|
||||
/// in the source format and trying to read back from the stream
|
||||
/// in the destination format. If either the source or destination
|
||||
/// types, or both, don't have a ReaderWriter object, the conversion
|
||||
/// fails and an empty Value is returned.
|
||||
/// Please note that unlike convertTo(), this method does not
|
||||
/// intentionally throw any exceptions.
|
||||
Value tryConvertTo(const Type &outtype) const;
|
||||
|
||||
/// Tries to get a string representation of the underlying value.
|
||||
/// This requires the value's type to have a ReaderWriter object
|
||||
/// associated to it. If the conversion can't be completed, an
|
||||
/// exception is thrown.
|
||||
std::string toString() const;
|
||||
|
||||
/// Compares two values for equality. Two empty values are considered
|
||||
/// equal. If the two values' types are different, a conversion is
|
||||
/// attempted and then the equality test is performed again.
|
||||
static bool compare(const Value &v1, const Value &v2);
|
||||
|
||||
private:
|
||||
// It's good to have friends!
|
||||
template<typename T> friend T variant_cast(const Value &v);
|
||||
template<typename T> friend T *extract_raw_data(Value &v);
|
||||
template<typename T> friend const T *extract_raw_data(const Value &v);
|
||||
|
||||
// throw an exception if the value is empty
|
||||
void check_empty() const;
|
||||
|
||||
// Base class for holding values. Provides a clone() method
|
||||
// which must be overriden in descendant classes.
|
||||
struct Instance_base
|
||||
{
|
||||
virtual Instance_base *clone() const = 0;
|
||||
virtual ~Instance_base() {}
|
||||
};
|
||||
|
||||
// Generic descendant of Instance_base for holding values of
|
||||
// type T. Note that values are created on the stack.
|
||||
template<typename T>
|
||||
struct Instance: Instance_base
|
||||
{
|
||||
Instance(T data): data_(data) {}
|
||||
virtual Instance_base *clone() const { return new Instance<T>(*this); }
|
||||
virtual ~Instance() {}
|
||||
T data_;
|
||||
};
|
||||
|
||||
// Base class for storage of Instance objects. Actually three
|
||||
// instances are created: the main instance which keeps the
|
||||
// desired value, an additional instance that keeps a reference
|
||||
// to that value, and another instance that keeps a const
|
||||
// reference to that value. These additional instances are queried
|
||||
// when casting the Value to a reference type.
|
||||
struct Instance_box_base
|
||||
{
|
||||
Instance_box_base()
|
||||
: inst_(0),
|
||||
ref_inst_(0),
|
||||
const_ref_inst_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Instance_box_base()
|
||||
{
|
||||
delete inst_;
|
||||
delete ref_inst_;
|
||||
delete const_ref_inst_;
|
||||
}
|
||||
|
||||
// clones the instance box
|
||||
virtual Instance_box_base *clone() const = 0;
|
||||
// returns the type of the value held
|
||||
virtual const Type *type() const = 0;
|
||||
// returns the actual pointed type if applicable
|
||||
virtual const Type *ptype() const { return 0; }
|
||||
// tests for equality
|
||||
virtual bool equal(const Value &v) const = 0;
|
||||
// returns whether the data is a null pointer
|
||||
virtual bool nullptr() const = 0;
|
||||
|
||||
Instance_base *inst_;
|
||||
Instance_base *ref_inst_;
|
||||
Instance_base *const_ref_inst_;
|
||||
};
|
||||
|
||||
// Generic instance box for non-pointer values.
|
||||
template<typename T>
|
||||
struct Instance_box: Instance_box_base
|
||||
{
|
||||
Instance_box(): Instance_box_base(), nullptr_(false) {}
|
||||
|
||||
Instance_box(const T &d, bool nullptr = false)
|
||||
: Instance_box_base(),
|
||||
nullptr_(nullptr)
|
||||
{
|
||||
Instance<T> *vl = new Instance<T>(d);
|
||||
inst_ = vl;
|
||||
ref_inst_ = new Instance<T &>(vl->data_);
|
||||
const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
}
|
||||
|
||||
virtual Instance_box_base *clone() const
|
||||
{
|
||||
Instance_box<T> *new_inbox = new Instance_box<T>();
|
||||
|
||||
// ??? this static_cast<> shouldn't be necessary, but the
|
||||
// MSVC++ compiler complains about invalid casting without it!
|
||||
Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
|
||||
|
||||
new_inbox->inst_ = vl;
|
||||
new_inbox->ref_inst_ = new Instance<T &>(vl->data_);
|
||||
new_inbox->const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
new_inbox->nullptr_ = nullptr_;
|
||||
return new_inbox;
|
||||
}
|
||||
|
||||
virtual const Type *type() const
|
||||
{
|
||||
return &typeof(static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual bool equal(const Value &v) const
|
||||
{
|
||||
return static_cast<Instance<T> *>(static_cast<Instance_box<T> *>(v.inbox_)->inst_)->data_ ==
|
||||
static_cast<Instance<T> *>(inst_)->data_;
|
||||
}
|
||||
|
||||
virtual bool nullptr() const
|
||||
{
|
||||
return nullptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool nullptr_;
|
||||
};
|
||||
|
||||
// Generic instance box for pointer values. Unlike Instance_box<>,
|
||||
// this struct template provides a ptype() method that unreferences
|
||||
// the pointer (T is supposed to be a pointer) and gets its actual
|
||||
// type.
|
||||
template<typename T>
|
||||
struct Ptr_instance_box: Instance_box_base
|
||||
{
|
||||
Ptr_instance_box(): Instance_box_base() {}
|
||||
|
||||
Ptr_instance_box(const T &d)
|
||||
: Instance_box_base()
|
||||
{
|
||||
Instance<T> *vl = new Instance<T>(d);
|
||||
inst_ = vl;
|
||||
ref_inst_ = new Instance<T &>(vl->data_);
|
||||
const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
}
|
||||
|
||||
virtual Instance_box_base *clone() const
|
||||
{
|
||||
Ptr_instance_box<T> *new_inbox = new Ptr_instance_box<T>();
|
||||
|
||||
// ??? this static_cast<> shouldn't be necessary, but the
|
||||
// MSVC++ compiler complains about invalid casting without it!
|
||||
Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
|
||||
|
||||
new_inbox->inst_ = vl;
|
||||
new_inbox->ref_inst_ = new Instance<T &>(vl->data_);
|
||||
new_inbox->const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
return new_inbox;
|
||||
}
|
||||
|
||||
virtual const Type *type() const
|
||||
{
|
||||
return &typeof(static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual const Type *ptype() const
|
||||
{
|
||||
if (!static_cast<Instance<T> *>(inst_)->data_) return 0;
|
||||
return &typeof(*static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual bool equal(const Value &v) const
|
||||
{
|
||||
return static_cast<Instance<T> *>(static_cast<Instance_box<T> *>(v.inbox_)->inst_)->data_ ==
|
||||
static_cast<Instance<T> *>(inst_)->data_;
|
||||
}
|
||||
|
||||
virtual bool nullptr() const
|
||||
{
|
||||
return static_cast<Instance<T> *>(inst_)->data_ == 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Instance_box_base *inbox_;
|
||||
const Type *type_;
|
||||
const Type *ptype_;
|
||||
};
|
||||
|
||||
/// A vector of values.
|
||||
typedef std::vector<Value> ValueList;
|
||||
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline Value::Value()
|
||||
: inbox_(0),
|
||||
type_(&Reflection::type_void()),
|
||||
ptype_(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(const T &v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<T>(v);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
inline Value::Value(const void *v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<const void *>(v, v == 0);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
inline Value::Value(void *v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<void *>(v, v == 0);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(const T *v)
|
||||
{
|
||||
inbox_ = new Ptr_instance_box<const T *>(v);
|
||||
type_ = inbox_->type();
|
||||
ptype_ = inbox_->ptype();
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(T *v)
|
||||
{
|
||||
inbox_ = new Ptr_instance_box<T *>(v);
|
||||
type_ = inbox_->type();
|
||||
ptype_ = inbox_->ptype();
|
||||
}
|
||||
|
||||
inline Value::Value(const Value ©)
|
||||
: inbox_(copy.inbox_? copy.inbox_->clone(): 0),
|
||||
type_(copy.type_),
|
||||
ptype_(copy.ptype_)
|
||||
{
|
||||
}
|
||||
|
||||
inline Value &Value::operator=(const Value ©)
|
||||
{
|
||||
std::auto_ptr<Instance_box_base> new_inbox(copy.inbox_? copy.inbox_->clone(): 0);
|
||||
delete inbox_;
|
||||
inbox_ = new_inbox.release();
|
||||
type_ = copy.type_;
|
||||
ptype_ = copy.ptype_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool Value::operator==(const Value &other) const
|
||||
{
|
||||
return compare(*this, other);
|
||||
}
|
||||
|
||||
inline bool Value::operator!=(const Value &other) const
|
||||
{
|
||||
return !compare(*this, other);
|
||||
}
|
||||
|
||||
inline Value::operator bool() const
|
||||
{
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
inline Value::~Value()
|
||||
{
|
||||
delete inbox_;
|
||||
}
|
||||
|
||||
inline const Type &Value::getType() const
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
inline const Type &Value::getInstanceType() const
|
||||
{
|
||||
if (ptype_)
|
||||
return *ptype_;
|
||||
return *type_;
|
||||
}
|
||||
|
||||
inline bool Value::isTypedPointer() const
|
||||
{
|
||||
return ptype_ != 0;
|
||||
}
|
||||
|
||||
inline bool Value::isEmpty() const
|
||||
{
|
||||
return inbox_ == 0;
|
||||
}
|
||||
|
||||
inline bool Value::isNullPointer() const
|
||||
{
|
||||
return inbox_->nullptr();
|
||||
}
|
||||
class Type;
|
||||
|
||||
class OSGINTROSPECTION_EXPORT Value
|
||||
{
|
||||
public:
|
||||
/// Default constructor. Initializes internal structures
|
||||
/// so that the Type returned by getType() is typeof(void),
|
||||
/// and the value is empty so that isEmpty() returns true.
|
||||
/// Be careful when using empty values, as some operations
|
||||
/// on them may throw an exception.
|
||||
inline Value();
|
||||
|
||||
/// Direct initialization constructor for void pointers.
|
||||
/// Although one of the constructor templates below could
|
||||
/// certainly handle void pointers as well, we need to treat
|
||||
/// them separately because void* can't be dereferenced.
|
||||
inline Value(void *v);
|
||||
|
||||
/// Direct initialization constructor for const void pointers.
|
||||
/// Although one of the constructor templates below could
|
||||
/// certainly handle void pointers as well, we need to treat
|
||||
/// them separately because void* can't be dereferenced.
|
||||
inline Value(const void *v);
|
||||
|
||||
/// Direct initialization constructor template for non-const
|
||||
/// pointers. By initializing an instance of Value through
|
||||
/// this constructor, internal structures will be configured
|
||||
/// to handle polymorphic types. This means you'll be able to
|
||||
/// call getInstanceType() to get the actual type of the
|
||||
/// dereferenced value.
|
||||
template<typename T> Value(T *v);
|
||||
|
||||
/// Direct initialization constructor template for non-const
|
||||
/// pointers. By initializing an instance of Value through
|
||||
/// this constructor, internal structures will be configured
|
||||
/// to handle polymorphic types. This means you'll be able to
|
||||
/// call getInstanceType() to get the actual type of the
|
||||
/// dereferenced value.
|
||||
template<typename T> Value(const T *v);
|
||||
|
||||
/// Direct initialization constructor template for all types
|
||||
/// that are not handled by any of the constructors above.
|
||||
/// Calling getInstanceType() on an instance constructed
|
||||
/// this way returns the same as getType().
|
||||
template<typename T> Value(const T &v);
|
||||
|
||||
/// Copy constructor. The underlying value's type must have
|
||||
/// consistent copy semantics.
|
||||
inline Value(const Value ©);
|
||||
|
||||
/// Destructor. Frees internal resources but it does NOT delete
|
||||
/// the value held. For example, this function will produce a
|
||||
/// memory leak: void f() { Value v(new int); }
|
||||
inline ~Value();
|
||||
|
||||
/// Assignment operator. Behaves like the copy constructor.
|
||||
inline Value &operator=(const Value ©);
|
||||
|
||||
/// Returns whether the value is a pointer and it points to
|
||||
/// something whose type is different than void.
|
||||
inline bool isTypedPointer() const;
|
||||
|
||||
/// Returns whether this Value is empty.
|
||||
inline bool isEmpty() const;
|
||||
|
||||
/// Returns whether the value is a null pointer.
|
||||
inline bool isNullPointer() const;
|
||||
|
||||
/// Returns the exact type of the value held.
|
||||
inline const Type &getType() const;
|
||||
|
||||
/// If the value is a pointer to a non-void type, this method
|
||||
/// returns the actual type of the dereferenced pointer. Please
|
||||
/// note it is not the same as getType().getPointedType(),
|
||||
/// because the latter would return the non-polymorphic type.
|
||||
/// If the value is not a pointer, this method behaves like
|
||||
/// getType().
|
||||
inline const Type &getInstanceType() const;
|
||||
|
||||
/// Equality test operator. Returns true if the value passed
|
||||
/// as parameter is equal to this instance. The compare() method
|
||||
/// is used to perform the actual comparison.
|
||||
inline bool operator==(const Value &other) const;
|
||||
|
||||
/// Inequality test operator. Returns !operator==(other).
|
||||
inline bool operator!=(const Value &other) const;
|
||||
|
||||
/// Conversion to bool operator. Returns true if the value is
|
||||
/// not empty, false otherwise.
|
||||
inline operator bool() const;
|
||||
|
||||
/// Tries to convert this instance to a Value of the given type.
|
||||
/// The conversion is performed by rendering to a temporary stream
|
||||
/// in the source format and trying to read back from the stream
|
||||
/// in the destination format. If either the source or destination
|
||||
/// types, or both, don't have a ReaderWriter object, the conversion
|
||||
/// fails and an exception is thrown. If the conversion can't be
|
||||
/// completed for other reasons, other exceptions may be thrown.
|
||||
Value convertTo(const Type &outtype) const;
|
||||
|
||||
/// Tries to convert this instance to a Value of the given type.
|
||||
/// The conversion is performed by rendering to a temporary stream
|
||||
/// in the source format and trying to read back from the stream
|
||||
/// in the destination format. If either the source or destination
|
||||
/// types, or both, don't have a ReaderWriter object, the conversion
|
||||
/// fails and an empty Value is returned.
|
||||
/// Please note that unlike convertTo(), this method does not
|
||||
/// intentionally throw any exceptions.
|
||||
Value tryConvertTo(const Type &outtype) const;
|
||||
|
||||
/// Tries to get a string representation of the underlying value.
|
||||
/// This requires the value's type to have a ReaderWriter object
|
||||
/// associated to it. If the conversion can't be completed, an
|
||||
/// exception is thrown.
|
||||
std::string toString() const;
|
||||
|
||||
/// Compares two values for equality. Two empty values are considered
|
||||
/// equal. If the two values' types are different, a conversion is
|
||||
/// attempted and then the equality test is performed again.
|
||||
static bool compare(const Value &v1, const Value &v2);
|
||||
|
||||
private:
|
||||
// It's good to have friends!
|
||||
template<typename T> friend T variant_cast(const Value &v);
|
||||
template<typename T> friend T *extract_raw_data(Value &v);
|
||||
template<typename T> friend const T *extract_raw_data(const Value &v);
|
||||
|
||||
// throw an exception if the value is empty
|
||||
void check_empty() const;
|
||||
|
||||
// Base class for holding values. Provides a clone() method
|
||||
// which must be overriden in descendant classes.
|
||||
struct Instance_base
|
||||
{
|
||||
virtual Instance_base *clone() const = 0;
|
||||
virtual ~Instance_base() {}
|
||||
};
|
||||
|
||||
// Generic descendant of Instance_base for holding values of
|
||||
// type T. Note that values are created on the stack.
|
||||
template<typename T>
|
||||
struct Instance: Instance_base
|
||||
{
|
||||
Instance(T data): data_(data) {}
|
||||
virtual Instance_base *clone() const { return new Instance<T>(*this); }
|
||||
virtual ~Instance() {}
|
||||
T data_;
|
||||
};
|
||||
|
||||
// Base class for storage of Instance objects. Actually three
|
||||
// instances are created: the main instance which keeps the
|
||||
// desired value, an additional instance that keeps a reference
|
||||
// to that value, and another instance that keeps a const
|
||||
// reference to that value. These additional instances are queried
|
||||
// when casting the Value to a reference type.
|
||||
struct Instance_box_base
|
||||
{
|
||||
Instance_box_base()
|
||||
: inst_(0),
|
||||
ref_inst_(0),
|
||||
const_ref_inst_(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Instance_box_base()
|
||||
{
|
||||
delete inst_;
|
||||
delete ref_inst_;
|
||||
delete const_ref_inst_;
|
||||
}
|
||||
|
||||
// clones the instance box
|
||||
virtual Instance_box_base *clone() const = 0;
|
||||
// returns the type of the value held
|
||||
virtual const Type *type() const = 0;
|
||||
// returns the actual pointed type if applicable
|
||||
virtual const Type *ptype() const { return 0; }
|
||||
// tests for equality
|
||||
virtual bool equal(const Value &v) const = 0;
|
||||
// returns whether the data is a null pointer
|
||||
virtual bool nullptr() const = 0;
|
||||
|
||||
Instance_base *inst_;
|
||||
Instance_base *ref_inst_;
|
||||
Instance_base *const_ref_inst_;
|
||||
};
|
||||
|
||||
// Generic instance box for non-pointer values.
|
||||
template<typename T>
|
||||
struct Instance_box: Instance_box_base
|
||||
{
|
||||
Instance_box(): Instance_box_base(), nullptr_(false) {}
|
||||
|
||||
Instance_box(const T &d, bool nullptr = false)
|
||||
: Instance_box_base(),
|
||||
nullptr_(nullptr)
|
||||
{
|
||||
Instance<T> *vl = new Instance<T>(d);
|
||||
inst_ = vl;
|
||||
ref_inst_ = new Instance<T &>(vl->data_);
|
||||
const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
}
|
||||
|
||||
virtual Instance_box_base *clone() const
|
||||
{
|
||||
Instance_box<T> *new_inbox = new Instance_box<T>();
|
||||
|
||||
// ??? this static_cast<> shouldn't be necessary, but the
|
||||
// MSVC++ compiler complains about invalid casting without it!
|
||||
Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
|
||||
|
||||
new_inbox->inst_ = vl;
|
||||
new_inbox->ref_inst_ = new Instance<T &>(vl->data_);
|
||||
new_inbox->const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
new_inbox->nullptr_ = nullptr_;
|
||||
return new_inbox;
|
||||
}
|
||||
|
||||
virtual const Type *type() const
|
||||
{
|
||||
return &typeof(static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual bool equal(const Value &v) const
|
||||
{
|
||||
return static_cast<Instance<T> *>(static_cast<Instance_box<T> *>(v.inbox_)->inst_)->data_ ==
|
||||
static_cast<Instance<T> *>(inst_)->data_;
|
||||
}
|
||||
|
||||
virtual bool nullptr() const
|
||||
{
|
||||
return nullptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool nullptr_;
|
||||
};
|
||||
|
||||
// Generic instance box for pointer values. Unlike Instance_box<>,
|
||||
// this struct template provides a ptype() method that unreferences
|
||||
// the pointer (T is supposed to be a pointer) and gets its actual
|
||||
// type.
|
||||
template<typename T>
|
||||
struct Ptr_instance_box: Instance_box_base
|
||||
{
|
||||
Ptr_instance_box(): Instance_box_base() {}
|
||||
|
||||
Ptr_instance_box(const T &d)
|
||||
: Instance_box_base()
|
||||
{
|
||||
Instance<T> *vl = new Instance<T>(d);
|
||||
inst_ = vl;
|
||||
ref_inst_ = new Instance<T &>(vl->data_);
|
||||
const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
}
|
||||
|
||||
virtual Instance_box_base *clone() const
|
||||
{
|
||||
Ptr_instance_box<T> *new_inbox = new Ptr_instance_box<T>();
|
||||
|
||||
// ??? this static_cast<> shouldn't be necessary, but the
|
||||
// MSVC++ compiler complains about invalid casting without it!
|
||||
Instance<T> *vl = static_cast<Instance<T> *>(inst_->clone());
|
||||
|
||||
new_inbox->inst_ = vl;
|
||||
new_inbox->ref_inst_ = new Instance<T &>(vl->data_);
|
||||
new_inbox->const_ref_inst_ = new Instance<const T &>(vl->data_);
|
||||
return new_inbox;
|
||||
}
|
||||
|
||||
virtual const Type *type() const
|
||||
{
|
||||
return &typeof(static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual const Type *ptype() const
|
||||
{
|
||||
if (!static_cast<Instance<T> *>(inst_)->data_) return 0;
|
||||
return &typeof(*static_cast<Instance<T> *>(inst_)->data_);
|
||||
}
|
||||
|
||||
virtual bool equal(const Value &v) const
|
||||
{
|
||||
return static_cast<Instance<T> *>(static_cast<Instance_box<T> *>(v.inbox_)->inst_)->data_ ==
|
||||
static_cast<Instance<T> *>(inst_)->data_;
|
||||
}
|
||||
|
||||
virtual bool nullptr() const
|
||||
{
|
||||
return static_cast<Instance<T> *>(inst_)->data_ == 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Instance_box_base *inbox_;
|
||||
const Type *type_;
|
||||
const Type *ptype_;
|
||||
};
|
||||
|
||||
/// A vector of values.
|
||||
typedef std::vector<Value> ValueList;
|
||||
|
||||
|
||||
// INLINE METHODS
|
||||
|
||||
inline Value::Value()
|
||||
: inbox_(0),
|
||||
type_(&Reflection::type_void()),
|
||||
ptype_(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(const T &v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<T>(v);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
inline Value::Value(const void *v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<const void *>(v, v == 0);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
inline Value::Value(void *v)
|
||||
: ptype_(0)
|
||||
{
|
||||
inbox_ = new Instance_box<void *>(v, v == 0);
|
||||
type_ = inbox_->type();
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(const T *v)
|
||||
{
|
||||
inbox_ = new Ptr_instance_box<const T *>(v);
|
||||
type_ = inbox_->type();
|
||||
ptype_ = inbox_->ptype();
|
||||
}
|
||||
|
||||
template<typename T> Value::Value(T *v)
|
||||
{
|
||||
inbox_ = new Ptr_instance_box<T *>(v);
|
||||
type_ = inbox_->type();
|
||||
ptype_ = inbox_->ptype();
|
||||
}
|
||||
|
||||
inline Value::Value(const Value ©)
|
||||
: inbox_(copy.inbox_? copy.inbox_->clone(): 0),
|
||||
type_(copy.type_),
|
||||
ptype_(copy.ptype_)
|
||||
{
|
||||
}
|
||||
|
||||
inline Value &Value::operator=(const Value ©)
|
||||
{
|
||||
std::auto_ptr<Instance_box_base> new_inbox(copy.inbox_? copy.inbox_->clone(): 0);
|
||||
delete inbox_;
|
||||
inbox_ = new_inbox.release();
|
||||
type_ = copy.type_;
|
||||
ptype_ = copy.ptype_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool Value::operator==(const Value &other) const
|
||||
{
|
||||
return compare(*this, other);
|
||||
}
|
||||
|
||||
inline bool Value::operator!=(const Value &other) const
|
||||
{
|
||||
return !compare(*this, other);
|
||||
}
|
||||
|
||||
inline Value::operator bool() const
|
||||
{
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
inline Value::~Value()
|
||||
{
|
||||
delete inbox_;
|
||||
}
|
||||
|
||||
inline const Type &Value::getType() const
|
||||
{
|
||||
return *type_;
|
||||
}
|
||||
|
||||
inline const Type &Value::getInstanceType() const
|
||||
{
|
||||
if (ptype_)
|
||||
return *ptype_;
|
||||
return *type_;
|
||||
}
|
||||
|
||||
inline bool Value::isTypedPointer() const
|
||||
{
|
||||
return ptype_ != 0;
|
||||
}
|
||||
|
||||
inline bool Value::isEmpty() const
|
||||
{
|
||||
return inbox_ == 0;
|
||||
}
|
||||
|
||||
inline bool Value::isNullPointer() const
|
||||
{
|
||||
return inbox_->nullptr();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -9,54 +9,54 @@
|
||||
namespace osgIntrospection
|
||||
{
|
||||
|
||||
/// Tries to convert an instance of Value to an object of type T.
|
||||
/// If T is a plain type or a pointer type (either const or non-const),
|
||||
/// and it matches the type of the value contained in v, then the actual
|
||||
/// value of type T is returned. If T is a [const] reference type, and
|
||||
/// its base (non reference) type matches the internal value's type,
|
||||
/// then a [const] reference to the internal value is returned.
|
||||
/// If none of the above conditions are met, a conversion is attempted
|
||||
/// as described in Value::convert() and then variant_cast is called again
|
||||
/// with the converted value as parameter.
|
||||
/// If the conversion can't be completed, an exception is thrown.
|
||||
/// Conversions that attempt to make a const pointer non-const will fail.
|
||||
template<typename T> T variant_cast(const Value &v)
|
||||
{
|
||||
// return value
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return i->data_;
|
||||
/// Tries to convert an instance of Value to an object of type T.
|
||||
/// If T is a plain type or a pointer type (either const or non-const),
|
||||
/// and it matches the type of the value contained in v, then the actual
|
||||
/// value of type T is returned. If T is a [const] reference type, and
|
||||
/// its base (non reference) type matches the internal value's type,
|
||||
/// then a [const] reference to the internal value is returned.
|
||||
/// If none of the above conditions are met, a conversion is attempted
|
||||
/// as described in Value::convert() and then variant_cast is called again
|
||||
/// with the converted value as parameter.
|
||||
/// If the conversion can't be completed, an exception is thrown.
|
||||
/// Conversions that attempt to make a const pointer non-const will fail.
|
||||
template<typename T> T variant_cast(const Value &v)
|
||||
{
|
||||
// return value
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return i->data_;
|
||||
|
||||
// return reference to value
|
||||
i = dynamic_cast<Value::Instance<T> *>(v.inbox_->ref_inst_);
|
||||
if (i) return i->data_;
|
||||
// return reference to value
|
||||
i = dynamic_cast<Value::Instance<T> *>(v.inbox_->ref_inst_);
|
||||
if (i) return i->data_;
|
||||
|
||||
// return const reference to value
|
||||
i = dynamic_cast<Value::Instance<T> *>(v.inbox_->const_ref_inst_);
|
||||
if (i) return i->data_;
|
||||
// return const reference to value
|
||||
i = dynamic_cast<Value::Instance<T> *>(v.inbox_->const_ref_inst_);
|
||||
if (i) return i->data_;
|
||||
|
||||
// try to convert v to type T and restart
|
||||
return variant_cast<T>(v.convertTo(typeof(T)));
|
||||
}
|
||||
// try to convert v to type T and restart
|
||||
return variant_cast<T>(v.convertTo(typeof(T)));
|
||||
}
|
||||
|
||||
/// Returns a typed pointer to the data contained in a Value
|
||||
/// instance. If the value's type is not identical to type T,
|
||||
/// a null pointer is returned.
|
||||
template<typename T> T *extract_raw_data(Value &v)
|
||||
{
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return &i->data_;
|
||||
return 0;
|
||||
}
|
||||
/// Returns a typed pointer to the data contained in a Value
|
||||
/// instance. If the value's type is not identical to type T,
|
||||
/// a null pointer is returned.
|
||||
template<typename T> T *extract_raw_data(Value &v)
|
||||
{
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return &i->data_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Returns a typed pointer to the data contained in a const Value
|
||||
/// instance. If the value's type is not identical to type T, a
|
||||
/// null pointer is returned.
|
||||
template<typename T> const T *extract_raw_data(const Value &v)
|
||||
{
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return &i->data_;
|
||||
return 0;
|
||||
}
|
||||
/// Returns a typed pointer to the data contained in a const Value
|
||||
/// instance. If the value's type is not identical to type T, a
|
||||
/// null pointer is returned.
|
||||
template<typename T> const T *extract_raw_data(const Value &v)
|
||||
{
|
||||
Value::Instance<T> *i = dynamic_cast<Value::Instance<T> *>(v.inbox_->inst_);
|
||||
if (i) return &i->data_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,39 +5,39 @@ using namespace osgIntrospection;
|
||||
|
||||
bool CustomAttributeProvider::isDefined(const Type &type, bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == type.getStdTypeInfo()) return true;
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == type.getStdTypeInfo()) return true;
|
||||
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
if ((*i)->isDefined(type, true)) return true;
|
||||
}
|
||||
}
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
if ((*i)->isDefined(type, true)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
const CustomAttribute *CustomAttributeProvider::getAttribute(const Type &type, bool inherit) const
|
||||
{
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == type.getStdTypeInfo()) return *i;
|
||||
for (CustomAttributeList::const_iterator i=attribs_.begin(); i!=attribs_.end(); ++i)
|
||||
if (typeid(**i) == type.getStdTypeInfo()) return *i;
|
||||
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
if (inherit)
|
||||
{
|
||||
CustomAttributeProviderList providers;
|
||||
getInheritedProviders(providers);
|
||||
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
const CustomAttribute *ca = (*i)->getAttribute(type, true);
|
||||
if (ca) return ca;
|
||||
}
|
||||
}
|
||||
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
|
||||
{
|
||||
const CustomAttribute *ca = (*i)->getAttribute(type, true);
|
||||
if (ca) return ca;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,12 +4,12 @@ using namespace osgIntrospection;
|
||||
|
||||
void MethodInfo::getInheritedProviders(CustomAttributeProviderList &providers) const
|
||||
{
|
||||
for (int i=0; i<decltype_.getNumBaseTypes(); ++i)
|
||||
{
|
||||
const MethodInfo *mi = decltype_.getBaseType(i).getMethod(name_, params_, false);
|
||||
if (mi)
|
||||
{
|
||||
providers.push_back(mi);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<decltype_.getNumBaseTypes(); ++i)
|
||||
{
|
||||
const MethodInfo *mi = decltype_.getBaseType(i).getMethod(name_, params_, false);
|
||||
if (mi)
|
||||
{
|
||||
providers.push_back(mi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,228 +6,228 @@ using namespace osgIntrospection;
|
||||
|
||||
void PropertyInfo::getInheritedProviders(CustomAttributeProviderList &providers) const
|
||||
{
|
||||
for (int i=0; i<decltype_.getNumBaseTypes(); ++i)
|
||||
{
|
||||
const PropertyInfo *pi = decltype_.getBaseType(i).getProperty(name_, ptype_, getIndexParameters(), false);
|
||||
if (pi)
|
||||
{
|
||||
providers.push_back(pi);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<decltype_.getNumBaseTypes(); ++i)
|
||||
{
|
||||
const PropertyInfo *pi = decltype_.getBaseType(i).getProperty(name_, ptype_, getIndexParameters(), false);
|
||||
if (pi)
|
||||
{
|
||||
providers.push_back(pi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Value PropertyInfo::getValue(const Value &instance) const
|
||||
{
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance);
|
||||
}
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance);
|
||||
}
|
||||
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::GET);
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::GET);
|
||||
|
||||
if (pta)
|
||||
return getm_->invoke(instance).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance);
|
||||
if (pta)
|
||||
return getm_->invoke(instance).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance);
|
||||
}
|
||||
|
||||
void PropertyInfo::setValue(Value &instance, const Value &value) const
|
||||
{
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, value);
|
||||
return;
|
||||
}
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::SET);
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::SET);
|
||||
|
||||
ValueList args;
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
ValueList args;
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
}
|
||||
|
||||
Value PropertyInfo::getIndexedValue(const Value &instance, ValueList &args) const
|
||||
{
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance, args).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance, args);
|
||||
}
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance, args).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance, args);
|
||||
}
|
||||
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::IGET);
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::IGET);
|
||||
|
||||
if (pta)
|
||||
return getm_->invoke(instance, args).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance, args);
|
||||
if (pta)
|
||||
return getm_->invoke(instance, args).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance, args);
|
||||
}
|
||||
|
||||
void PropertyInfo::setIndexedValue(Value &instance, ValueList &args, const Value &value) const
|
||||
{
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, args, value);
|
||||
return;
|
||||
}
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, args, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ISET);
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ISET);
|
||||
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
args.pop_back();
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
args.pop_back();
|
||||
}
|
||||
|
||||
int PropertyInfo::getNumArrayItems(const Value &instance) const
|
||||
{
|
||||
const CustomPropertyCountAttribute *ccount = getAttribute<CustomPropertyCountAttribute>(false);
|
||||
if (ccount) return ccount->getCounter()->count(instance);
|
||||
const CustomPropertyCountAttribute *ccount = getAttribute<CustomPropertyCountAttribute>(false);
|
||||
if (ccount) return ccount->getCounter()->count(instance);
|
||||
|
||||
if (!numm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::COUNT);
|
||||
if (!numm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::COUNT);
|
||||
|
||||
return variant_cast<int>(numm_->invoke(instance));
|
||||
return variant_cast<int>(numm_->invoke(instance));
|
||||
}
|
||||
|
||||
Value PropertyInfo::getArrayItem(const Value &instance, int i) const
|
||||
{
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
const PropertyTypeAttribute *pta = getAttribute<PropertyTypeAttribute>(false);
|
||||
const CustomPropertyGetAttribute *cget = getAttribute<CustomPropertyGetAttribute>(false);
|
||||
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance, i).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance, i);
|
||||
}
|
||||
if (cget)
|
||||
{
|
||||
if (pta)
|
||||
return cget->getGetter()->get(instance, i).convertTo(pta->getPropertyType());
|
||||
return cget->getGetter()->get(instance, i);
|
||||
}
|
||||
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::AGET);
|
||||
if (!getm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::AGET);
|
||||
|
||||
ValueList args;
|
||||
args.push_back(i);
|
||||
ValueList args;
|
||||
args.push_back(i);
|
||||
|
||||
if (pta)
|
||||
return getm_->invoke(instance, args).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance, args);
|
||||
if (pta)
|
||||
return getm_->invoke(instance, args).convertTo(pta->getPropertyType());
|
||||
return getm_->invoke(instance, args);
|
||||
}
|
||||
|
||||
void PropertyInfo::setArrayItem(Value &instance, int i, const Value &value) const
|
||||
{
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, i, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ASET);
|
||||
const CustomPropertySetAttribute *cset = getAttribute<CustomPropertySetAttribute>(false);
|
||||
if (cset)
|
||||
{
|
||||
cset->getSetter()->set(instance, i, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ASET);
|
||||
|
||||
ValueList args;
|
||||
args.push_back(i);
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
ValueList args;
|
||||
args.push_back(i);
|
||||
args.push_back(value);
|
||||
setm_->invoke(instance, args);
|
||||
}
|
||||
|
||||
void PropertyInfo::addArrayItem(Value &instance, const Value &value) const
|
||||
{
|
||||
const CustomPropertyAddAttribute *cadd = getAttribute<CustomPropertyAddAttribute>(false);
|
||||
if (cadd)
|
||||
{
|
||||
cadd->getAdder()->add(instance, value);
|
||||
return;
|
||||
}
|
||||
const CustomPropertyAddAttribute *cadd = getAttribute<CustomPropertyAddAttribute>(false);
|
||||
if (cadd)
|
||||
{
|
||||
cadd->getAdder()->add(instance, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ADD);
|
||||
if (!addm_)
|
||||
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ADD);
|
||||
|
||||
ValueList args;
|
||||
args.push_back(value);
|
||||
addm_->invoke(instance, args);
|
||||
ValueList args;
|
||||
args.push_back(value);
|
||||
addm_->invoke(instance, args);
|
||||
}
|
||||
|
||||
Value PropertyInfo::getDefaultValue() const
|
||||
{
|
||||
if (isArray() || isIndexed()) return Value();
|
||||
if (isArray() || isIndexed()) return Value();
|
||||
|
||||
const CustomAttributeList &cal = getCustomAttributes();
|
||||
for (CustomAttributeList::const_iterator i=cal.begin(); i!=cal.end(); ++i)
|
||||
{
|
||||
if (dynamic_cast<const NoDefaultValueAttribute *>(*i) != 0)
|
||||
return Value();
|
||||
const CustomAttributeList &cal = getCustomAttributes();
|
||||
for (CustomAttributeList::const_iterator i=cal.begin(); i!=cal.end(); ++i)
|
||||
{
|
||||
if (dynamic_cast<const NoDefaultValueAttribute *>(*i) != 0)
|
||||
return Value();
|
||||
|
||||
const DefaultValueAttribute *dv = dynamic_cast<const DefaultValueAttribute *>(*i);
|
||||
if (dv)
|
||||
{
|
||||
return dv->getDefaultValue();
|
||||
}
|
||||
}
|
||||
const DefaultValueAttribute *dv = dynamic_cast<const DefaultValueAttribute *>(*i);
|
||||
if (dv)
|
||||
{
|
||||
return dv->getDefaultValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (decltype_.isAbstract())
|
||||
{
|
||||
if (ptype_.isAbstract() || !ptype_.isDefined())
|
||||
return Value();
|
||||
return ptype_.createInstance();
|
||||
}
|
||||
if (decltype_.isAbstract())
|
||||
{
|
||||
if (ptype_.isAbstract() || !ptype_.isDefined())
|
||||
return Value();
|
||||
return ptype_.createInstance();
|
||||
}
|
||||
|
||||
// auto default value
|
||||
Value instance = decltype_.createInstance();
|
||||
return getValue(instance);
|
||||
// auto default value
|
||||
Value instance = decltype_.createInstance();
|
||||
return getValue(instance);
|
||||
}
|
||||
|
||||
void PropertyInfo::getIndexValueSet(int whichindex, const Value &instance, ValueList &values) const
|
||||
{
|
||||
const CustomIndexAttribute *cia = getAttribute<CustomIndexAttribute>(false);
|
||||
if (cia)
|
||||
{
|
||||
cia->getIndexInfo()->getIndexValueSet(whichindex, instance, values);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<int, const IndexTypeAttribute *> ita_map;
|
||||
const CustomAttributeList &cal = getCustomAttributes();
|
||||
for (CustomAttributeList::const_iterator i=cal.begin(); i!=cal.end(); ++i)
|
||||
{
|
||||
const IndexTypeAttribute *ita = dynamic_cast<const IndexTypeAttribute *>(*i);
|
||||
if (ita)
|
||||
ita_map[ita->getWhichIndex()] = ita;
|
||||
}
|
||||
const CustomIndexAttribute *cia = getAttribute<CustomIndexAttribute>(false);
|
||||
if (cia)
|
||||
{
|
||||
cia->getIndexInfo()->getIndexValueSet(whichindex, instance, values);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<int, const IndexTypeAttribute *> ita_map;
|
||||
const CustomAttributeList &cal = getCustomAttributes();
|
||||
for (CustomAttributeList::const_iterator i=cal.begin(); i!=cal.end(); ++i)
|
||||
{
|
||||
const IndexTypeAttribute *ita = dynamic_cast<const IndexTypeAttribute *>(*i);
|
||||
if (ita)
|
||||
ita_map[ita->getWhichIndex()] = ita;
|
||||
}
|
||||
|
||||
const EnumLabelMap &elm = getIndexParameters().at(whichindex)->getParameterType().getEnumLabels();
|
||||
if (elm.empty())
|
||||
throw IndexValuesNotDefinedException(name_, getIndexParameters().at(whichindex)->getName());
|
||||
const EnumLabelMap &elm = getIndexParameters().at(whichindex)->getParameterType().getEnumLabels();
|
||||
if (elm.empty())
|
||||
throw IndexValuesNotDefinedException(name_, getIndexParameters().at(whichindex)->getName());
|
||||
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (ita_map[whichindex])
|
||||
values.push_back(Value(i->first).convertTo(ita_map[whichindex]->getIndexType()));
|
||||
else
|
||||
values.push_back(Value(i->first).convertTo(indices_[whichindex]->getParameterType()));
|
||||
}
|
||||
}
|
||||
for (EnumLabelMap::const_iterator i=elm.begin(); i!=elm.end(); ++i)
|
||||
{
|
||||
if (ita_map[whichindex])
|
||||
values.push_back(Value(i->first).convertTo(ita_map[whichindex]->getIndexType()));
|
||||
else
|
||||
values.push_back(Value(i->first).convertTo(indices_[whichindex]->getParameterType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ParameterInfoList &PropertyInfo::getIndexParameters() const
|
||||
{
|
||||
const CustomIndexAttribute *cia = getAttribute<CustomIndexAttribute>(false);
|
||||
if (cia)
|
||||
{
|
||||
return cia->getIndexInfo()->getIndexParameters();
|
||||
}
|
||||
const CustomIndexAttribute *cia = getAttribute<CustomIndexAttribute>(false);
|
||||
if (cia)
|
||||
{
|
||||
return cia->getIndexInfo()->getIndexParameters();
|
||||
}
|
||||
|
||||
return indices_;
|
||||
return indices_;
|
||||
}
|
||||
|
@ -13,66 +13,66 @@ Reflection::StaticData *Reflection::staticdata__ = 0;
|
||||
|
||||
const TypeMap &Reflection::getTypes()
|
||||
{
|
||||
return getOrCreateStaticData().typemap;
|
||||
return getOrCreateStaticData().typemap;
|
||||
}
|
||||
|
||||
Reflection::StaticData &Reflection::getOrCreateStaticData()
|
||||
{
|
||||
static OpenThreads::Mutex access_mtx;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(access_mtx);
|
||||
static OpenThreads::Mutex access_mtx;
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(access_mtx);
|
||||
|
||||
if (!staticdata__)
|
||||
{
|
||||
staticdata__ = new StaticData;
|
||||
std::auto_ptr<Type> tvoid(new Type(typeid(void)));
|
||||
staticdata__->typemap.insert(std::make_pair(&typeid(void), tvoid.get()));
|
||||
staticdata__->type_void = tvoid.release();
|
||||
}
|
||||
return *staticdata__;
|
||||
if (!staticdata__)
|
||||
{
|
||||
staticdata__ = new StaticData;
|
||||
std::auto_ptr<Type> tvoid(new Type(typeid(void)));
|
||||
staticdata__->typemap.insert(std::make_pair(&typeid(void), tvoid.get()));
|
||||
staticdata__->type_void = tvoid.release();
|
||||
}
|
||||
return *staticdata__;
|
||||
}
|
||||
|
||||
const Type &Reflection::getType(const std::type_info &ti)
|
||||
{
|
||||
const TypeMap &types = getTypes();
|
||||
const TypeMap &types = getTypes();
|
||||
|
||||
TypeMap::const_iterator i = types.find(&ti);
|
||||
if (i == types.end())
|
||||
{
|
||||
return *registerType(ti);
|
||||
}
|
||||
return *i->second;
|
||||
TypeMap::const_iterator i = types.find(&ti);
|
||||
if (i == types.end())
|
||||
{
|
||||
return *registerType(ti);
|
||||
}
|
||||
return *i->second;
|
||||
}
|
||||
|
||||
const Type &Reflection::getType(const std::string &qname)
|
||||
{
|
||||
const TypeMap &types = getTypes();
|
||||
const TypeMap &types = getTypes();
|
||||
|
||||
for (TypeMap::const_iterator i=types.begin(); i!=types.end(); ++i)
|
||||
if (i->second->isDefined() && i->second->getQualifiedName().compare(qname) == 0)
|
||||
return *i->second;
|
||||
for (TypeMap::const_iterator i=types.begin(); i!=types.end(); ++i)
|
||||
if (i->second->isDefined() && i->second->getQualifiedName().compare(qname) == 0)
|
||||
return *i->second;
|
||||
|
||||
throw TypeNotFoundException(qname);
|
||||
throw TypeNotFoundException(qname);
|
||||
}
|
||||
|
||||
const Type &Reflection::type_void()
|
||||
{
|
||||
return *getOrCreateStaticData().type_void;
|
||||
return *getOrCreateStaticData().type_void;
|
||||
}
|
||||
|
||||
Type *Reflection::registerType(const std::type_info &ti)
|
||||
{
|
||||
std::auto_ptr<Type> type(new Type(ti));
|
||||
getOrCreateStaticData().typemap.insert(std::make_pair(&ti, type.get()));
|
||||
return type.release();
|
||||
std::auto_ptr<Type> type(new Type(ti));
|
||||
getOrCreateStaticData().typemap.insert(std::make_pair(&ti, type.get()));
|
||||
return type.release();
|
||||
}
|
||||
|
||||
Type *Reflection::registerOrReplaceType(const std::type_info &ti)
|
||||
{
|
||||
TypeMap &tm = getOrCreateStaticData().typemap;
|
||||
TypeMap::iterator i = tm.find(&ti);
|
||||
TypeMap &tm = getOrCreateStaticData().typemap;
|
||||
TypeMap::iterator i = tm.find(&ti);
|
||||
|
||||
if (i != tm.end())
|
||||
return new (i->second) Type(ti);
|
||||
if (i != tm.end())
|
||||
return new (i->second) Type(ti);
|
||||
|
||||
return registerType(ti);
|
||||
return registerType(ti);
|
||||
}
|
||||
|
@ -13,235 +13,235 @@ using namespace osgIntrospection;
|
||||
namespace
|
||||
{
|
||||
|
||||
struct MethodMatch
|
||||
{
|
||||
int list_pos;
|
||||
int exact_args;
|
||||
const MethodInfo *method;
|
||||
struct MethodMatch
|
||||
{
|
||||
int list_pos;
|
||||
int exact_args;
|
||||
const MethodInfo *method;
|
||||
|
||||
bool operator < (const MethodMatch &m) const
|
||||
{
|
||||
if (exact_args > m.exact_args) return true;
|
||||
if (exact_args < m.exact_args) return false;
|
||||
if (list_pos < m.list_pos) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
bool operator < (const MethodMatch &m) const
|
||||
{
|
||||
if (exact_args > m.exact_args) return true;
|
||||
if (exact_args < m.exact_args) return false;
|
||||
if (list_pos < m.list_pos) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Type::~Type()
|
||||
{
|
||||
for (PropertyInfoList::const_iterator i=props_.begin(); i!=props_.end(); ++i)
|
||||
delete *i;
|
||||
for (MethodInfoList::const_iterator i=methods_.begin(); i!=methods_.end(); ++i)
|
||||
delete *i;
|
||||
delete icb_;
|
||||
delete rw_;
|
||||
for (PropertyInfoList::const_iterator i=props_.begin(); i!=props_.end(); ++i)
|
||||
delete *i;
|
||||
for (MethodInfoList::const_iterator i=methods_.begin(); i!=methods_.end(); ++i)
|
||||
delete *i;
|
||||
delete icb_;
|
||||
delete rw_;
|
||||
}
|
||||
|
||||
bool Type::isSubclassOf(const Type &type) const
|
||||
{
|
||||
check_defined();
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
if (**i == type.getStdTypeInfo())
|
||||
return true;
|
||||
if ((*i)->isSubclassOf(type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
check_defined();
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
if (**i == type.getStdTypeInfo())
|
||||
return true;
|
||||
if ((*i)->isSubclassOf(type))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const MethodInfo *Type::getCompatibleMethod(const std::string &name, const ValueList &values, bool inherit) const
|
||||
{
|
||||
check_defined();
|
||||
check_defined();
|
||||
|
||||
MethodInfoList allmethods;
|
||||
const MethodInfoList *methods;
|
||||
if (inherit)
|
||||
{
|
||||
getAllMethods(allmethods);
|
||||
methods = &allmethods;
|
||||
}
|
||||
else
|
||||
methods = &methods_;
|
||||
MethodInfoList allmethods;
|
||||
const MethodInfoList *methods;
|
||||
if (inherit)
|
||||
{
|
||||
getAllMethods(allmethods);
|
||||
methods = &allmethods;
|
||||
}
|
||||
else
|
||||
methods = &methods_;
|
||||
|
||||
typedef std::vector<MethodMatch> MatchList;
|
||||
MatchList matches;
|
||||
typedef std::vector<MethodMatch> MatchList;
|
||||
MatchList matches;
|
||||
|
||||
int pos = 0;
|
||||
for (MethodInfoList::const_iterator j=methods->begin(); j!=methods->end(); ++j, ++pos)
|
||||
{
|
||||
const MethodInfo *mi = *j;
|
||||
if (mi->getName().compare(name) == 0)
|
||||
{
|
||||
const ParameterInfoList &other_params = mi->getParameters();
|
||||
if (values.size() == other_params.size())
|
||||
{
|
||||
if (values.empty())
|
||||
return mi;
|
||||
ParameterInfoList::const_iterator i1 = other_params.begin();
|
||||
ValueList::const_iterator i2 = values.begin();
|
||||
bool candidate = true;
|
||||
int exact_args = 0;
|
||||
for (; i1<other_params.end(); ++i1, ++i2)
|
||||
{
|
||||
if ((*i1)->getParameterType() != i2->getType())
|
||||
{
|
||||
if (i2->tryConvertTo((*i1)->getParameterType()).isEmpty())
|
||||
{
|
||||
candidate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
++exact_args;
|
||||
}
|
||||
if (candidate)
|
||||
{
|
||||
MethodMatch mm;
|
||||
mm.list_pos = pos;
|
||||
mm.exact_args = exact_args;
|
||||
mm.method = mi;
|
||||
matches.push_back(mm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int pos = 0;
|
||||
for (MethodInfoList::const_iterator j=methods->begin(); j!=methods->end(); ++j, ++pos)
|
||||
{
|
||||
const MethodInfo *mi = *j;
|
||||
if (mi->getName().compare(name) == 0)
|
||||
{
|
||||
const ParameterInfoList &other_params = mi->getParameters();
|
||||
if (values.size() == other_params.size())
|
||||
{
|
||||
if (values.empty())
|
||||
return mi;
|
||||
ParameterInfoList::const_iterator i1 = other_params.begin();
|
||||
ValueList::const_iterator i2 = values.begin();
|
||||
bool candidate = true;
|
||||
int exact_args = 0;
|
||||
for (; i1<other_params.end(); ++i1, ++i2)
|
||||
{
|
||||
if ((*i1)->getParameterType() != i2->getType())
|
||||
{
|
||||
if (i2->tryConvertTo((*i1)->getParameterType()).isEmpty())
|
||||
{
|
||||
candidate = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
++exact_args;
|
||||
}
|
||||
if (candidate)
|
||||
{
|
||||
MethodMatch mm;
|
||||
mm.list_pos = pos;
|
||||
mm.exact_args = exact_args;
|
||||
mm.method = mi;
|
||||
matches.push_back(mm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matches.empty())
|
||||
{
|
||||
std::sort(matches.begin(), matches.end());
|
||||
return matches.front().method;
|
||||
}
|
||||
if (!matches.empty())
|
||||
{
|
||||
std::sort(matches.begin(), matches.end());
|
||||
return matches.front().method;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const MethodInfo *Type::getMethod(const std::string &name, const ParameterInfoList ¶ms, bool inherit) const
|
||||
{
|
||||
check_defined();
|
||||
for (MethodInfoList::const_iterator j=methods_.begin(); j!=methods_.end(); ++j)
|
||||
{
|
||||
const MethodInfo &mi = **j;
|
||||
if (mi.getName().compare(name) == 0)
|
||||
{
|
||||
const ParameterInfoList &other_params = mi.getParameters();
|
||||
if (params.size() == other_params.size())
|
||||
{
|
||||
if (params.empty())
|
||||
return &mi;
|
||||
ParameterInfoList::const_iterator i1 = params.begin();
|
||||
ParameterInfoList::const_iterator i2 = other_params.begin();
|
||||
for (; i1<params.end(); ++i1, ++i2)
|
||||
{
|
||||
const ParameterInfo &p1 = **i1;
|
||||
const ParameterInfo &p2 = **i2;
|
||||
if (p1.getParameterType() == p2.getParameterType() &&
|
||||
p1.getAttributes() == p2.getAttributes() &&
|
||||
p1.getPosition() == p2.getPosition())
|
||||
{
|
||||
return &mi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
check_defined();
|
||||
for (MethodInfoList::const_iterator j=methods_.begin(); j!=methods_.end(); ++j)
|
||||
{
|
||||
const MethodInfo &mi = **j;
|
||||
if (mi.getName().compare(name) == 0)
|
||||
{
|
||||
const ParameterInfoList &other_params = mi.getParameters();
|
||||
if (params.size() == other_params.size())
|
||||
{
|
||||
if (params.empty())
|
||||
return &mi;
|
||||
ParameterInfoList::const_iterator i1 = params.begin();
|
||||
ParameterInfoList::const_iterator i2 = other_params.begin();
|
||||
for (; i1<params.end(); ++i1, ++i2)
|
||||
{
|
||||
const ParameterInfo &p1 = **i1;
|
||||
const ParameterInfo &p2 = **i2;
|
||||
if (p1.getParameterType() == p2.getParameterType() &&
|
||||
p1.getAttributes() == p2.getAttributes() &&
|
||||
p1.getPosition() == p2.getPosition())
|
||||
{
|
||||
return &mi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit)
|
||||
{
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
const MethodInfo *mi = (*i)->getMethod(name, params, true);
|
||||
if (mi) return mi;
|
||||
}
|
||||
}
|
||||
if (inherit)
|
||||
{
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
const MethodInfo *mi = (*i)->getMethod(name, params, true);
|
||||
if (mi) return mi;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Type::getInheritedProviders(CustomAttributeProviderList &providers) const
|
||||
{
|
||||
check_defined();
|
||||
providers.assign(base_.begin(), base_.end());
|
||||
check_defined();
|
||||
providers.assign(base_.begin(), base_.end());
|
||||
}
|
||||
|
||||
const PropertyInfo *Type::getProperty(const std::string &name, const Type &ptype, const ParameterInfoList &indices, bool inherit) const
|
||||
{
|
||||
check_defined();
|
||||
for (PropertyInfoList::const_iterator i=props_.begin(); i!=props_.end(); ++i)
|
||||
{
|
||||
const PropertyInfo &pi = **i;
|
||||
if (pi.getName() == name && pi.getPropertyType() == ptype)
|
||||
{
|
||||
const ParameterInfoList &other_indices = pi.getIndexParameters();
|
||||
if (indices.size() == other_indices.size())
|
||||
{
|
||||
if (indices.empty())
|
||||
return π
|
||||
ParameterInfoList::const_iterator i1 = indices.begin();
|
||||
ParameterInfoList::const_iterator i2 = other_indices.begin();
|
||||
for (; i1<indices.end(); ++i1, ++i2)
|
||||
{
|
||||
const ParameterInfo &p1 = **i1;
|
||||
const ParameterInfo &p2 = **i2;
|
||||
if (p1.getParameterType() == p2.getParameterType() &&
|
||||
p1.getAttributes() == p2.getAttributes() &&
|
||||
p1.getPosition() == p2.getPosition())
|
||||
{
|
||||
return π
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
check_defined();
|
||||
for (PropertyInfoList::const_iterator i=props_.begin(); i!=props_.end(); ++i)
|
||||
{
|
||||
const PropertyInfo &pi = **i;
|
||||
if (pi.getName() == name && pi.getPropertyType() == ptype)
|
||||
{
|
||||
const ParameterInfoList &other_indices = pi.getIndexParameters();
|
||||
if (indices.size() == other_indices.size())
|
||||
{
|
||||
if (indices.empty())
|
||||
return π
|
||||
ParameterInfoList::const_iterator i1 = indices.begin();
|
||||
ParameterInfoList::const_iterator i2 = other_indices.begin();
|
||||
for (; i1<indices.end(); ++i1, ++i2)
|
||||
{
|
||||
const ParameterInfo &p1 = **i1;
|
||||
const ParameterInfo &p2 = **i2;
|
||||
if (p1.getParameterType() == p2.getParameterType() &&
|
||||
p1.getAttributes() == p2.getAttributes() &&
|
||||
p1.getPosition() == p2.getPosition())
|
||||
{
|
||||
return π
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inherit)
|
||||
{
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
const PropertyInfo *pi = (*i)->getProperty(name, ptype, indices, true);
|
||||
if (pi) return pi;
|
||||
}
|
||||
}
|
||||
if (inherit)
|
||||
{
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
const PropertyInfo *pi = (*i)->getProperty(name, ptype, indices, true);
|
||||
if (pi) return pi;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Value Type::invokeMethod(const std::string &name, const Value &instance, ValueList &args, bool inherit) const
|
||||
{
|
||||
check_defined();
|
||||
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
|
||||
if (!mi) throw MethodNotFoundException(name, name_);
|
||||
return mi->invoke(instance, args);
|
||||
check_defined();
|
||||
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
|
||||
if (!mi) throw MethodNotFoundException(name, name_);
|
||||
return mi->invoke(instance, args);
|
||||
}
|
||||
|
||||
Value Type::invokeMethod(const std::string &name, Value &instance, ValueList &args, bool inherit) const
|
||||
{
|
||||
check_defined();
|
||||
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
|
||||
if (!mi) throw MethodNotFoundException(name, name_);
|
||||
return mi->invoke(instance, args);
|
||||
check_defined();
|
||||
const MethodInfo *mi = getCompatibleMethod(name, args, inherit);
|
||||
if (!mi) throw MethodNotFoundException(name, name_);
|
||||
return mi->invoke(instance, args);
|
||||
}
|
||||
|
||||
|
||||
void Type::getAllProperties(PropertyInfoList &props) const
|
||||
{
|
||||
check_defined();
|
||||
std::copy(props_.begin(), props_.end(), std::back_inserter(props));
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
(*i)->getAllProperties(props);
|
||||
}
|
||||
check_defined();
|
||||
std::copy(props_.begin(), props_.end(), std::back_inserter(props));
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
(*i)->getAllProperties(props);
|
||||
}
|
||||
}
|
||||
|
||||
void Type::getAllMethods(MethodInfoList &methods) const
|
||||
{
|
||||
check_defined();
|
||||
std::copy(methods_.begin(), methods_.end(), std::back_inserter(methods));
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
(*i)->getAllMethods(methods);
|
||||
}
|
||||
check_defined();
|
||||
std::copy(methods_.begin(), methods_.end(), std::back_inserter(methods));
|
||||
for (TypeList::const_iterator i=base_.begin(); i!=base_.end(); ++i)
|
||||
{
|
||||
(*i)->getAllMethods(methods);
|
||||
}
|
||||
}
|
||||
|
@ -10,78 +10,78 @@ using namespace osgIntrospection;
|
||||
|
||||
Value Value::convertTo(const Type &outtype) const
|
||||
{
|
||||
Value v = tryConvertTo(outtype);
|
||||
if (v.isEmpty())
|
||||
throw TypeConversionException(type_->getStdTypeInfo(), outtype.getStdTypeInfo());
|
||||
return v;
|
||||
Value v = tryConvertTo(outtype);
|
||||
if (v.isEmpty())
|
||||
throw TypeConversionException(type_->getStdTypeInfo(), outtype.getStdTypeInfo());
|
||||
return v;
|
||||
}
|
||||
|
||||
Value Value::tryConvertTo(const Type &outtype) const
|
||||
{
|
||||
check_empty();
|
||||
check_empty();
|
||||
|
||||
if (type_ == &outtype)
|
||||
return *this;
|
||||
if (type_ == &outtype)
|
||||
return *this;
|
||||
|
||||
if (type_->isConstPointer() && outtype.isNonConstPointer())
|
||||
return Value();
|
||||
if (type_->isConstPointer() && outtype.isNonConstPointer())
|
||||
return Value();
|
||||
|
||||
std::auto_ptr<ReaderWriter::Options> wopt;
|
||||
std::auto_ptr<ReaderWriter::Options> wopt;
|
||||
|
||||
if (type_->isEnum() && (outtype.getQualifiedName() == "int" || outtype.getQualifiedName() == "unsigned int"))
|
||||
{
|
||||
wopt.reset(new ReaderWriter::Options);
|
||||
wopt->setForceNumericOutput(true);
|
||||
}
|
||||
if (type_->isEnum() && (outtype.getQualifiedName() == "int" || outtype.getQualifiedName() == "unsigned int"))
|
||||
{
|
||||
wopt.reset(new ReaderWriter::Options);
|
||||
wopt->setForceNumericOutput(true);
|
||||
}
|
||||
|
||||
const ReaderWriter *src_rw = type_->getReaderWriter();
|
||||
if (src_rw)
|
||||
{
|
||||
const ReaderWriter *dst_rw = outtype.getReaderWriter();
|
||||
if (dst_rw)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (src_rw->writeTextValue(oss, *this, wopt.get()))
|
||||
{
|
||||
Value v;
|
||||
std::istringstream iss(oss.str());
|
||||
if (dst_rw->readTextValue(iss, v))
|
||||
{
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const ReaderWriter *src_rw = type_->getReaderWriter();
|
||||
if (src_rw)
|
||||
{
|
||||
const ReaderWriter *dst_rw = outtype.getReaderWriter();
|
||||
if (dst_rw)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (src_rw->writeTextValue(oss, *this, wopt.get()))
|
||||
{
|
||||
Value v;
|
||||
std::istringstream iss(oss.str());
|
||||
if (dst_rw->readTextValue(iss, v))
|
||||
{
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Value();
|
||||
return Value();
|
||||
}
|
||||
|
||||
std::string Value::toString() const
|
||||
{
|
||||
check_empty();
|
||||
check_empty();
|
||||
|
||||
const ReaderWriter *rw = type_->getReaderWriter();
|
||||
if (rw)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (!rw->writeTextValue(oss, *this))
|
||||
throw StreamWriteErrorException();
|
||||
return oss.str();
|
||||
}
|
||||
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, type_->getStdTypeInfo());
|
||||
const ReaderWriter *rw = type_->getReaderWriter();
|
||||
if (rw)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (!rw->writeTextValue(oss, *this))
|
||||
throw StreamWriteErrorException();
|
||||
return oss.str();
|
||||
}
|
||||
throw StreamingNotSupportedException(StreamingNotSupportedException::ANY, type_->getStdTypeInfo());
|
||||
}
|
||||
|
||||
bool Value::compare(const Value &v1, const Value &v2)
|
||||
{
|
||||
if (v1.isEmpty() && v2.isEmpty()) return true;
|
||||
if (v1.isEmpty() || v2.isEmpty()) return false;
|
||||
if (v1.type_ == v2.type_) return v1.inbox_->equal(v2);
|
||||
Value temp(v2.convertTo(v1.getType()));
|
||||
return compare(v1, temp);
|
||||
if (v1.isEmpty() && v2.isEmpty()) return true;
|
||||
if (v1.isEmpty() || v2.isEmpty()) return false;
|
||||
if (v1.type_ == v2.type_) return v1.inbox_->equal(v2);
|
||||
Value temp(v2.convertTo(v1.getType()));
|
||||
return compare(v1, temp);
|
||||
}
|
||||
|
||||
void Value::check_empty() const
|
||||
{
|
||||
if (!type_ || !inbox_)
|
||||
throw EmptyValueException();
|
||||
if (!type_ || !inbox_)
|
||||
throw EmptyValueException();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user