From Marco Jez, updates to osgIntrospection.

This commit is contained in:
Robert Osfield
2005-04-04 13:50:07 +00:00
parent 21a69b5317
commit 5f75f765f0
30 changed files with 7591 additions and 3213 deletions

View File

@@ -0,0 +1,15 @@
#include <osgIntrospection/ConstructorInfo>
using namespace osgIntrospection;
void ConstructorInfo::getInheritedProviders(CustomAttributeProviderList &providers) const
{
for (int i=0; i<decltype_.getNumBaseTypes(); ++i)
{
const ConstructorInfo *ci = decltype_.getBaseType(i).getConstructor(params_);
if (ci)
{
providers.push_back(ci);
}
}
}

View File

@@ -7,27 +7,28 @@
ABSTRACT_OBJECT_REFLECTOR(void)
STD_VALUE_REFLECTOR(char)
STD_VALUE_REFLECTOR(signed char)
STD_VALUE_REFLECTOR(unsigned char)
ATOMIC_VALUE_REFLECTOR(char)
ATOMIC_VALUE_REFLECTOR(signed char)
ATOMIC_VALUE_REFLECTOR(unsigned char)
STD_VALUE_REFLECTOR(int)
STD_VALUE_REFLECTOR(unsigned int)
STD_VALUE_REFLECTOR(long int)
STD_VALUE_REFLECTOR(long long int)
STD_VALUE_REFLECTOR(unsigned long int)
STD_VALUE_REFLECTOR(short int)
STD_VALUE_REFLECTOR(unsigned short int)
ATOMIC_VALUE_REFLECTOR(int)
ATOMIC_VALUE_REFLECTOR(unsigned int)
ATOMIC_VALUE_REFLECTOR(long int)
ATOMIC_VALUE_REFLECTOR(long long int)
ATOMIC_VALUE_REFLECTOR(unsigned long int)
ATOMIC_VALUE_REFLECTOR(unsigned long long int)
ATOMIC_VALUE_REFLECTOR(short int)
ATOMIC_VALUE_REFLECTOR(unsigned short int)
STD_VALUE_REFLECTOR(bool)
ATOMIC_VALUE_REFLECTOR(bool)
STD_VALUE_REFLECTOR(float)
ATOMIC_VALUE_REFLECTOR(float)
STD_VALUE_REFLECTOR(double)
STD_VALUE_REFLECTOR(long double)
ATOMIC_VALUE_REFLECTOR(double)
ATOMIC_VALUE_REFLECTOR(long double)
// STL types
STD_VALUE_REFLECTOR(std::string)
ATOMIC_VALUE_REFLECTOR(std::string)

View File

@@ -2,12 +2,14 @@ TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
ConstructorInfo.cpp\
CustomAttributeProvider.cpp\
DefaultReflectors.cpp\
MethodInfo.cpp\
PropertyInfo.cpp\
Reflection.cpp\
Type.cpp\
Utility.cpp\
Value.cpp\

View File

@@ -13,3 +13,48 @@ void MethodInfo::getInheritedProviders(CustomAttributeProviderList &providers) c
}
}
}
bool MethodInfo::overrides(const MethodInfo *other) const
{
if (isConst() != other->isConst()) return false;
if (decltype_ != other->decltype_) return false;
if (rtype_ != other->rtype_) return false;
if (name_ != other->name_) return false;
if (params_.size() != other->params_.size()) return false;
ParameterInfoList::const_iterator i=params_.begin();
ParameterInfoList::const_iterator j=other->params_.begin();
for (; i!=params_.end(); ++i, ++j)
{
if (&(*i)->getParameterType() != &(*j)->getParameterType())
return false;
}
return true;
/*
std::size_t num_fixed_1 = 0;
std::size_t num_optional_1 = 0;
for (ParameterInfoList::const_iterator i=params_.begin(); i!=params_.end(); ++i)
{
if ((*i)->getDefaultValue().isEmpty())
++num_fixed_1;
else
++num_optional_1;
}
std::size_t num_fixed_2 = 0;
std::size_t num_optional_2 = 0;
for (ParameterInfoList::const_iterator i=other->params_.begin(); i!=other->params_.end(); ++i)
{
if ((*i)->getDefaultValue().isEmpty())
++num_fixed_2;
else
++num_optional_2;
}
if (num_fixed_1 > num_fixed_2)
{
}
*/
}

