From 00081d77200a08baac2e62cc2797c7530caacea3 Mon Sep 17 00:00:00 2001 From: Mark Spruiell Date: Fri, 16 Jan 2004 22:22:44 +0000 Subject: initial check-in --- cpp/src/FreezeScript/Data.cpp | 2637 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2637 insertions(+) create mode 100644 cpp/src/FreezeScript/Data.cpp (limited to 'cpp/src/FreezeScript/Data.cpp') diff --git a/cpp/src/FreezeScript/Data.cpp b/cpp/src/FreezeScript/Data.cpp new file mode 100644 index 00000000000..63d56ef8354 --- /dev/null +++ b/cpp/src/FreezeScript/Data.cpp @@ -0,0 +1,2637 @@ +// ********************************************************************** +// +// Copyright (c) 2004 +// ZeroC, Inc. +// Billerica, MA, USA +// +// All Rights Reserved. +// +// Ice is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation. +// +// ********************************************************************** + +#include +#include +#include +#include + +using namespace std; +using namespace IceUtil; + +namespace FreezeScript +{ + +// +// ObjectWriter +// +class ObjectWriter : public Ice::Object +{ +public: + + ObjectWriter(const ObjectDataPtr&); + + virtual void __write(IceInternal::BasicStream*, bool) const; + virtual void __read(IceInternal::BasicStream*, bool = true); + +private: + + ObjectDataPtr _value; +}; + +// +// ObjectReader +// +class ObjectReader : public Ice::Object +{ +public: + + ObjectReader(const DataFactoryPtr&, const Slice::TypePtr&); + + virtual void __write(IceInternal::BasicStream*, bool) const; + virtual void __read(IceInternal::BasicStream*, bool = true); + + ObjectDataPtr getValue() const; + +private: + + DataFactoryPtr _factory; + Slice::TypePtr _type; + ObjectDataPtr _value; +}; +typedef IceUtil::Handle ObjectReaderPtr; + +} // End of namespace Transform + +// +// ObjectWriter +// +FreezeScript::ObjectWriter::ObjectWriter(const ObjectDataPtr& value) : + _value(value) +{ +} + +void +FreezeScript::ObjectWriter::__write(IceInternal::BasicStream* os, bool) const +{ + Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(_value->_type); + Slice::ClassDefPtr type; + if(decl) + { + type = decl->definition(); + } + while(type) + { + os->writeTypeId(type->scoped()); + os->startWriteSlice(); + Slice::DataMemberList members = type->dataMembers(); + for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + { + DataMemberMap::const_iterator q = _value->_members.find((*p)->name()); + assert(q != _value->_members.end()); + q->second->marshal(*os); + } + os->endWriteSlice(); + + Slice::ClassList bases = type->bases(); + if(!bases.empty() && !bases.front()->isInterface()) + { + type = bases.front(); + } + else + { + type = 0; + } + } + + // + // Ice::Object slice + // + os->writeTypeId(Ice::Object::ice_staticId()); + os->startWriteSlice(); + _value->_facetMap->marshal(*os); + os->endWriteSlice(); +} + +void +FreezeScript::ObjectWriter::__read(IceInternal::BasicStream*, bool) +{ + assert(false); +} + +// +// ObjectReader +// +FreezeScript::ObjectReader::ObjectReader(const DataFactoryPtr& factory, const Slice::TypePtr& type) : + _factory(factory), _type(type) +{ +} + +void +FreezeScript::ObjectReader::__write(IceInternal::BasicStream*, bool) const +{ + assert(false); +} + +void +FreezeScript::ObjectReader::__read(IceInternal::BasicStream* is, bool rid) +{ + const_cast(_value) = new ObjectData(_factory, _type, true); + Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(_type); + Slice::ClassDefPtr type; + if(decl) + { + type = decl->definition(); + } + while(type) + { + if(rid) + { + string id; + is->readTypeId(id); + assert(id == type->scoped()); + } + + is->startReadSlice(); + Slice::DataMemberList members = type->dataMembers(); + for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + { + DataMemberMap::iterator q = _value->_members.find((*p)->name()); + assert(q != _value->_members.end()); + q->second->unmarshal(*is); + } + is->endReadSlice(); + + Slice::ClassList bases = type->bases(); + if(!bases.empty() && !bases.front()->isInterface()) + { + type = bases.front(); + } + else + { + type = 0; + } + + rid = true; + } + + // + // Ice::Object slice + // + if(rid) + { + string id; + is->readTypeId(id); + if(id != Ice::Object::ice_staticId()) + { + throw Ice::MarshalException(__FILE__, __LINE__); + } + } + is->startReadSlice(); + _value->_facetMap->unmarshal(*is); + is->endReadSlice(); +} + +FreezeScript::ObjectDataPtr +FreezeScript::ObjectReader::getValue() const +{ + return _value; +} + +// +// DataInitializer +// +FreezeScript::DataInitializer::~DataInitializer() +{ +} + +// +// DataFactory +// +FreezeScript::DataFactory::DataFactory(const Ice::CommunicatorPtr& communicator, const Slice::UnitPtr& unit, + const ErrorReporterPtr& errorReporter) : + _communicator(communicator), _unit(unit), _errorReporter(errorReporter), _initializersEnabled(true) +{ +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::create(const Slice::TypePtr& type, bool readOnly) +{ + DataPtr data = createImpl(type, readOnly); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createBoolean(bool b, bool readOnly) +{ + DataPtr data = new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createInteger(Ice::Long i, bool readOnly) +{ + DataPtr data = new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createDouble(double d, bool readOnly) +{ + DataPtr data = new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createString(const string& s, bool readOnly) +{ + DataPtr data = new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createNil(bool readOnly) +{ + DataPtr data = new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly); + if(!readOnly) + { + initialize(data); + } + return data; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createObject(const Slice::TypePtr& type, bool readOnly) +{ + ObjectRefPtr obj; + Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type); + if(cl) + { + Slice::ClassDefPtr def = cl->definition(); + if(!def) + { + _errorReporter->error("class " + cl->scoped() + " declared but not defined"); + } + obj = new ObjectRef(this, cl, readOnly); + } + else + { + Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type); + if(b && b->kind() == Slice::Builtin::KindObject) + { + obj = new ObjectRef(this, b, readOnly); + } + } + + if(!obj) + { + _errorReporter->error("type `" + typeToString(type) + "' is not a class"); + } + + obj->instantiate(); + + if(!readOnly) + { + initialize(obj); + } + + return obj; +} + +Slice::BuiltinPtr +FreezeScript::DataFactory::getBuiltin(Slice::Builtin::Kind kind) const +{ + return _unit->builtin(kind); +} + +void +FreezeScript::DataFactory::addInitializer(const string& type, const DataInitializerPtr& init) +{ + _initializers.insert(InitMap::value_type(type, init)); +} + +void +FreezeScript::DataFactory::enableInitializers() +{ + _initializersEnabled = true; +} + +void +FreezeScript::DataFactory::disableInitializers() +{ + _initializersEnabled = false; +} + +Ice::CommunicatorPtr +FreezeScript::DataFactory::getCommunicator() const +{ + return _communicator; +} + +FreezeScript::ErrorReporterPtr +FreezeScript::DataFactory::getErrorReporter() const +{ + return _errorReporter; +} + +FreezeScript::DataPtr +FreezeScript::DataFactory::createImpl(const Slice::TypePtr& type, bool readOnly) +{ + Slice::BuiltinPtr builtin = Slice::BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Slice::Builtin::KindBool: + return new BooleanData(builtin, _errorReporter, readOnly); + + case Slice::Builtin::KindByte: + case Slice::Builtin::KindShort: + case Slice::Builtin::KindInt: + case Slice::Builtin::KindLong: + return new IntegerData(builtin, _errorReporter, readOnly); + + case Slice::Builtin::KindFloat: + case Slice::Builtin::KindDouble: + return new DoubleData(builtin, _errorReporter, readOnly); + + case Slice::Builtin::KindString: + return new StringData(this, builtin, _errorReporter, readOnly); + + case Slice::Builtin::KindObject: + return new ObjectRef(this, builtin, readOnly); + + case Slice::Builtin::KindObjectProxy: + return new ProxyData(builtin, _communicator, _errorReporter, readOnly); + + case Slice::Builtin::KindLocalObject: + assert(false); + return 0; + } + } + + Slice::SequencePtr seq = Slice::SequencePtr::dynamicCast(type); + if(seq) + { + return new SequenceData(this, seq, _errorReporter, readOnly); + } + + Slice::ProxyPtr proxy = Slice::ProxyPtr::dynamicCast(type); + if(proxy) + { + return new ProxyData(proxy, _communicator, _errorReporter, readOnly); + } + + Slice::StructPtr st = Slice::StructPtr::dynamicCast(type); + if(st) + { + return new StructData(this, st, _errorReporter, readOnly); + } + + Slice::EnumPtr en = Slice::EnumPtr::dynamicCast(type); + if(en) + { + return new EnumData(en, _errorReporter, readOnly); + } + + Slice::DictionaryPtr dict = Slice::DictionaryPtr::dynamicCast(type); + if(dict) + { + return new DictionaryData(this, dict, _errorReporter, readOnly); + } + + Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type); + if(cl) + { + Slice::ClassDefPtr def = cl->definition(); + if(!def) + { + _errorReporter->error("class " + cl->scoped() + " declared but not defined"); + } + return new ObjectRef(this, cl, readOnly); + } + + return 0; +} + +void +FreezeScript::DataFactory::initialize(const DataPtr& data) +{ + if(_initializersEnabled) + { + string name = typeToString(data->getType()); + InitMap::iterator p = _initializers.find(name); + if(p != _initializers.end()) + { + p->second->initialize(this, data, _communicator); + } + } +} + +// +// Data +// +FreezeScript::Data::Data(const ErrorReporterPtr& errorReporter, bool readOnly) : + _errorReporter(errorReporter), _readOnly(readOnly) +{ +} + +FreezeScript::Data::~Data() +{ +} + +bool +FreezeScript::Data::readOnly() const +{ + return _readOnly; +} + +// +// PrimitiveData +// +FreezeScript::PrimitiveData::PrimitiveData(const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly) +{ +} + +FreezeScript::DataPtr +FreezeScript::PrimitiveData::getMember(const string&) const +{ + return 0; +} + +FreezeScript::DataPtr +FreezeScript::PrimitiveData::getElement(const DataPtr&) const +{ + _errorReporter->error("element requested of primitive value"); + return 0; +} + +void +FreezeScript::PrimitiveData::destroy() +{ +} + +// +// BooleanData +// +FreezeScript::BooleanData::BooleanData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(false) +{ +} + +FreezeScript::BooleanData::BooleanData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly, bool value) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(value) +{ +} + +bool +FreezeScript::BooleanData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::BooleanData::operator!=(const Data& rhs) const +{ + const BooleanData* b = dynamic_cast(&rhs); + if(!b) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != b->_value; +} + +bool +FreezeScript::BooleanData::operator<(const Data& rhs) const +{ + const BooleanData* b = dynamic_cast(&rhs); + if(!b) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < b->_value; +} + +FreezeScript::DataPtr +FreezeScript::BooleanData::clone() const +{ + return new BooleanData(_type, _errorReporter, _readOnly, _value); +} + +Slice::TypePtr +FreezeScript::BooleanData::getType() const +{ + return _type; +} + +void +FreezeScript::BooleanData::marshal(IceInternal::BasicStream& os) const +{ + os.write(_value); +} + +void +FreezeScript::BooleanData::unmarshal(IceInternal::BasicStream& is) +{ + is.read(_value); +} + +bool +FreezeScript::BooleanData::booleanValue(bool) const +{ + return _value; +} + +Ice::Long +FreezeScript::BooleanData::integerValue(bool) const +{ + _errorReporter->error("boolean cannot be converted to integer"); + return 0; +} + +double +FreezeScript::BooleanData::doubleValue(bool) const +{ + _errorReporter->error("boolean cannot be converted to double"); + return 0; +} + +string +FreezeScript::BooleanData::stringValue(bool convert) const +{ + if(convert) + { + return toString(); + } + else + { + return string(); + } +} + +string +FreezeScript::BooleanData::toString() const +{ + return (_value ? "true" : "false"); +} + +void +FreezeScript::BooleanData::visit(DataVisitor& visitor) +{ + visitor.visitBoolean(this); +} + +bool +FreezeScript::BooleanData::getValue() const +{ + return _value; +} + +void +FreezeScript::BooleanData::setValue(bool v) +{ + _value = v; +} + +// +// IntegerData +// +FreezeScript::IntegerData::IntegerData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(0) +{ +} + +FreezeScript::IntegerData::IntegerData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly, Ice::Long value) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(value) +{ +} + +bool +FreezeScript::IntegerData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::IntegerData::operator!=(const Data& rhs) const +{ + const IntegerData* i = dynamic_cast(&rhs); + if(!i) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != i->_value; +} + +bool +FreezeScript::IntegerData::operator<(const Data& rhs) const +{ + const IntegerData* i = dynamic_cast(&rhs); + if(!i) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < i->_value; +} + +FreezeScript::DataPtr +FreezeScript::IntegerData::clone() const +{ + return new IntegerData(_type, _errorReporter, _readOnly, _value); +} + +Slice::TypePtr +FreezeScript::IntegerData::getType() const +{ + return _type; +} + +void +FreezeScript::IntegerData::marshal(IceInternal::BasicStream& os) const +{ + rangeCheck(_value, true); + + switch(_type->kind()) + { + case Slice::Builtin::KindByte: + { + os.write(static_cast(_value)); + break; + } + case Slice::Builtin::KindShort: + { + os.write(static_cast(_value)); + break; + } + case Slice::Builtin::KindInt: + { + os.write(static_cast(_value)); + break; + } + case Slice::Builtin::KindLong: + { + os.write(_value); + break; + } + + case Slice::Builtin::KindBool: + case Slice::Builtin::KindFloat: + case Slice::Builtin::KindDouble: + case Slice::Builtin::KindString: + case Slice::Builtin::KindObject: + case Slice::Builtin::KindObjectProxy: + case Slice::Builtin::KindLocalObject: + assert(false); + } +} + +void +FreezeScript::IntegerData::unmarshal(IceInternal::BasicStream& is) +{ + switch(_type->kind()) + { + case Slice::Builtin::KindByte: + { + Ice::Byte val; + is.read(val); + _value = val & 0xff; + break; + } + case Slice::Builtin::KindShort: + { + Ice::Short val; + is.read(val); + _value = val; + break; + } + case Slice::Builtin::KindInt: + { + Ice::Int val; + is.read(val); + _value = val; + break; + } + case Slice::Builtin::KindLong: + { + is.read(_value); + break; + } + + case Slice::Builtin::KindBool: + case Slice::Builtin::KindFloat: + case Slice::Builtin::KindDouble: + case Slice::Builtin::KindString: + case Slice::Builtin::KindObject: + case Slice::Builtin::KindObjectProxy: + case Slice::Builtin::KindLocalObject: + assert(false); + } +} + +bool +FreezeScript::IntegerData::booleanValue(bool) const +{ + _errorReporter->error("integer cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::IntegerData::integerValue(bool) const +{ + return _value; +} + +double +FreezeScript::IntegerData::doubleValue(bool convert) const +{ + if(convert) + { + return static_cast(_value); + } + else + { + _errorReporter->error("integer cannot be converted to double"); + return 0; + } +} + +string +FreezeScript::IntegerData::stringValue(bool convert) const +{ + if(convert) + { + return toString(); + } + else + { + _errorReporter->error("integer cannot be converted to string"); + return string(); + } +} + +string +FreezeScript::IntegerData::toString() const +{ + return toString(_value); +} + +void +FreezeScript::IntegerData::visit(DataVisitor& visitor) +{ + visitor.visitInteger(this); +} + +Ice::Long +FreezeScript::IntegerData::getValue() const +{ + return _value; +} + +void +FreezeScript::IntegerData::setValue(Ice::Long v, bool fatal) +{ + if(rangeCheck(v, fatal)) + { + _value = v; + } +} + +bool +FreezeScript::IntegerData::rangeCheck(Ice::Long value, bool fatal) const +{ + switch(_type->kind()) + { + case Slice::Builtin::KindByte: + { + if(value < 0 || value > 255) + { + _errorReporter->rangeError(toString(value), _type, fatal); + } + else + { + return true; + } + break; + } + + case Slice::Builtin::KindShort: + { + if(value < SHRT_MIN || value > SHRT_MAX) + { + _errorReporter->rangeError(toString(value), _type, fatal); + } + else + { + return true; + } + break; + } + + case Slice::Builtin::KindInt: + { + if(value < INT_MIN || value > INT_MAX) + { + _errorReporter->rangeError(toString(value), _type, fatal); + } + else + { + return true; + } + break; + } + + case Slice::Builtin::KindLong: + { + return true; + } + + case Slice::Builtin::KindBool: + case Slice::Builtin::KindFloat: + case Slice::Builtin::KindDouble: + case Slice::Builtin::KindString: + case Slice::Builtin::KindObject: + case Slice::Builtin::KindObjectProxy: + case Slice::Builtin::KindLocalObject: + assert(false); + } + + return false; +} + +string +FreezeScript::IntegerData::toString(Ice::Long value) +{ + char buf[64]; +#ifdef WIN32 + sprintf(buf, "%I64d", value); +#else + sprintf(buf, "%lld", value); +#endif + return string(buf); +} + +// +// DoubleData +// +FreezeScript::DoubleData::DoubleData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(0) +{ +} + +FreezeScript::DoubleData::DoubleData(const Slice::BuiltinPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly, double value) : + PrimitiveData(errorReporter, readOnly), _type(type), _value(value) +{ +} + +bool +FreezeScript::DoubleData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::DoubleData::operator!=(const Data& rhs) const +{ + const DoubleData* d = dynamic_cast(&rhs); + if(!d) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != d->_value; +} + +bool +FreezeScript::DoubleData::operator<(const Data& rhs) const +{ + const DoubleData* d = dynamic_cast(&rhs); + if(!d) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < d->_value; +} + +FreezeScript::DataPtr +FreezeScript::DoubleData::clone() const +{ + return new DoubleData(_type, _errorReporter, _readOnly, _value); +} + +Slice::TypePtr +FreezeScript::DoubleData::getType() const +{ + return _type; +} + +void +FreezeScript::DoubleData::marshal(IceInternal::BasicStream& os) const +{ + switch(_type->kind()) + { + case Slice::Builtin::KindFloat: + { + os.write(static_cast(_value)); + break; + } + case Slice::Builtin::KindDouble: + { + os.write(_value); + break; + } + + case Slice::Builtin::KindByte: + case Slice::Builtin::KindShort: + case Slice::Builtin::KindInt: + case Slice::Builtin::KindLong: + case Slice::Builtin::KindBool: + case Slice::Builtin::KindString: + case Slice::Builtin::KindObject: + case Slice::Builtin::KindObjectProxy: + case Slice::Builtin::KindLocalObject: + assert(false); + } +} + +void +FreezeScript::DoubleData::unmarshal(IceInternal::BasicStream& is) +{ + switch(_type->kind()) + { + case Slice::Builtin::KindFloat: + { + Ice::Float val; + is.read(val); + _value = val; + break; + } + case Slice::Builtin::KindDouble: + { + is.read(_value); + break; + } + + case Slice::Builtin::KindByte: + case Slice::Builtin::KindShort: + case Slice::Builtin::KindInt: + case Slice::Builtin::KindLong: + case Slice::Builtin::KindBool: + case Slice::Builtin::KindString: + case Slice::Builtin::KindObject: + case Slice::Builtin::KindObjectProxy: + case Slice::Builtin::KindLocalObject: + assert(false); + } +} + +bool +FreezeScript::DoubleData::booleanValue(bool) const +{ + _errorReporter->error("double cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::DoubleData::integerValue(bool convert) const +{ + if(convert) + { + return static_cast(_value); + } + else + { + _errorReporter->error("double cannot be converted to integer"); + return 0; + } +} + +double +FreezeScript::DoubleData::doubleValue(bool) const +{ + return _value; +} + +string +FreezeScript::DoubleData::stringValue(bool convert) const +{ + if(convert) + { + return toString(); + } + else + { + _errorReporter->error("double cannot be converted to string"); + return string(); + } +} + +string +FreezeScript::DoubleData::toString() const +{ + char buff[64]; + sprintf(buff, "%g", _value); + return string(buff); +} + +void +FreezeScript::DoubleData::visit(DataVisitor& visitor) +{ + visitor.visitDouble(this); +} + +double +FreezeScript::DoubleData::getValue() const +{ + return _value; +} + +void +FreezeScript::DoubleData::setValue(double v) +{ + _value = v; +} + +// +// StringData +// +FreezeScript::StringData::StringData(const DataFactoryPtr& factory, const Slice::BuiltinPtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly) : + PrimitiveData(errorReporter, readOnly), _factory(factory), _type(type) +{ + setValue(""); +} + +FreezeScript::StringData::StringData(const DataFactoryPtr& factory, const Slice::BuiltinPtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly, const string& value) : + PrimitiveData(errorReporter, readOnly), _factory(factory), _type(type) +{ + setValue(value); +} + +FreezeScript::DataPtr +FreezeScript::StringData::getMember(const string& member) const +{ + if(member == "length") + { + _length->setValue(static_cast(_value.size()), false); + return _length; + } + + return 0; +} + +bool +FreezeScript::StringData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::StringData::operator!=(const Data& rhs) const +{ + const StringData* s = dynamic_cast(&rhs); + if(!s) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != s->_value; +} + +bool +FreezeScript::StringData::operator<(const Data& rhs) const +{ + const StringData* s = dynamic_cast(&rhs); + if(!s) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < s->_value; +} + +FreezeScript::DataPtr +FreezeScript::StringData::clone() const +{ + return new StringData(_factory, _type, _errorReporter, _readOnly, _value); +} + +Slice::TypePtr +FreezeScript::StringData::getType() const +{ + return _type; +} + +void +FreezeScript::StringData::marshal(IceInternal::BasicStream& os) const +{ + os.write(_value); +} + +void +FreezeScript::StringData::unmarshal(IceInternal::BasicStream& is) +{ + string s; + is.read(s); + setValue(s); +} + +bool +FreezeScript::StringData::booleanValue(bool) const +{ + _errorReporter->error("string cannot be converted to boolean"); + return false; +} + +Ice::Long +FreezeScript::StringData::integerValue(bool) const +{ + _errorReporter->error("string cannot be converted to integer"); + return 0; +} + +double +FreezeScript::StringData::doubleValue(bool) const +{ + _errorReporter->error("string cannot be converted to double"); + return 0; +} + +string +FreezeScript::StringData::stringValue(bool) const +{ + return _value; +} + +string +FreezeScript::StringData::toString() const +{ + return _value; +} + +void +FreezeScript::StringData::visit(DataVisitor& visitor) +{ + visitor.visitString(this); +} + +string +FreezeScript::StringData::getValue() const +{ + return _value; +} + +void +FreezeScript::StringData::setValue(const string& v) +{ + _value = v; +} + +// +// ProxyData +// +FreezeScript::ProxyData::ProxyData(const Slice::TypePtr& type, const Ice::CommunicatorPtr& communicator, + const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly), _type(type), _communicator(communicator) +{ +} + +FreezeScript::ProxyData::ProxyData(const Slice::TypePtr& type, const Ice::CommunicatorPtr& communicator, + const ErrorReporterPtr& errorReporter, bool readOnly, const Ice::ObjectPrx& value) : + Data(errorReporter, readOnly), _type(type), _communicator(communicator), _value(value) +{ +} + +FreezeScript::DataPtr +FreezeScript::ProxyData::getMember(const string& member) const +{ + // TODO: Support members (id, facet, etc.)? + + return 0; +} + +FreezeScript::DataPtr +FreezeScript::ProxyData::getElement(const DataPtr&) const +{ + _errorReporter->error("element requested of proxy value"); + return 0; +} + +bool +FreezeScript::ProxyData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::ProxyData::operator!=(const Data& rhs) const +{ + const ProxyData* p = dynamic_cast(&rhs); + if(!p) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != p->_value; +} + +bool +FreezeScript::ProxyData::operator<(const Data& rhs) const +{ + const ProxyData* p = dynamic_cast(&rhs); + if(!p) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < p->_value; +} + +FreezeScript::DataPtr +FreezeScript::ProxyData::clone() const +{ + return new ProxyData(_type, _communicator, _errorReporter, _readOnly, _value); +} + +Slice::TypePtr +FreezeScript::ProxyData::getType() const +{ + return _type; +} + +void +FreezeScript::ProxyData::destroy() +{ +} + +void +FreezeScript::ProxyData::marshal(IceInternal::BasicStream& os) const +{ + os.write(_value); +} + +void +FreezeScript::ProxyData::unmarshal(IceInternal::BasicStream& is) +{ + is.read(_value); +} + +bool +FreezeScript::ProxyData::booleanValue(bool) const +{ + _errorReporter->error("proxy cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::ProxyData::integerValue(bool) const +{ + _errorReporter->error("proxy cannot be converted to integer"); + return 0; +} + +double +FreezeScript::ProxyData::doubleValue(bool) const +{ + _errorReporter->error("proxy cannot be converted to double"); + return 0; +} + +string +FreezeScript::ProxyData::stringValue(bool) const +{ + _errorReporter->error("proxy cannot be converted to string"); + return string(); +} + +string +FreezeScript::ProxyData::toString() const +{ + if(_value && _str.empty()) + { + const_cast(_str) = _communicator->proxyToString(_value); + } + return _str; +} + +void +FreezeScript::ProxyData::visit(DataVisitor& visitor) +{ + visitor.visitProxy(this); +} + +Ice::ObjectPrx +FreezeScript::ProxyData::getValue() const +{ + return _value; +} + +void +FreezeScript::ProxyData::setValue(const string& str, bool fatal) +{ + try + { + _value = _communicator->stringToProxy(str); + _str = str; + } + catch(const Ice::LocalException&) + { + _errorReporter->conversionError(str, _type, fatal); + } +} + +void +FreezeScript::ProxyData::setValue(const Ice::ObjectPrx& v) +{ + _value = v; + _str.clear(); +} + + +// +// StructData +// +FreezeScript::StructData::StructData(const DataFactoryPtr& factory, const Slice::StructPtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly), _type(type) +{ + Slice::DataMemberList members = type->dataMembers(); + for(Slice::DataMemberList::iterator q = members.begin(); q != members.end(); ++q) + { + DataPtr value = factory->create((*q)->type(), _readOnly); + assert(value); + _members[(*q)->name()] = value; + } +} + +FreezeScript::StructData::StructData(const Slice::StructPtr& type, const ErrorReporterPtr& errorReporter, + bool readOnly, const DataMemberMap& members) : + Data(errorReporter, readOnly), _type(type) +{ + for(DataMemberMap::const_iterator p = members.begin(); p != members.end(); ++p) + { + _members[p->first] = p->second->clone(); + } +} + +FreezeScript::DataPtr +FreezeScript::StructData::getMember(const string& member) const +{ + DataMemberMap::const_iterator p = _members.find(member); + if(p != _members.end()) + { + return p->second; + } + + return 0; +} + +FreezeScript::DataPtr +FreezeScript::StructData::getElement(const DataPtr&) const +{ + _errorReporter->error("element requested of struct value"); + return 0; +} + +bool +FreezeScript::StructData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::StructData::operator!=(const Data& rhs) const +{ + const StructData* s = dynamic_cast(&rhs); + if(!s || _type->scoped() != s->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + assert(_members.size() == s->_members.size()); + + for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p) + { + DataMemberMap::const_iterator q = s->_members.find(p->first); + assert(q != s->_members.end()); + + if(p->second != q->second) + { + return true; + } + } + + return false; +} + +bool +FreezeScript::StructData::operator<(const Data& rhs) const +{ + const StructData* s = dynamic_cast(&rhs); + if(!s || _type->scoped() != s->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + assert(_members.size() == s->_members.size()); + + for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p) + { + DataMemberMap::const_iterator q = s->_members.find(p->first); + assert(q != s->_members.end()); + + if(p->second < q->second) + { + return true; + } + else if(q->second < p->second) + { + return false; + } + } + + return false; +} + +FreezeScript::DataPtr +FreezeScript::StructData::clone() const +{ + return new StructData(_type, _errorReporter, _readOnly, _members); +} + +Slice::TypePtr +FreezeScript::StructData::getType() const +{ + return _type; +} + +void +FreezeScript::StructData::destroy() +{ + for(DataMemberMap::const_iterator p = _members.begin(); p != _members.end(); ++p) + { + p->second->destroy(); + } +} + +void +FreezeScript::StructData::marshal(IceInternal::BasicStream& os) const +{ + Slice::DataMemberList members = _type->dataMembers(); + for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + { + DataMemberMap::const_iterator q = _members.find((*p)->name()); + assert(q != _members.end()); + q->second->marshal(os); + } +} + +void +FreezeScript::StructData::unmarshal(IceInternal::BasicStream& is) +{ + Slice::DataMemberList members = _type->dataMembers(); + for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + { + DataMemberMap::const_iterator q = _members.find((*p)->name()); + assert(q != _members.end()); + q->second->unmarshal(is); + } +} + +bool +FreezeScript::StructData::booleanValue(bool) const +{ + _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::StructData::integerValue(bool) const +{ + _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to integer"); + return 0; +} + +double +FreezeScript::StructData::doubleValue(bool) const +{ + _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to double"); + return 0; +} + +string +FreezeScript::StructData::stringValue(bool) const +{ + _errorReporter->error("struct " + typeToString(_type) + " cannot be converted to string"); + return string(); +} + +string +FreezeScript::StructData::toString() const +{ + return stringValue(); +} + +void +FreezeScript::StructData::visit(DataVisitor& visitor) +{ + visitor.visitStruct(this); +} + +FreezeScript::DataMemberMap& +FreezeScript::StructData::getMembers() +{ + return _members; +} + +// +// SequenceData +// +FreezeScript::SequenceData::SequenceData(const DataFactoryPtr& factory, const Slice::SequencePtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly), _factory(factory), _type(type) +{ + _length = IntegerDataPtr::dynamicCast(_factory->createInteger(0, true)); +} + +FreezeScript::SequenceData::SequenceData(const DataFactoryPtr& factory, const Slice::SequencePtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly, + const DataList& elements) : + Data(errorReporter, readOnly), _factory(factory), _type(type) +{ + for(DataList::const_iterator p = elements.begin(); p != elements.end(); ++p) + { + _elements.push_back((*p)->clone()); + } + _length = IntegerDataPtr::dynamicCast(_factory->createInteger(static_cast(_elements.size()), true)); +} + +FreezeScript::DataPtr +FreezeScript::SequenceData::getMember(const string& member) const +{ + if(member == "length") + { + _length->setValue(static_cast(_elements.size()), false); + return _length; + } + + return 0; +} + +FreezeScript::DataPtr +FreezeScript::SequenceData::getElement(const DataPtr& element) const +{ + IntegerDataPtr i = IntegerDataPtr::dynamicCast(element); + if(!i) + { + _errorReporter->error("invalid sequence index type " + typeToString(element->getType())); + } + + Ice::Long iv = i->integerValue(); + if(iv < 0 || iv >= _elements.size()) + { + _errorReporter->error("sequence index " + i->toString() + " out of range"); + } + + return _elements[static_cast(iv)]; +} + +bool +FreezeScript::SequenceData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::SequenceData::operator!=(const Data& rhs) const +{ + const SequenceData* s = dynamic_cast(&rhs); + if(!s || _type->scoped() != s->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _elements != s->_elements; +} + +bool +FreezeScript::SequenceData::operator<(const Data& rhs) const +{ + const SequenceData* s = dynamic_cast(&rhs); + if(!s || _type->scoped() != s->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _elements < s->_elements; +} + +FreezeScript::DataPtr +FreezeScript::SequenceData::clone() const +{ + return new SequenceData(_factory, _type, _errorReporter, _readOnly, _elements); +} + +Slice::TypePtr +FreezeScript::SequenceData::getType() const +{ + return _type; +} + +void +FreezeScript::SequenceData::destroy() +{ + for(DataList::const_iterator p = _elements.begin(); p != _elements.end(); ++p) + { + (*p)->destroy(); + } +} + +void +FreezeScript::SequenceData::marshal(IceInternal::BasicStream& os) const +{ + os.writeSize(_elements.size()); + for(DataList::const_iterator p = _elements.begin(); p != _elements.end(); ++p) + { + (*p)->marshal(os); + } +} + +void +FreezeScript::SequenceData::unmarshal(IceInternal::BasicStream& is) +{ + Slice::TypePtr type = _type->type(); + Ice::Int sz; + is.readSize(sz); + _elements.reserve(sz); + for(Ice::Int i = 0; i < sz; ++i) + { + DataPtr v = _factory->create(type, _readOnly); + v->unmarshal(is); + _elements.push_back(v); + } + _length->setValue(sz, false); +} + +bool +FreezeScript::SequenceData::booleanValue(bool) const +{ + _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::SequenceData::integerValue(bool) const +{ + _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to integer"); + return 0; +} + +double +FreezeScript::SequenceData::doubleValue(bool) const +{ + _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to double"); + return 0; +} + +string +FreezeScript::SequenceData::stringValue(bool) const +{ + _errorReporter->error("sequence " + typeToString(_type) + " cannot be converted to string"); + return string(); +} + +string +FreezeScript::SequenceData::toString() const +{ + return stringValue(); +} + +void +FreezeScript::SequenceData::visit(DataVisitor& visitor) +{ + visitor.visitSequence(this); +} + +FreezeScript::DataList& +FreezeScript::SequenceData::getElements() +{ + return _elements; +} + +// +// EnumData +// +FreezeScript::EnumData::EnumData(const Slice::EnumPtr& type, const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly), _type(type), _value(0) +{ + _count = static_cast(type->getEnumerators().size()); +} + +FreezeScript::EnumData::EnumData(const Slice::EnumPtr& type, const ErrorReporterPtr& errorReporter, bool readOnly, + Ice::Int value) : + Data(errorReporter, readOnly), _type(type), _value(value) +{ + _count = static_cast(type->getEnumerators().size()); +} + +FreezeScript::DataPtr +FreezeScript::EnumData::getMember(const string&) const +{ + return 0; +} + +FreezeScript::DataPtr +FreezeScript::EnumData::getElement(const DataPtr&) const +{ + _errorReporter->error("element requested of enum value"); + return 0; +} + +bool +FreezeScript::EnumData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::EnumData::operator!=(const Data& rhs) const +{ + const EnumData* e = dynamic_cast(&rhs); + if(!e || _type->scoped() != e->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value != e->_value; +} + +bool +FreezeScript::EnumData::operator<(const Data& rhs) const +{ + const EnumData* e = dynamic_cast(&rhs); + if(!e || _type->scoped() != e->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _value < e->_value; +} + +FreezeScript::DataPtr +FreezeScript::EnumData::clone() const +{ + return new EnumData(_type, _errorReporter, _value); +} + +Slice::TypePtr +FreezeScript::EnumData::getType() const +{ + return _type; +} + +void +FreezeScript::EnumData::destroy() +{ +} + +void +FreezeScript::EnumData::marshal(IceInternal::BasicStream& os) const +{ + if(_count <= 127) + { + os.write(static_cast(_value)); + } + else if(_count <= 32767) + { + os.write(static_cast(_value)); + } + else + { + os.write(_value); + } +} + +void +FreezeScript::EnumData::unmarshal(IceInternal::BasicStream& is) +{ + if(_count <= 127) + { + Ice::Byte val; + is.read(val); + _value = val & 0xff; + } + else if(_count <= 32767) + { + Ice::Short val; + is.read(val); + _value = val; + } + else + { + is.read(_value); + } +} + +bool +FreezeScript::EnumData::booleanValue(bool) const +{ + _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::EnumData::integerValue(bool convert) const +{ + if(convert) + { + return _value; + } + else + { + _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to integer"); + return 0; + } +} + +double +FreezeScript::EnumData::doubleValue(bool) const +{ + _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to double"); + return 0; +} + +string +FreezeScript::EnumData::stringValue(bool) const +{ + _errorReporter->error("enum " + typeToString(_type) + " cannot be converted to string"); + return string(); +} + +string +FreezeScript::EnumData::toString() const +{ + if(_name.empty()) + { + Slice::EnumeratorList l = _type->getEnumerators(); + Slice::EnumeratorList::const_iterator p = l.begin(); + Ice::Int i = _value; + while(i > 0) + { + ++p; + assert(p != l.end()); + --i; + } + const_cast(_name) = (*p)->name(); + } + return _name; +} + +void +FreezeScript::EnumData::visit(DataVisitor& visitor) +{ + visitor.visitEnum(this); +} + +Ice::Int +FreezeScript::EnumData::getValue() const +{ + return _value; +} + +bool +FreezeScript::EnumData::setValue(Ice::Int v) +{ + if(v >= 0 && v < _count) + { + _value = v; + _name.clear(); + return true; + } + return false; +} + +bool +FreezeScript::EnumData::setValueAsString(const string& v) +{ + Slice::EnumeratorList l = _type->getEnumerators(); + Slice::EnumeratorList::const_iterator p; + Ice::Int i = 0; + for(p = l.begin(); p != l.end(); ++p, ++i) + { + if((*p)->name() == v) + { + _value = i; + _name = v; + break; + } + } + return p != l.end(); +} + +// +// DictionaryData +// +FreezeScript::DictionaryData::DictionaryData(const DataFactoryPtr& factory, const Slice::DictionaryPtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly) : + Data(errorReporter, readOnly), _factory(factory), _type(type) +{ + _length = IntegerDataPtr::dynamicCast(_factory->createInteger(0, true)); +} + +FreezeScript::DictionaryData::DictionaryData(const DataFactoryPtr& factory, const Slice::DictionaryPtr& type, + const ErrorReporterPtr& errorReporter, bool readOnly, const DataMap& m) : + Data(errorReporter, readOnly), _factory(factory), _type(type) +{ + for(DataMap::const_iterator p = m.begin(); p != m.end(); ++p) + { + _map.insert(DataMap::value_type(p->first->clone(), p->second->clone())); + } + _length = IntegerDataPtr::dynamicCast(_factory->createInteger(static_cast(_map.size()), true)); +} + +FreezeScript::DataPtr +FreezeScript::DictionaryData::getMember(const string& member) const +{ + if(member == "length") + { + _length->setValue(static_cast(_map.size()), false); + return _length; + } + + return 0; +} + +FreezeScript::DataPtr +FreezeScript::DictionaryData::getElement(const DataPtr& element) const +{ + DataMap::const_iterator p = _map.find(element); + if(p != _map.end()) + { + return p->second; + } + + return 0; +} + +bool +FreezeScript::DictionaryData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::DictionaryData::operator!=(const Data& rhs) const +{ + const DictionaryData* d = dynamic_cast(&rhs); + if(!d || _type->scoped() != d->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _map != d->_map; +} + +bool +FreezeScript::DictionaryData::operator<(const Data& rhs) const +{ + const DictionaryData* d = dynamic_cast(&rhs); + if(!d || _type->scoped() != d->_type->scoped()) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + assert(false); + } + + return _map < d->_map; +} + +FreezeScript::DataPtr +FreezeScript::DictionaryData::clone() const +{ + return new DictionaryData(_factory, _type, _errorReporter, _readOnly, _map); +} + +Slice::TypePtr +FreezeScript::DictionaryData::getType() const +{ + return _type; +} + +void +FreezeScript::DictionaryData::destroy() +{ + for(DataMap::const_iterator p = _map.begin(); p != _map.end(); ++p) + { + p->first->destroy(); + p->second->destroy(); + } +} + +void +FreezeScript::DictionaryData::marshal(IceInternal::BasicStream& os) const +{ + os.writeSize(_map.size()); + for(DataMap::const_iterator p = _map.begin(); p != _map.end(); ++p) + { + p->first->marshal(os); + p->second->marshal(os); + } +} + +void +FreezeScript::DictionaryData::unmarshal(IceInternal::BasicStream& is) +{ + Slice::TypePtr keyType = _type->keyType(); + Slice::TypePtr valueType = _type->valueType(); + + Ice::Int sz; + is.readSize(sz); + + for(Ice::Int i = 0; i < sz; ++i) + { + DataPtr key = _factory->create(keyType, _readOnly); + key->unmarshal(is); + + DataPtr value = _factory->create(valueType, _readOnly); + value->unmarshal(is); + + _map.insert(DataMap::value_type(key, value)); + } + + _length->setValue(static_cast(_map.size()), false); +} + +bool +FreezeScript::DictionaryData::booleanValue(bool) const +{ + _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::DictionaryData::integerValue(bool) const +{ + _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to integer"); + return 0; +} + +double +FreezeScript::DictionaryData::doubleValue(bool) const +{ + _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to double"); + return 0; +} + +string +FreezeScript::DictionaryData::stringValue(bool) const +{ + _errorReporter->error("dictionary " + typeToString(_type) + " cannot be converted to string"); + return string(); +} + +string +FreezeScript::DictionaryData::toString() const +{ + return stringValue(); +} + +void +FreezeScript::DictionaryData::visit(DataVisitor& visitor) +{ + visitor.visitDictionary(this); +} + +FreezeScript::DataMap& +FreezeScript::DictionaryData::getElements() +{ + return _map; +} + +// +// ObjectData +// +FreezeScript::ObjectData::ObjectData(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly) : + Data(factory->getErrorReporter(), readOnly), _type(type), _refCount(0) +{ + // + // Create a Data object for the facet map. We add this to the _members map so that + // the `ice_facets' member is handled like all other members. + // + Slice::TypeList l = _type->unit()->lookupType("::_FacetMap", false); + assert(!l.empty()); + _facetMap = factory->create(l.front(), readOnly); + _members["ice_facets"] = _facetMap; + + Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(type); + if(decl) + { + Slice::ClassDefPtr def = decl->definition(); + assert(def); + Slice::DataMemberList members = def->allDataMembers(); + for(Slice::DataMemberList::iterator p = members.begin(); p != members.end(); ++p) + { + _members[(*p)->name()] = factory->create((*p)->type(), _readOnly); + } + _id = factory->createString(decl->scoped(), true); + } + else + { + _id = factory->createString("::Ice::Object", true); + } +} + +FreezeScript::DataPtr +FreezeScript::ObjectData::getMember(const string& member) const +{ + if(member == "ice_id") + { + return _id; + } + + DataMemberMap::const_iterator p = _members.find(member); + if(p != _members.end()) + { + return p->second; + } + + return 0; +} + +FreezeScript::DataPtr +FreezeScript::ObjectData::getElement(const DataPtr& element) const +{ + _errorReporter->error("element requested of object value"); + return 0; +} + +bool +FreezeScript::ObjectData::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::ObjectData::operator!=(const Data& rhs) const +{ + _errorReporter->error("object comparison not supported"); + return false; +} + +bool +FreezeScript::ObjectData::operator<(const Data& rhs) const +{ + _errorReporter->error("object comparison not supported"); + return false; +} + +FreezeScript::DataPtr +FreezeScript::ObjectData::clone() const +{ + assert(false); + return 0; +} + +Slice::TypePtr +FreezeScript::ObjectData::getType() const +{ + return _type; +} + +void +FreezeScript::ObjectData::destroy() +{ + assert(false); +} + +void +FreezeScript::ObjectData::marshal(IceInternal::BasicStream& os) const +{ + if(!_marshaler) + { + const_cast(_marshaler) = new ObjectWriter(const_cast(this)); + } + os.write(_marshaler); +} + +void +FreezeScript::ObjectData::unmarshal(IceInternal::BasicStream& is) +{ + // + // Unmarshaling is done by ObjectReader. + // + assert(false); +} + +bool +FreezeScript::ObjectData::booleanValue(bool) const +{ + assert(false); + return 0; +} + +Ice::Long +FreezeScript::ObjectData::integerValue(bool) const +{ + assert(false); + return 0; +} + +double +FreezeScript::ObjectData::doubleValue(bool) const +{ + assert(false); + return 0; +} + +string +FreezeScript::ObjectData::stringValue(bool) const +{ + assert(false); + return string(); +} + +string +FreezeScript::ObjectData::toString() const +{ + assert(false); + return string(); +} + +void +FreezeScript::ObjectData::visit(DataVisitor& visitor) +{ + assert(false); +} + +FreezeScript::DataMemberMap& +FreezeScript::ObjectData::getMembers() +{ + return _members; +} + +void +FreezeScript::ObjectData::incRef() +{ + _refCount++; +} + +void +FreezeScript::ObjectData::decRef() +{ + assert(_refCount > 0); + _refCount--; + if(_refCount == 0) + { + destroyI(); + } +} + +void +FreezeScript::ObjectData::destroyI() +{ + DataMemberMap members = _members; + + _members.clear(); + _marshaler = 0; + + for(DataMemberMap::const_iterator p = members.begin(); p != members.end(); ++p) + { + p->second->destroy(); + } +} + +// +// ObjectRef +// +FreezeScript::ObjectRef::ObjectRef(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly) : + Data(factory->getErrorReporter(), readOnly), _factory(factory), _type(type) +{ +} + +FreezeScript::ObjectRef::ObjectRef(const DataFactoryPtr& factory, const Slice::TypePtr& type, bool readOnly, + const ObjectDataPtr& value) : + Data(factory->getErrorReporter(), readOnly), _factory(factory), _type(type), _value(value) +{ + _value->incRef(); +} + +FreezeScript::DataPtr +FreezeScript::ObjectRef::getMember(const string& member) const +{ + if(!_value) + { + _errorReporter->error("member `" + member + "' requested of nil object"); + } + + return _value->getMember(member); +} + +FreezeScript::DataPtr +FreezeScript::ObjectRef::getElement(const DataPtr&) const +{ + _errorReporter->error("element requested of object value"); + return 0; +} + +bool +FreezeScript::ObjectRef::operator==(const Data& rhs) const +{ + return !operator!=(rhs); +} + +bool +FreezeScript::ObjectRef::operator!=(const Data& rhs) const +{ + const ObjectRef* r = dynamic_cast(&rhs); + if(!r) + { + _errorReporter->typeMismatchError(_type, rhs.getType(), true); + } + + // + // Reference comparison. + // + return _value.get() != r->_value.get(); +} + +bool +FreezeScript::ObjectRef::operator<(const Data& rhs) const +{ + _errorReporter->error("object comparison not supported"); + return false; +} + +FreezeScript::DataPtr +FreezeScript::ObjectRef::clone() const +{ + return new ObjectRef(_factory, _type, _value); +} + +Slice::TypePtr +FreezeScript::ObjectRef::getType() const +{ + return _type; +} + +void +FreezeScript::ObjectRef::destroy() +{ + if(_value) + { + _value->decRef(); + _value = 0; + } +} + +void +FreezeScript::ObjectRef::marshal(IceInternal::BasicStream& os) const +{ + if(!_value) + { + os.write(Ice::ObjectPtr()); + return; + } + + _value->marshal(os); +} + +static void +patchObject(void* addr, Ice::ObjectPtr& v) +{ + if(v) + { + FreezeScript::ObjectRef* ref = static_cast(addr); + assert(ref); + + FreezeScript::ObjectReaderPtr reader = FreezeScript::ObjectReaderPtr::dynamicCast(v); + assert(reader); + + ref->setValue(reader->getValue()); + } +} + +void +FreezeScript::ObjectRef::unmarshal(IceInternal::BasicStream& is) +{ + is.read(patchObject, this); +} + +bool +FreezeScript::ObjectRef::booleanValue(bool) const +{ + _errorReporter->error(typeToString(_type) + " cannot be converted to boolean"); + return 0; +} + +Ice::Long +FreezeScript::ObjectRef::integerValue(bool) const +{ + _errorReporter->error(typeToString(_type) + " cannot be converted to integer"); + return 0; +} + +double +FreezeScript::ObjectRef::doubleValue(bool) const +{ + _errorReporter->error(typeToString(_type) + " cannot be converted to double"); + return 0; +} + +string +FreezeScript::ObjectRef::stringValue(bool) const +{ + _errorReporter->error(typeToString(_type) + " cannot be converted to string"); + return string(); +} + +string +FreezeScript::ObjectRef::toString() const +{ + return stringValue(); +} + +void +FreezeScript::ObjectRef::visit(DataVisitor& visitor) +{ + visitor.visitObject(this); +} + +void +FreezeScript::ObjectRef::instantiate() +{ + ObjectDataPtr data = new ObjectData(_factory, _type, _readOnly); + setValue(data); +} + +FreezeScript::ObjectDataPtr +FreezeScript::ObjectRef::getValue() const +{ + return _value; +} + +void +FreezeScript::ObjectRef::setValue(const ObjectDataPtr& value) +{ + // TODO: Type check? + ObjectDataPtr oldValue = _value; + _value = value; + if(_value) + { + _value->incRef(); + } + if(oldValue) + { + oldValue->decRef(); + } +} + +// +// ObjectFactory +// +FreezeScript::ObjectFactory::ObjectFactory(const DataFactoryPtr& factory, const Slice::UnitPtr& unit) : + _factory(factory), _unit(unit) +{ +} + +Ice::ObjectPtr +FreezeScript::ObjectFactory::create(const string& id) +{ + Ice::ObjectPtr result; + + if(id == Ice::Object::ice_staticId()) + { + result = new ObjectReader(_factory, _unit->builtin(Slice::Builtin::KindObject)); + } + else + { + Slice::TypeList l = _unit->lookupTypeNoBuiltin(id); + if(!l.empty()) + { + Slice::ClassDeclPtr decl = Slice::ClassDeclPtr::dynamicCast(l.front()); + if(!decl) + { + _factory->getErrorReporter()->error("Slice definition for `" + id + "' is not a class"); + } + Slice::ClassDefPtr def = decl->definition(); + if(!def) + { + _factory->getErrorReporter()->error("no class definition for `" + id + "'"); + } + result = new ObjectReader(_factory, decl); + } + } + + return result; +} + +void +FreezeScript::ObjectFactory::destroy() +{ +} + +// +// DataVisitor +// +FreezeScript::DataVisitor::~DataVisitor() +{ +} + +void +FreezeScript::DataVisitor::visitBoolean(const BooleanDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitInteger(const IntegerDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitDouble(const DoubleDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitString(const StringDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitProxy(const ProxyDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitStruct(const StructDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitSequence(const SequenceDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitEnum(const EnumDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitDictionary(const DictionaryDataPtr&) +{ +} + +void +FreezeScript::DataVisitor::visitObject(const ObjectRefPtr&) +{ +} -- cgit v1.2.3