From Marco Jez, updates to osgIntrospection.
This commit is contained in:
15
src/osgIntrospection/ConstructorInfo.cpp
Normal file
15
src/osgIntrospection/ConstructorInfo.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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\
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 π
|
||||
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 (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 ¶ms) const
|
||||
{
|
||||
check_defined();
|
||||
|
||||
for (ConstructorInfoList::const_iterator j=cons_.begin(); j!=cons_.end(); ++j)
|
||||
{
|
||||
if (areParametersCompatible(params, (*j)->getParameters()))
|
||||
return *j;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
71
src/osgIntrospection/Utility.cpp
Normal file
71
src/osgIntrospection/Utility.cpp
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user