View File

@@ -36,6 +36,26 @@ Value PropertyInfo::getValue(const Value &instance) const
return getm_->invoke(instance);
}
Value PropertyInfo::getValue(Value &instance) const
{
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 (!getm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::GET);
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);
@@ -74,6 +94,26 @@ Value PropertyInfo::getIndexedValue(const Value &instance, ValueList &args) cons
return getm_->invoke(instance, args);
}
Value PropertyInfo::getIndexedValue(Value &instance, ValueList &args) const
{
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 (!getm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::IGET);
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);
@@ -125,6 +165,29 @@ Value PropertyInfo::getArrayItem(const Value &instance, int i) const
return getm_->invoke(instance, args);
}
Value PropertyInfo::getArrayItem(Value &instance, int i) const
{
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 (!getm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::AGET);
ValueList args;
args.push_back(i);
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);
@@ -160,6 +223,23 @@ void PropertyInfo::addArrayItem(Value &instance, const Value &value) const
addm_->invoke(instance, args);
}
void PropertyInfo::removeArrayItem(Value &instance, int i) const
{
const CustomPropertyRemoveAttribute *crem = getAttribute<CustomPropertyRemoveAttribute>(false);
if (crem)
{
crem->getRemover()->remove(instance, i);
return;
}
if (!remm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::REMOVE);
ValueList args;
args.push_back(i);
remm_->invoke(instance, args);
}
Value PropertyInfo::getDefaultValue() const
{
if (isArray() || isIndexed()) return Value();

View File

@@ -48,8 +48,13 @@ const Type &Reflection::getType(const std::string &qname)
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 (int j=0; j<i->second->getNumAliases(); ++j)
if (i->second->getAlias(j).compare(qname) == 0)
return *i->second;
}
throw TypeNotFoundException(qname);
}
@@ -66,13 +71,28 @@ Type *Reflection::registerType(const std::type_info &ti)
return type.release();
}
Type *Reflection::registerOrReplaceType(const std::type_info &ti)
Type *Reflection::getOrRegisterType(const std::type_info &ti, bool replace_if_defined)
{
TypeMap &tm = getOrCreateStaticData().typemap;
TypeMap::iterator i = tm.find(&ti);
if (i != tm.end())
return new (i->second) Type(ti);
{
if (replace_if_defined && i->second->isDefined())
{
std::string old_name = i->second->getName();
std::string old_namespace = i->second->getNamespace();
std::vector<std::string> old_aliases = i->second->aliases_;
Type *newtype = new (i->second) Type(ti);
newtype->name_ = old_name;
newtype->namespace_ = old_namespace;
newtype->aliases_.swap(old_aliases);
return newtype;
}
return i->second;
}
return registerType(ti);
}

View File

