Added Marco Jez's osgIntrospection + osgWrapper libs with osgintrospection

example
This commit is contained in:
Robert Osfield
2004-12-09 05:28:20 +00:00
parent dd0fac434a
commit 28d31c96b6
40 changed files with 6766 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
#include <osgIntrospection/CustomAttributeProvider>
#include <osgIntrospection/Type>
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;
if (inherit)
{
CustomAttributeProviderList providers;
getInheritedProviders(providers);
for (CustomAttributeProviderList::const_iterator i=providers.begin(); i!=providers.end(); ++i)
{
if ((*i)->isDefined(type, true)) return true;
}
}
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;
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;
}
}
return 0;
}

View File

@@ -0,0 +1,33 @@
#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/ReaderWriter>
#include <string>
// Built-in types
ABSTRACT_OBJECT_REFLECTOR(void)
STD_VALUE_REFLECTOR(char)
STD_VALUE_REFLECTOR(signed char)
STD_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)
STD_VALUE_REFLECTOR(bool)
STD_VALUE_REFLECTOR(float)
STD_VALUE_REFLECTOR(double)
STD_VALUE_REFLECTOR(long double)
// STL types
STD_VALUE_REFLECTOR(std::string)

View File

@@ -0,0 +1,20 @@
TOPDIR = ../..
include $(TOPDIR)/Make/makedefs
CXXFILES =\
CustomAttributeProvider.cpp\
DefaultReflectors.cpp\
MethodInfo.cpp\
PropertyInfo.cpp\
Reflection.cpp\
Type.cpp\
Value.cpp\
LIBS += $(OTHER_LIBS) $(DYNAMICLIBRARYLIB)
DEF += -DOSGINTROSPECTION_LIBRARY
TARGET_BASENAME = osgIntrospection
LIB = $(LIB_PREFIX)$(TARGET_BASENAME).$(LIB_EXT)
include $(TOPDIR)/Make/makerules

View File

@@ -0,0 +1,15 @@
#include <osgIntrospection/MethodInfo>
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);
}
}
}

View File

@@ -0,0 +1,233 @@
#include <osgIntrospection/PropertyInfo>
#include <osgIntrospection/Attributes>
#include <osgIntrospection/variant_cast>
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);
}
}
}
Value PropertyInfo::getValue(const 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);
if (cset)
{
cset->getSetter()->set(instance, value);
return;
}
if (!setm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::SET);
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);
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);
if (cset)
{
cset->getSetter()->set(instance, args, value);
return;
}
if (!setm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ISET);
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);
if (!numm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::COUNT);
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);
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);
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);
}
void PropertyInfo::addArrayItem(Value &instance, const Value &value) const
{
const CustomPropertyAddAttribute *cadd = getAttribute<CustomPropertyAddAttribute>(false);
if (cadd)
{
cadd->getAdder()->add(instance, value);
return;
}
if (!addm_)
throw PropertyAccessException(decltype_.getQualifiedName() + "::" + name_, PropertyAccessException::ADD);
ValueList args;
args.push_back(value);
addm_->invoke(instance, args);
}
Value PropertyInfo::getDefaultValue() const
{
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 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();
}
// 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 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()));
}
}
}
const ParameterInfoList &PropertyInfo::getIndexParameters() const
{
const CustomIndexAttribute *cia = getAttribute<CustomIndexAttribute>(false);
if (cia)
{
return cia->getIndexInfo()->getIndexParameters();
}
return indices_;
}

View File

@@ -0,0 +1,78 @@
#include <osgIntrospection/Reflection>
#include <osgIntrospection/Exceptions>
#include <osgIntrospection/Type>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>
#include <memory>
using namespace osgIntrospection;
Reflection::StaticData *Reflection::staticdata__ = 0;
const TypeMap &Reflection::getTypes()
{
return getOrCreateStaticData().typemap;
}
Reflection::StaticData &Reflection::getOrCreateStaticData()
{
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__;
}
const Type &Reflection::getType(const std::type_info &ti)
{
const TypeMap &types = getTypes();
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();
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);
}
const Type &Reflection::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();
}
Type *Reflection::registerOrReplaceType(const std::type_info &ti)
{
TypeMap &tm = getOrCreateStaticData().typemap;
TypeMap::iterator i = tm.find(&ti);
if (i != tm.end())
return new (i->second) Type(ti);
return registerType(ti);
}

View File

@@ -0,0 +1,247 @@
#include <osgIntrospection/Type>
#include <osgIntrospection/Value>
#include <osgIntrospection/Reflection>
#include <osgIntrospection/PropertyInfo>
#include <osgIntrospection/MethodInfo>
#include <osgIntrospection/ReaderWriter>
#include <iterator>
#include <algorithm>
using namespace osgIntrospection;
namespace
{
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;
}
};
}
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_;
}
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;
}
const MethodInfo *Type::getCompatibleMethod(const std::string &name, const ValueList &values, bool inherit) const
{
check_defined();
MethodInfoList allmethods;
const MethodInfoList *methods;
if (inherit)
{
getAllMethods(allmethods);
methods = &allmethods;
}
else
methods = &methods_;
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);
}
}
}
}
if (!matches.empty())
{
std::sort(matches.begin(), matches.end());
return matches.front().method;
}
return 0;
}
const MethodInfo *Type::getMethod(const std::string &name, const ParameterInfoList &params, 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;
}
}
}
}
}
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;
}
void Type::getInheritedProviders(CustomAttributeProviderList &providers) const
{
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 &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 (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;
}
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);
}
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);
}
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);
}
}
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);
}
}

View File

@@ -0,0 +1,87 @@
#include <osgIntrospection/Value>
#include <osgIntrospection/Type>
#include <osgIntrospection/Exceptions>
#include <osgIntrospection/ReaderWriter>
#include <sstream>
#include <memory>
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 Value::tryConvertTo(const Type &outtype) const
{
check_empty();
if (type_ == &outtype)
return *this;
if (type_->isConstPointer() && outtype.isNonConstPointer())
return Value();
std::auto_ptr<ReaderWriter::Options> wopt;
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;
}
}
}
}
return Value();
}
std::string Value::toString() const
{
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());
}
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();
}