@@ -4,6 +4,9 @@
#include <osgIntrospection/PropertyInfo>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/ReaderWriter>
#include <osgIntrospection/Utility>
#include <osgIntrospection/ConstructorInfo>
#include <osgIntrospection/Comparator>
#include <iterator>
#include <algorithm>
@@ -13,21 +16,25 @@ using namespace osgIntrospection;
namespace
{
struct MethodMatch
template<typename T>
struct ObjectMatch
{
int list_pos;
int exact_args;
const MethodInfo *method;
float match;
const T *object;
bool operator < (const MethodMatch &m) const
bool operator < (const ObjectMatch &m) const
{
if (exact_args > m.exact_args) return true;
if (exact_args < m.exact_args) return false;
if (match > m.match) return true;
if (match < m.match) return false;
if (list_pos < m.list_pos) return true;
return false;
}
};
typedef ObjectMatch<MethodInfo> MethodMatch;
typedef ObjectMatch<ConstructorInfo> ConstructorMatch;
}
Type::~Type()
@@ -36,8 +43,11 @@ Type::~Type()
delete *i;
for (MethodInfoList::const_iterator i=methods_.begin(); i!=methods_.end(); ++i)
delete *i;
delete icb_;
for (ConstructorInfoList::const_iterator i=cons_.begin(); i!=cons_.end(); ++i)
delete *i;
delete rw_;
delete cmp_;
}
bool Type::isSubclassOf(const Type &type) const
@@ -76,44 +86,22 @@ const MethodInfo *Type::getCompatibleMethod(const std::string &name, const Value
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);
}
}
float match;
if (areArgumentsCompatible(values, mi->getParameters(), match))
{
MethodMatch mm;
mm.list_pos = pos;
mm.match = match;
mm.object = mi;
matches.push_back(mm);
}
}
}
if (!matches.empty())
{
std::sort(matches.begin(), matches.end());
return matches.front().method;
return matches.front().object;
}
return 0;
@@ -124,28 +112,13 @@ const MethodInfo *Type::getMethod(const std::string &name, const ParameterInfoLi
check_defined();
for (MethodInfoList::const_iterator j=methods_.begin(); j!=methods_.end(); ++j)
{
const MethodInfo &mi = **j;
if (mi.getName().compare(name) == 0)
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 (areParametersCompatible(params, mi->getParameters()))
{
return mi;
}
}
}
@@ -172,28 +145,13 @@ const PropertyInfo *Type::getProperty(const std::string &name, const Type &ptype
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 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 &pi;
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 &pi;
}
}
}
if (areParametersCompatible(indices, pi->getIndexParameters()))
{
return pi;
}
}
}
@@ -225,7 +183,6 @@ Value Type::invokeMethod(const std::string &name, Value &instance, ValueList &ar
return mi->invoke(instance, args);
}
void Type::getAllProperties(PropertyInfoList &props) const
{
check_defined();
@@ -245,3 +202,58 @@ void Type::getAllMethods(MethodInfoList &methods) const
(*i)->getAllMethods(methods);
}
}
Value Type::createInstance(ValueList &args) const
{
if (isAbstract())
throw TypeIsAbstractException(ti_);
const ConstructorInfo *ci = getCompatibleConstructor(args);
if (!ci)
throw ConstructorNotFoundException(ti_);
return ci->createInstance(args);
}
const ConstructorInfo *Type::getCompatibleConstructor(const ValueList &values) const
{
check_defined();
typedef std::vector<ConstructorMatch> MatchList;
MatchList matches;
int pos = 0;
for (ConstructorInfoList::const_iterator j=cons_.begin(); j!=cons_.end(); ++j, ++pos)
{
float match;
if (areArgumentsCompatible(values, (*j)->getParameters(), match))
{
ConstructorMatch mm;
mm.list_pos = pos;
mm.match = match;
mm.object = *j;
matches.push_back(mm);
}
}
if (!matches.empty())
{
std::sort(matches.begin(), matches.end());
return matches.front().object;
}
return 0;
}
const ConstructorInfo *Type::getConstructor(const ParameterInfoList &params) const
{
check_defined();
for (ConstructorInfoList::const_iterator j=cons_.begin(); j!=cons_.end(); ++j)
{
if (areParametersCompatible(params, (*j)->getParameters()))
return *j;
}
return 0;
}

View File

@@ -0,0 +1,71 @@
#include <osgIntrospection/Utility>
using namespace osgIntrospection;
bool osgIntrospection::areParametersCompatible(const ParameterInfoList &pl1, const ParameterInfoList &pl2)
{
if (pl1.size() == pl2.size())
{
if (pl1.empty())
return true;
ParameterInfoList::const_iterator i1 = pl1.begin();
ParameterInfoList::const_iterator i2 = pl2.begin();
for (; i1<pl1.end(); ++i1, ++i2)
{
const ParameterInfo &p1 = **i1;
const ParameterInfo &p2 = **i2;
if (p1.getParameterType() == p2.getParameterType() &&
p1.getAttributes() == p2.getAttributes())
{
return true;
}
}
}
return false;
}
bool osgIntrospection::areArgumentsCompatible(const ValueList &vl, const ParameterInfoList &pl, float &match)
{
if (pl.empty())
{
if (vl.empty())
{
match = 1.0f;
return true;
}
return false;
}
ParameterInfoList::const_iterator i1 = pl.begin();
ValueList::const_iterator i2 = vl.begin();
int exact_args = 0;
for (; i1<pl.end(); ++i1)
{
if (i2 == vl.end())
{
if ((*i1)->getDefaultValue().isEmpty())
return false;
continue;
}
if ((*i1)->getParameterType() != i2->getType())
{
if (i2->tryConvertTo((*i1)->getParameterType()).isEmpty())
{
return false;
}
}
else
++exact_args;
++i2;
}
match = static_cast<float>(exact_args) / pl.size();
return true;
}

View File

@@ -2,6 +2,7 @@
#include <osgIntrospection/Type>
#include <osgIntrospection/Exceptions>
#include <osgIntrospection/ReaderWriter>
#include <osgIntrospection/Comparator>
#include <sstream>
#include <memory>
@@ -71,17 +72,115 @@ std::string Value::toString() const
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);
}
void Value::check_empty() const
{
if (!type_ || !inbox_)
throw EmptyValueException();
}
void Value::swap(Value &v)
{
std::swap(inbox_, v.inbox_);
std::swap(type_, v.type_);
std::swap(ptype_, v.ptype_);
}
bool Value::operator ==(const Value &other) const
{
if (isEmpty() && other.isEmpty())
return true;
if (isEmpty() ^ other.isEmpty())
return false;
const Comparator *cmp1 = type_->getComparator();
const Comparator *cmp2 = other.type_->getComparator();
const Comparator *cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(type_->getStdTypeInfo());
if (cmp1 == cmp2)
return cmp->isEqualTo(*this, other);
if (cmp1)
return cmp1->isEqualTo(*this, other.convertTo(*type_));
return cmp2->isEqualTo(convertTo(*other.type_), other);
}
bool Value::operator <=(const Value &other) const
{
const Comparator *cmp1 = type_->getComparator();
const Comparator *cmp2 = other.type_->getComparator();
const Comparator *cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(type_->getStdTypeInfo());
if (cmp1 == cmp2)
return cmp->isLessThanOrEqualTo(*this, other);
if (cmp1)
return cmp1->isLessThanOrEqualTo(*this, other.convertTo(*type_));
return cmp2->isLessThanOrEqualTo(convertTo(*other.type_), other);
}
bool Value::operator !=(const Value &other) const
{
return !operator==(other);
}
bool Value::operator >(const Value &other) const
{
return !operator<=(other);
}
bool Value::operator <(const Value &other) const
{
const Comparator *cmp1 = type_->getComparator();
const Comparator *cmp2 = other.type_->getComparator();
const Comparator *cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(type_->getStdTypeInfo());
if (cmp1 == cmp2)
return cmp->isLessThanOrEqualTo(*this, other) && !cmp->isEqualTo(*this, other);
if (cmp1)
{
Value temp(other.convertTo(*type_));
return cmp1->isLessThanOrEqualTo(*this, temp) && !cmp1->isEqualTo(*this, temp);
}
Value temp(convertTo(*other.type_));
return cmp2->isLessThanOrEqualTo(temp, other) && !cmp2->isEqualTo(temp, other);
}
bool Value::operator >=(const Value &other) const
{
const Comparator *cmp1 = type_->getComparator();
const Comparator *cmp2 = other.type_->getComparator();
const Comparator *cmp = cmp1? cmp1: cmp2;
if (!cmp)
throw ComparisonNotPermittedException(type_->getStdTypeInfo());
if (cmp1 == cmp2)
return !cmp->isLessThanOrEqualTo(*this, other) || cmp->isEqualTo(*this, other);
if (cmp1)
{
Value temp(other.convertTo(*type_));
return !cmp1->isLessThanOrEqualTo(*this, temp) || cmp1->isEqualTo(*this, temp);
}
Value temp(convertTo(*other.type_));
return !cmp2->isLessThanOrEqualTo(temp, other) || cmp2->isEqualTo(temp, other);
}