diff options
author | Mark Spruiell <mes@zeroc.com> | 2017-09-15 17:21:38 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2017-09-15 17:21:38 -0700 |
commit | 1c1bff5336eb239ea19622dcbde3d47553b55907 (patch) | |
tree | 2d02cbe24bd2d99783546063d23207ce99b5e2aa | |
parent | changes for compatibility with MATLAB R2016a (diff) | |
download | ice-1c1bff5336eb239ea19622dcbde3d47553b55907.tar.bz2 ice-1c1bff5336eb239ea19622dcbde3d47553b55907.tar.xz ice-1c1bff5336eb239ea19622dcbde3d47553b55907.zip |
Adding support for Slice classes and optional values; Adding more tests
84 files changed, 6692 insertions, 1670 deletions
diff --git a/cpp/src/slice2matlab/Main.cpp b/cpp/src/slice2matlab/Main.cpp index 398ba1eb94d..391711e6af2 100644 --- a/cpp/src/slice2matlab/Main.cpp +++ b/cpp/src/slice2matlab/Main.cpp @@ -120,6 +120,27 @@ fixIdent(const string& ident) } string +fixExceptionMemberIdent(const string& ident) +{ + // + // User exceptions are subclasses of MATLAB's MException class. Subclasses cannot redefine a member that + // conflicts with MException's properties. Unfortunately MException also has some undocumented non-public + // properties that will cause run-time errors. + // + string s = fixIdent(ident); + if(s == "identifier" || + s == "message" || + s == "stack" || + s == "cause" || + s == "type") // Undocumented + { + s.push_back('_'); + } + + return s; +} + +string replace(string s, string patt, string val) { string r = s; @@ -382,7 +403,7 @@ defaultValue(const DataMemberPtr& m) } else if(m->optional()) { - return "[]"; + return "Ice.Unset"; } else { @@ -413,8 +434,7 @@ defaultValue(const DataMemberPtr& m) DictionaryPtr dict = DictionaryPtr::dynamicCast(m->type()); if(dict) { - return "containers.Map('KeyType', '" + typeToString(dict->keyType()) + "', 'ValueType', '" + - typeToString(dict->valueType()) + "')"; + return getAbsolute(dict) + ".new()"; } return "[]"; @@ -479,7 +499,8 @@ private: }; typedef list<ParamInfo> ParamInfoList; - ParamInfoList getInParams(const OperationPtr&); + ParamInfoList getAllInParams(const OperationPtr&); + void getInParams(const OperationPtr&, ParamInfoList&, ParamInfoList&); ParamInfoList getAllOutParams(const OperationPtr&); void getOutParams(const OperationPtr&, ParamInfoList&, ParamInfoList&); @@ -539,18 +560,69 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) const DataMemberList members = p->dataMembers(); if(!members.empty()) { - out << nl << "properties"; - out.inc(); - for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + if(p->hasMetaData("protected")) { - out << nl << fixIdent((*q)->name()); - if(declarePropertyType((*q)->type(), (*q)->optional())) + // + // All members are protected. + // + out << nl << "properties(Access=protected)"; + out.inc(); + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { - out << " " << typeToString((*q)->type()); + out << nl << fixIdent((*q)->name()); + if(declarePropertyType((*q)->type(), (*q)->optional())) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; + } + else + { + DataMemberList prot, pub; + for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) + { + if((*q)->hasMetaData("protected")) + { + prot.push_back(*q); + } + else + { + pub.push_back(*q); + } + } + if(!pub.empty()) + { + out << nl << "properties"; + out.inc(); + for(DataMemberList::const_iterator q = pub.begin(); q != pub.end(); ++q) + { + out << nl << fixIdent((*q)->name()); + if(declarePropertyType((*q)->type(), (*q)->optional())) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; + } + if(!prot.empty()) + { + out << nl << "properties(Access=protected)"; + out.inc(); + for(DataMemberList::const_iterator q = prot.begin(); q != prot.end(); ++q) + { + out << nl << fixIdent((*q)->name()); + if(declarePropertyType((*q)->type(), (*q)->optional())) + { + out << " " << typeToString((*q)->type()); + } + } + out.dec(); + out << nl << "end"; } } - out.dec(); - out << nl << "end"; } MemberInfoList allMembers; @@ -632,7 +704,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "os.endSlice();"; if(base) { - out << nl << "iceWriteImpl_@" << getAbsolute(base) << "(obj);"; + out << nl << "iceWriteImpl_@" << getAbsolute(base) << "(obj, os);"; } out.dec(); out << nl << "end"; @@ -667,7 +739,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "is.endSlice();"; if(base) { - out << nl << "obj = iceReadImpl_@" << getAbsolute(base) << "(obj);"; + out << nl << "obj = iceReadImpl_@" << getAbsolute(base) << "(obj, is);"; } out.dec(); out << nl << "end"; @@ -719,6 +791,29 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl; out.close(); + + if(p->compactId() >= 0) + { + ostringstream ostr; + ostr << "::IceCompactId::TypeId_" << p->compactId(); + + openClass(ostr.str(), out); + + out << nl << "classdef TypeId_" << p->compactId(); + out.inc(); + + out << nl << "properties(Constant)"; + out.inc(); + out << nl << "typeId = '" << scoped << "'"; + out.dec(); + out << nl << "end"; + + out.dec(); + out << nl << "end"; + out << nl; + + out.close(); + } } else if(!p->isLocal()) { @@ -755,34 +850,17 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out.inc(); // - // Constructor. - // - out << nl << "function obj = " << prxName << "(impl)"; - out.inc(); - if(!bases.empty()) - { - for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) - { - out << nl << "obj = obj@" << getAbsolute(*q, "", "Prx") << "(impl);"; - } - } - else - { - out << nl << "obj = obj@Ice.ObjectPrx(impl);"; - } - out.dec(); - out << nl << "end"; - - // // Operations. // const OperationList ops = p->operations(); for(OperationList::const_iterator q = ops.begin(); q != ops.end(); ++q) { OperationPtr op = *q; - const ParamInfoList inParams = getInParams(op); + ParamInfoList requiredInParams, optionalInParams; + getInParams(op, requiredInParams, optionalInParams); ParamInfoList requiredOutParams, optionalOutParams; getOutParams(op, requiredOutParams, optionalOutParams); + const ParamInfoList allInParams = getAllInParams(op); const ParamInfoList allOutParams = getAllOutParams(op); const bool twowayOnly = op->returnsData(); @@ -813,7 +891,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) self = "obj_"; } } - for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + for(ParamInfoList::const_iterator r = allInParams.begin(); r != allInParams.end(); ++r) { if(r->fixedName == "obj") { @@ -845,7 +923,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << fixIdent(op->name()) << spar; out << self; - for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + for(ParamInfoList::const_iterator r = allInParams.begin(); r != allInParams.end(); ++r) { out << r->fixedName; } @@ -853,7 +931,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << epar; out.inc(); - if(!inParams.empty()) + if(!allInParams.empty()) { if(op->format() == DefaultFormat) { @@ -864,16 +942,24 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "os_ = " << self << ".startWriteParamsWithFormat_(" << getFormatType(op->format()) << ");"; } - for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + for(ParamInfoList::const_iterator r = requiredInParams.begin(); r != requiredInParams.end(); ++r) + { + marshal(out, "os_", r->fixedName, r->type, false, 0); + } + for(ParamInfoList::const_iterator r = optionalInParams.begin(); r != optionalInParams.end(); ++r) { marshal(out, "os_", r->fixedName, r->type, r->optional, r->tag); } + if(op->sendsClasses(false)) + { + out << nl << "os_.writePendingValues();"; + } out << nl << self << ".endWriteParams_(os_);"; } out << nl << "[ok_, is_] = " << self << ".invoke_('" << op->name() << "', '" << getOperationMode(op->sendMode()) << "', " << (twowayOnly ? "true" : "false") - << ", " << (inParams.empty() ? "[]" : "os_") << ", varargin{:});"; + << ", " << (allInParams.empty() ? "[]" : "os_") << ", varargin{:});"; if(!twowayOnly) { @@ -988,7 +1074,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) // out << nl << "function r_ = " << fixIdent(op->name()) << "Async" << spar; out << self; - for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + for(ParamInfoList::const_iterator r = allInParams.begin(); r != allInParams.end(); ++r) { out << r->fixedName; } @@ -996,7 +1082,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << epar; out.inc(); - if(!inParams.empty()) + if(!allInParams.empty()) { if(op->format() == DefaultFormat) { @@ -1007,10 +1093,18 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "os_ = " << self << ".startWriteParamsWithFormat_(" << getFormatType(op->format()) << ");"; } - for(ParamInfoList::const_iterator r = inParams.begin(); r != inParams.end(); ++r) + for(ParamInfoList::const_iterator r = requiredInParams.begin(); r != requiredInParams.end(); ++r) + { + marshal(out, "os_", r->fixedName, r->type, false, 0); + } + for(ParamInfoList::const_iterator r = optionalInParams.begin(); r != optionalInParams.end(); ++r) { marshal(out, "os_", r->fixedName, r->type, r->optional, r->tag); } + if(op->sendsClasses(false)) + { + out << nl << "os_.writePendingValues();"; + } out << nl << self << ".endWriteParams_(os_);"; } @@ -1131,7 +1225,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out << nl << "r_ = " << self << ".invokeAsync_('" << op->name() << "', '" << getOperationMode(op->sendMode()) << "', " << (twowayOnly ? "true" : "false") << ", " - << (inParams.empty() ? "[]" : "os_") << ", " << allOutParams.size() << ", " + << (allInParams.empty() ? "[]" : "os_") << ", " << allOutParams.size() << ", " << (twowayOnly ? "@unmarshal" : "[]") << ", varargin{:});"; out.dec(); @@ -1166,6 +1260,29 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) out.dec(); out << nl << "end"; + // + // Constructor. + // + out << nl << "methods(Hidden)"; + out.inc(); + out << nl << "function obj = " << prxName << "(impl, communicator)"; + out.inc(); + if(!bases.empty()) + { + for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) + { + out << nl << "obj = obj@" << getAbsolute(*q, "", "Prx") << "(impl, communicator);"; + } + } + else + { + out << nl << "obj = obj@Ice.ObjectPrx(impl, communicator);"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out.dec(); out << nl << "end"; out << nl; @@ -1182,7 +1299,11 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) openClass(scoped, out); out << nl << "classdef (Abstract) " << name; - if(!bases.empty()) + if(bases.empty()) + { + out << " < handle"; + } + else { out << " < "; for(ClassList::const_iterator q = bases.begin(); q != bases.end(); ++q) @@ -1225,7 +1346,7 @@ CodeVisitor::visitClassDefStart(const ClassDefPtr& p) } out << fixIdent(op->name()) << spar; string self = "obj"; - const ParamInfoList inParams = getInParams(op); + const ParamInfoList inParams = getAllInParams(op); for(ParamInfoList::const_iterator r = outParams.begin(); r != outParams.end(); ++r) { if(r->fixedName == "obj") @@ -1294,7 +1415,7 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) out.inc(); for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { - out << nl << fixIdent((*q)->name()); + out << nl << fixExceptionMemberIdent((*q)->name()); if(declarePropertyType((*q)->type(), (*q)->optional())) { out << " " << typeToString((*q)->type()); @@ -1405,30 +1526,32 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) out << nl << "is.startSlice();"; for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { + string m = fixExceptionMemberIdent((*q)->name()); if(!(*q)->optional()) { if(isClass((*q)->type())) { - string func = "@(v) obj.setValueMember_('" + fixIdent((*q)->name()) + "', v)"; + string func = "@(v) obj.setValueMember_('" + m + "', v)"; unmarshal(out, "is", func, (*q)->type(), false, 0); } else { - unmarshal(out, "is", "obj." + fixIdent((*q)->name()), (*q)->type(), false, 0); + unmarshal(out, "is", "obj." + m, (*q)->type(), false, 0); } } } const DataMemberList optionalMembers = p->orderedOptionalDataMembers(); for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q) { + string m = fixExceptionMemberIdent((*q)->name()); if(isClass((*q)->type())) { - string func = "@(v) obj.setValueMember_('" + fixIdent((*q)->name()) + "', v)"; + string func = "@(v) obj.setValueMember_('" + m + "', v)"; unmarshal(out, "is", func, (*q)->type(), true, (*q)->tag()); } else { - unmarshal(out, "is", "obj." + fixIdent((*q)->name()), (*q)->type(), true, (*q)->tag()); + unmarshal(out, "is", "obj." + m, (*q)->type(), true, (*q)->tag()); } } out << nl << "is.endSlice();"; @@ -1447,7 +1570,7 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) { out << nl << "methods(Hidden=true)"; out.inc(); - if(!base || (base && !base->usesClasses(false))) + if(p->usesClasses(false) && (!base || (base && !base->usesClasses(false)))) { out << nl << "function r = usesClasses_(obj)"; out.inc(); @@ -1455,18 +1578,26 @@ CodeVisitor::visitExceptionStart(const ExceptionPtr& p) out.dec(); out << nl << "end"; } + if(!base || (base && !base->usesClasses(true))) + { + out << nl << "function r = usesAnyClasses_(obj)"; + out.inc(); + out << nl << "r = true;"; + out.dec(); + out << nl << "end"; + } out << nl << "function obj = resolveValues_(obj)"; out.inc(); for(DataMemberList::const_iterator q = classMembers.begin(); q != classMembers.end(); ++q) { - const string name = fixIdent((*q)->name()); - out << nl << "if obj.valueTable_.isKey('" << name << "')"; + string m = fixExceptionMemberIdent((*q)->name()); + out << nl << "if obj.valueTable_.isKey('" << m << "')"; out.inc(); - out << nl << "obj." << name << " = obj.valueTable_('" << name << "');"; + out << nl << "obj." << m << " = obj.valueTable_('" << m << "');"; out.dec(); out << nl << "end"; } - if(base && base->usesClasses(false)) + if(base && base->usesClasses(true)) { out << nl << "obj = resolveValues_@" << getAbsolute(base) << "(obj);"; } @@ -1547,6 +1678,16 @@ CodeVisitor::visitStructStart(const StructPtr& p) out << nl << "end"; out.dec(); out << nl << "end"; + out << nl << "function r = eq(obj, other)"; + out.inc(); + out << nl << "r = isequal(obj, other);"; + out.dec(); + out << nl << "end"; + out << nl << "function r = ne(obj, other)"; + out.inc(); + out << nl << "r = ~isequal(obj, other);"; + out.dec(); + out << nl << "end"; out.dec(); out << nl << "end"; @@ -1555,35 +1696,78 @@ CodeVisitor::visitStructStart(const StructPtr& p) { out << nl << "methods(Static)"; out.inc(); - out << nl << "function r = ice_read(is_)"; + out << nl << "function r = ice_read(is)"; out.inc(); out << nl << "r = " << abs << "();"; for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { if(isClass((*q)->type())) { - unmarshal(out, "is_", "@r.set_" + fixIdent((*q)->name()) + "_", (*q)->type(), false, 0); + unmarshal(out, "is", "@r.set_" + fixIdent((*q)->name()) + "_", (*q)->type(), false, 0); } else { - unmarshal(out, "is_", "r." + fixIdent((*q)->name()), (*q)->type(), false, 0); + unmarshal(out, "is", "r." + fixIdent((*q)->name()), (*q)->type(), false, 0); } } out.dec(); out << nl << "end"; - out << nl << "function ice_write(os_, v_)"; + + out << nl << "function r = ice_readOpt(is, tag)"; out.inc(); - out << nl << "if isempty(v_)"; + out << nl << "if is.readOptional(tag, " << getOptionalFormat(p) << ")"; out.inc(); - out << nl << "v_ = " << abs << "();"; + if(p->isVariableLength()) + { + out << nl << "is.skip(4);"; + } + else + { + out << nl << "is.skipSize();"; + } + out << nl << "r = " << abs << ".ice_read(is);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "r = Ice.Unset;"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + + out << nl << "function ice_write(os, v)"; + out.inc(); + out << nl << "if isempty(v)"; + out.inc(); + out << nl << "v = " << abs << "();"; out.dec(); out << nl << "end"; for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q) { - marshal(out, "os_", "v_." + fixIdent((*q)->name()), (*q)->type(), false, 0); + marshal(out, "os", "v." + fixIdent((*q)->name()), (*q)->type(), false, 0); } out.dec(); out << nl << "end"; + + out << nl << "function ice_writeOpt(os, tag, v)"; + out.inc(); + out << nl << "if v ~= Ice.Unset && os.writeOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + if(p->isVariableLength()) + { + out << nl << "pos = os.startSize();"; + out << nl << abs << ".ice_write(os, v);"; + out << nl << "os.endSize(pos);"; + } + else + { + out << nl << "os.writeSize(" << p->minWireSize() << ");"; + out << nl << abs << ".ice_write(os, v);"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; out.dec(); out << nl << "end"; @@ -1675,8 +1859,25 @@ CodeVisitor::visitSequence(const SequencePtr& p) out << nl << "methods(Static)"; out.inc(); + if(cls) + { + out << nl << "function r = new()"; + out.inc(); + out << nl << "r = containers.Map('KeyType', 'int32', 'ValueType', 'any');"; + out.dec(); + out << nl << "end"; + } + out << nl << "function write(os, seq)"; out.inc(); + if(cls) + { + out << nl << "if ~isempty(seq) && ~isa(seq, 'containers.Map')"; + out.inc(); + out << nl << "throw(MException('Ice:ArgumentException', 'expecting a containers.Map'));"; + out.dec(); + out << nl << "end"; + } out << nl << "sz = length(seq);"; out << nl << "os.writeSize(sz);"; out << nl << "for i = 1:sz"; @@ -1694,12 +1895,48 @@ CodeVisitor::visitSequence(const SequencePtr& p) out.dec(); out << nl << "end"; + out << nl << "function writeOpt(os, tag, seq)"; + out.inc(); + out << nl << "if seq ~= Ice.Unset && os.writeOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + if(p->type()->isVariableLength()) + { + out << nl << "pos = os.startSize();"; + out << nl << abs << ".write(os, seq);"; + out << nl << "os.endSize(pos);"; + } + else + { + // + // The element is a fixed-size type. If the element type is bool or byte, we do NOT write an extra size. + // + const size_t sz = p->type()->minWireSize(); + if(sz > 1) + { + out << nl << "len = length(seq);"; + out << nl << "if len > 254"; + out.inc(); + out << nl << "os.writeSize(len * " << sz << " + 5);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "os.writeSize(len * " << sz << " + 1);"; + out .dec(); + out << nl << "end"; + } + out << nl << abs << ".write(os, seq);"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "function r = read(is)"; out.inc(); out << nl << "sz = is.readSize();"; if(cls) { - out << nl << "r = containers.Map('KeyType', 'int32', 'ValueType', 'any');"; + out << nl << "r = " << abs << ".new();"; } else { @@ -1722,11 +1959,33 @@ CodeVisitor::visitSequence(const SequencePtr& p) } out.dec(); out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "function r = readOpt(is, tag)"; + out.inc(); + out << nl << "if is.readOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + if(p->type()->isVariableLength()) + { + out << nl << "is.skip(4);"; + } + else if(p->type()->minWireSize() > 1) + { + out << nl << "is.skipSize();"; + } + out << nl << "r = " << abs << ".read(is);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "r = Ice.Unset;"; out.dec(); out << nl << "end"; out.dec(); out << nl << "end"; + out.dec(); + out << nl << "end"; + if(cls) { out << nl << "methods(Static,Hidden=true)"; @@ -1861,6 +2120,43 @@ CodeVisitor::visitDictionary(const DictionaryPtr& p) out.dec(); out << nl << "end"; + out << nl << "function writeOpt(os, tag, d)"; + out.inc(); + out << nl << "if d ~= Ice.Unset && os.writeOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + if(key->isVariableLength() || value->isVariableLength()) + { + out << nl << "pos = os.startSize();"; + out << nl << abs << ".write(os, d);"; + out << nl << "os.endSize(pos);"; + } + else + { + const size_t sz = key->minWireSize() + value->minWireSize(); + if(cls) + { + out << nl << "len = length(d.array);"; + } + else + { + out << nl << "len = length(d);"; + } + out << nl << "if len > 254"; + out.inc(); + out << nl << "os.writeSize(len * " << sz << " + 5);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "os.writeSize(len * " << sz << " + 1);"; + out .dec(); + out << nl << "end"; + out << nl << abs << ".write(os, d);"; + } + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "function r = read(is)"; out.inc(); out << nl << "sz = is.readSize();"; @@ -1928,6 +2224,28 @@ CodeVisitor::visitDictionary(const DictionaryPtr& p) out << nl << "end"; out.dec(); out << nl << "end"; + + out << nl << "function r = readOpt(is, tag)"; + out.inc(); + out << nl << "if is.readOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + if(key->isVariableLength() || value->isVariableLength()) + { + out << nl << "is.skip(4);"; + } + else + { + out << nl << "is.skipSize();"; + } + out << nl << "r = " << abs << ".read(is);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "r = Ice.Unset;"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; } out.dec(); @@ -1981,12 +2299,37 @@ CodeVisitor::visitEnum(const EnumPtr& p) out << nl << "end"; out.dec(); out << nl << "end"; + + out << nl << "function ice_writeOpt(os, tag, v)"; + out.inc(); + out << nl << "if v ~= Ice.Unset && os.writeOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + out << nl << abs << ".ice_write(os, v);"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; + out << nl << "function r = ice_read(is)"; out.inc(); out << nl << "v = is.readEnum(" << p->maxValue() << ");"; out << nl << "r = " << abs << ".ice_getValue(v);"; out.dec(); out << nl << "end"; + + out << nl << "function r = ice_readOpt(is, tag)"; + out.inc(); + out << nl << "if is.readOptional(tag, " << getOptionalFormat(p) << ")"; + out.inc(); + out << nl << "r = " << abs << ".ice_read(is);"; + out.dec(); + out << nl << "else"; + out.inc(); + out << nl << "r = Ice.Unset;"; + out.dec(); + out << nl << "end"; + out.dec(); + out << nl << "end"; } out << nl << "function r = ice_getValue(v)"; out.inc(); @@ -2142,7 +2485,7 @@ CodeVisitor::collectExceptionMembers(const ExceptionPtr& p, MemberInfoList& allM for(DataMemberList::iterator q = members.begin(); q != members.end(); ++q) { MemberInfo m; - m.fixedName = fixIdent((*q)->name()); + m.fixedName = fixExceptionMemberIdent((*q)->name()); m.inherited = inherited; m.dataMember = *q; allMembers.push_back(m); @@ -2150,7 +2493,7 @@ CodeVisitor::collectExceptionMembers(const ExceptionPtr& p, MemberInfoList& allM } CodeVisitor::ParamInfoList -CodeVisitor::getInParams(const OperationPtr& op) +CodeVisitor::getAllInParams(const OperationPtr& op) { const ParamDeclList l = op->inParameters(); ParamInfoList r; @@ -2167,6 +2510,36 @@ CodeVisitor::getInParams(const OperationPtr& op) return r; } +void +CodeVisitor::getInParams(const OperationPtr& op, ParamInfoList& required, ParamInfoList& optional) +{ + const ParamInfoList params = getAllInParams(op); + for(ParamInfoList::const_iterator p = params.begin(); p != params.end(); ++p) + { + if(p->optional) + { + optional.push_back(*p); + } + else + { + required.push_back(*p); + } + } + + // + // Sort optional parameters by tag. + // + class SortFn + { + public: + static bool compare(const ParamInfo& lhs, const ParamInfo& rhs) + { + return lhs.tag < rhs.tag; + } + }; + optional.sort(SortFn::compare); +} + CodeVisitor::ParamInfoList CodeVisitor::getAllOutParams(const OperationPtr& op) { @@ -2250,33 +2623,33 @@ CodeVisitor::getOptionalFormat(const TypePtr& type) case Builtin::KindByte: case Builtin::KindBool: { - return "'OptionalFormatF1'"; + return "Ice.OptionalFormat.F1"; } case Builtin::KindShort: { - return "'OptionalFormatF2'"; + return "Ice.OptionalFormat.F2"; } case Builtin::KindInt: case Builtin::KindFloat: { - return "'OptionalFormatF4'"; + return "Ice.OptionalFormat.F4"; } case Builtin::KindLong: case Builtin::KindDouble: { - return "'OptionalFormatF8'"; + return "Ice.OptionalFormat.F8"; } case Builtin::KindString: { - return "'OptionalFormatVSize'"; + return "Ice.OptionalFormat.VSize"; } case Builtin::KindObject: { - return "'OptionalFormatClass'"; + return "Ice.OptionalFormat.Class"; } case Builtin::KindObjectProxy: { - return "'OptionalFormatFSize'"; + return "Ice.OptionalFormat.FSize"; } case Builtin::KindLocalObject: { @@ -2285,43 +2658,43 @@ CodeVisitor::getOptionalFormat(const TypePtr& type) } case Builtin::KindValue: { - return "'OptionalFormatClass'"; + return "Ice.OptionalFormat.Class"; } } } if(EnumPtr::dynamicCast(type)) { - return "'OptionalFormatSize'"; + return "Ice.OptionalFormat.Size"; } SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { - return seq->type()->isVariableLength() ? "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + return seq->type()->isVariableLength() ? "Ice.OptionalFormat.FSize" : "Ice.OptionalFormat.VSize"; } DictionaryPtr d = DictionaryPtr::dynamicCast(type); if(d) { return (d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) ? - "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + "Ice.OptionalFormat.FSize" : "Ice.OptionalFormat.VSize"; } StructPtr st = StructPtr::dynamicCast(type); if(st) { - return st->isVariableLength() ? "'OptionalFormatFSize'" : "'OptionalFormatVSize'"; + return st->isVariableLength() ? "Ice.OptionalFormat.FSize" : "Ice.OptionalFormat.VSize"; } if(ProxyPtr::dynamicCast(type)) { - return "'OptionalFormatFSize'"; + return "Ice.OptionalFormat.FSize"; } ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); assert(cl); - return "'OptionalFormatClass'"; + return "Ice.OptionalFormat.Class"; } string @@ -2515,29 +2888,7 @@ CodeVisitor::marshal(IceUtilInternal::Output& out, const string& stream, const s const string typeS = getAbsolute(st); if(optional) { - if(optional) - { - out << nl << "if ~isempty(" << v << ") && " << stream << ".writeOptional(" << tag << ", " - << getOptionalFormat(type) << ")"; - out.inc(); - } - - if(st->isVariableLength()) - { - out << nl << "pos = " << stream << ".startSize();"; - out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; - out << nl << stream << ".endSize(pos);"; - } - else - { - out << nl << stream << ".writeSize(" << st->minWireSize() << ");"; - out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; - } - if(optional) - { - out.dec(); - out << nl << "end"; - } + out << nl << typeS << ".ice_writeOpt(" << stream << ", " << tag << ", " << v << ");"; } else { @@ -2552,11 +2903,7 @@ CodeVisitor::marshal(IceUtilInternal::Output& out, const string& stream, const s const string typeS = getAbsolute(en); if(optional) { - out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(type) << ")"; - out.inc(); - out << nl << typeS << ".ice_write(" << stream << ", " << v << ");"; - out.dec(); - out << nl << "end"; + out << nl << typeS << ".ice_writeOpt(" << stream << ", " << tag << ", " << v << ");"; } else { @@ -2570,11 +2917,7 @@ CodeVisitor::marshal(IceUtilInternal::Output& out, const string& stream, const s { if(optional) { - out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(dict) << "))"; - out.inc(); - out << nl << getAbsolute(dict) << ".write(" << stream << ", " << v << ");"; - out.dec(); - out << nl << "end"; + out << nl << getAbsolute(dict) << ".writeOpt(" << stream << ", " << tag << ", " << v << ");"; } else { @@ -2623,11 +2966,7 @@ CodeVisitor::marshal(IceUtilInternal::Output& out, const string& stream, const s if(optional) { - out << nl << "if " << stream << ".writeOptional(" << tag << ", " << getOptionalFormat(seq) << "))"; - out.inc(); - out << nl << getAbsolute(seq) << ".write(" << stream << ", " << v << ");"; - out.dec(); - out << nl << "end"; + out << nl << getAbsolute(seq) << ".writeOpt(" << stream << ", " << tag << ", " << v << ");"; } else { @@ -2750,7 +3089,7 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const { if(optional) { - out << nl << stream << ".readValue(" << tag << ", " << v << ", 'Ice.Value');"; + out << nl << stream << ".readValueOpt(" << tag << ", " << v << ", 'Ice.Value');"; } else { @@ -2782,19 +3121,33 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const ProxyPtr prx = ProxyPtr::dynamicCast(type); if(prx) { - const string typeS = getAbsolute(prx->_class(), "", "Prx"); - if(optional) + if(prx->_class()->isInterface()) { - out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; - out.inc(); - out << nl << stream << ".skip(4);"; - out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; - out.dec(); - out << nl << "end"; + const string typeS = getAbsolute(prx->_class(), "", "Prx"); + if(optional) + { + out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; + out.inc(); + out << nl << stream << ".skip(4);"; + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + out.dec(); + out << nl << "end"; + } + else + { + out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + } } else { - out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; + if(optional) + { + out << nl << v << " = " << stream << ".readProxyOpt(" << tag << ");"; + } + else + { + out << nl << v << " = " << stream << ".readProxy();"; + } } return; } @@ -2802,13 +3155,14 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); if(cl) { + const string cls = cl->isInterface() ? "Ice.Value" : getAbsolute(cl); if(optional) { - out << nl << stream << ".readValue(" << tag << ", " << v << ", '" << getAbsolute(cl) << "');"; + out << nl << stream << ".readValueOpt(" << tag << ", " << v << ", '" << cls << "');"; } else { - out << nl << stream << ".readValue(" << v << ", '" << getAbsolute(cl) << "');"; + out << nl << stream << ".readValue(" << v << ", '" << cls << "');"; } return; } @@ -2819,22 +3173,7 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const const string typeS = getAbsolute(st); if(optional) { - out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; - out.inc(); - - if(st->isVariableLength()) - { - out << nl << stream << ".skip(4);"; - } - else - { - out << nl << stream << ".skipSize();"; - } - - out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; - - out.dec(); - out << nl << "end"; + out << nl << v << " = " << typeS << ".ice_readOpt(" << stream << ", " << tag << ");"; } else { @@ -2849,11 +3188,7 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const const string typeS = getAbsolute(en); if(optional) { - out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(type) << ")"; - out.inc(); - out << nl << v << " = " << typeS << ".ice_read(" << stream << ");"; - out.dec(); - out << nl << "end"; + out << nl << v << " = " << typeS << ".ice_readOpt(" << stream << ", " << tag << ");"; } else { @@ -2867,11 +3202,7 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const { if(optional) { - out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(dict) << "))"; - out.inc(); - out << nl << v << " = " << getAbsolute(dict) << ".read(" << stream << ");"; - out.dec(); - out << nl << "end"; + out << nl << v << " = " << getAbsolute(dict) << ".readOpt(" << stream << ", " << tag << ");"; } else { @@ -2919,11 +3250,7 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const if(optional) { - out << nl << "if " << stream << ".readOptional(" << tag << ", " << getOptionalFormat(seq) << "))"; - out.inc(); - out << nl << v << " = " << getAbsolute(seq) << ".read(" << stream << ");"; - out.dec(); - out << nl << "end"; + out << nl << v << " = " << getAbsolute(seq) << ".readOpt(" << stream << ", " << tag << ");"; } else { diff --git a/matlab/README.md b/matlab/README.md index 69d1e294126..8deff7b1cc1 100644 --- a/matlab/README.md +++ b/matlab/README.md @@ -7,8 +7,7 @@ in a production application.* The build system currently requires Microsoft Visual Studio 2015. -Ice for MATLAB is intended to support MATLAB 2016a or later but has only been -tested with 2017a. +Ice for MATLAB supports MATLAB 2016a or later. ## Build Instructions @@ -74,10 +73,8 @@ these DLLs to `matlab\src\IceMatlab`. ### Running the Tests -Two tests have been ported to MATLAB so far: - - - `matlab\test\Ice\operations` - - `matlab\test\Ice\exceptions` +Several tests have been ported to MATLAB so far. You can find them in +`matlab\test\Ice\*`. Since Ice for MATLAB only supports client functionality, you will have to build and start a matching test server from a different language mapping. @@ -86,11 +83,7 @@ In a Command Prompt, start a test server. In MATLAB, change to a test directory: - cd matlab\test\Ice\operations - -Or: - - cd matlab\test\Ice\exceptions + cd matlab\test\Ice\... Now you can start the MATLAB test client. Assuming the server is running on the same host, use this command: diff --git a/matlab/lib/+Ice/Communicator.m b/matlab/lib/+Ice/Communicator.m index d8f51275780..f012fe79ba3 100644 --- a/matlab/lib/+Ice/Communicator.m +++ b/matlab/lib/+Ice/Communicator.m @@ -11,21 +11,62 @@ ICE_LICENSE file included in this distribution. classdef Communicator < IceInternal.WrapperObject methods - function obj = Communicator(impl) + function obj = Communicator(impl, vfm) obj = obj@IceInternal.WrapperObject(impl); + obj.valueFactoryManager = vfm; + end + function r = identityToString(obj, id) + r = obj.callWithResult_('identityToString', id); end function r = stringToProxy(obj, str) impl = libpointer('voidPtr'); - Ice.Util.callMethod(obj, 'stringToProxy', str, impl); - r = Ice.ObjectPrx(impl); + obj.call_('stringToProxy', str, impl); + if isNull(impl) + r = []; + else + r = Ice.ObjectPrx(impl, obj); + end + end + function r = propertyToProxy(obj, prop) + impl = libpointer('voidPtr'); + obj.call_('propertyToProxy', prop, impl); + if isNull(impl) + r = []; + else + r = Ice.ObjectPrx(impl, obj); + end + end + function r = proxyToProperty(obj, proxy, prop) + if isempty(proxy) + r = containers.Map('KeyType', 'char', 'ValueType', 'char'); + elseif ~isa(proxy, 'Ice.ObjectPrx') + throw(MException('Ice:ArgumentException', 'expecting a proxy')); + else + r = obj.callWithResult_('proxyToProperty', proxy.impl_, prop); + end + end + function r = proxyToString(obj, proxy) + if isempty(proxy) + r = ''; + elseif ~isa(proxy, 'Ice.ObjectPrx') + throw(MException('Ice:ArgumentException', 'expecting a proxy')); + else + r = obj.callWithResult_('proxyToString', proxy.impl_); + end end function r = getProperties(obj) impl = libpointer('voidPtr'); - Ice.Util.callMethod(obj, 'getProperties', impl); + obj.call_('getProperties', impl); r = Ice.Properties(impl); end + function r = getValueFactoryManager(obj) + r = obj.valueFactoryManager; + end function destroy(obj) - Ice.Util.callMethod(obj, 'destroy'); + obj.call_('destroy'); end end + properties(Access=private) + valueFactoryManager + end end diff --git a/matlab/lib/+Ice/Connection.m b/matlab/lib/+Ice/Connection.m index 8d8d05807e7..16df914b15a 100755 --- a/matlab/lib/+Ice/Connection.m +++ b/matlab/lib/+Ice/Connection.m @@ -14,63 +14,68 @@ ICE_LICENSE file included in this distribution. classdef Connection < IceInternal.WrapperObject
methods
- function obj = Connection(impl)
+ function obj = Connection(impl, communicator)
obj = obj@IceInternal.WrapperObject(impl);
+ obj.communicator = communicator;
end
function close(obj, mode)
- Ice.Util.callMethod(obj, 'close', mode);
+ obj.call_('close', mode);
end
function r = createProxy(obj, id)
proxy = libpointer('voidPtr');
- Ice.Util.callMethod(obj, 'createProxy', id, proxy);
- r = Ice.ObjectPrx(proxy);
+ obj.call_('createProxy', id, proxy);
+ r = Ice.ObjectPrx(proxy, obj.communicator);
end
function r = getEndpoint(obj)
throw(Ice.FeatureNotSupportedException('', '', 'getEndpoint'));
end
function flushBatchRequests(obj, compress)
- Ice.Util.callMethod(obj, 'flushBatchRequests', compress);
+ obj.call_('flushBatchRequests', compress);
end
function r = flushBatchRequestsAsync(obj)
future = libpointer('voidPtr');
- Ice.Util.callMethod(obj, 'flushBatchRequestsAsync', future);
+ obj.call_('flushBatchRequestsAsync', future);
assert(~isNull(future));
r = Ice.Future(future, 'flushBatchRequests', 0, 'Ice_SentFuture', []);
end
function heartbeat(obj)
- Ice.Util.callMethod(obj, 'heartbeat');
+ obj.call_('heartbeat');
end
function r = heartbeatAsync(obj)
future = libpointer('voidPtr');
- Ice.Util.callMethod(obj, 'heartbeatAsync', future);
+ obj.call_('heartbeatAsync', future);
assert(~isNull(future));
r = Ice.Future(future, 'heartbeat', 0, 'Ice_SentFuture', []);
end
function setACM(obj, timeout, close, heartbeat)
- Ice.Util.callMethod(obj, 'setACM', timeout, close, heartbeat);
+ obj.call_('setACM', timeout, close, heartbeat);
end
function r = getACM(obj)
- r = Ice.Util.callMethodWithResult(obj, 'getACM');
+ r = obj.callWithResult_('getACM');
end
function r = type(obj)
- r = Ice.Util.callMethodWithResult(obj, 'type');
+ r = obj.callWithResult_('type');
end
function r = timeout(obj)
t = libpointer('int32Ptr', 0);
- r = Ice.Util.callMethod(obj, 'timeout', t);
+ r = obj.call_('timeout', t);
r = t.Value;
end
function r = toString(obj)
- r = Ice.Util.callMethodWithResult(obj, 'toString');
+ r = obj.callWithResult_('toString');
end
function r = getInfo(obj)
throw(Ice.FeatureNotSupportedException('', '', 'getInfo'));
end
function setBufferSize(obj, rcvSize, sndSize)
- Ice.Util.callMethod(obj, 'setBufferSize', rcvSize, sndSize);
+ obj.call_('setBufferSize', rcvSize, sndSize);
end
function throwException(obj)
- Ice.Util.callMethod(obj, 'throwException');
+ obj.call_('throwException');
end
end
+
+ properties(Access=private)
+ communicator % The communicator wrapper
+ end
end
diff --git a/matlab/lib/+Ice/FormatType.m b/matlab/lib/+Ice/FormatType.m new file mode 100644 index 00000000000..da6cf9a533e --- /dev/null +++ b/matlab/lib/+Ice/FormatType.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef FormatType + enumeration + DefaultFormat + CompactFormat + SlicedFormat + end +end diff --git a/matlab/lib/+Ice/Future.m b/matlab/lib/+Ice/Future.m index 2da4a1db5b0..1a5d6d25ef1 100644 --- a/matlab/lib/+Ice/Future.m +++ b/matlab/lib/+Ice/Future.m @@ -9,7 +9,7 @@ ICE_LICENSE file included in this distribution. ********************************************************************** %} -classdef Future < handle +classdef Future < IceInternal.WrapperObject properties(SetAccess=private) ID = 0 NumOutputArguments @@ -19,45 +19,41 @@ classdef Future < handle end methods function obj = Future(impl, op, numOutArgs, type, fetchFunc) - obj.impl = impl; + obj = obj@IceInternal.WrapperObject(impl, type); obj.Operation = op; obj.NumOutputArguments = numOutArgs; - obj.type_ = type; - obj.fetchFunc_ = fetchFunc; + obj.fetchFunc = fetchFunc; idPtr = libpointer('uint64Ptr', 0); - Ice.Util.callMethodOnType(obj, obj.type_, 'id', idPtr); + obj.call_('id', idPtr); obj.ID = idPtr.Value; end function delete(obj) - if ~isempty(obj.impl) - Ice.Util.callMethodOnType(obj, obj.type_, '_release'); + if ~isempty(obj.impl_) + obj.call_('_release'); end + obj.impl_ = []; end function ok = wait(obj) okPtr = libpointer('uint8Ptr', 0); % Output param - Ice.Util.callMethodOnType(obj, obj.type_, 'wait', okPtr); + obj.call_('wait', okPtr); ok = okPtr.Value == 1; end function varargout = fetchOutputs(obj) if obj.Read throw(MException('Ice:InvalidStateException', 'outputs already read')); end - [varargout{1:obj.NumOutputArguments}] = obj.fetchFunc_(obj); + [varargout{1:obj.NumOutputArguments}] = obj.fetchFunc(obj); obj.Read = true; end function cancel(obj) - Ice.Util.callMethodOnType(obj, obj.type_, 'cancel'); + obj.call_('cancel'); end function r = get.State(obj) - obj.State = Ice.Util.callMethodOnTypeWithResult(obj, obj.type_, 'state'); + obj.State = obj.callWithResult_('state'); r = obj.State; end end properties(Access=private) - type_ - fetchFunc_ - end - properties(Hidden,SetAccess=protected) - impl + fetchFunc end end diff --git a/matlab/lib/+Ice/InputStream.m b/matlab/lib/+Ice/InputStream.m index efbfebde3fb..d18046b4e39 100644 --- a/matlab/lib/+Ice/InputStream.m +++ b/matlab/lib/+Ice/InputStream.m @@ -11,125 +11,200 @@ ICE_LICENSE file included in this distribution. classdef InputStream < IceInternal.WrapperObject methods - function obj = InputStream(impl) + function obj = InputStream(impl, communicator) obj = obj@IceInternal.WrapperObject(impl); - obj.encoding = Ice.Util.callMethodWithResult(obj, 'getEncoding'); + obj.communicator = communicator; + obj.encoding = obj.callWithResult_('getEncoding'); + obj.sliceValues = true; + end + function r = getCommunicator(obj) + r = obj.communicator; end function r = readBool(obj) v = libpointer('uint8Ptr', 0); - Ice.Util.callMethod(obj, 'readBool', v); + obj.call_('readBool', v); r = v.Value == 1; end function r = readBoolSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readBoolSeq'); + r = obj.callWithResult_('readBoolSeq'); end function r = readBoolOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readBoolOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F1) + r = obj.readBool(); + else + r = Ice.Unset; + end end function r = readBoolSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readBoolSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + r = obj.readBoolSeq(); + else + r = Ice.Unset; + end end function r = readByte(obj) v = libpointer('uint8Ptr', 0); - Ice.Util.callMethod(obj, 'readByte', v); + obj.call_('readByte', v); r = v.Value; end function r = readByteSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readByteSeq'); + r = obj.callWithResult_('readByteSeq'); end function r = readByteOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readByteOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F1) + r = obj.readByte(); + else + r = Ice.Unset; + end end function r = readByteSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readByteSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + r = obj.readByteSeq(); + else + r = Ice.Unset; + end end function r = readShort(obj) v = libpointer('int16Ptr', 0); - Ice.Util.callMethod(obj, 'readShort', v); + obj.call_('readShort', v); r = v.Value; end function r = readShortSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readShortSeq'); + r = obj.callWithResult_('readShortSeq'); end function r = readShortOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readShortOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F2) + r = obj.readShort(); + else + r = Ice.Unset; + end end function r = readShortSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readShortSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + obj.skipSize(); + r = obj.readShortSeq(); + else + r = Ice.Unset; + end end function r = readInt(obj) v = libpointer('int32Ptr', 0); - Ice.Util.callMethod(obj, 'readInt', v); + obj.call_('readInt', v); r = v.Value; end function r = readIntSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readIntSeq'); + r = obj.callWithResult_('readIntSeq'); end function r = readIntOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readIntOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F4) + r = obj.readInt(); + else + r = Ice.Unset; + end end function r = readIntSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readIntSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + obj.skipSize(); + r = obj.readIntSeq(); + else + r = Ice.Unset; + end end function r = readLong(obj) v = libpointer('int64Ptr', 0); - Ice.Util.callMethod(obj, 'readLong', v); + obj.call_('readLong', v); r = v.Value; end function r = readLongSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readLongSeq'); + r = obj.callWithResult_('readLongSeq'); end function r = readLongOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readLongOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F8) + r = obj.readLong(); + else + r = Ice.Unset; + end end function r = readLongSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readLongSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + obj.skipSize(); + r = obj.readLongSeq(); + else + r = Ice.Unset; + end end function r = readFloat(obj) v = libpointer('singlePtr', 0); - Ice.Util.callMethod(obj, 'readFloat', v); + obj.call_('readFloat', v); r = v.Value; end function r = readFloatSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readFloatSeq'); + r = obj.callWithResult_('readFloatSeq'); end function r = readFloatOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readFloatOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F4) + r = obj.readFloat(); + else + r = Ice.Unset; + end end function r = readFloatSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readFloatSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + obj.skipSize(); + r = obj.readFloatSeq(); + else + r = Ice.Unset; + end end function r = readDouble(obj) v = libpointer('doublePtr', 0); - Ice.Util.callMethod(obj, 'readDouble', v); + obj.call_('readDouble', v); r = v.Value; end function r = readDoubleSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readDoubleSeq'); + r = obj.callWithResult_('readDoubleSeq'); end function r = readDoubleOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readDoubleOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.F8) + r = obj.readDouble(); + else + r = Ice.Unset; + end end function r = readDoubleSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readDoubleSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + obj.skipSize(); + r = obj.readDoubleSeq(); + else + r = Ice.Unset; + end end function r = readString(obj) - r = Ice.Util.callMethodWithResult(obj, 'readString'); + r = obj.callWithResult_('readString'); end function r = readStringSeq(obj) - r = Ice.Util.callMethodWithResult(obj, 'readStringSeq'); + r = obj.callWithResult_('readStringSeq'); end function r = readStringOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readStringOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.VSize) + r = obj.readString(); + else + r = Ice.Unset; + end end function r = readStringSeqOpt(obj, tag) - r = Ice.Util.callMethodWithResult(obj, 'readStringSeqOpt', tag); + if obj.readOptional(tag, Ice.OptionalFormat.FSize) + obj.skip(4); + r = obj.readStringSeq(); + else + r = Ice.Unset; + end end function skip(obj, n) - Ice.Util.callMethod(obj, 'skip', n); + obj.call_('skip', n); end function skipSize(obj) - Ice.Util.callMethod(obj, 'skipSize'); + obj.call_('skipSize'); end function startException(obj) assert(~isempty(obj.currentEncaps) && ~isempty(obj.currentEncaps.decoder)); @@ -137,14 +212,14 @@ classdef InputStream < IceInternal.WrapperObject end function endException(obj) % TODO: preserve assert(~isempty(obj.currentEncaps) && ~isempty(obj.currentEncaps.decoder)); - obj.currentEncaps.decoder.endInstance(); + obj.currentEncaps.decoder.endInstance(false); end function startEncapsulation(obj) oldEncaps = obj.currentEncaps; if isempty(oldEncaps) % First allocated encaps? - obj.currentEncaps = IceInternal.Encaps(); + obj.currentEncaps = IceInternal.ReadEncaps(); else - obj.currentEncaps = IceInternal.Encaps(); + obj.currentEncaps = IceInternal.ReadEncaps(); obj.currentEncaps.previous = oldEncaps; end obj.currentEncaps.start = obj.pos(); @@ -174,7 +249,7 @@ classdef InputStream < IceInternal.WrapperObject function endEncapsulation(obj) assert(~isempty(obj.currentEncaps)); - if ~isequal(obj.currentEncaps.encoding, obj.Encoding_1_0) + if ~isequal(obj.currentEncaps.encoding, IceInternal.Protocol.Encoding_1_0) obj.skipOptionals(); if obj.pos() ~= obj.currentEncaps.start + obj.currentEncaps.sz throw(Ice.EncapsulationException()); @@ -207,7 +282,7 @@ classdef InputStream < IceInternal.WrapperObject encoding = Ice.EncodingVersion.ice_read(obj); %IceInternal::checkSupportedEncoding(encoding); // Make sure the encoding is supported % TODO - if isequal(encoding, obj.Encoding_1_0) + if isequal(encoding, IceInternal.Protocol.Encoding_1_0) if sz ~= 6 throw(Ice.EncapsulationException()); end @@ -219,7 +294,7 @@ classdef InputStream < IceInternal.WrapperObject r = encoding; end function skipEncapsulation(obj) - Ice.Util.callMethod(obj, 'skipEncapsulation'); + obj.call_('skipEncapsulation'); end function r = getEncoding(obj) if isempty(obj.currentEncaps) @@ -242,7 +317,7 @@ classdef InputStream < IceInternal.WrapperObject end function r = readSize(obj) v = libpointer('int32Ptr', 0); - Ice.Util.callMethod(obj, 'readSize', v); + obj.call_('readSize', v); r = v.Value; end function r = readOptional(obj, tag, fmt) @@ -250,7 +325,7 @@ classdef InputStream < IceInternal.WrapperObject if ~isempty(obj.currentEncaps.decoder) r = obj.currentEncaps.decoder.readOptional(tag, fmt); else - r = obj.readOptImpl(tag, fmt); + r = obj.readOptionalImpl(tag, fmt); end end function skipOptionals(obj) @@ -263,7 +338,7 @@ classdef InputStream < IceInternal.WrapperObject end v = obj.readByte(); - if v == obj.OPTIONAL_END_MARKER + if v == IceInternal.Protocol.OPTIONAL_END_MARKER return; end @@ -276,68 +351,95 @@ classdef InputStream < IceInternal.WrapperObject end function skipOptional(format) switch format - case obj.OptionalFormatF1 + case Ice.OptionalFormat.F1 obj.skip(1); - case OptionalFormatF2 + case Ice.OptionalFormat.F2 obj.skip(2); - case obj.OptionalFormatF4 + case Ice.OptionalFormat.F4 obj.skip(4); - case obj.OptionalFormatF8 + case Ice.OptionalFormat.F8 obj.skip(8); - case obj.OptionalFormatSize + case Ice.OptionalFormat.Size obj.skipSize(); - case obj.OptionalFormatVSize + case Ice.OptionalFormat.VSize obj.skip(obj.readSize()); - case obj.OptionalFormatFSize + case Ice.OptionalFormat.FSize sz = obj.readInt(); if sz < 0 throw(Ice.UnmarshalOutOfBoundsException()); end obj.skip(sz); - case obj.OptionalFormatClass + case Ice.OptionalFormat.Class obj.readValue(); % TODO end end function r = readProxy(obj) v = libpointer('voidPtr'); - Ice.Util.callMethod(obj, 'readProxy', v); + obj.call_('readProxy', v); if ~isNull(v) - r = Ice.ObjectPrx(v); + r = Ice.ObjectPrx(v, obj.communicator); else r = []; end end function r = readProxyOpt(obj, tag) - v = libpointer('voidPtr'); - Ice.Util.callMethod(obj, 'readProxyOpt', tag, v); - if ~isNull(v) - r = Ice.ObjectPrx(v); + if obj.readOptional(tag, Ice.OptionalFormat.FSize) + obj.skip(4); + r = obj.readProxy(); else - r = []; + r = Ice.Unset; end end function r = readEnum(obj, maxValue) v = libpointer('int32Ptr', 0); - Ice.Util.callMethod(obj, 'readEnum', maxValue, v); + obj.call_('readEnum', maxValue, v); r = v.Value; end - function readValue(obj, func, formalType) - fprintf('About to call readValue\n'); - if isempty(obj.valueFunctions) - obj.valueFunctions = {}; + function readValue(obj, cb, formalType) + obj.initEncaps(); + function check(v) + if isempty(v) || isa(v, formalType) + cb(v); + else + Ice.InputStream.throwUOE(formalType, v); + end + end + if isempty(cb) + obj.currentEncaps.decoder.readValue([]); + else + obj.currentEncaps.decoder.readValue(@(v) check(v)); + end + end + function readValueOpt(obj, tag, cb, formalType) + if obj.readOptional(tag, Ice.OptionalFormat.Class) + obj.readValue(cb, formalType); + elseif ~isempty(cb) + cb(Ice.Unset); end - obj.valueFunctions{end + 1} = func; - Ice.Util.callMethod(obj, 'readValue', obj, func, formalType); end function readPendingValues(obj) - Ice.Util.callMethod(obj, 'readPendingValues'); - obj.valueFunctions = {}; + if ~isempty(obj.currentEncaps) && ~isempty(obj.currentEncaps.decoder) + obj.currentEncaps.decoder.readPendingValues(); + elseif isequal(obj.getEncoding(), IceInternal.Protocol.Encoding_1_0) + % + % If using the 1.0 encoding and no instances were read, we + % still read an empty sequence of pending instances if + % requested (i.e.: if this is called). + % + % This is required by the 1.0 encoding, even if no instances + % are written we do marshal an empty sequence if marshaled + % data types use classes. + % + obj.skipSize(); + end end function startValue(obj) - Ice.Util.callMethod(obj, 'startValue'); + assert(~isempty(obj.currentEncaps) && ~isempty(obj.currentEncaps.decoder)); + obj.currentEncaps.decoder.startInstance(IceInternal.SliceType.ValueSlice); end - function endValue(obj, preserve) - Ice.Util.callMethod(obj, 'endValue'); + function r = endValue(obj, preserve) + assert(~isempty(obj.currentEncaps) && ~isempty(obj.currentEncaps.decoder)); + r = obj.currentEncaps.decoder.endInstance(preserve); end function throwException(obj) obj.initEncaps(); @@ -345,47 +447,110 @@ classdef InputStream < IceInternal.WrapperObject end function r = pos(obj) v = libpointer('uint32Ptr', 0); - Ice.Util.callMethod(obj, 'pos', v); + obj.call_('pos', v); r = v.Value; end + function setPos(obj, pos) + obj.call_('setPos', pos); + end function r = size(obj) v = libpointer('uint32Ptr', 0); - Ice.Util.callMethod(obj, 'size', v); + obj.call_('size', v); r = v.Value; end + function r = readOptionalImpl(obj, readTag, expectedFormat) + if isequal(obj.getEncoding(), IceInternal.Protocol.Encoding_1_0) + r = false; % Optional members aren't supported with the 1.0 encoding. + return; + end + + while true + if obj.pos() >= obj.currentEncaps.start + obj.currentEncaps.sz + r = false; % End of encapsulation also indicates end of optionals. + return; + end + + b = obj.readByte(); + v = b; + if v == IceInternal.Protocol.OPTIONAL_END_MARKER + obj.setPos(obj.pos() - 1); % Rewind. + r = false; + return; + end + + format = bitand(v, 7); % First 3 bits. + tag = bitshift(v, -3); + if tag == 30 + tag = obj.readSize(); + end + + if tag > readTag + offset = 0; + if tag < 30 + offset = 1; + elseif tag < 255 + offset = 2; + else + offset = 6; + end + obj.setPos(obj.pos() - offset); % Rewind + r = false; % No optional data members with the requested tag. + return; + elseif tag < readTag + obj.skipOptional(format); % Skip optional data members + else + if format ~= expectedFormat + throw(Ice.MarshalException('', '', ... + sprintf('invalid optional data member ''%d'': unexpected format', tag))); + end + r = true; + return; + end + end + end end methods(Access=private) function initEncaps(obj) if isempty(obj.currentEncaps) - obj.currentEncaps = IceInternal.Encaps(); + obj.currentEncaps = IceInternal.ReadEncaps(); obj.currentEncaps.encoding = obj.encoding; end + valueFactoryManager = obj.communicator.getValueFactoryManager(); + compactIdResolver = []; % TODO if isempty(obj.currentEncaps.decoder) if obj.currentEncaps.encoding.major == 1 && obj.currentEncaps.encoding.minor == 0 - obj.currentEncaps.decoder = IceInternal.EncapsDecoder10(obj, obj.currentEncaps); + obj.currentEncaps.decoder = ... + IceInternal.EncapsDecoder10(obj, obj.currentEncaps, obj.sliceValues, valueFactoryManager); else - obj.currentEncaps.decoder = IceInternal.EncapsDecoder11(obj, obj.currentEncaps); + obj.currentEncaps.decoder = ... + IceInternal.EncapsDecoder11(obj, obj.currentEncaps, obj.sliceValues, valueFactoryManager, ... + compactIdResolver); end end end end + methods(Static,Access=private) + function throwUOE(expectedType, v) + % + % If the object is an unknown sliced object, we didn't find a + % value factory, in this case raise a NoValueFactoryException + % instead. + % + if isa(v, 'Ice.UnknownSlicedValue') + throw(Ice.NoValueFactoryException('', '', '', v.ice_id())); + end + + type = class(v); + throw(Ice.UnexpectedObjectException('', '', ... + sprintf('expected element of type ''%s'' but received ''%s''', expectedType, type), type, ... + expectedType)); + end + end properties(Access=private) - valueFunctions + communicator encoding currentEncaps - end - properties(Constant) - Encoding_1_0 = Ice.EncodingVersion(1, 0) - Encoding_1_1 = Ice.EncodingVersion(1, 1) - OPTIONAL_END_MARKER = hex2dec('ff') - OptionalFormatF1 = 0 - OptionalFormatF2 = 1 - OptionalFormatF4 = 2 - OptionalFormatF8 = 3 - OptionalFormatSize = 4 - OptionalFormatVSize = 5 - OptionalFormatFSize = 6 - OptionalFormatClass = 7 + sliceValues end end diff --git a/matlab/lib/+Ice/InterfaceByValue.m b/matlab/lib/+Ice/InterfaceByValue.m new file mode 100644 index 00000000000..86c3b104e4f --- /dev/null +++ b/matlab/lib/+Ice/InterfaceByValue.m @@ -0,0 +1,32 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef InterfaceByValue < Ice.Value + methods + function obj = InterfaceByValue(id) + obj.id = id; + end + function id = ice_id(obj) + id = obj.id; + end + function iceWriteImpl_(obj, os) + os.startSlice(obj.ice_id(), -1, true); + os.endSlice(); + end + function obj = iceReadImpl_(obj, is) + is.startSlice(); + is.endSlice(); + end + end + properties(Access=private) + id + end +end diff --git a/matlab/lib/+Ice/ObjectPrx.m b/matlab/lib/+Ice/ObjectPrx.m index 438dc1979ce..e09f218482a 100644 --- a/matlab/lib/+Ice/ObjectPrx.m +++ b/matlab/lib/+Ice/ObjectPrx.m @@ -11,522 +11,523 @@ ICE_LICENSE file included in this distribution. classdef ObjectPrx < IceInternal.WrapperObject methods - function self = ObjectPrx(impl) - self = self@IceInternal.WrapperObject(impl); + function obj = ObjectPrx(impl, communicator) + obj = obj@IceInternal.WrapperObject(impl, 'Ice_ObjectPrx'); + obj.communicator = communicator; end - function delete(self) - self.callMethod('_release'); - self.impl = []; + function delete(obj) + obj.call_('_release'); + obj.impl_ = []; end % % Override == operator. % - function r = eq(self, other) + function r = eq(obj, other) if isempty(other) || ~isa(other, 'Ice.ObjectPrx') r = false; else v = libpointer('uint8Ptr', 0); - self.callMethod('equals', other.impl, v); + obj.call_('equals', other.impl_, v); r = v.Value == 1; end end - function r = ice_createOutputStream(self) + function r = ice_createOutputStream(obj) stream = libpointer('voidPtr'); - self.callMethod('ice_createOutputStream', stream); - r = Ice.OutputStream(stream); + obj.call_('ice_createOutputStream', stream); + r = Ice.OutputStream(stream, obj.communicator); end - function r = ice_toString(self) - r = self.callMethodWithResult('ice_toString'); + function r = ice_toString(obj) + r = obj.callWithResult_('ice_toString'); end - function r = ice_getCommunicator(self) - v = libpointer('voidPtr'); - self.callMethod('ice_getCommunicator', v); - assert(~isNull(v)); - r = Ice.Communicator(v); + function r = ice_getCommunicator(obj) + r = obj.communicator; end - function ice_ping(self, varargin) - [ok, inStream] = self.invoke_('ice_ping', 'Nonmutating', false, [], varargin{:}); - self.checkNoResponse_(ok, inStream); + function ice_ping(obj, varargin) + [ok, inStream] = obj.invoke_('ice_ping', 'Nonmutating', false, [], varargin{:}); + obj.checkNoResponse_(ok, inStream); end - function r = ice_pingAsync(self, varargin) - r = self.invokeAsync_('ice_ping', 'Nonmutating', false, [], 0, [], varargin{:}); + function r = ice_pingAsync(obj, varargin) + r = obj.invokeAsync_('ice_ping', 'Nonmutating', false, [], 0, [], varargin{:}); end - function r = ice_isA(self, id, varargin) - os = self.startWriteParams_(); + function r = ice_isA(obj, id, varargin) + os = obj.startWriteParams_(); os.writeString(id); - self.endWriteParams_(os); - [ok, inStream] = self.invoke_('ice_isA', 'Nonmutating', true, os, varargin{:}); + obj.endWriteParams_(os); + [ok, inStream] = obj.invoke_('ice_isA', 'Nonmutating', true, os, varargin{:}); if ok inStream.startEncapsulation(); r = inStream.readBool(); inStream.endEncapsulation(); else - self.throwUserException_(inStream); + obj.throwUserException_(inStream); end end - function r = ice_isAAsync(self, id, varargin) - os = self.startWriteParams_(); + function r = ice_isAAsync(obj, id, varargin) + os = obj.startWriteParams_(); os.writeString(id); - self.endWriteParams_(os); + obj.endWriteParams_(os); function varargout = unmarshal(ok, is) if ok is.startEncapsulation(); varargout{1} = is.readBool(); is.endEncapsulation(); else - self.throwUserException_(is); + obj.throwUserException_(is); end end - r = self.invokeAsync_('ice_isA', 'Nonmutating', true, os, 1, @unmarshal, varargin{:}); + r = obj.invokeAsync_('ice_isA', 'Nonmutating', true, os, 1, @unmarshal, varargin{:}); end - function r = ice_id(self, varargin) - [ok, inStream] = self.invoke_('ice_id', 'Nonmutating', true, [], varargin{:}); + function r = ice_id(obj, varargin) + [ok, inStream] = obj.invoke_('ice_id', 'Nonmutating', true, [], varargin{:}); if ok inStream.startEncapsulation(); r = inStream.readString(); inStream.endEncapsulation(); else - self.throwUserException_(inStream); + obj.throwUserException_(inStream); end end - function r = ice_idAsync(self, varargin) + function r = ice_idAsync(obj, varargin) function varargout = unmarshal(ok, is) if ok is.startEncapsulation(); varargout{1} = is.readString(); is.endEncapsulation(); else - self.throwUserException_(is); + obj.throwUserException_(is); end end - r = self.invokeAsync_('ice_id', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); + r = obj.invokeAsync_('ice_id', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); end - function r = ice_ids(self, varargin) - [ok, inStream] = self.invoke_('ice_ids', 'Nonmutating', true, [], varargin{:}); + function r = ice_ids(obj, varargin) + [ok, inStream] = obj.invoke_('ice_ids', 'Nonmutating', true, [], varargin{:}); if ok inStream.startEncapsulation(); r = inStream.readStringSeq(); inStream.endEncapsulation(); else - self.throwUserException_(inStream); + obj.throwUserException_(inStream); end end - function r = ice_idsAsync(self, varargin) + function r = ice_idsAsync(obj, varargin) function varargout = unmarshal(ok, is) if ok is.startEncapsulation(); varargout{1} = is.readStringSeq(); is.endEncapsulation(); else - self.throwUserException_(is); + obj.throwUserException_(is); end end - r = self.invokeAsync_('ice_ids', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); + r = obj.invokeAsync_('ice_ids', 'Nonmutating', true, [], 1, @unmarshal, varargin{:}); end - function r = ice_getIdentity(self) - r = self.callMethodWithResult('ice_getIdentity'); + function r = ice_getIdentity(obj) + r = obj.callWithResult_('ice_getIdentity'); end - function r = ice_identity(self, id) + function r = ice_identity(obj, id) v = libpointer('voidPtr'); - self.callMethod('ice_identity', id, v); + obj.call_('ice_identity', id, v); if isNull(v) - r = self; + r = obj; else - r = Ice.ObjectPrx(v); % Don't use newInstance_ here + r = Ice.ObjectPrx(v, obj.communicator); % Don't use newInstance_ here end end - function r = ice_getContext(self) - r = self.callMethodWithResult('ice_getContext'); + function r = ice_getContext(obj) + r = obj.callWithResult_('ice_getContext'); end - function r = ice_context(self, ctx) + function r = ice_context(obj, ctx) v = libpointer('voidPtr'); - self.callMethod('ice_context', ctx, v); + obj.call_('ice_context', ctx, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getFacet(self) - r = self.callMethodWithResult('ice_getFacet'); + function r = ice_getFacet(obj) + r = obj.callWithResult_('ice_getFacet'); end - function r = ice_facet(self, f) + function r = ice_facet(obj, f) v = libpointer('voidPtr'); - self.callMethod('ice_facet', f, v); + obj.call_('ice_facet', f, v); if isNull(v) - r = self; + r = obj; else - r = Ice.ObjectPrx(v); % Don't use newInstance_ here + r = Ice.ObjectPrx(v, obj.communicator); % Don't use newInstance_ here end end - function r = ice_getAdapterId(self) - r = self.callMethodWithResult('ice_getAdapterId'); + function r = ice_getAdapterId(obj) + r = obj.callWithResult_('ice_getAdapterId'); end - function r = ice_adapterId(self, id) + function r = ice_adapterId(obj, id) v = libpointer('voidPtr'); - self.callMethod('ice_adapterId', id, v); + obj.call_('ice_adapterId', id, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getEndpoints(self) - r = self.callMethodWithResult('ice_getEndpoints'); + function r = ice_getEndpoints(obj) + r = obj.callWithResult_('ice_getEndpoints'); end - function r = ice_endpoints(self, endpts) + function r = ice_endpoints(obj, endpts) v = libpointer('voidPtr'); - self.callMethod('ice_endpoints', endpts, v); + obj.call_('ice_endpoints', endpts, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getLocatorCacheTimeout(self) + function r = ice_getLocatorCacheTimeout(obj) v = libpointer('int32Ptr', 0); - self.callMethod('ice_getLocatorCacheTimeout', v); + obj.call_('ice_getLocatorCacheTimeout', v); r = v.Value; end - function r = ice_locatorcacheTimeout(self, t) + function r = ice_locatorCacheTimeout(obj, t) v = libpointer('voidPtr'); - self.callMethod('ice_locatorCacheTimeout', t, v); + obj.call_('ice_locatorCacheTimeout', t, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getInvocationTimeout(self) + function r = ice_getInvocationTimeout(obj) v = libpointer('int32Ptr', 0); - self.callMethod('ice_getInvocationTimeout', v); + obj.call_('ice_getInvocationTimeout', v); r = v.Value; end - function r = ice_invocationTimeout(self, t) + function r = ice_invocationTimeout(obj, t) v = libpointer('voidPtr'); - self.callMethod('ice_invocationTimeout', t, v); + obj.call_('ice_invocationTimeout', t, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getConnectionId(self) - r = self.callMethodWithResult('ice_getConnectionId'); + function r = ice_getConnectionId(obj) + r = obj.callWithResult_('ice_getConnectionId'); end - function r = ice_connectionId(self, id) + function r = ice_connectionId(obj, id) v = libpointer('voidPtr'); - self.callMethod('ice_connectionId', id, v); + obj.call_('ice_connectionId', id, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isConnectionCached(self) + function r = ice_isConnectionCached(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isConnectionCached', v); + obj.call_('ice_isConnectionCached', v); r = v.Value == 1; end - function r = ice_connectionCached(self, b) + function r = ice_connectionCached(obj, b) v = libpointer('voidPtr'); if b val = 1; else val = 0; end - self.callMethod('ice_connectionCached', val, v); + obj.call_('ice_connectionCached', val, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getEndpointSelection(self) - v = libpointer('Ice_EndpointSelectionType', 'Random'); - self.callMethod('ice_getEndpointSelection', v); - r = v.Value; + function r = ice_getEndpointSelection(obj) + v = libpointer('int32Ptr', 0); + obj.call_('ice_getEndpointSelection', v); + r = Ice.EndpointSelectionType.ice_getValue(v.Value); end - function r = ice_endpointSelection(self, t) + function r = ice_endpointSelection(obj, t) + if ~isa(t, 'Ice.EndpointSelectionType') + throw(MException('Ice:ArgumentException', 'expected an Ice.EndpointSelectionType enumerator')); + end v = libpointer('voidPtr'); - self.callMethod('ice_endpointSelection', t, v); + obj.call_('ice_endpointSelection', int32(t), v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getEncodingVersion(self) - r = self.callMethodWithResult('ice_getEncodingVersion'); + function r = ice_getEncodingVersion(obj) + r = obj.callWithResult_('ice_getEncodingVersion'); end - function r = ice_encodingVersion(self, ver) + function r = ice_encodingVersion(obj, ver) v = libpointer('voidPtr'); - self.callMethod('ice_encodingVersion', ver, v); + obj.call_('ice_encodingVersion', ver, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getRouter(self) + function r = ice_getRouter(obj) v = libpointer('voidPtr'); - self.callMethod('ice_getRouter', v); + obj.call_('ice_getRouter', v); if isNull(v) r = []; else - r = Ice.RouterPrx(v); + r = Ice.RouterPrx(v, obj.communicator); end end - function r = ice_router(self, rtr) + function r = ice_router(obj, rtr) v = libpointer('voidPtr'); if isempty(rtr) impl = libpointer('voidPtr'); else - impl = rtr.impl; + impl = rtr.impl_; end - self.callMethod('ice_router', impl, v); + obj.call_('ice_router', impl, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getLocator(self) + function r = ice_getLocator(obj) v = libpointer('voidPtr'); - self.callMethod('ice_getLocator', v); + obj.call_('ice_getLocator', v); if isNull(v) r = []; else - r = Ice.LocatorPrx(v); + r = Ice.LocatorPrx(v, obj.communicator); end end - function r = ice_locator(self, loc) + function r = ice_locator(obj, loc) v = libpointer('voidPtr'); if isempty(loc) impl = libpointer('voidPtr'); else - impl = loc.impl; + impl = loc.impl_; end - self.callMethod('ice_locator', impl, v); + obj.call_('ice_locator', impl, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isSecure(self) + function r = ice_isSecure(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isSecure', v); + obj.call_('ice_isSecure', v); r = v.Value == 1; end - function r = ice_secure(self, b) + function r = ice_secure(obj, b) v = libpointer('voidPtr'); if b val = 1; else val = 0; end - self.callMethod('ice_secure', val, v); + obj.call_('ice_secure', val, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isPreferSecure(self) + function r = ice_isPreferSecure(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isPreferSecure', v); + obj.call_('ice_isPreferSecure', v); r = v.Value == 1; end - function r = ice_preferSecure(self, b) + function r = ice_preferSecure(obj, b) v = libpointer('voidPtr'); if b val = 1; else val = 0; end - self.callMethod('ice_preferSecure', val, v); + obj.call_('ice_preferSecure', val, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isTwoway(self) + function r = ice_isTwoway(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isTwoway', v); + obj.call_('ice_isTwoway', v); r = v.Value == 1; end - function r = ice_twoway(self) + function r = ice_twoway(obj) v = libpointer('voidPtr'); - self.callMethod('ice_twoway', v); + obj.call_('ice_twoway', v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isOneway(self) + function r = ice_isOneway(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isOneway', v); + obj.call_('ice_isOneway', v); r = v.Value == 1; end - function r = ice_oneway(self) + function r = ice_oneway(obj) v = libpointer('voidPtr'); - self.callMethod('ice_oneway', v); + obj.call_('ice_oneway', v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isBatchOneway(self) + function r = ice_isBatchOneway(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isBatchOneway', v); + obj.call_('ice_isBatchOneway', v); r = v.Value == 1; end - function r = ice_batchOneway(self) + function r = ice_batchOneway(obj) v = libpointer('voidPtr'); - self.callMethod('ice_batchOneway', v); + obj.call_('ice_batchOneway', v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isDatagram(self) + function r = ice_isDatagram(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isDatagram', v); + obj.call_('ice_isDatagram', v); r = v.Value == 1; end - function r = ice_datagram(self) + function r = ice_datagram(obj) v = libpointer('voidPtr'); - self.callMethod('ice_datagram', v); + obj.call_('ice_datagram', v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_isBatchDatagram(self) + function r = ice_isBatchDatagram(obj) v = libpointer('uint8Ptr', 0); - self.callMethod('ice_isBatchDatagram', v); + obj.call_('ice_isBatchDatagram', v); r = v.Value == 1; end - function r = ice_batchDatagram(self) + function r = ice_batchDatagram(obj) v = libpointer('voidPtr'); - self.callMethod('ice_batchDatagram', v); + obj.call_('ice_batchDatagram', v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_compress(self, b) + function r = ice_compress(obj, b) v = libpointer('voidPtr'); if b val = 1; else val = 0; end - self.callMethod('ice_compress', val, v); + obj.call_('ice_compress', val, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_timeout(self, t) + function r = ice_timeout(obj, t) v = libpointer('voidPtr'); - self.callMethod('ice_timeout', t, v); + obj.call_('ice_timeout', t, v); if isNull(v) - r = self; + r = obj; else - r = self.newInstance_(v); + r = obj.newInstance_(v); end end - function r = ice_getConnection(self) + function r = ice_getConnection(obj) v = libpointer('voidPtr'); - self.callMethod('ice_getConnection', v); + obj.call_('ice_getConnection', v); if isNull(v) r = []; else - r = Ice.Connection(v); + r = Ice.Connection(v, obj.communicator); end end - function r = ice_getConnectionAsync(self) + function r = ice_getConnectionAsync(obj) future = libpointer('voidPtr'); - self.callMethod('ice_getConnectionAsync', future); + obj.call_('ice_getConnectionAsync', future); assert(~isNull(future)); function varargout = fetch(f) con = libpointer('voidPtr', 0); % Output param - Ice.Util.callMethodOnType(f, 'Ice_GetConnectionFuture', 'fetch', con); + f.call_('fetch', con); assert(~isNull(con)); varargout{1} = Ice.Connection(con); end r = Ice.Future(future, 'ice_getConnection', 1, 'Ice_GetConnectionFuture', @fetch); end - function r = ice_getCachedConnection(self) + function r = ice_getCachedConnection(obj) v = libpointer('voidPtr'); - self.callMethod('ice_getCachedConnection', v); + obj.call_('ice_getCachedConnection', v); if isNull(v) r = []; else @@ -534,24 +535,24 @@ classdef ObjectPrx < IceInternal.WrapperObject end end - function ice_flushBatchRequests(self) - self.callMethod('ice_flushBatchRequests'); + function ice_flushBatchRequests(obj) + obj.call_('ice_flushBatchRequests'); end - function r = ice_flushBatchRequestsAsync(self) + function r = ice_flushBatchRequestsAsync(obj) future = libpointer('voidPtr'); - self.callMethod('ice_flushBatchRequestsAsync', future); + obj.call_('ice_flushBatchRequestsAsync', future); assert(~isNull(future)); r = Ice.Future(future, 'ice_flushBatchRequests', 0, 'Ice_SentFuture', []); end end methods(Access=protected) - function checkNoResponse_(self, ok, inStream) - if self.ice_isTwoway() + function checkNoResponse_(obj, ok, inStream) + if obj.ice_isTwoway() if ok == 0 try - self.throwUserException_(inStream); + obj.throwUserException_(inStream); catch ex ex.throwAsCaller(); end @@ -561,53 +562,53 @@ classdef ObjectPrx < IceInternal.WrapperObject end end - function os = startWriteParams_(self) - os = self.ice_createOutputStream(); - os.startEncapsulation(); + function os = startWriteParams_(obj) + os = obj.ice_createOutputStream(); + os.startEncapsulation([]); end - function os = startWriteParamsWithFormat_(self, format) - os = self.ice_createOutputStream(); - os.startEncapsulationWithFormat(format); + function os = startWriteParamsWithFormat_(obj, format) + os = obj.ice_createOutputStream(); + os.startEncapsulation(format); end - function endWriteParams_(self, os) + function endWriteParams_(obj, os) os.endEncapsulation(); end - function [ok, inStream] = invoke_(self, op, mode, twowayOnly, os, varargin) - try + function [ok, inStream] = invoke_(obj, op, mode, twowayOnly, os, varargin) + %try TODO % Vararg accepted for optional context argument. if length(varargin) > 1 throw(MException('Ice:ArgumentException', 'one optional argument is allowed for request context')) end - if twowayOnly && ~self.ice_isTwoway() + if twowayOnly && ~obj.ice_isTwoway() throw(Ice.TwowayOnlyException('', 'invocation requires twoway proxy', op)); end if ~isempty(os) - outStream = os.impl; + outStream = os.impl_; else outStream = libpointer('voidPtr'); % Null pointer for output stream end okPtr = libpointer('uint8Ptr', 0); % Output param inStreamPtr = libpointer('voidPtr'); % Output param if length(varargin) == 1 - self.callMethod('ice_invoke', op, mode, outStream, varargin{1}, okPtr, inStreamPtr); + obj.call_('ice_invoke', op, mode, outStream, varargin{1}, okPtr, inStreamPtr); else - self.callMethod('ice_invokeNC', op, mode, outStream, okPtr, inStreamPtr); + obj.call_('ice_invokeNC', op, mode, outStream, okPtr, inStreamPtr); end ok = okPtr.Value == 1; inStream = []; if ~isNull(inStreamPtr) - inStream = Ice.InputStream(inStreamPtr); + inStream = Ice.InputStream(inStreamPtr, obj.communicator); end - catch ex - ex.throwAsCaller(); - end + %catch ex + % ex.throwAsCaller(); + %end end - function fut = invokeAsync_(self, op, mode, twowayOnly, os, numOutArgs, unmarshalFunc, varargin) - isTwoway = self.ice_isTwoway(); + function fut = invokeAsync_(obj, op, mode, twowayOnly, os, numOutArgs, unmarshalFunc, varargin) + isTwoway = obj.ice_isTwoway(); % This nested function is invoked by Future.fetchOutputs() function varargout = fetch(f) @@ -619,14 +620,14 @@ classdef ObjectPrx < IceInternal.WrapperObject % okPtr = libpointer('uint8Ptr', 0); % Output param inStreamPtr = libpointer('voidPtr', 0); % Output param - Ice.Util.callMethodOnType(f, 'Ice_InvocationFuture', 'stream', okPtr, inStreamPtr); + f.call_('stream', okPtr, inStreamPtr); ok = okPtr.Value == 1; assert(~isNull(inStreamPtr)); - inStream = Ice.InputStream(inStreamPtr); + inStream = Ice.InputStream(inStreamPtr, obj.communicator); if isempty(unmarshalFunc) if ~ok % Unexpected user exception - self.throwUserException_(inStream); + obj.throwUserException_(inStream); else inStream.skipEmptyEncapsulation(); end @@ -637,7 +638,7 @@ classdef ObjectPrx < IceInternal.WrapperObject % % Check for a local exception. % - Ice.Util.callMethodOnType(f, 'Ice_InvocationFuture', 'check'); + f.call_('check'); end catch ex ex.throwAsCaller(); @@ -649,19 +650,19 @@ classdef ObjectPrx < IceInternal.WrapperObject if length(varargin) > 1 throw(MException('Ice:ArgumentException', 'one optional argument is allowed for request context')) end - if twowayOnly && ~self.ice_isTwoway() + if twowayOnly && ~obj.ice_isTwoway() throw(Ice.TwowayOnlyException('', 'invocation requires twoway proxy', op)); end if ~isempty(os) - outStream = os.impl; + outStream = os.impl_; else outStream = libpointer('voidPtr'); % Null pointer for output stream end futPtr = libpointer('voidPtr'); % Output param if length(varargin) == 1 - self.callMethod('ice_invokeAsync', op, mode, outStream, varargin{1}, futPtr); + obj.call_('ice_invokeAsync', op, mode, outStream, varargin{1}, futPtr); else - self.callMethod('ice_invokeAsyncNC', op, mode, outStream, futPtr); + obj.call_('ice_invokeAsyncNC', op, mode, outStream, futPtr); end assert(~isNull(futPtr)); fut = Ice.Future(futPtr, op, numOutArgs, 'Ice_InvocationFuture', @fetch); @@ -670,7 +671,7 @@ classdef ObjectPrx < IceInternal.WrapperObject end end - function throwUserException_(self, inStream, varargin) % Varargs are user exception type names + function throwUserException_(obj, inStream, varargin) % Varargs are user exception type names try inStream.startEncapsulation(); inStream.throwException(); @@ -690,36 +691,43 @@ classdef ObjectPrx < IceInternal.WrapperObject end end - function r = newInstance_(self, impl) - constructor = str2func(class(self)); % Obtain the constructor for this class - r = constructor(impl); % Call the constructor + function r = newInstance_(obj, impl) + constructor = str2func(class(obj)); % Obtain the constructor for this class + r = constructor(impl, obj.communicator); % Call the constructor end - function r = clone_(self) + function r = clone_(obj) implPtr = libpointer('voidPtr'); % Output param - self.callMethod('clone', implPtr); + obj.call_('clone', implPtr); r = implPtr; end end - methods(Access=private) - % We don't use the functions in Ice.Util because they use the most-derived class name, whereas we always - % want to use Ice_ObjectPrx_xxx. - function callMethod(self, fn, varargin) - name = strcat('Ice_ObjectPrx_', fn); - ex = calllib('icematlab', name, self.impl, varargin{:}); - if ~isempty(ex) - ex.throwAsCaller(); + methods(Static) + function r = ice_staticId() + r = '::Ice::Object'; + end + + function r = checkedCast(p, varargin) + if length(varargin) == 0 + r = p; + else + r = Ice.ObjectPrx.checkedCast(p, Ice.ObjectPrx.ice_staticId(), 'Ice.ObjectPrx', varargin{:}); end end - function r = callMethodWithResult(self, fn, varargin) - name = strcat('Ice_ObjectPrx_', fn); - result = calllib('icematlab', name, self.impl, varargin{:}); - if ~isempty(result.exception) - result.exception.throwAsCaller(); + function r = uncheckedCast(p, varargin) + if length(varargin) == 0 + r = p; + elseif length(varargin) == 1 + if ~isempty(p) + r = p.ice_facet(varargin{1}); + else + r = p; + end + else + throw(MException('Ice:ArgumentException', 'too many arguments to uncheckedCast')); end - r = result.result; end end @@ -728,23 +736,30 @@ classdef ObjectPrx < IceInternal.WrapperObject p = inStream.readProxy(); if ~isempty(p) constructor = str2func(cls); - r = constructor(p.clone_()); + r = constructor(p.clone_(), inStream.getCommunicator()); else r = []; end end function r = checkedCast_(p, id, cls, varargin) - %try + try hasFacet = false; facet = []; context = {}; if length(varargin) == 1 - facet = varargin{1}; - hasFacet = true; + if isa(varargin{1}, 'containers.Map') + context = { varargin{1} }; + elseif isempty(varargin{1}) || isa(varargin{1}, 'char') + hasFacet = true; + facet = varargin{1}; + else + throw(MException('Ice:ArgumentException', 'expecting string or containers.Map')); + end elseif length(varargin) == 2 + hasFacet = true; facet = varargin{1}; - context = {varargin{2}}; + context = { varargin{2} }; elseif length(varargin) > 2 throw(MException('Ice:ArgumentException', 'too many arguments to checkedCast')); end @@ -756,16 +771,16 @@ classdef ObjectPrx < IceInternal.WrapperObject r = p; elseif p.ice_isA(id, context{:}) constructor = str2func(cls); - r = constructor(p.clone_()); + r = constructor(p.clone_(), p.communicator); else r = []; end else r = p; end - %catch ex - % ex.throwAsCaller(); - %end + catch ex + ex.throwAsCaller(); + end end function r = uncheckedCast_(p, cls, varargin) @@ -783,11 +798,15 @@ classdef ObjectPrx < IceInternal.WrapperObject r = p; else constructor = str2func(cls); - r = constructor(p.clone_()); + r = constructor(p.clone_(), p.communicator); end else r = p; end end end + + properties(Access=private) + communicator % The communicator wrapper + end end diff --git a/matlab/lib/+Ice/Optional.m b/matlab/lib/+Ice/Optional.m deleted file mode 100644 index ec30540fd11..00000000000 --- a/matlab/lib/+Ice/Optional.m +++ /dev/null @@ -1,48 +0,0 @@ -%{ -********************************************************************** - -Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. - -This copy of Ice is licensed to you under the terms described in the -ICE_LICENSE file included in this distribution. - -********************************************************************** -%} - -classdef Optional - methods - function obj = Optional(v) - if nargin == 0 - obj.isSet = false - else - obj.value = v - end - end - function obj = set.value(obj, v) - if isempty(v) - obj.value = v - obj.isSet = false - else - obj.value = v - obj.isSet = true - end - end - function v = get.value(obj) - if obj.isSet - v = obj.value - else - throw(MException('ICE:IllegalStateException', 'Optional does not have a value')) - end - end - function obj = clear(obj) % Use with v = v.clear() - obj.value = [] - obj.isSet = false - end - end - properties - value - end - properties(SetAccess = private) - isSet - end -end diff --git a/matlab/lib/+Ice/OptionalFormat.m b/matlab/lib/+Ice/OptionalFormat.m new file mode 100644 index 00000000000..f484118127a --- /dev/null +++ b/matlab/lib/+Ice/OptionalFormat.m @@ -0,0 +1,23 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef OptionalFormat < uint32 + enumeration + F1 (0) + F2 (1) + F4 (2) + F8 (3) + Size (4) + VSize (5) + FSize (6) + Class (7) + end +end diff --git a/matlab/lib/+Ice/OutputStream.m b/matlab/lib/+Ice/OutputStream.m index 7dcca395573..92cbfa288e7 100644 --- a/matlab/lib/+Ice/OutputStream.m +++ b/matlab/lib/+Ice/OutputStream.m @@ -11,159 +11,381 @@ ICE_LICENSE file included in this distribution. classdef OutputStream < IceInternal.WrapperObject methods - function obj = OutputStream(impl) + function obj = OutputStream(impl, communicator) obj = obj@IceInternal.WrapperObject(impl); + obj.communicator = communicator; + obj.encoding = obj.callWithResult_('getEncoding'); + obj.encapsStack = []; + obj.encapsCache = []; + end + function r = getCommunicator(obj) + r = obj.communicator; + end + function r = getEncoding(obj) + if isempty(obj.encapsStack) + r = obj.encoding; + else + r = obj.encapsStack.encoding; + end + end + function setFormat(obj, format) + obj.format = format; end function writeBool(obj, v) - Ice.Util.callMethod(obj, 'writeBool', v); + obj.call_('writeBool', v); end function writeBoolOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeBoolOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F1) + obj.call_('writeBool', v); + end end function writeBoolSeq(obj, v) - Ice.Util.callMethod(obj, 'writeBoolSeq', v, length(v)); + obj.call_('writeBoolSeq', v, length(v)); end function writeBoolSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeBoolSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.VSize) + obj.call_('writeBoolSeq', v, length(v)); + end end function writeByte(obj, v) - Ice.Util.callMethod(obj, 'writeByte', v); + obj.call_('writeByte', v); end function writeByteOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeByteOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F1) + obj.call_('writeByte', v); + end end function writeByteSeq(obj, v) - Ice.Util.callMethod(obj, 'writeByteSeq', v, length(v)); + obj.call_('writeByteSeq', v, length(v)); end function writeByteSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeByteSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.VSize) + obj.call_('writeByteSeq', v, length(v)); + end end function writeShort(obj, v) - Ice.Util.callMethod(obj, 'writeShort', v); + obj.call_('writeShort', v); end function writeShortOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeShortOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F2) + obj.call_('writeShort', v); + end end function writeShortSeq(obj, v) - Ice.Util.callMethod(obj, 'writeShortSeq', v, length(v)); + obj.call_('writeShortSeq', v, length(v)); end function writeShortSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeShortSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptionalVSize(tag, length(v), 2) + obj.call_('writeShortSeq', v, length(v)); + end end function writeInt(obj, v) - Ice.Util.callMethod(obj, 'writeInt', v); + obj.call_('writeInt', v); end function writeIntOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeIntOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F4) + obj.call_('writeInt', v); + end end function writeIntSeq(obj, v) - Ice.Util.callMethod(obj, 'writeIntSeq', v, length(v)); + obj.call_('writeIntSeq', v, length(v)); end function writeIntSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeIntSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptionalVSize(tag, length(v), 4) + obj.call_('writeIntSeq', v, length(v)); + end end function writeLong(obj, v) - Ice.Util.callMethod(obj, 'writeLong', v); + obj.call_('writeLong', v); end function writeLongOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeLongOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F8) + obj.call_('writeLong', v); + end end function writeLongSeq(obj, v) - Ice.Util.callMethod(obj, 'writeLongSeq', v, length(v)); + obj.call_('writeLongSeq', v, length(v)); end function writeLongSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeLongSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptionalVSize(tag, length(v), 8) + obj.call_('writeLongSeq', v, length(v)); + end end function writeFloat(obj, v) - Ice.Util.callMethod(obj, 'writeFloat', v); + obj.call_('writeFloat', v); end function writeFloatOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeFloatOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F4) + obj.call_('writeFloat', v); + end end function writeFloatSeq(obj, v) - Ice.Util.callMethod(obj, 'writeFloatSeq', v, length(v)); + obj.call_('writeFloatSeq', v, length(v)); end function writeFloatSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeFloatSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptionalVSize(tag, length(v), 4) + obj.call_('writeFloatSeq', v, length(v)); + end end function writeDouble(obj, v) - Ice.Util.callMethod(obj, 'writeDouble', v); + obj.call_('writeDouble', v); end function writeDoubleOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeDoubleOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.F8) + obj.call_('writeDouble', v); + end end function writeDoubleSeq(obj, v) - Ice.Util.callMethod(obj, 'writeDoubleSeq', v, length(v)); + obj.call_('writeDoubleSeq', v, length(v)); end function writeDoubleSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeDoubleSeqOpt', tag, v, length(v)); + if v ~= Ice.Unset && obj.writeOptionalVSize(tag, length(v), 8) + obj.call_('writeDoubleSeq', v, length(v)); + end end - function writeString(obj, str) - Ice.Util.callMethod(obj, 'writeString', str); + function writeString(obj, v) + obj.call_('writeString', v); end - function writeStringOpt(obj, tag, str) - Ice.Util.callMethod(obj, 'writeStringOpt', tag, str); + function writeStringOpt(obj, tag, v) + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.VSize) + obj.call_('writeString', v); + end end function writeStringSeq(obj, v) - Ice.Util.callMethod(obj, 'writeStringSeq', v); + obj.call_('writeStringSeq', v); end function writeStringSeqOpt(obj, tag, v) - Ice.Util.callMethod(obj, 'writeStringSeqOpt', tag, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.FSize) + pos = obj.startSize(); + obj.call_('writeStringSeq', v); + obj.endSize(pos); + end end function writeSize(obj, size) - Ice.Util.callMethod(obj, 'writeSize', size); + obj.call_('writeSize', size); end function writeProxy(obj, v) if isempty(v) impl = libpointer; else - impl = v.impl; + impl = v.impl_; end - Ice.Util.callMethod(obj, 'writeProxy', impl); + obj.call_('writeProxy', impl); end function writeProxyOpt(obj, tag, v) - if ~isempty(v) - Ice.Util.callMethod(obj, 'writeProxyOpt', tag, v.impl); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.FSize) + pos = obj.startSize(); + obj.writeProxy(v); + obj.endSize(pos); end end function writeEnum(obj, v, maxValue) - Ice.Util.callMethod(obj, 'writeEnum', v, maxValue); + obj.call_('writeEnum', v, maxValue); end function writeValue(obj, v) - % Pass a reference to the wrapper object. - Ice.Util.callMethod(obj, 'writeValue', obj, v); + if isempty(obj.format) + % Lazy initialization + if obj.communicator.getProperties().getPropertyAsIntWithDefault('Ice.Default.SlicedFormat', 0) > 0 + obj.format = Ice.FormatType.SlicedFormat; + else + obj.format = Ice.FormatType.CompactFormat; + end + end + + obj.initEncaps(); + obj.encapsStack.encoder.writeValue(v); end function writeValueOpt(obj, tag, v) - % Pass a reference to the wrapper object. - Ice.Util.callMethod(obj, 'writeValueOpt', tag, obj, v); + if v ~= Ice.Unset && obj.writeOptional(tag, Ice.OptionalFormat.Class) + obj.writeValue(v); + end + end + function startValue(obj, slicedData) + assert(~isempty(obj.encapsStack) && ~isempty(obj.encapsStack.encoder)); + obj.encapsStack.encoder.startInstance(IceInternal.SliceType.ValueSlice, slicedData); end - function startEncapsulation(obj) - Ice.Util.callMethod(obj, 'startEncapsulation'); + function endValue(obj) + assert(~isempty(obj.encapsStack) && ~isempty(obj.encapsStack.encoder)); + obj.encapsStack.encoder.endInstance(); end - function startEncapsulationWithFormat(obj, fmt) - Ice.Util.callMethod(obj, 'startEncapsulationWithFormat', fmt); + function startEncapsulation(obj, format) + % + % If no encoding version is specified, use the current write + % encapsulation encoding version if there's a current write + % encapsulation, otherwise, use the stream encoding version. + % + + encoding = []; + if ~isempty(obj.encapsStack) + encoding = obj.encapsStack.encoding; + if isempty(format) + format = obj.encapsStack.format; + end + else + encoding = obj.encoding; + if isempty(format) + format = Ice.FormatType.DefaultFormat; + end + end + + curr = obj.encapsCache; + if ~isempty(curr) + curr.encoder = []; + obj.encapsCache = obj.encapsCache.next; + else + curr = IceInternal.WriteEncaps(); + end + curr.next = obj.encapsStack; + obj.encapsStack = curr; + + obj.encapsStack.format = format; + obj.encapsStack.encoding = encoding; + obj.encapsStack.start = obj.pos(); + + obj.writeInt(0); % Placeholder for the encapsulation length. + Ice.EncodingVersion.ice_write(obj, obj.encapsStack.encoding); end function endEncapsulation(obj) - Ice.Util.callMethod(obj, 'endEncapsulation'); + assert(~isempty(obj.encapsStack)); + + % Size includes size and version. + start = obj.encapsStack.start; + sz = obj.pos() - start; + obj.rewriteInt(sz, start); + + curr = obj.encapsStack; + obj.encapsStack = curr.next; + curr.next = obj.encapsCache; + obj.encapsCache = curr; + obj.encapsCache.encoder = []; end function startSlice(obj, typeId, compactId, last) - Ice.Util.callMethod(obj, 'startSlice', typeId, compactId, last); + assert(~isempty(obj.encapsStack) && ~isempty(obj.encapsStack.encoder)); + obj.encapsStack.encoder.startSlice(typeId, compactId, last); end function endSlice(obj) - Ice.Util.callMethod(obj, 'endSlice'); + assert(~isempty(obj.encapsStack) && ~isempty(obj.encapsStack.encoder)); + obj.encapsStack.encoder.endSlice(); + end + function writePendingValues(obj) + if ~isempty(obj.encapsStack) && ~isempty(obj.encapsStack.encoder) + obj.encapsStack.encoder.writePendingValues(); + elseif isequal(obj.getEncoding(), IceInternal.Protocol.Encoding_1_0) + % + % If using the 1.0 encoding and no instances were written, we + % still write an empty sequence for pending instances if + % requested (i.e.: if this is called). + % + % This is required by the 1.0 encoding, even if no instances + % are written we do marshal an empty sequence if marshaled + % data types use classes. + % + obj.writeSize(0); + end end - function r = writeOptional(obj, tag, f) - supportsOptionals = libpointer('uint8Ptr', 0); - Ice.Util.callMethod(obj, 'writeOptional', tag, f, supportsOptionals); - r = supportsOptionals.Value; + function r = writeOptional(obj, tag, format) + assert(~isempty(obj.encapsStack)); + if ~isempty(obj.encapsStack.encoder) + r = obj.encapsStack.encoder.writeOptional(tag, format); + else + r = obj.writeOptionalImpl(tag, format); + end + end + function r = writeOptionalImpl(obj, tag, format) + if isequal(obj.getEncoding(), IceInternal.Protocol.Encoding_1_0) + r = false; % Optional members aren't supported with the 1.0 encoding. + return; + end + + v = uint8(format); % One of Ice.OptionalFormat... + if tag < 30 + v = bitor(v, bitshift(tag, 3)); + obj.writeByte(v); + else + v = bitor(v, 240); % tag = 30 + obj.writeByte(v); + obj.writeSize(tag); + end + r = true; end function r = startSize(obj) pos = libpointer('uint32Ptr', 0); - Ice.Util.callMethod(obj, 'startSize', pos); + obj.call_('startSize', pos); r = pos.Value; end function endSize(obj, pos) - Ice.Util.callMethod(obj, 'endSize', pos); + obj.call_('endSize', pos); + end + function r = pos(obj) + p = libpointer('uint32Ptr', 0); + obj.call_('pos', p); + r = p.Value; + end + function rewriteByte(obj, v, pos) + obj.call_('rewriteByte', v, pos); end + function rewriteInt(obj, v, pos) + obj.call_('rewriteInt', v, pos); + end + function writeBlob(obj, bytes) + obj.call_('writeBlob', bytes, length(bytes)); + end + end + methods(Access=private) + function r = isEncoding_1_0(obj) + if ~isempty(obj.encapsStack) + r = isequal(obj.encapsStack.encoding, IceInternal.Protocol.Encoding_1_0); + else + r = isequal(obj.encoding, IceInternal.Protocol.Encoding_1_0); + end + end + function initEncaps(obj) + if isempty(obj.encapsStack) % Lazy initialization + obj.encapsStack = obj.encapsCache; + if ~isempty(obj.encapsStack) + obj.encapsCache = obj.encapsCache.next; + else + obj.encapsStack = IceInternal.WriteEncaps(); + end + obj.encapsStack.encoding = obj.encoding; + end + + if obj.encapsStack.format == Ice.FormatType.DefaultFormat + obj.encapsStack.format = obj.format; + end + + if isempty(obj.encapsStack.encoder) % Lazy initialization. + if isequal(obj.getEncoding(), IceInternal.Protocol.Encoding_1_0) + obj.encapsStack.encoder = IceInternal.EncapsEncoder10(obj, obj.encapsStack); + else + obj.encapsStack.encoder = IceInternal.EncapsEncoder11(obj, obj.encapsStack); + end + end + end + function r = writeOptionalVSize(obj, tag, len, elemSize) + r = false; + if obj.writeOptional(tag, Ice.OptionalFormat.VSize) + if len == 0 + obj.writeSize(1); + obj.writeSize(0); + else + sz = len * elemSize; + if len > 254 + sz = sz + 5; + else + sz = sz + 1; + end + obj.writeSize(sz); + r = true; + end + end + end + end + properties(Access=private) + communicator + encoding + format + encapsStack + encapsCache end end diff --git a/matlab/lib/+Ice/Properties.m b/matlab/lib/+Ice/Properties.m index 5169ac2f9a7..5791aeabc31 100644 --- a/matlab/lib/+Ice/Properties.m +++ b/matlab/lib/+Ice/Properties.m @@ -15,48 +15,48 @@ classdef Properties < IceInternal.WrapperObject obj = obj@IceInternal.WrapperObject(impl); end function r = getProperty(obj, key) - r = Ice.Util.callMethodWithResult(obj, 'getProperty', key); + r = obj.callWithResult_('getProperty', key); end function r = getPropertyWithDefault(obj, key, def) - r = Ice.Util.callMethodWithResult(obj, 'getPropertyWithDefault', key, def); + r = obj.callWithResult_('getPropertyWithDefault', key, def); end function r = getPropertyAsInt(obj, key) v = libpointer('int32Ptr', 0); - Ice.Util.callMethod(obj, 'getPropertyAsInt', key, v); + obj.call_('getPropertyAsInt', key, v); r = v.Value; end function r = getPropertyAsIntWithDefault(obj, key, def) v = libpointer('int32Ptr', 0); - Ice.Util.callMethod(obj, 'getPropertyAsIntWithDefault', key, def, v); + obj.call_('getPropertyAsIntWithDefault', key, def, v); r = v.Value; end function r = getPropertyAsList(obj, key) - r = Ice.Util.callMethodWithResult(obj, 'getPropertyAsList', key); + r = obj.callWithResult_('getPropertyAsList', key); end function r = getPropertyAsListWithDefault(obj, key, def) - r = Ice.Util.callMethodWithResult(obj, 'getPropertyAsListWithDefault', key, def); + r = obj.callWithResult_('getPropertyAsListWithDefault', key, def); end function r = getPropertiesForPrefix(obj, prefix) - r = Ice.Util.callMethodWithResult(obj, 'getPropertiesForPrefix', prefix); + r = obj.callWithResult_('getPropertiesForPrefix', prefix); end function setProperty(obj, key, value) - Ice.Util.callMethod(obj, 'setProperty', key, value); + obj.call_('setProperty', key, value); end function r = getCommandLineOptions(obj) - r = Ice.Util.callMethodWithResult(obj, 'getCommandLineOptions'); + r = obj.callWithResult_('getCommandLineOptions'); end function r = parseCommandLineOptions(obj, prefix, options) - r = Ice.Util.callMethodWithResult(obj, 'parseCommandLineOptions', prefix, options); + r = obj.callWithResult_('parseCommandLineOptions', prefix, options); end function r = parseIceCommandLineOptions(obj, options) - r = Ice.Util.callMethodWithResult(obj, 'parseIceCommandLineOptions', options); + r = obj.callWithResult_('parseIceCommandLineOptions', options); end function load(obj, file) - Ice.Util.callMethod(obj, 'load', file); + obj.call_('load', file); end function r = clone(obj) impl = libpointer('voidPtr'); - Ice.Util.callMethod(obj, 'clone', impl); + obj.call_('clone', impl); r = Ice.Properties(impl); end end diff --git a/matlab/lib/+Ice/SlicedData.m b/matlab/lib/+Ice/SlicedData.m new file mode 100644 index 00000000000..b93f8acf920 --- /dev/null +++ b/matlab/lib/+Ice/SlicedData.m @@ -0,0 +1,25 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +% +% SlicedData holds the slices of unknown types. +% +classdef SlicedData < handle + properties(SetAccess=private) + % The details of each slice, in order of most-derived to least-derived. + slices + end + methods + function obj = SlicedData(slices) + obj.slices = slices; + end + end +end diff --git a/matlab/lib/+Ice/UnknownSlicedValue.m b/matlab/lib/+Ice/UnknownSlicedValue.m new file mode 100644 index 00000000000..749ac4f0e27 --- /dev/null +++ b/matlab/lib/+Ice/UnknownSlicedValue.m @@ -0,0 +1,39 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +% +% UnknownSlicedValue holds an instance of an unknown Slice class type. +% +classdef UnknownSlicedValue < Ice.Value + methods + function obj = UnknownSlicedValue(unknownTypeId) + obj.unknownTypeId = unknownTypeId; + end + function r = ice_getSlicedData(obj) + r = obj.slicedData; + end + function id = ice_id(obj) + id = obj.unknownTypeId; + end + function iceWrite_(obj, os) + os.startValue(obj.slicedData); + os.endValue(); + end + function obj = iceRead_(obj, is) + is.startValue(); + obj.slicedData = is.endValue(true); + end + end + properties(Accses=private) + unknownTypeId + slicedData + end +end diff --git a/matlab/lib/+Ice/Unset.m b/matlab/lib/+Ice/Unset.m new file mode 100644 index 00000000000..072d862106e --- /dev/null +++ b/matlab/lib/+Ice/Unset.m @@ -0,0 +1,17 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +% +% This function returns a singleton instance that we use as a sentinel value to indicate an unset optional value. +% +function r = Unset() + r = IceInternal.UnsetI.getInstance(); +end diff --git a/matlab/lib/+Ice/UserException.m b/matlab/lib/+Ice/UserException.m index 829423e07ff..edecd23342c 100644 --- a/matlab/lib/+Ice/UserException.m +++ b/matlab/lib/+Ice/UserException.m @@ -18,18 +18,46 @@ classdef (Abstract) UserException < Ice.Exception methods(Hidden=true) function obj = read_(obj, is) is.startException(); - if obj.usesClasses_() + if obj.usesAnyClasses_() + % + % Exceptions are value types. We use a shared map (which is a handle type) to keep track of class + % instances as they are unmarshaled. + % obj.valueTable_ = containers.Map('KeyType', 'char', 'ValueType', 'any'); end obj = obj.readImpl_(is); is.endException(); + if obj.usesClasses_() + is.readPendingValues(); + end + if obj.usesAnyClasses_() + % + % Retrieve the value instances from the map and update our data members. + % + obj = obj.resolveValues_(); + end end function r = usesClasses_(obj) + % + % Overridden by subclasses to indicate whether they contain any *required* data members that use classes. + % + r = false; + end + function r = usesAnyClasses_(obj) + % + % Overridden by subclasses to indicate whether they contain any data members that use classes. + % r = false; end function obj = resolveValues_(obj) + % + % Overridden by subclasses that have class members. + % end function setValueMember_(obj, k, v) + % + % Store an unmarshaled class instance in our map. + % obj.valueTable_(k) = v; end end diff --git a/matlab/lib/+Ice/Util.m b/matlab/lib/+Ice/Util.m deleted file mode 100644 index c5db26ce1cc..00000000000 --- a/matlab/lib/+Ice/Util.m +++ /dev/null @@ -1,122 +0,0 @@ -%{ -********************************************************************** - -Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. - -This copy of Ice is licensed to you under the terms described in the -ICE_LICENSE file included in this distribution. - -********************************************************************** -%} - -classdef Util - methods(Static) - % - % Internal method - invoke a C function with the given name. - % The value for fn MUST be given in single quotes! - % - function call(fn, varargin) - ex = calllib('icematlab', fn, varargin{:}); - if ~isempty(ex) - ex.throwAsCaller(); - end - end - - % - % Internal method - invoke a C function representing a global function. - % The value for fn MUST be given in single quotes! - % - function r = callWithResult(fn, varargin) - result = calllib('icematlab', fn, varargin{:}); - if isempty(result) - r = result; - elseif ~isempty(result.exception) - result.exception.throwAsCaller(); - else - r = result.result; - end - end - - % - % Internal method - invoke a C function representing an object method. - % The value for fn MUST be given in single quotes! - % - function callMethod(obj, fn, varargin) - name = strrep(strcat(class(obj), '.', fn), '.', '_'); - ex = calllib('icematlab', name, obj.impl, varargin{:}); - if ~isempty(ex) - ex.throwAsCaller(); - end - end - - % - % Internal method - invoke a C function representing an object method. - % The value for fn MUST be given in single quotes! - % - function r = callMethodWithResult(obj, fn, varargin) - name = strrep(strcat(class(obj), '.', fn), '.', '_'); - result = calllib('icematlab', name, obj.impl, varargin{:}); - if isempty(result) - r = result; - elseif ~isempty(result.exception) - result.exception.throwAsCaller(); - else - r = result.result; - end - end - - % - % Internal method - invoke a C function representing an object method. - % The value for fn MUST be given in single quotes! - % - function callMethodOnType(obj, type, fn, varargin) - name = strcat(type, '_', fn); - ex = calllib('icematlab', name, obj.impl, varargin{:}); - if ~isempty(ex) - ex.throwAsCaller(); - end - end - - % - % Internal method - invoke a C function representing an object method. - % The value for fn MUST be given in single quotes! - % - function r = callMethodOnTypeWithResult(obj, type, fn, varargin) - name = strcat(type, '_', fn); - result = calllib('icematlab', name, obj.impl, varargin{:}); - if isempty(result) - r = result; - elseif ~isempty(result.exception) - result.exception.throwAsCaller(); - else - r = result.result; - end - end - - function r = idToClass(id) - assert(length(id) > 2 && strcmp(id(1:2), '::')); - r = strrep(id, '::', '.'); - r = r(2:end); - end - - function r = strcmp(s1, s2) - n = min(length(s1), length(s2)); - for i = 1:n - if s1(i) < s2(i) - r = -1; - return; - elseif s1(i) > s2(i) - r = 1; - return; - end - end - if length(s1) > n - r = 1; - elseif length(s2) > n - r = -1; - else - r = 0; - end - end - end -end diff --git a/matlab/lib/+Ice/Value.m b/matlab/lib/+Ice/Value.m index dcbff0963c4..dea394a9fdb 100644 --- a/matlab/lib/+Ice/Value.m +++ b/matlab/lib/+Ice/Value.m @@ -15,8 +15,8 @@ classdef (Abstract) Value < matlab.mixin.Copyable end function ice_postUnmarshal(obj) end - function id = ice_id(obj) - id = ice_staticId() + function r = ice_getSlicedData(obj) + r = []; end function iceWrite_(obj, os) os.startValue([]); @@ -30,12 +30,16 @@ classdef (Abstract) Value < matlab.mixin.Copyable end end methods(Abstract) + id = ice_id(obj) iceWriteImpl_(obj, os) obj = iceReadImpl_(obj, is) end methods(Static) function id = ice_staticId() - id = '::Ice::Object' + id = '::Ice::Object'; end end + properties(Hidden) + internal_ int32 = -1 + end end diff --git a/matlab/lib/+Ice/ValueFactoryManagerI.m b/matlab/lib/+Ice/ValueFactoryManagerI.m new file mode 100644 index 00000000000..d4d07277171 --- /dev/null +++ b/matlab/lib/+Ice/ValueFactoryManagerI.m @@ -0,0 +1,37 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef ValueFactoryManagerI < Ice.ValueFactoryManager + methods + function obj = ValueFactoryManagerI() + obj.factories = containers.Map('KeyType', 'char', 'ValueType', 'any'); + end + function add(obj, factory, id) + if obj.factories.isKey(id) + throw(Ice.AlreadyRegisteredException('', '', 'value factory', id)); + elseif ~isa(factory, 'function_handle') + throw(MException('Ice:ArgumentException', 'factory argument is not a function handle')); + else + obj.factories(id) = factory; + end + end + function r = find(obj, id) + if obj.factories.isKey(id) + r = obj.factories(id); + else + r = []; + end + end + end + properties(Access=private) + factories + end +end diff --git a/matlab/lib/+Ice/createProperties.m b/matlab/lib/+Ice/createProperties.m index d619a4de343..f381114bd66 100644 --- a/matlab/lib/+Ice/createProperties.m +++ b/matlab/lib/+Ice/createProperties.m @@ -19,11 +19,11 @@ function [properties, remArgs] = createProperties(varargin) if ~isa(varargin{2}, 'Ice.Properties') throw(MException('Ice:ArgumentException', 'expecting Ice.Properties object')); end - defaults = varargin{2}.impl; + defaults = varargin{2}.impl_; else defaults = libpointer('voidPtr'); end impl = libpointer('voidPtr'); - remArgs = Ice.Util.callWithResult('Ice_createProperties', args, defaults, impl); + remArgs = IceInternal.Util.callWithResult('Ice_createProperties', args, defaults, impl); properties = Ice.Properties(impl); end diff --git a/matlab/lib/+Ice/currentEncoding.m b/matlab/lib/+Ice/currentEncoding.m new file mode 100644 index 00000000000..dd7cf548248 --- /dev/null +++ b/matlab/lib/+Ice/currentEncoding.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = currentEncoding() + r = IceInternal.Util.callWithResult('Ice_currentEncoding'); +end diff --git a/matlab/lib/+Ice/currentProtocol.m b/matlab/lib/+Ice/currentProtocol.m new file mode 100644 index 00000000000..cb6d32f5cc5 --- /dev/null +++ b/matlab/lib/+Ice/currentProtocol.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = currentProtocol() + r = IceInternal.Util.callWithResult('Ice_currentProtocol'); +end diff --git a/matlab/lib/+Ice/currentProtocolEncoding.m b/matlab/lib/+Ice/currentProtocolEncoding.m new file mode 100644 index 00000000000..a46ce0353ae --- /dev/null +++ b/matlab/lib/+Ice/currentProtocolEncoding.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = currentProtocolEncoding() + r = IceInternal.Util.callWithResult('Ice_currentProtocolEncoding'); +end diff --git a/matlab/lib/+Ice/encodingVersionToString.m b/matlab/lib/+Ice/encodingVersionToString.m new file mode 100644 index 00000000000..bbd0a356d77 --- /dev/null +++ b/matlab/lib/+Ice/encodingVersionToString.m @@ -0,0 +1,17 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = encodingVersionToString(v) + if ~isa(v, 'Ice.EncodingVersion') + throw(MException('Ice:ArgumentException', 'expecting an Ice.EncodingVersion')); + end + r = sprintf('%d.%d', v.major, v.minor); +end diff --git a/matlab/lib/+Ice/identityToString.m b/matlab/lib/+Ice/identityToString.m index d3580ef1819..ce4e5173335 100644 --- a/matlab/lib/+Ice/identityToString.m +++ b/matlab/lib/+Ice/identityToString.m @@ -9,6 +9,13 @@ ICE_LICENSE file included in this distribution. ********************************************************************** %} -function r = identityToString(id) - r = Ice.Util.callWithResult('Ice_identityToString', id); +function r = identityToString(id, varargin) + if length(varargin) == 1 + mode = varargin{1}; + elseif length(varargin) == 0 + mode = Ice.ToStringMode.Unicode; + elseif length(varargin) > 2 + throw(MException('Ice:ArgumentException', 'too many arguments')); + end + r = IceInternal.Util.callWithResult('Ice_identityToString', id, int32(mode)); end diff --git a/matlab/lib/+Ice/initialize.m b/matlab/lib/+Ice/initialize.m index b164fe6c40a..ce0f96c3780 100644 --- a/matlab/lib/+Ice/initialize.m +++ b/matlab/lib/+Ice/initialize.m @@ -26,22 +26,37 @@ function [communicator, args] = initialize(varargin) end % - % Implementation note: We need to extract and pass the libpointer object for properties to the C function. - % Passing the wrapper (Ice.Properties) object won't work because the C code has no way to obtain the - % inner pointer. + % Implementation notes: + % + % We need to extract and pass the libpointer object for properties to the C function. Passing the wrapper + % (Ice.Properties) object won't work because the C code has no way to obtain the inner pointer. + % + % The communicator wrapper holds the value factory manager. % props = libpointer('voidPtr'); + vfm = []; if ~isempty(initData) if ~isempty(initData.properties_) if ~isa(initData.properties_, 'Ice.Properties') throw(MException('Ice:ArgumentException', 'invalid value for properties_ member')); else - props = initData.properties_.impl; + props = initData.properties_.impl_; end end + if ~isempty(initData.valueFactoryManager) + if ~isa(initData.valueFactoryManager, 'Ice.ValueFactoryManager') + throw(MException('Ice:ArgumentException', 'invalid value for valueFactoryManager member')); + else + vfm = initData.valueFactoryManager; + end + end + end + + if isempty(vfm) + vfm = Ice.ValueFactoryManagerI(); end impl = libpointer('voidPtr'); - args = Ice.Util.callWithResult('Ice_initialize', args, props, impl); - communicator = Ice.Communicator(impl); + args = IceInternal.Util.callWithResult('Ice_initialize', args, props, impl); + communicator = Ice.Communicator(impl, vfm); end diff --git a/matlab/lib/+Ice/intVersion.m b/matlab/lib/+Ice/intVersion.m new file mode 100644 index 00000000000..1ae018aaf83 --- /dev/null +++ b/matlab/lib/+Ice/intVersion.m @@ -0,0 +1,16 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = intVersion() + v = libpointer('int32Ptr', 0); + IceInternal.Util.call('Ice_intVersion', v); + r = v.Value; +end diff --git a/matlab/lib/+Ice/protocolVersionToString.m b/matlab/lib/+Ice/protocolVersionToString.m new file mode 100644 index 00000000000..b34175c9d41 --- /dev/null +++ b/matlab/lib/+Ice/protocolVersionToString.m @@ -0,0 +1,17 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = protocolVersionToString(v) + if ~isa(v, 'Ice.ProtocolVersion') + throw(MException('Ice:ArgumentException', 'expecting an Ice.ProtocolVersion')); + end + r = sprintf('%d.%d', v.major, v.minor); +end diff --git a/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m b/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m index ff9549f0188..f4bb75b6dac 100644 --- a/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m +++ b/matlab/lib/+Ice/proxyIdentityAndFacetCompare.m @@ -19,12 +19,12 @@ function r = proxyIdentityAndFacetCompare(lhs, rhs) else lhsIdentity = lhs.ice_getIdentity(); rhsIdentity = rhs.ice_getIdentity(); - n = Ice.Util.strcmp(lhsIdentity.name, rhsIdentity.name); + n = IceInternal.Util.strcmp(lhsIdentity.name, rhsIdentity.name); if n ~= 0 r = n; return; end - n = Ice.Util.strcmp(lhsIdentity.category, rhsIdentity.category); + n = IceInternal.Util.strcmp(lhsIdentity.category, rhsIdentity.category); if n ~= 0 r = n; return; @@ -39,7 +39,7 @@ function r = proxyIdentityAndFacetCompare(lhs, rhs) elseif isempty(rhsFacet) r = 1; else - r = Ice.Util.strcmp(lhsFacet, rhsFacet); + r = IceInternal.Util.strcmp(lhsFacet, rhsFacet); end end end diff --git a/matlab/lib/+Ice/proxyIdentityCompare.m b/matlab/lib/+Ice/proxyIdentityCompare.m index 0b660c86346..85593c72135 100644 --- a/matlab/lib/+Ice/proxyIdentityCompare.m +++ b/matlab/lib/+Ice/proxyIdentityCompare.m @@ -19,11 +19,11 @@ function r = proxyIdentityCompare(lhs, rhs) else lhsIdentity = lhs.ice_getIdentity(); rhsIdentity = rhs.ice_getIdentity(); - n = Ice.Util.strcmp(lhsIdentity.name, rhsIdentity.name); + n = IceInternal.Util.strcmp(lhsIdentity.name, rhsIdentity.name); if n ~= 0 r = n; return; end - r = Ice.Util.strcmp(lhsIdentity.category, rhsIdentity.category); + r = IceInternal.Util.strcmp(lhsIdentity.category, rhsIdentity.category); end end diff --git a/matlab/lib/+Ice/stringToEncodingVersion.m b/matlab/lib/+Ice/stringToEncodingVersion.m new file mode 100644 index 00000000000..d0c61f5bf72 --- /dev/null +++ b/matlab/lib/+Ice/stringToEncodingVersion.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = stringToEncodingVersion(s) + tokens = regexp(s, '^([0-9]+)\.([0-9]+)$', 'tokens'); + if isempty(tokens) + throw(MException('Ice:ArgumentException', 'expecting a version in X.Y format')); + end + r = Ice.EncodingVersion(str2num(tokens{1}{1}), str2num(tokens{1}{2})); +end diff --git a/matlab/lib/+Ice/stringToIdentity.m b/matlab/lib/+Ice/stringToIdentity.m index e846ad1a61e..f39876601a4 100644 --- a/matlab/lib/+Ice/stringToIdentity.m +++ b/matlab/lib/+Ice/stringToIdentity.m @@ -10,5 +10,5 @@ ICE_LICENSE file included in this distribution. %} function r = stringToIdentity(s) - r = Ice.Util.callWithResult('Ice_stringToIdentity', s); + r = IceInternal.Util.callWithResult('Ice_stringToIdentity', s); end diff --git a/matlab/lib/+Ice/stringToProtocolVersion.m b/matlab/lib/+Ice/stringToProtocolVersion.m new file mode 100644 index 00000000000..5d2abe32285 --- /dev/null +++ b/matlab/lib/+Ice/stringToProtocolVersion.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = stringToProtocolVersion(s) + tokens = regexp(s, '^([0-9]+)\.([0-9]+)$', 'tokens'); + if isempty(tokens) + throw(MException('Ice:ArgumentException', 'expecting a version in X.Y format')); + end + r = Ice.ProtocolVersion(str2num(tokens{1}{1}), str2num(tokens{1}{2})); +end diff --git a/matlab/lib/+Ice/stringVersion.m b/matlab/lib/+Ice/stringVersion.m new file mode 100644 index 00000000000..2e8acd3f34d --- /dev/null +++ b/matlab/lib/+Ice/stringVersion.m @@ -0,0 +1,14 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +function r = stringVersion() + r = IceInternal.Util.callWithResult('Ice_stringVersion'); +end diff --git a/matlab/lib/+IceInternal/EncapsDecoder.m b/matlab/lib/+IceInternal/EncapsDecoder.m index 08fc6426571..0e9f8c71b41 100644 --- a/matlab/lib/+IceInternal/EncapsDecoder.m +++ b/matlab/lib/+IceInternal/EncapsDecoder.m @@ -11,26 +11,40 @@ ICE_LICENSE file included in this distribution. classdef (Abstract) EncapsDecoder < handle methods - function obj = EncapsDecoder(is, encaps) + function obj = EncapsDecoder(is, encaps, sliceValues, valueFactoryManager) obj.is = is; obj.encaps = encaps; - obj.typeIdMap = containers.Map('KeyType', 'int32', 'ValueType', 'char'); + obj.sliceValues = sliceValues; + obj.valueFactoryManager = valueFactoryManager; + obj.patchMap = []; + obj.unmarshaledMap = containers.Map('KeyType', 'int32', 'ValueType', 'any'); + obj.typeIdMap = []; obj.typeIdIndex = 0; + obj.valueList = {}; end - function r = readOptional(tag, format) + + function r = readOptional(obj, readTag, expectedFormat) r = false; end + + function readPendingValues(obj) + end end methods(Abstract) + readValue(obj, cb) throwException(obj) startInstance(obj, sliceType) - endInstance(obj) % TODO: SlicedData + r = endInstance(obj, preserve) r = startSlice(obj) endSlice(obj) skipSlice(obj) end methods(Access=protected) function r = readTypeId(obj, isIndex) + if isempty(obj.typeIdMap) % Lazy initialization + obj.typeIdMap = containers.Map('KeyType', 'int32', 'ValueType', 'char'); + end + if isIndex index = obj.is.readSize(); if obj.typeIdMap.isKey(index) @@ -44,13 +58,165 @@ classdef (Abstract) EncapsDecoder < handle obj.typeIdMap(obj.typeIdIndex) = r; end end + + function r = newInstance(obj, typeId) + % + % Try to find a factory registered for the specific type. + % + userFactory = obj.valueFactoryManager.find(typeId); + v = []; + if ~isempty(userFactory) + v = userFactory(typeId); + end + + % + % If that fails, invoke the default factory if one has been registered. + % + if isempty(v) + userFactory = obj.valueFactoryManager.find(''); + if ~isempty(userFactory) + v = userFactory(typeId); + end + end + + % + % Last chance: try to instantiate the class dynamically. + % + if isempty(v) + % + % Translate the type ID into a class name. + % + cls = IceInternal.Util.idToClass(typeId); + + try + v = eval(cls); + catch e + throw(Ice.NoValueFactoryException('', 'no value factory', typeId)); + end + end + + r = v; + end + + function addPatchEntry(obj, index, cb) + assert(index > 0); + + % + % Check if we have already unmarshalled the instance. If that's the case, + % just invoke the callback and we're done. + % + if obj.unmarshaledMap.isKey(index) + v = obj.unmarshaledMap(index); + cb(v); + return; + end + + if isempty(obj.patchMap) % Lazy initialization + obj.patchMap = containers.Map('KeyType', 'int32', 'ValueType', 'any'); + end + + % + % Add patch entry if the instance isn't unmarshaled yet, + % the callback will be called when the instance is + % unmarshaled. + % + pl = []; + if obj.patchMap.isKey(index) + pl = obj.patchMap(index); + else + % + % We have no outstanding instances to be patched for this + % index, so make a new entry in the patch map. + % + pl = IceInternal.PatchList(); + obj.patchMap(index) = pl; + end + + % + % Append a patch entry for this instance. + % + pl.list{end + 1} = cb; + end + + function unmarshal(obj, index, v) + % + % Add the instance to the map of unmarshaled instances, this must + % be done before reading the instances (for circular references). + % + obj.unmarshaledMap(index) = v; + + % + % Read the instance. + % + v.iceRead_(obj.is); + + if ~isempty(obj.patchMap) && obj.patchMap.isKey(index) + % + % Patch all instances now that the instance is unmarshaled. + % + l = obj.patchMap(index); + assert(length(l.list) > 0); + + % + % Patch all pointers that refer to the instance. + % + for i = 1:length(l.list) + cb = l.list{i}; + cb(v); + end + + % + % Clear out the patch map for that index -- there is nothing left + % to patch for that index for the time being. + % + obj.patchMap.remove(index); + end + + if (isempty(obj.patchMap) || obj.patchMap.Count == 0) && isempty(obj.valueList) + try + v.ice_postUnmarshal(); + catch ex + % TODO: logger? + %String s = "exception raised by ice_postUnmarshal:\n" + com.zeroc.IceInternal.Ex.toString(ex); + %_stream.instance().initializationData().logger.warning(s); + end + else + obj.valueList{end + 1} = v; + + if isempty(obj.patchMap) || obj.patchMap.Count == 0 + % + % Iterate over the instance list and invoke ice_postUnmarshal on + % each instance. We must do this after all instances have been + % unmarshaled in order to ensure that any instance data members + % have been properly patched. + % + for i = 1:length(obj.valueList) + p = obj.valueList{i}; + try + p.ice_postUnmarshal(); + catch ex + % TODO: logger? + %String s = "exception raised by ice_postUnmarshal:\n" + + %com.zeroc.IceInternal.Ex.toString(ex); + %_stream.instance().initializationData().logger.warning(s); + end + end + obj.valueList = {}; + end + end + end end properties(Access=protected) is encaps + sliceValues + valueFactoryManager + patchMap end properties(Access=private) + unmarshaledMap typeIdMap typeIdIndex + valueList end end diff --git a/matlab/lib/+IceInternal/EncapsDecoder10.m b/matlab/lib/+IceInternal/EncapsDecoder10.m index c7c12a39d39..fea757a8eb0 100644 --- a/matlab/lib/+IceInternal/EncapsDecoder10.m +++ b/matlab/lib/+IceInternal/EncapsDecoder10.m @@ -11,10 +11,48 @@ ICE_LICENSE file included in this distribution. classdef EncapsDecoder10 < IceInternal.EncapsDecoder methods - function obj = EncapsDecoder10(is, encaps) - obj = obj@IceInternal.EncapsDecoder(is, encaps); + function obj = EncapsDecoder10(is, encaps, sliceValues, valueFactoryManager) + obj = obj@IceInternal.EncapsDecoder(is, encaps, sliceValues, valueFactoryManager); obj.sliceType = IceInternal.SliceType.NoSlice; end + + function readPendingValues(obj) + num = obj.is.readSize(); + while num > 0 + for k = 1:num + obj.readInstance(); + end + num = obj.is.readSize(); + end + + if ~isempty(obj.patchMap) && obj.patchMap.Count > 0 + % + % If any entries remain in the patch map, the sender has sent an index for an object, but failed + % to supply the object. + % + throw(Ice.MarshalException('', '', 'index for class received, but no instance')); + end + end + + function readValue(obj, cb) + assert(~isempty(cb)); + + % + % Object references are encoded as a negative integer in 1.0. + % + index = obj.is.readInt(); + if index > 0 + throw(Ice.MarshalException('', '', 'invalid object id')); + end + index = -index; + + if index == 0 + cb([]); + else + obj.addPatchEntry(index, cb); + end + end + function throwException(obj) assert(obj.sliceType == IceInternal.SliceType.NoSlice); @@ -39,7 +77,7 @@ classdef EncapsDecoder10 < IceInternal.EncapsDecoder % % Translate the type ID into a class name. % - cls = Ice.Util.idToClass(obj.typeId); + cls = IceInternal.Util.idToClass(obj.typeId); % % Try to instantiate the class. @@ -54,10 +92,13 @@ classdef EncapsDecoder10 < IceInternal.EncapsDecoder end if ~isempty(ex) + % + % Exceptions are value types so we have to replace 'ex' with its new value after calling read_(). + % ex = ex.read_(obj.is); - if usesClasses - obj.readPendingValues(); - end + % + % Note that read_() takes care of calling readPendingValues if necessary. + % throw(ex); else % @@ -83,24 +124,28 @@ classdef EncapsDecoder10 < IceInternal.EncapsDecoder end end end + function startInstance(obj, sliceType) assert(obj.sliceType == sliceType); obj.skipFirstSlice = true; end - function endInstance(obj) % TODO: SlicedData + + function r = endInstance(obj, preserve) % % Read the Ice::Value slice. % if obj.sliceType == IceInternal.SliceType.ValueSlice obj.startSlice(); sz = obj.is.readSize(); % For compatibility with the old AFM. - if sz != 0 - throw(Ice.MarshalException('', '', "invalid Object slice")); + if sz ~= 0 + throw(Ice.MarshalException('', '', 'invalid Object slice')); end obj.endSlice(); end obj.sliceType = IceInternal.SliceType.NoSlice; + r = []; end + function r = startSlice(obj) % % If first slice, don't read the header, it was already read in @@ -131,18 +176,77 @@ classdef EncapsDecoder10 < IceInternal.EncapsDecoder end r = obj.typeId; end + function endSlice(obj) % Nothing to do end + function skipSlice(obj) %obj.is.traceSkipSlice(obj.typeId, obj.sliceType); assert(obj.sliceSize >= 4); obj.is.skip(obj.sliceSize - 4); end - function r = readOptional(obj, tag, format) + + function r = readOptional(obj, readTag, expectedFormat) r = false; end end + methods(Access=private) + function readInstance(obj) + index = obj.is.readInt(); + + if index <= 0 + throw(Ice.MarshalException('', '', 'invalid object id')); + end + + obj.sliceType = IceInternal.SliceType.ValueSlice; + obj.skipFirstSlice = false; + + % + % Read the first slice header. + % + obj.startSlice(); + mostDerivedId = obj.typeId; + v = []; + while true + % + % For the 1.0 encoding, the type ID for the base Object class + % marks the last slice. + % + if strcmp(obj.typeId, Ice.Value.ice_staticId()) + throw(Ice.NoValueFactoryException('', '', '', mostDerivedId)); + end + + v = obj.newInstance(obj.typeId); + + % + % We found a factory, we get out of this loop. + % + if ~isempty(v) + break; + end + + % + % If slicing is disabled, stop unmarshaling. + % + if ~obj.sliceValues + throw(Ice.NoValueFactoryException('', '', 'no value factory found and slicing is disabled', ... + obj.typeId)); + end + + % + % Slice off what we don't understand. + % + obj.skipSlice(); + obj.startSlice(); % Read next Slice header for next iteration. + end + + % + % Unmarshal the instance and add it to the map of unmarshaled instances. + % + obj.unmarshal(index, v); + end + end properties(Access=private) sliceType skipFirstSlice diff --git a/matlab/lib/+IceInternal/EncapsDecoder11.m b/matlab/lib/+IceInternal/EncapsDecoder11.m index d1ced40e930..aa01b8e5c02 100644 --- a/matlab/lib/+IceInternal/EncapsDecoder11.m +++ b/matlab/lib/+IceInternal/EncapsDecoder11.m @@ -11,10 +11,46 @@ ICE_LICENSE file included in this distribution. classdef EncapsDecoder11 < IceInternal.EncapsDecoder methods - function obj = EncapsDecoder11(is, encaps) - obj = obj@IceInternal.EncapsDecoder(is, encaps); + function obj = EncapsDecoder11(is, encaps, sliceValues, valueFactoryManager, compactIdResolver) + obj = obj@IceInternal.EncapsDecoder(is, encaps, sliceValues, valueFactoryManager); + obj.compactIdResolver = compactIdResolver; + obj.current = []; + obj.valueIdIndex = 1; end + + function readValue(obj, cb) + import IceInternal.Protocol; + index = obj.is.readSize(); + if index < 0 + throw(Ice.MarshalException('', '', 'invalid object id')); + elseif index == 0 + if ~isempty(cb) + cb([]); + end + elseif ~isempty(obj.current) && bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_INDIRECTION_TABLE) + % + % When reading a class instance within a slice and there's an + % indirect instance table, always read an indirect reference + % that points to an instance from the indirect instance table + % marshaled at the end of the Slice. + % + % Maintain a list of indirect references. Note that the + % indirect index starts at 1, so we decrement it by one to + % derive an index into the indirection table that we'll read + % at the end of the slice. + % + if ~isempty(cb) + sz = length(obj.current.indirectPatchList); + obj.current.indirectPatchList(sz + 1).index = index - 1; + obj.current.indirectPatchList(sz + 1).cb = cb; + end + else + obj.readInstance(index, cb); + end + end + function throwException(obj) + import IceInternal.Protocol; assert(isempty(obj.current)); obj.push(IceInternal.SliceType.ExceptionSlice); @@ -28,7 +64,7 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder % % Translate the type ID into a class name. % - cls = Ice.Util.idToClass(obj.current.typeId); + cls = IceInternal.Util.idToClass(obj.current.typeId); % % Try to instantiate the class. @@ -54,7 +90,7 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder % % If this is the last slice, raise an exception and stop unmarshaling. % - if bitand(obj.current.sliceFlags, obj.FLAG_IS_LAST_SLICE) + if bitand(obj.current.sliceFlags, Protocol.FLAG_IS_LAST_SLICE) throw(Ice.UnknownUserException('', '', mostDerivedId)); end @@ -62,26 +98,25 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder end end end + function startInstance(obj, sliceType) assert(obj.current.sliceType == sliceType); obj.current.skipFirstSlice = true; end - function endInstance(obj) % TODO: SlicedData - %{ - SlicedDataPtr slicedData; - if(preserve) - { - slicedData = readSlicedData(); - } - _current->slices.clear(); - _current->indirectionTables.clear(); - _current = _current->previous; - return slicedData; - %} - obj.current.slices = []; + + function r = endInstance(obj, preserve) + slicedData = []; + if preserve + slicedData = obj.readSlicedData(); + end + obj.current.slices = {}; + obj.current.indirectionTables = {}; obj.current = obj.current.previous; + r = slicedData; end + function r = startSlice(obj) + import IceInternal.Protocol; % % If first slice, don't read the header, it was already read in % readInstance or throwException to find the factory. @@ -101,11 +136,11 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder % if obj.current.sliceType == IceInternal.SliceType.ValueSlice % Must be checked first! - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_TYPE_ID_COMPACT) == obj.FLAG_HAS_TYPE_ID_COMPACT + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_TYPE_ID_COMPACT) == Protocol.FLAG_HAS_TYPE_ID_COMPACT obj.current.typeId = ''; obj.current.compactId = obj.is.readSize(); - elseif bitand(obj.current.sliceFlags, bitor(obj.FLAG_HAS_TYPE_ID_STRING, obj.FLAG_HAS_TYPE_ID_INDEX)) - obj.current.typeId = obj.readTypeId(bitand(obj.current.sliceFlags, obj.FLAG_HAS_TYPE_ID_INDEX) > 0); + elseif bitand(obj.current.sliceFlags, bitor(Protocol.FLAG_HAS_TYPE_ID_STRING, Protocol.FLAG_HAS_TYPE_ID_INDEX)) + obj.current.typeId = obj.readTypeId(bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_TYPE_ID_INDEX) > 0); obj.current.compactId = -1; else % Only the most derived slice encodes the type ID for the compact format. @@ -119,7 +154,7 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder % % Read the slice size if necessary. % - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_SLICE_SIZE) + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_SLICE_SIZE) obj.current.sliceSize = obj.is.readInt(); if obj.current.sliceSize < 4 throw(Ice.UnmarshalOutOfBoundsException()); @@ -130,60 +165,63 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder r = obj.current.typeId; end + function endSlice(obj) - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_OPTIONAL_MEMBERS) + import IceInternal.Protocol; + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS) obj.is.skipOptionals(); end % - % Read the indirect object table if one is present. + % Read the indirection table if one is present and transform the + % indirect patch list into patch entries with direct references. % - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_INDIRECTION_TABLE) - %{ - % TODO - IndexList indirectionTable(obj.is.readAndCheckSeqSize(1)); - for(IndexList::iterator p = indirectionTable.begin(); p != indirectionTable.end(); ++p) - { - *p = readInstance(obj.is.readSize(), 0, 0); - } + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_INDIRECTION_TABLE) + % + % The table is written as a sequence<size> to conserve space. + % + sz = obj.is.readAndCheckSeqSize(1); + indirectionTable = cell(1, sz); + for i = 1:sz + indirectionTable{i} = obj.readInstance(obj.is.readSize(), []); + end % % Sanity checks. If there are optional members, it's possible - % that not all object references were read if they are from + % that not all instance references were read if they are from % unknown optional data members. % - if(indirectionTable.empty()) - { - throw MarshalException(__FILE__, __LINE__, "empty indirection table"); - } - if(obj.current.indirectPatchList.empty() && !(obj.current.sliceFlags & FLAG_HAS_OPTIONAL_MEMBERS)) - { - throw MarshalException(__FILE__, __LINE__, "no references to indirection table"); - } + if length(indirectionTable) == 0 + throw(Ice.MarshalException('', '', 'empty indirection table')); + end + if isempty(obj.current.indirectPatchList) && ... + bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS) == 0 + throw(Ice.MarshalException('', '', 'no references to indirection table')); + end % % Convert indirect references into direct references. % - IndirectPatchList::iterator p; - for(p = obj.current.indirectPatchList.begin(); p != obj.current.indirectPatchList.end(); ++p) - { - assert(p->index >= 0); - if(p->index >= static_cast<Int>(indirectionTable.size())) - { - throw MarshalException(__FILE__, __LINE__, "indirection out of range"); - } - addPatchEntry(indirectionTable[p->index], p->patchFunc, p->patchAddr); - } - obj.current.indirectPatchList.clear(); - %} + if ~isempty(obj.current.indirectPatchList) + for e = obj.current.indirectPatchList + assert(e.index >= 0); + if e.index >= length(indirectionTable) + throw(Ice.MarshalException('', '', 'indirection out of range')); + end + obj.addPatchEntry(indirectionTable{e.index}, e.cb); + end + obj.current.indirectPatchList = []; + end end end + function skipSlice(obj) + import IceInternal.Protocol; %obj.is.traceSkipSlice(obj.current.typeId, obj.current.sliceType); start = obj.is.pos(); - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_SLICE_SIZE) + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_SLICE_SIZE) assert(obj.current.sliceSize >= 4); obj.is.skip(obj.current.sliceSize - 4); else @@ -202,8 +240,8 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder info = Ice.SliceInfo(); info.typeId = obj.current.typeId; info.compactId = obj.current.compactId; - info.hasOptionalMembers = bitand(obj.current.sliceFlags, obj.FLAG_HAS_OPTIONAL_MEMBERS) > 0; - info.isLastSlice = bitand(obj.current.sliceFlags, obj.FLAG_IS_LAST_SLICE) > 0; + info.hasOptionalMembers = bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS) > 0; + info.isLastSlice = bitand(obj.current.sliceFlags, Protocol.FLAG_IS_LAST_SLICE) > 0; if info.hasOptionalMembers % % Don't include the optional member end marker. It will be re-written by @@ -214,57 +252,260 @@ classdef EncapsDecoder11 < IceInternal.EncapsDecoder info.bytes = obj.is.getBytes(start, obj.is.pos()); end - %{ - % TODO - obj.current.indirectionTables.push_back(IndexList()); - % - % Read the indirect object table. We read the instances or their + % Read the indirect instance table. We read the instances or their % IDs if the instance is a reference to an already un-marhsaled % object. % % The SliceInfo object sequence is initialized only if % readSlicedData is called. % - if bitand(obj.current.sliceFlags, obj.FLAG_HAS_INDIRECTION_TABLE) - IndexList& table = obj.current.indirectionTables.back(); - table.resize(obj.is.readAndCheckSeqSize(1)); - for(IndexList::iterator p = table.begin(); p != table.end(); ++p) - { - *p = readInstance(obj.is.readSize(), 0, 0); - } - - obj.current.slices.push_back(info); - %} + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_INDIRECTION_TABLE) + sz = obj.is.readAndCheckSeqSize(1); + indirectionTable = cell(1, sz); + for i = 1:sz + indirectionTable{i} = obj.readInstance(obj.is.readSize(), []); + end + obj.current.indirectionTables{end + 1} = indirectionTable; + else + obj.current.indirectionTables{end + 1} = {}; + end + + obj.current.slices{end + 1} = info; end + function r = readOptional(obj, readTag, expectedFormat) + import IceInternal.Protocol; if isempty(obj.current) - r = obj.is.readOptImpl(readTag, expectedFormat); + r = obj.is.readOptionalImpl(readTag, expectedFormat); return; - elseif bitand(obj.current.sliceFlags, obj.FLAG_HAS_OPTIONAL_MEMBERS) - r = obj.is.readOptImpl(readTag, expectedFormat); + elseif bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS) + r = obj.is.readOptionalImpl(readTag, expectedFormat); return; end r = false; end + end methods(Access=private) + function r = readInstance(obj, index, cb) + import IceInternal.Protocol; + assert(index > 0); + + if index > 1 + if ~isempty(cb) + obj.addPatchEntry(index, cb); + end + r = index; + return; + end + + obj.push(IceInternal.SliceType.ValueSlice); + + % + % Get the instance ID before we start reading slices. If some + % slices are skipped, the indirect instance table is still read and + % might read other instances. + % + obj.valueIdIndex = obj.valueIdIndex + 1; + index = obj.valueIdIndex; + + % + % Read the first slice header. + % + obj.startSlice(); + mostDerivedId = obj.current.typeId; + v = []; + while true + updateCache = false; + + if obj.current.compactId >= 0 + updateCache = true; + + % + % Translate a compact (numeric) type ID into a class. + % + if isempty(obj.compactIdCache) % Lazy initialization. + obj.compactIdCache = containers.Map('KeyType', 'int32', 'ValueType', 'char'); + else + % + % Check the cache to see if we've already translated the compact type ID into a class. + % + if obj.compactIdCache.isKey(obj.current.compactId) + cls = obj.compactIdCache(obj.current.compactId); + try + v = eval(cls); + updateCache = false; + catch e + throw(Ice.NoValueFactoryException('', 'no value factory', ... + sprintf('compact ID %d', obj.current.compactId))); + end + end + end + + % + % If we haven't already cached a class for the compact ID, then try to translate the + % compact ID into a type ID. + % + if isempty(v) + obj.current.typeId = ''; + if ~isempty(obj.compactIdResolver) + try + obj.current.typeId = obj.compactIdResolver(obj.current.compactId); + catch ex + if isa(ex, 'Ice.LocalException') + rethrow(ex); + else + throw(Ice.MarshalException('', '', ... + sprintf('exception in compact ID resolver for ID %d', ... + obj.current.compactId))); + end + end + end + + if isempty(obj.current.typeId) + obj.current.typeId = obj.resolveCompactId(obj.current.compactId); + end + end + end + + if isempty(v) && ~isempty(obj.current.typeId) + v = obj.newInstance(obj.current.typeId); + end + + if ~isempty(v) + if updateCache + assert(obj.current.compactId >= 0); + obj.compactIdCache(obj.current.compactId) = class(v); + end + + % + % We have an instance, get out of this loop. + % + break; + end + + % + % If slicing is disabled, stop unmarshaling. + % + if ~obj.sliceValues + throw(Ice.NoValueFactoryException('', '', 'no value factory found and slicing is disabled', ... + obj.current.typeId)); + end + + % + % Slice off what we don't understand. + % + obj.skipSlice(); + + % + % If this is the last slice, keep the instance as an opaque + % UnknownSlicedValue object. + % + if bitand(obj.current.sliceFlags, Protocol.FLAG_IS_LAST_SLICE) + % + % Provide a factory with an opportunity to supply the instance. + % We pass the "::Ice::Object" ID to indicate that this is the + % last chance to preserve the instance. + % + v = obj.newInstance(Ice.Value.ice_staticId()); + if isempty(v) + v = Ice.UnknownSlicedValue(mostDerivedId); + end + + break; + end + + obj.startSlice(); % Read next Slice header for next iteration. + end + + % + % Unmarshal the instance. + % + obj.unmarshal(index, v); + + if isempty(obj.current) && ~isempty(obj.patchMap) + % + % If any entries remain in the patch map, the sender has sent an index for an instance, but failed + % to supply the instance. + % + throw(Ice.MarshalException('', '', 'index for class received, but no instance')); + end + + if ~isempty(cb) + cb(v); + end + + r = index; + end + + function r = readSlicedData(obj) + if isempty(obj.current.slices) % No preserved slices. + r = []; + end + + % + % The _indirectionTables member holds the indirection table for each slice + % in _slices. + % + assert(length(obj.current.slices) == length(obj.current.indirectionTables)); + function setInstance(si, n, v) + si.instances{n} = v; + end + for n = 1:length(obj.current.slices) + % + % We use the "instances" list in SliceInfo to hold references + % to the target instances. Note that the instances might not have + % been read yet in the case of a circular reference to an + % enclosing instance. + % + table = obj.current.indirectionTables{n}; + info = obj.current.slices{n}; + info.instances = cell(1, length(table)); + for j = 1:length(info.instances) + obj.addPatchEntry(table{j}, @(v) setInstance(info, j, v)); + end + end + + r = obj.current.slices; % Makes a copy + end + + function r = resolveCompactId(obj, id) + type = ''; + + if ~isempty(obj.compactIdResolver) + try + type = obj.compactIdResolver(id); + catch ex + if isa(ex, 'Ice.LocalException') + rethrow(ex); + else + throw(Ice.MarshalException('', '', sprintf('exception in compact ID resolver for ID %d', id))); + end + end + end + + if isempty(type) + prop = sprintf('IceCompactId.TypeId_%d.typeId', id); + try + type = eval(prop); + catch ex + end + end + + r = type; + end + function push(obj, sliceType) - obj.current = IceInternal.InstanceData(obj.current); + obj.current = IceInternal.EncapsDecoder11_InstanceData(obj.current); obj.current.sliceType = sliceType; obj.current.skipFirstSlice = false; end end properties(Access=private) + compactIdResolver current - end - properties(Constant,Access=private) - FLAG_HAS_TYPE_ID_STRING = bitshift(1, 0) - FLAG_HAS_TYPE_ID_INDEX = bitshift(1, 1) - FLAG_HAS_TYPE_ID_COMPACT = bitor(bitshift(1, 0), bitshift(1, 1)) - FLAG_HAS_OPTIONAL_MEMBERS = bitshift(1, 2) - FLAG_HAS_INDIRECTION_TABLE = bitshift(1, 3) - FLAG_HAS_SLICE_SIZE = bitshift(1, 4) - FLAG_IS_LAST_SLICE = bitshift(1, 5) + valueIdIndex + compactIdCache end end diff --git a/matlab/lib/+IceInternal/InstanceData.m b/matlab/lib/+IceInternal/EncapsDecoder11_InstanceData.m index 1f8d2e7ad3d..3ff3ab908f6 100644 --- a/matlab/lib/+IceInternal/InstanceData.m +++ b/matlab/lib/+IceInternal/EncapsDecoder11_InstanceData.m @@ -9,14 +9,17 @@ ICE_LICENSE file included in this distribution. ********************************************************************** %} -classdef InstanceData < handle +classdef EncapsDecoder11_InstanceData < handle methods - function obj = InstanceData(p) + function obj = EncapsDecoder11_InstanceData(p) if ~isempty(p) obj.previous = p; p.next = obj; end + obj.slices = {}; + obj.indirectionTables = {}; obj.sliceFlags = uint8(0); + obj.indirectPatchList = []; end end properties diff --git a/matlab/lib/+IceInternal/EncapsEncoder.m b/matlab/lib/+IceInternal/EncapsEncoder.m new file mode 100644 index 00000000000..5ba8fae1e38 --- /dev/null +++ b/matlab/lib/+IceInternal/EncapsEncoder.m @@ -0,0 +1,55 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) EncapsEncoder < handle + methods + function obj = EncapsEncoder(os, encaps) + obj.os = os; + obj.encaps = encaps; + obj.typeIdIndex = 0; + end + + function r = writeOptional(obj, tag, format) + r = false; + end + end + methods(Abstract) + writeValue(obj, v) + startInstance(obj, sliceType, slicedData) + endInstance(obj) + startSlice(obj, typeId, compactId, last) + endSlice(obj) + writePendingValues(obj) + end + methods(Access=protected) + function r = registerTypeId(obj, typeId) + if isempty(obj.typeIdMap) % Lazy initialization + obj.typeIdMap = containers.Map('KeyType', 'char', 'ValueType', 'int32'); + end + + if obj.typeIdMap.isKey(typeId) + r = obj.typeIdMap(typeId); + else + obj.typeIdIndex = obj.typeIdIndex + 1; + obj.typeIdMap(typeId) = obj.typeIdIndex; + r = -1; + end + end + end + properties(Access=protected) + os + encaps + end + properties(Access=private) + typeIdMap + typeIdIndex + end +end diff --git a/matlab/lib/+IceInternal/EncapsEncoder10.m b/matlab/lib/+IceInternal/EncapsEncoder10.m new file mode 100644 index 00000000000..bdb01792572 --- /dev/null +++ b/matlab/lib/+IceInternal/EncapsEncoder10.m @@ -0,0 +1,171 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef EncapsEncoder10 < IceInternal.EncapsEncoder + methods + function obj = EncapsEncoder10(os, encaps) + obj = obj@IceInternal.EncapsEncoder(os, encaps); + obj.sliceType = IceInternal.SliceType.NoSlice; + obj.valueIdIndex = 0; + obj.toBeMarshaledMap = containers.Map('KeyType', 'int32', 'ValueType', 'any'); + obj.marshaledMap = containers.Map('KeyType', 'int32', 'ValueType', 'any'); + end + + function writeValue(obj, v) + % + % Object references are encoded as a negative integer in 1.0. + % + if ~isempty(v) + obj.os.writeInt(-obj.registerValue(v)); + else + obj.os.writeInt(0); + end + end + + function startInstance(obj, sliceType, slicedData) + obj.sliceType = sliceType; + end + + function endInstance(obj) + if obj.sliceType == IceInternal.SliceType.ValueSlice + % + % Write the Object slice. + % + obj.startSlice(Ice.Value.ice_staticId(), -1, true); + obj.os.writeSize(0); % For compatibility with the old AFM. + obj.endSlice(); + end + obj.sliceType = IceInternal.SliceType.NoSlice; + end + + function startSlice(obj, typeId, compactId, last) + % + % For instance slices, encode a boolean to indicate how the type ID + % is encoded and the type ID either as a string or index. For + % exception slices, always encode the type ID as a string. + % + if obj.sliceType == IceInternal.SliceType.ValueSlice + index = obj.registerTypeId(typeId); + if index < 0 + obj.os.writeBool(false); + obj.os.writeString(typeId); + else + obj.os.writeBool(true); + obj.os.writeSize(index); + end + else + obj.os.writeString(typeId); + end + + obj.os.writeInt(0); % Placeholder for the slice length. + + obj.writeSlice = obj.os.pos(); + end + + function endSlice(obj) + % + % Write the slice length. + % + sz = obj.os.pos() - obj.writeSlice + 4; + obj.os.rewriteInt(sz, obj.writeSlice - 4); + end + + function writePendingValues(obj) + while obj.toBeMarshaledMap.Count > 0 + % + % Consider the to be marshalled instances as marshaled now, + % this is necessary to avoid adding again the "to be + % marshaled instances" into toBeMarshaledMap while writing + % instances. + % + obj.marshaledMap = [obj.marshaledMap; obj.toBeMarshaledMap]; + + savedMap = obj.toBeMarshaledMap; + obj.toBeMarshaledMap = containers.Map('KeyType', 'int32', 'ValueType', 'any'); + obj.os.writeSize(savedMap.Count); + keys = savedMap.keys(); + for i = 1:length(keys) + % + % Ask the instance to marshal itself. Any new class + % instances that are triggered by the classes marshaled + % are added to toBeMarshaledMap. + % + obj.os.writeInt(keys{i}); + + v = savedMap(keys{i}); + try + v.ice_preMarshal(); + catch ex + % TODO: logger + %String s = "exception raised by ice_preMarshal:\n" + com.zeroc.IceInternal.Ex.toString(ex); + %obj.os.instance().initializationData().logger.warning(s); + end + + v.iceWrite_(obj.os); + end + end + obj.os.writeSize(0); % Zero marker indicates end of sequence of sequences of instances. + + % + % Clear the identifier from all instances. + % + values = obj.marshaledMap.values(); + for i = 1:length(values) + values{i}.internal_ = -1; + end + end + end + methods(Access=protected) + function r = registerValue(obj, v) + assert(~isempty(v)); + + % + % We can't use object identity in MATLAB so we assign each value a unique identifier. + % + if v.internal_ == -1 + % + % We haven't seen this value yet. + % + obj.valueIdIndex = obj.valueIdIndex + 1; + v.internal_ = obj.valueIdIndex; + end + + r = v.internal_; + + % + % Look for this instance in the to-be-marshaled map. + % + if obj.toBeMarshaledMap.isKey(v.internal_) + return; + end + + % + % Didn't find it, try the marshaled map next. + % + if obj.marshaledMap.isKey(v.internal_) + return; + end + + % + % We haven't seen this instance previously, create a new + % index, and insert it into the to-be-marshaled map. + % + obj.toBeMarshaledMap(v.internal_) = v; + end + end + properties(Access=private) + sliceType + writeSlice + valueIdIndex + toBeMarshaledMap + marshaledMap + end +end diff --git a/matlab/lib/+IceInternal/EncapsEncoder11.m b/matlab/lib/+IceInternal/EncapsEncoder11.m new file mode 100644 index 00000000000..705817f3e68 --- /dev/null +++ b/matlab/lib/+IceInternal/EncapsEncoder11.m @@ -0,0 +1,281 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef EncapsEncoder11 < IceInternal.EncapsEncoder + methods + function obj = EncapsEncoder11(os, encaps) + obj = obj@IceInternal.EncapsEncoder(os, encaps); + obj.current = []; + obj.valueIdIndex = 1; + obj.internalIdIndex = 0; + obj.marshaledMap = containers.Map('KeyType', 'int32', 'ValueType', 'int32'); + obj.values = {}; + end + + function writeValue(obj, v) + if isempty(v) + obj.os.writeSize(0); + else + % + % We can't index by object identity in MATLAB, so we assign a unique ID to each value. + % We clear this setting in writePendingValues(). + % + if v.internal_ == -1 + v.internal_ = obj.internalIdIndex; + obj.internalIdIndex = obj.internalIdIndex + 1; + obj.values{end + 1} = v; + end + + if ~isempty(obj.current) && obj.encaps.format == Ice.FormatType.SlicedFormat + % + % If writing an instance within a slice and using the sliced + % format, write an index from the instance indirection + % table. The indirect instance table is encoded at the end of + % each slice and is always read (even if the Slice is + % unknown). + % + if ~obj.current.indirectionMap.isKey(v.internal_) + obj.current.indirectionTable{end + 1} = v; + idx = length(obj.current.indirectionTable); % 0 is reserved for nil + obj.current.indirectionMap(v.internal_) = idx; + obj.os.writeSize(idx); + else + obj.os.writeSize(obj.current.indirectionMap(v.internal_)); + end + else + obj.writeInstance(v); % Write the instance or a reference if already marshaled. + end + end + end + + function startInstance(obj, sliceType, slicedData) + if isempty(obj.current) + obj.current = IceInternal.EncapsEncoder11_InstanceData([]); + else + if isempty(obj.current.next) + obj.current = IceInternal.EncapsEncoder11_InstanceData(obj.current); + else + obj.current = obj.current.next; + end + end + obj.current.sliceType = sliceType; + obj.current.firstSlice = true; + + if ~isempty(slicedData) + obj.writeSlicedData(slicedData); + end + end + + function endInstance(obj) + obj.current = obj.current.previous; + end + + function startSlice(obj, typeId, compactId, last) + import IceInternal.Protocol; + assert(isempty(obj.current.indirectionTable) && isempty(obj.current.indirectionMap)); + + obj.current.sliceFlagsPos = obj.os.pos(); + + obj.current.sliceFlags = uint8(0); + if obj.encaps.format == Ice.FormatType.SlicedFormat + % Encode the slice size if using the sliced format. + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_SLICE_SIZE); + end + if last + % This is the last slice. + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_IS_LAST_SLICE); + end + + obj.os.writeByte(0); % Placeholder for the slice flags + + % + % For instance slices, encode the flag and the type ID either as a + % string or index. For exception slices, always encode the type + % ID a string. + % + if obj.current.sliceType == IceInternal.SliceType.ValueSlice + % + % Encode the type ID (only in the first slice for the compact + % encoding). + % + if obj.encaps.format == Ice.FormatType.SlicedFormat || obj.current.firstSlice + if compactId >= 0 + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_TYPE_ID_COMPACT); + obj.os.writeSize(compactId); + else + index = obj.registerTypeId(typeId); + if index < 0 + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_TYPE_ID_STRING); + obj.os.writeString(typeId); + else + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_TYPE_ID_INDEX); + obj.os.writeSize(index); + end + end + end + else + obj.os.writeString(typeId); + end + + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_SLICE_SIZE) + obj.os.writeInt(0); % Placeholder for the slice length. + end + + obj.current.writeSlice = obj.os.pos(); + obj.current.firstSlice = false; + end + + function endSlice(obj) + import IceInternal.Protocol; + % + % Write the optional member end marker if some optional members + % were encoded. Note that the optional members are encoded before + % the indirection table and are included in the slice size. + % + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS) + obj.os.writeByte(Protocol.OPTIONAL_END_MARKER); + end + + % + % Write the slice length if necessary. + % + if bitand(obj.current.sliceFlags, Protocol.FLAG_HAS_SLICE_SIZE) + sz = obj.os.pos() - obj.current.writeSlice + 4; + obj.os.rewriteInt(sz, obj.current.writeSlice - 4); + end + + % + % Only write the indirection table if it contains entries. + % + if ~isempty(obj.current.indirectionTable) + assert(obj.encaps.format == Ice.FormatType.SlicedFormat); + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_INDIRECTION_TABLE); + + % + % Write the indirection instance table. + % + obj.os.writeSize(length(obj.current.indirectionTable)); + for i = 1:length(obj.current.indirectionTable) + obj.writeInstance(obj.current.indirectionTable{i}); + end + obj.current.indirectionTable = {}; + obj.current.indirectionMap = containers.Map('KeyType', 'int32', 'ValueType', 'int32'); + end + + % + % Finally, update the slice flags. + % + obj.os.rewriteByte(obj.current.sliceFlags, obj.current.sliceFlagsPos); + end + + function r = writeOptional(obj, tag, format) + import IceInternal.Protocol; + if isempty(obj.current) + r = obj.os.writeOptionalImpl(tag, format); + else + if obj.os.writeOptionalImpl(tag, format) + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS); + r = true; + else + r = false; + end + end + end + + function writePendingValues(obj) + % + % Clear the identifier from all instances. + % + for i = 1:length(obj.values) + obj.values{i}.internal_ = -1; + end + obj.values = {}; + end + end + methods(Access=private) + function writeSlicedData(obj, slicedData) + import IceInternal.Protocol; + assert(~isempty(slicedData)); + + % + % We only remarshal preserved slices if we are using the sliced + % format. Otherwise, we ignore the preserved slices, which + % essentially "slices" the instance into the most-derived type + % known by the sender. + % + if obj.encaps.format ~= Ice.FormatType.SlicedFormat + return; + end + + for info = slicedData.slices + obj.startSlice(info.typeId, info.compactId, info.isLastSlice); + + % + % Write the bytes associated with this slice. + % + obj.os.writeBlob(info.bytes); + + if info.hasOptionalMembers + obj.current.sliceFlags = bitor(obj.current.sliceFlags, Protocol.FLAG_HAS_OPTIONAL_MEMBERS); + end + + % + % Make sure to also re-write the instance indirection table. + % + if ~isempty(info.instances) + for o = info.instances + obj.current.indirectionTable{end + 1} = o; + end + end + + obj.endSlice(); + end + end + + function writeInstance(obj, v) + assert(~isempty(v)); + assert(v.internal_ ~= -1); + + % + % If the instance was already marshaled, just write its ID. + % + if obj.marshaledMap.isKey(v.internal_) + obj.os.writeSize(obj.marshaledMap(v.internal_)); + return; + end + + % + % We haven't seen this instance previously, create a new ID, + % insert it into the marshaled map, and write the instance. + % + obj.valueIdIndex = obj.valueIdIndex + 1; + obj.marshaledMap(v.internal_) = obj.valueIdIndex; + + try + v.ice_preMarshal(); + catch ex + % TODO logger + %String s = "exception raised by ice_preMarshal:\n" + com.zeroc.IceInternal.Ex.toString(ex); + %obj.os.instance().initializationData().logger.warning(s); + end + + obj.os.writeSize(1); % Class instance marker. + v.iceWrite_(obj.os); + end + end + properties(Access=private) + current + valueIdIndex + internalIdIndex + marshaledMap + values + end +end diff --git a/matlab/lib/+IceInternal/EncapsEncoder11_InstanceData.m b/matlab/lib/+IceInternal/EncapsEncoder11_InstanceData.m new file mode 100644 index 00000000000..02ac9149786 --- /dev/null +++ b/matlab/lib/+IceInternal/EncapsEncoder11_InstanceData.m @@ -0,0 +1,37 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef EncapsEncoder11_InstanceData < handle + methods + function obj = EncapsEncoder11_InstanceData(previous) + if ~isempty(previous) + previous.next = obj; + end + obj.previous = previous; + obj.next = []; + obj.indirectionTable = {}; + obj.indirectionMap = containers.Map('KeyType', 'int32', 'ValueType', 'int32'); + end + end + properties + % Instance attributes + sliceType + firstSlice + % Slice attributes + sliceFlags + writeSlice % Position of the slice data members + sliceFlagsPos % Position of the slice flags + indirectionTable + indirectionMap + previous + next + end +end diff --git a/matlab/lib/+IceInternal/PatchList.m b/matlab/lib/+IceInternal/PatchList.m new file mode 100644 index 00000000000..d42d2b3f70a --- /dev/null +++ b/matlab/lib/+IceInternal/PatchList.m @@ -0,0 +1,16 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef PatchList < handle + properties + list = {} + end +end diff --git a/matlab/lib/+IceInternal/Protocol.m b/matlab/lib/+IceInternal/Protocol.m new file mode 100644 index 00000000000..2710a35bd80 --- /dev/null +++ b/matlab/lib/+IceInternal/Protocol.m @@ -0,0 +1,27 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Protocol + properties(Constant) + FLAG_HAS_TYPE_ID_STRING = bitshift(1, 0) + FLAG_HAS_TYPE_ID_INDEX = bitshift(1, 1) + FLAG_HAS_TYPE_ID_COMPACT = bitor(bitshift(1, 0), bitshift(1, 1)) + FLAG_HAS_OPTIONAL_MEMBERS = bitshift(1, 2) + FLAG_HAS_INDIRECTION_TABLE = bitshift(1, 3) + FLAG_HAS_SLICE_SIZE = bitshift(1, 4) + FLAG_IS_LAST_SLICE = bitshift(1, 5) + + OPTIONAL_END_MARKER = hex2dec('ff') + + Encoding_1_0 = Ice.EncodingVersion(1, 0) + Encoding_1_1 = Ice.EncodingVersion(1, 1) + end +end diff --git a/matlab/lib/+IceInternal/Encaps.m b/matlab/lib/+IceInternal/ReadEncaps.m index 0bf3d80e65b..34edc693560 100644 --- a/matlab/lib/+IceInternal/Encaps.m +++ b/matlab/lib/+IceInternal/ReadEncaps.m @@ -9,7 +9,7 @@ ICE_LICENSE file included in this distribution. ********************************************************************** %} -classdef Encaps < handle +classdef ReadEncaps < handle properties start sz diff --git a/matlab/lib/+IceInternal/UnsetI.m b/matlab/lib/+IceInternal/UnsetI.m new file mode 100644 index 00000000000..1da87a949a2 --- /dev/null +++ b/matlab/lib/+IceInternal/UnsetI.m @@ -0,0 +1,37 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +% +% Singleton used to indicate an unset optional value. +% +classdef UnsetI < handle + methods(Access=private) + function obj = UnsetI() + end + end + methods + function r = eq(obj, other) + r = isequal(obj, other); + end + function r = ne(obj, other) + r = ~isequal(obj, other); + end + end + methods(Static) + function obj = getInstance() + persistent singleton; + if isempty(singleton) || ~isvalid(singleton) + singleton = IceInternal.UnsetI(); + end + obj = singleton; + end + end +end diff --git a/matlab/lib/+IceInternal/Util.m b/matlab/lib/+IceInternal/Util.m new file mode 100644 index 00000000000..b5799efcf85 --- /dev/null +++ b/matlab/lib/+IceInternal/Util.m @@ -0,0 +1,66 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Util + methods(Static) + % + % Internal method - invoke a C function with the given name. + % The value for fn MUST be given in single quotes! + % + function call(fn, varargin) + ex = calllib('icematlab', fn, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + + % + % Internal method - invoke a C function representing a global function. + % The value for fn MUST be given in single quotes! + % + function r = callWithResult(fn, varargin) + result = calllib('icematlab', fn, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; + end + end + + function r = idToClass(id) + assert(length(id) > 2 && strcmp(id(1:2), '::')); + r = strrep(id, '::', '.'); + r = r(2:end); + end + + function r = strcmp(s1, s2) + n = min(length(s1), length(s2)); + for i = 1:n + if s1(i) < s2(i) + r = -1; + return; + elseif s1(i) > s2(i) + r = 1; + return; + end + end + if length(s1) > n + r = 1; + elseif length(s2) > n + r = -1; + else + r = 0; + end + end + end +end diff --git a/matlab/lib/+IceInternal/WrapperObject.m b/matlab/lib/+IceInternal/WrapperObject.m index 35fcf0cb0c8..125c879958d 100644 --- a/matlab/lib/+IceInternal/WrapperObject.m +++ b/matlab/lib/+IceInternal/WrapperObject.m @@ -11,16 +11,63 @@ ICE_LICENSE file included in this distribution. classdef (Abstract) WrapperObject < handle methods - function obj = WrapperObject(impl) - obj.impl = impl; + function obj = WrapperObject(impl, type) + % + % If no type was supplied, we convert the class name into the prefix that we'll use for invoking + % external C functions. + % + if nargin == 1 + type = strrep(class(obj), '.', '_'); % E.g., Ice.Communicator -> Ice_Communicator + end + obj.impl_ = impl; + obj.type_ = type; end + end + methods(Hidden) function delete(obj) - if ~isempty(obj.impl) - Ice.Util.callMethod(obj, '_release'); + if ~isempty(obj.impl_) + obj.call_('_release'); + end + end + function call_(obj, fn, varargin) + name = strcat(obj.type_, '_', fn); + ex = calllib('icematlab', name, obj.impl_, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + function r = callWithResult_(obj, fn, varargin) + name = strcat(obj.type_, '_', fn); + result = calllib('icematlab', name, obj.impl_, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; + end + end + function callOnType_(obj, type, fn, varargin) + name = strcat(type, '_', fn); + ex = calllib('icematlab', name, obj.impl_, varargin{:}); + if ~isempty(ex) + ex.throwAsCaller(); + end + end + function r = callOnTypeWithResult_(obj, type, fn, varargin) + name = strcat(type, '_', fn); + result = calllib('icematlab', name, obj.impl_, varargin{:}); + if isempty(result) + r = result; + elseif ~isempty(result.exception) + result.exception.throwAsCaller(); + else + r = result.result; end end end properties(Hidden,SetAccess=protected) - impl + impl_ + type_ end end diff --git a/matlab/lib/+IceInternal/WriteEncaps.m b/matlab/lib/+IceInternal/WriteEncaps.m new file mode 100644 index 00000000000..b4f286771e2 --- /dev/null +++ b/matlab/lib/+IceInternal/WriteEncaps.m @@ -0,0 +1,20 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef WriteEncaps < handle + properties + start + format = Ice.FormatType.DefaultFormat + encoding + encoder + next + end +end diff --git a/matlab/msbuild/ice.proj b/matlab/msbuild/ice.proj index d4ad11159c7..f82956be32c 100644 --- a/matlab/msbuild/ice.proj +++ b/matlab/msbuild/ice.proj @@ -23,10 +23,15 @@ </PropertyGroup> <ItemGroup> + <Slice Include="$(sliceDir)\Ice\Communicator.ice" /> <Slice Include="$(sliceDir)\Ice\Connection.ice" /> <Slice Include="$(sliceDir)\Ice\Current.ice" /> + <Slice Include="$(sliceDir)\Ice\EndpointTypes.ice" /> <Slice Include="$(sliceDir)\Ice\Identity.ice" /> <Slice Include="$(sliceDir)\Ice\LocalException.ice" /> + <Slice Include="$(sliceDir)\Ice\Locator.ice" /> + <Slice Include="$(sliceDir)\Ice\Router.ice" /> + <Slice Include="$(sliceDir)\Ice\ValueFactory.ice" /> <Slice Include="$(sliceDir)\Ice\Version.ice" /> </ItemGroup> @@ -43,8 +48,12 @@ <Target Name="Build" DependsOnTargets="CppPrereqs"> <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(MSBuildThisFileDirectory)..\lib\generated %(Slice.FullPath)"/> - <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\operations\generated $(testDir)\Ice\operations\Test.ice"/> <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\exceptions\generated $(testDir)\Ice\exceptions\Test.ice"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\objects\generated $(testDir)\Ice\objects\Test.ice"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\operations\generated $(testDir)\Ice\operations\Test.ice"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\optional\generated $(testDir)\Ice\optional\Test.ice"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) -I$(testDir)\Ice\optional --output-dir $(testDir)\Ice\optional\generated $(testDir)\Ice\optional\ClientPrivate.ice"/> + <Exec Command="$(slice2matlabexe) -I$(sliceDir) --output-dir $(testDir)\Ice\proxy\generated $(testDir)\Ice\proxy\Test.ice"/> <Exec Command="mex -v -outdir $(srcDir) -output icematlab $(MexCompilerFlags) -I$(topSrcDir)\cpp\include -I$(topSrcDir)\cpp\include\generated\cpp11\$(Platform)\$(Configuration) -DICE_CPP11_MAPPING -DICE_BUILDING_SRC -L$(topSrcDir)\cpp\lib\$(Platform)\$(Configuration) -lmex -lmx $(srcDir)\*.cpp"/> <Exec Command="copy /Y $(topSrcDir)\cpp\bin\$(Platform)\$(Configuration)\bzip2$(DebugExt).dll $(srcDir)"/> <Exec Command="copy /Y "$(topSrcDir)\cpp\bin\$(Platform)\$(Configuration)\ice37++11$(DebugExt).dll" $(srcDir)"/> diff --git a/matlab/src/IceMatlab/Communicator.cpp b/matlab/src/IceMatlab/Communicator.cpp index 0d4208bf9f9..a9a0b02c98f 100644 --- a/matlab/src/IceMatlab/Communicator.cpp +++ b/matlab/src/IceMatlab/Communicator.cpp @@ -13,6 +13,7 @@ #include <Ice/Proxy.h> #include <Ice/OutputStream.h> #include "icematlab.h" +#include "ObjectPrx.h" #include "Util.h" #define SELF (*(reinterpret_cast<shared_ptr<Ice::Communicator>*>(self))) @@ -31,12 +32,57 @@ Ice_Communicator__release(void* self) } EXPORTED_FUNCTION mxArray* +Ice_Communicator_identityToString(void* self, mxArray* id) +{ + try + { + Ice::Identity ident; + getIdentity(id, ident); + return createResultValue(createStringFromUTF8(SELF->identityToString(ident))); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* Ice_Communicator_stringToProxy(void* self, const char* s, void** proxy) { try { shared_ptr<Ice::ObjectPrx> p = SELF->stringToProxy(s); - *proxy = new shared_ptr<Ice::ObjectPrx>(p); + if(p) + { + *proxy = new shared_ptr<Ice::ObjectPrx>(p); + } + else + { + *proxy = 0; + } + } + catch(const std::exception& ex) + { + return convertException(ex); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_propertyToProxy(void* self, const char* prop, void** proxy) +{ + try + { + shared_ptr<Ice::ObjectPrx> p = SELF->propertyToProxy(prop); + if(p) + { + *proxy = new shared_ptr<Ice::ObjectPrx>(p); + } + else + { + *proxy = 0; + } } catch(const std::exception& ex) { @@ -46,6 +92,39 @@ Ice_Communicator_stringToProxy(void* self, const char* s, void** proxy) } EXPORTED_FUNCTION mxArray* +Ice_Communicator_proxyToProperty(void* self, void* proxy, const char* prop) +{ + assert(proxy); + try + { + shared_ptr<Ice::ObjectPrx> p = getProxy(proxy); + Ice::PropertyDict d = SELF->proxyToProperty(p, prop); + return createResultValue(createStringMap(d)); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_Communicator_proxyToString(void* self, void* proxy) +{ + assert(proxy); + try + { + shared_ptr<Ice::ObjectPrx> p = getProxy(proxy); + return createResultValue(createStringFromUTF8(SELF->proxyToString(p))); + } + catch(const std::exception& ex) + { + return createResultException(convertException(ex)); + } + return 0; +} + +EXPORTED_FUNCTION mxArray* Ice_Communicator_getProperties(void* self, void** props) { try diff --git a/matlab/src/IceMatlab/Init.cpp b/matlab/src/IceMatlab/Init.cpp index 772647763f1..f67860dbaa7 100644 --- a/matlab/src/IceMatlab/Init.cpp +++ b/matlab/src/IceMatlab/Init.cpp @@ -139,7 +139,6 @@ Ice_initialize(mxArray* args, void* propsImpl, void** r) id.properties = *(reinterpret_cast<shared_ptr<Ice::Properties>*>(propsImpl)); } - //id.valueFactoryManager = make_shared<ValueFactoryManager>(); //id.logger = make_shared<Logger>(""); // TODO shared_ptr<Ice::Communicator> c = Ice::initialize(a, id); @@ -169,13 +168,14 @@ Ice_stringToIdentity(mxArray* s) } EXPORTED_FUNCTION mxArray* -Ice_identityToString(mxArray* id) +Ice_identityToString(mxArray* id, int mode) { try { + Ice::ToStringMode m = static_cast<Ice::ToStringMode>(mode); Ice::Identity ident; getIdentity(id, ident); - return createResultValue(createStringFromUTF8(Ice::identityToString(ident))); + return createResultValue(createStringFromUTF8(Ice::identityToString(ident, m))); } catch(const std::exception& ex) { @@ -184,6 +184,37 @@ Ice_identityToString(mxArray* id) return 0; } +EXPORTED_FUNCTION mxArray* +Ice_stringVersion() +{ + return createResultValue(createStringFromUTF8(ICE_STRING_VERSION)); +} + +EXPORTED_FUNCTION mxArray* +Ice_intVersion(int* v) +{ + *v = ICE_INT_VERSION; + return 0; +} + +EXPORTED_FUNCTION mxArray* +Ice_currentEncoding() +{ + return createResultValue(createEncodingVersion(Ice::currentEncoding)); +} + +EXPORTED_FUNCTION mxArray* +Ice_currentProtocol() +{ + return createResultValue(createProtocolVersion(Ice::currentProtocol)); +} + +EXPORTED_FUNCTION mxArray* +Ice_currentProtocolEncoding() +{ + return createResultValue(createEncodingVersion(Ice::currentProtocolEncoding)); +} + // // This function exists so that mex may be used to compile the library. It is not otherwise needed. // diff --git a/matlab/src/IceMatlab/InputStream.cpp b/matlab/src/IceMatlab/InputStream.cpp index 83c7173bcc5..afbc2d147a4 100644 --- a/matlab/src/IceMatlab/InputStream.cpp +++ b/matlab/src/IceMatlab/InputStream.cpp @@ -15,7 +15,7 @@ #include "InputStream.h" #include "Util.h" -#define SELF (reinterpret_cast<IceMatlab::InputStreamData*>(self)) +#define SELF (reinterpret_cast<InputStreamData*>(self)) using namespace std; using namespace IceMatlab; @@ -23,6 +23,12 @@ using namespace IceMatlab; namespace { +struct InputStreamData +{ + std::vector<Ice::Byte> data; + Ice::InputStream* in; +}; + template<typename T> mxArray* readSeq(Ice::InputStream* in, mxClassID cls) @@ -46,51 +52,6 @@ readSeq(Ice::InputStream* in, mxClassID cls) return 0; } -template<typename T> -mxArray* -readOpt(Ice::InputStream* in, int tag, mxClassID cls) -{ - try - { - Ice::optional<T> opt; - in->read(tag, opt); - if(opt.has_value()) - { - mxArray* r = mxCreateUninitNumericMatrix(1, 1, cls, mxREAL); - *(reinterpret_cast<T*>(mxGetData(r))) = opt.value(); - return createResultValue(r); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - -template<typename T> -mxArray* -readSeqOpt(Ice::InputStream* in, int tag, mxClassID cls) -{ - try - { - Ice::optional<pair<const T*, const T*>> opt; - in->read(tag, opt); - const size_t sz = opt.value().second - opt.value().first; - if(opt.has_value() && sz > 0) - { - mxArray* r = mxCreateUninitNumericMatrix(1, sz / sizeof(T), cls, mxREAL); - memcpy(reinterpret_cast<T*>(mxGetData(r)), opt.value().first, sz); - return createResultValue(r); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - } void* @@ -153,47 +114,6 @@ Ice_InputStream_readBoolSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readBoolOpt(void* self, int tag) -{ - try - { - Ice::optional<bool> opt; - SELF->in->read(tag, opt); - if(opt.has_value()) - { - return createResultValue(mxCreateLogicalScalar(opt.value())); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readBoolSeqOpt(void* self, int tag) -{ - try - { - Ice::optional<pair<const bool*, const bool*>> opt; - SELF->in->read(tag, opt); - const size_t sz = opt.value().second - opt.value().first; - if(opt.has_value() && sz > 0) - { - mxArray* r = mxCreateLogicalMatrix(1, sz); - memcpy(mxGetLogicals(r), opt.value().first, sz); - return createResultValue(r); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readByte(void* self, unsigned char* v) { try @@ -216,18 +136,6 @@ Ice_InputStream_readByteSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readByteOpt(void* self, int tag) -{ - return readOpt<Ice::Byte>(SELF->in, tag, mxUINT8_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readByteSeqOpt(void* self, int tag) -{ - return readSeqOpt<Ice::Byte>(SELF->in, tag, mxUINT8_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readShort(void* self, short* v) { try @@ -248,18 +156,6 @@ Ice_InputStream_readShortSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readShortOpt(void* self, int tag) -{ - return readOpt<short>(SELF->in, tag, mxINT16_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readShortSeqOpt(void* self, int tag) -{ - return readSeqOpt<short>(SELF->in, tag, mxINT16_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readInt(void* self, int* v) { try @@ -280,18 +176,6 @@ Ice_InputStream_readIntSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readIntOpt(void* self, int tag) -{ - return readOpt<int>(SELF->in, tag, mxINT32_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readIntSeqOpt(void* self, int tag) -{ - return readSeqOpt<int>(SELF->in, tag, mxINT32_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readLong(void* self, long long* v) { try @@ -312,18 +196,6 @@ Ice_InputStream_readLongSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readLongOpt(void* self, int tag) -{ - return readOpt<long long>(SELF->in, tag, mxINT64_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readLongSeqOpt(void* self, int tag) -{ - return readSeqOpt<long long>(SELF->in, tag, mxINT64_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloat(void* self, float* v) { try @@ -344,18 +216,6 @@ Ice_InputStream_readFloatSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readFloatOpt(void* self, int tag) -{ - return readOpt<float>(SELF->in, tag, mxSINGLE_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readFloatSeqOpt(void* self, int tag) -{ - return readSeqOpt<float>(SELF->in, tag, mxSINGLE_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readDouble(void* self, double* v) { try @@ -376,18 +236,6 @@ Ice_InputStream_readDoubleSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readDoubleOpt(void* self, int tag) -{ - return readOpt<double>(SELF->in, tag, mxDOUBLE_CLASS); -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readDoubleSeqOpt(void* self, int tag) -{ - return readSeqOpt<double>(SELF->in, tag, mxDOUBLE_CLASS); -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_readString(void* self) { string s; @@ -419,43 +267,6 @@ Ice_InputStream_readStringSeq(void* self) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readStringOpt(void* self, int tag) -{ - try - { - Ice::optional<string> opt; - SELF->in->read(tag, opt); - if(opt.has_value()) - { - return createResultValue(createStringFromUTF8(opt.value())); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* -Ice_InputStream_readStringSeqOpt(void* self, int tag) -{ - try - { - if(SELF->in->readOptional(tag, Ice::OptionalFormat::FSize)) - { - SELF->in->skip(4); - return Ice_InputStream_readStringSeq(self); - } - } - catch(const std::exception& ex) - { - return createResultException(convertException(ex)); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_InputStream_skip(void* self, int n) { try @@ -535,20 +346,11 @@ Ice_InputStream_readProxy(void* self, void** r) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readProxyOpt(void* self, int tag, void** r) +Ice_InputStream_readEnum(void* self, int maxValue, int* r) { try { - Ice::optional<shared_ptr<Ice::ObjectPrx>> opt; - SELF->in->readAll({tag}, opt); - if(opt.has_value()) - { - *r = new shared_ptr<Ice::ObjectPrx>(opt.value()); - } - else - { - *r = 0; - } + *r = SELF->in->readEnum(maxValue); } catch(const std::exception& ex) { @@ -558,11 +360,11 @@ Ice_InputStream_readProxyOpt(void* self, int tag, void** r) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_readEnum(void* self, int maxValue, int* r) +Ice_InputStream_pos(void* self, unsigned int* pos) { try { - *r = SELF->in->readEnum(maxValue); + *pos = SELF->in->pos(); } catch(const std::exception& ex) { @@ -572,11 +374,11 @@ Ice_InputStream_readEnum(void* self, int maxValue, int* r) } EXPORTED_FUNCTION mxArray* -Ice_InputStream_pos(void* self, unsigned int* pos) +Ice_InputStream_setPos(void* self, unsigned int pos) { try { - *pos = SELF->in->pos(); + SELF->in->pos(pos); } catch(const std::exception& ex) { diff --git a/matlab/src/IceMatlab/InputStream.h b/matlab/src/IceMatlab/InputStream.h index a801d6a5cb4..f86b1121c9a 100644 --- a/matlab/src/IceMatlab/InputStream.h +++ b/matlab/src/IceMatlab/InputStream.h @@ -12,12 +12,6 @@ namespace IceMatlab { -struct InputStreamData -{ - std::vector<Ice::Byte> data; - Ice::InputStream* in; -}; - // // Consumes the vector. // diff --git a/matlab/src/IceMatlab/ObjectPrx.cpp b/matlab/src/IceMatlab/ObjectPrx.cpp index 0bdb8c32087..2c2145ced2f 100644 --- a/matlab/src/IceMatlab/ObjectPrx.cpp +++ b/matlab/src/IceMatlab/ObjectPrx.cpp @@ -13,6 +13,7 @@ #include "icematlab.h" #include "Future.h" #include "InputStream.h" +#include "ObjectPrx.h" #include "Util.h" #define DEREF(x) (*(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(x))) @@ -201,6 +202,12 @@ GetConnectionFuture::isFinished() const } +shared_ptr<Ice::ObjectPrx> +IceMatlab::getProxy(void* p) +{ + return DEREF(p); +} + extern "C" { @@ -391,13 +398,6 @@ Ice_ObjectPrx_ice_toString(void* self) } EXPORTED_FUNCTION mxArray* -Ice_ObjectPrx_ice_getCommunicator(void* self, void** r) -{ - *r = new shared_ptr<Ice::Communicator>(SELF->ice_getCommunicator()); - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getIdentity(void* self) { return createResultValue(createIdentity(SELF->ice_getIdentity())); @@ -601,14 +601,14 @@ Ice_ObjectPrx_ice_connectionCached(void* self, unsigned char v, void** r) } EXPORTED_FUNCTION mxArray* -Ice_ObjectPrx_ice_getEndpointSelection(void* self, Ice_EndpointSelectionType* r) +Ice_ObjectPrx_ice_getEndpointSelection(void* self, int* r) { - *r = SELF->ice_getEndpointSelection() == Ice::EndpointSelectionType::Random ? Random : Ordered; + *r = static_cast<int>(SELF->ice_getEndpointSelection()); return 0; } EXPORTED_FUNCTION mxArray* -Ice_ObjectPrx_ice_endpointSelection(void* self, Ice_EndpointSelectionType v, void** r) +Ice_ObjectPrx_ice_endpointSelection(void* self, int v, void** r) { try { diff --git a/matlab/src/IceMatlab/OutputStream.cpp b/matlab/src/IceMatlab/OutputStream.cpp index 46dee32dc62..d72957ee86c 100644 --- a/matlab/src/IceMatlab/OutputStream.cpp +++ b/matlab/src/IceMatlab/OutputStream.cpp @@ -18,88 +18,12 @@ using namespace std; using namespace IceMatlab; -namespace -{ - -typedef std::map<mxArray*, shared_ptr<Ice::Value>> ValueMap; - -// -// A Closure instance is associated with an OutputStream whenever values are marshaled. -// -struct Closure -{ - ValueMap valueMap; - mxArray* stream; -}; - -// -// ValueWriter wraps a Matlab object for marshaling. -// -class ValueWriter : public Ice::Value -{ -public: - - ValueWriter(mxArray*); - - virtual void ice_preMarshal(); - - virtual void _iceWrite(Ice::OutputStream*) const; - virtual void _iceRead(Ice::InputStream*); - -protected: - - virtual shared_ptr<Ice::Value> _iceCloneImpl() const; - -private: - - mxArray* _value; -}; - -ValueWriter::ValueWriter(mxArray* v) : - _value(v) -{ -} - -void -ValueWriter::ice_preMarshal() -{ - mexCallMATLAB(0, 0, 1, &_value, "ice_preMarshal"); -} - -void -ValueWriter::_iceWrite(Ice::OutputStream* os) const -{ - Closure* c = reinterpret_cast<Closure*>(os->getClosure()); - assert(c); - - mxArray* params[2]; - params[0] = _value; - params[1] = c->stream; - mexCallMATLAB(0, 0, 2, params, "iceWrite_"); -} - -void -ValueWriter::_iceRead(Ice::InputStream*) -{ - assert(false); -} - -shared_ptr<Ice::Value> -ValueWriter::_iceCloneImpl() const -{ - return nullptr; -} - -} - extern "C" { EXPORTED_FUNCTION mxArray* Ice_OutputStream__release(void* self) { - Closure* c = reinterpret_cast<Closure*>(SELF->getClosure()); - delete c; delete SELF; return 0; } @@ -119,20 +43,6 @@ Ice_OutputStream_writeBool(void* self, unsigned char v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeBoolOpt(void* self, int tag, unsigned char v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<bool>(v == 1)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolSeq(void* self, const unsigned char* v, int size) { const bool* p = reinterpret_cast<const bool*>(v); @@ -148,24 +58,6 @@ Ice_OutputStream_writeBoolSeq(void* self, const unsigned char* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeBoolSeqOpt(void* self, int tag, const unsigned char* v, int size) -{ - const bool* p = reinterpret_cast<const bool*>(v); - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(p, p + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByte(void* self, unsigned char v) { try @@ -180,20 +72,6 @@ Ice_OutputStream_writeByte(void* self, unsigned char v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeByteOpt(void* self, int tag, unsigned char v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<Ice::Byte>(static_cast<Ice::Byte>(v))); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteSeq(void* self, const unsigned char* v, int size) { const Ice::Byte* p = reinterpret_cast<const Ice::Byte*>(v); @@ -209,24 +87,6 @@ Ice_OutputStream_writeByteSeq(void* self, const unsigned char* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeByteSeqOpt(void* self, int tag, const unsigned char* v, int size) -{ - const Ice::Byte* p = reinterpret_cast<const Ice::Byte*>(v); - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(p, p + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShort(void* self, short v) { try @@ -241,20 +101,6 @@ Ice_OutputStream_writeShort(void* self, short v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeShortOpt(void* self, int tag, short v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<short>(v)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortSeq(void* self, const short* v, int size) { try @@ -269,23 +115,6 @@ Ice_OutputStream_writeShortSeq(void* self, const short* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeShortSeqOpt(void* self, int tag, const short* v, int size) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(v, v + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeInt(void* self, int v) { try @@ -300,20 +129,6 @@ Ice_OutputStream_writeInt(void* self, int v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeIntOpt(void* self, int tag, int v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<int>(v)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntSeq(void* self, const int* v, int size) { try @@ -328,23 +143,6 @@ Ice_OutputStream_writeIntSeq(void* self, const int* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeIntSeqOpt(void* self, int tag, const int* v, int size) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(v, v + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLong(void* self, long long v) { try @@ -359,20 +157,6 @@ Ice_OutputStream_writeLong(void* self, long long v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeLongOpt(void* self, int tag, long long v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<long long>(v)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongSeq(void* self, const long long* v, int size) { try @@ -387,23 +171,6 @@ Ice_OutputStream_writeLongSeq(void* self, const long long* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeLongSeqOpt(void* self, int tag, const long long* v, int size) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(v, v + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloat(void* self, float v) { try @@ -418,20 +185,6 @@ Ice_OutputStream_writeFloat(void* self, float v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeFloatOpt(void* self, int tag, float v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<float>(v)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatSeq(void* self, const float* v, int size) { try @@ -446,23 +199,6 @@ Ice_OutputStream_writeFloatSeq(void* self, const float* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeFloatSeqOpt(void* self, int tag, const float* v, int size) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(v, v + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDouble(void* self, double v) { try @@ -477,20 +213,6 @@ Ice_OutputStream_writeDouble(void* self, double v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeDoubleOpt(void* self, int tag, double v) -{ - try - { - SELF->writeAll({tag}, IceUtil::Optional<double>(v)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleSeq(void* self, const double* v, int size) { try @@ -505,23 +227,6 @@ Ice_OutputStream_writeDoubleSeq(void* self, const double* v, int size) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeDoubleSeqOpt(void* self, int tag, const double* v, int size) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(v, v + size); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeString(void* self, mxArray* str) { try @@ -536,23 +241,6 @@ Ice_OutputStream_writeString(void* self, mxArray* str) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeStringOpt(void* self, int tag, mxArray* str) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::VSize)) - { - SELF->write(getStringFromUTF16(str), false); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringSeq(void* self, mxArray* v) { try @@ -589,29 +277,6 @@ Ice_OutputStream_writeStringSeq(void* self, mxArray* v) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeStringSeqOpt(void* self, int tag, mxArray* v) -{ - try - { - if(SELF->writeOptional(tag, Ice::OptionalFormat::FSize)) - { - Ice::OutputStream::size_type pos = SELF->startSize(); - mxArray* ex = Ice_OutputStream_writeStringSeq(self, v); - if(ex) - { - return ex; - } - SELF->endSize(pos); - } - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeSize(void* self, int size) { try @@ -645,22 +310,6 @@ Ice_OutputStream_writeProxy(void* self, void* proxy) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeProxyOpt(void* self, int tag, void* proxy) -{ - assert(proxy); // Wrapper only calls this function for a non-nil value. - shared_ptr<Ice::ObjectPrx> p = *(reinterpret_cast<shared_ptr<Ice::ObjectPrx>*>(proxy)); - try - { - SELF->writeAll({tag}, IceUtil::Optional<shared_ptr<Ice::ObjectPrx>>(p)); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeEnum(void* self, int val, int maxValue) { try @@ -675,88 +324,11 @@ Ice_OutputStream_writeEnum(void* self, int val, int maxValue) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeValue(void* self, mxArray* stream, mxArray* val) -{ - if(mxIsEmpty(val)) - { - shared_ptr<Ice::Value> nil = nullptr; - SELF->write(nil); - return 0; - } - - // - // Attach a Closure instance to the stream upon writing the first non-nil Value. - // - Closure* c = reinterpret_cast<Closure*>(SELF->getClosure()); - if(!c) - { - c = new Closure; - c->stream = stream; - SELF->setClosure(c); - } - - // - // We're assuming that a mxArray pointer uniquely identifies an object. We use the closure's map to - // track the instances. - // - shared_ptr<Ice::Value> w; - ValueMap::iterator p = c->valueMap.find(val); - if(p == c->valueMap.end()) - { - w = make_shared<ValueWriter>(val); - c->valueMap.insert(ValueMap::value_type(val, w)); - } - else - { - w = p->second; - } - - try - { - SELF->write(w); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeValueOpt(void* self, int tag, mxArray* stream, mxArray* val) -{ - // - // We assume an empty value means an unset optional (as opposed to an optional set to a null value). - // - if(!mxIsEmpty(val) && SELF->writeOptional(tag, Ice::OptionalFormat::Class)) - { - return Ice_OutputStream_writeValue(self, stream, val); - } - - return 0; -} - -EXPORTED_FUNCTION mxArray* -Ice_OutputStream_startEncapsulation(void* self) -{ - try - { - SELF->startEncapsulation(); - } - catch(const std::exception& ex) - { - return convertException(ex); - } - return 0; -} - -EXPORTED_FUNCTION mxArray* -Ice_OutputStream_startEncapsulationWithFormat(void* self, Ice_FormatType t) +Ice_OutputStream_startSize(void* self, unsigned int* pos) { - Ice::FormatType type = static_cast<Ice::FormatType>(t); try { - SELF->startEncapsulation(SELF->getEncoding(), type); + *pos = static_cast<unsigned int>(SELF->startSize()); } catch(const std::exception& ex) { @@ -766,11 +338,11 @@ Ice_OutputStream_startEncapsulationWithFormat(void* self, Ice_FormatType t) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_endEncapsulation(void* self) +Ice_OutputStream_endSize(void* self, unsigned int pos) { try { - SELF->endEncapsulation(); + SELF->endSize(pos); } catch(const std::exception& ex) { @@ -780,11 +352,11 @@ Ice_OutputStream_endEncapsulation(void* self) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_startSlice(void* self, const char* typeId, int compactId, unsigned char last) +Ice_OutputStream_pos(void* self, unsigned int* pos) { try { - SELF->startSlice(typeId, compactId, last == 1); + *pos = SELF->pos(); } catch(const std::exception& ex) { @@ -794,26 +366,19 @@ Ice_OutputStream_startSlice(void* self, const char* typeId, int compactId, unsig } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_endSlice(void* self) +Ice_OutputStream_rewriteByte(void* self, unsigned char v, unsigned int pos) { - try - { - SELF->endSlice(); - } - catch(const std::exception& ex) - { - return convertException(ex); - } + Ice::Byte* dest = &(*(SELF->b.begin() + pos)); + *dest = v; return 0; } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_writeOptional(void* self, int tag, Ice_OptionalFormat f, unsigned char* supportsOptionals) +Ice_OutputStream_rewriteInt(void* self, int v, unsigned int pos) { - Ice::OptionalFormat fmt = static_cast<Ice::OptionalFormat>(f); try { - *supportsOptionals = SELF->writeOptional(tag, fmt); + SELF->rewrite(v, pos); } catch(const std::exception& ex) { @@ -823,11 +388,12 @@ Ice_OutputStream_writeOptional(void* self, int tag, Ice_OptionalFormat f, unsign } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_startSize(void* self, unsigned int* pos) +Ice_OutputStream_writeBlob(void* self, const unsigned char* v, int size) { + const Ice::Byte* p = reinterpret_cast<const Ice::Byte*>(v); try { - *pos = static_cast<unsigned int>(SELF->startSize()); + SELF->writeBlob(p, size); } catch(const std::exception& ex) { @@ -837,15 +403,15 @@ Ice_OutputStream_startSize(void* self, unsigned int* pos) } EXPORTED_FUNCTION mxArray* -Ice_OutputStream_endSize(void* self, unsigned int pos) +Ice_OutputStream_getEncoding(void* self) { try { - SELF->endSize(pos); + return createResultValue(createEncodingVersion(SELF->getEncoding())); } catch(const std::exception& ex) { - return convertException(ex); + return createResultException(convertException(ex)); } return 0; } diff --git a/matlab/src/IceMatlab/Util.cpp b/matlab/src/IceMatlab/Util.cpp index d4c15b7255e..8414c716f2e 100644 --- a/matlab/src/IceMatlab/Util.cpp +++ b/matlab/src/IceMatlab/Util.cpp @@ -66,7 +66,7 @@ IceMatlab::createStringFromUTF8(const string& s) #else u16string utf16 = wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t>{}.from_bytes(s.data()); #endif - mwSize dims[2] = { 1, utf16.size() }; + mwSize dims[2] = { 1, static_cast<mwSize>(utf16.size()) }; mxArray* r = mxCreateCharArray(2, dims); mxChar* buf = mxGetChars(r); int i = 0; @@ -440,6 +440,7 @@ IceMatlab::convertException(const std::exception& exc) } catch(const Ice::UnsupportedEncodingException& e) { + params[idx++] = createStringFromUTF8(e.reason); params[idx++] = createEncodingVersion(e.bad); params[idx++] = createEncodingVersion(e.supported); } diff --git a/matlab/src/IceMatlab/icematlab.h b/matlab/src/IceMatlab/icematlab.h index 0b52babf28c..016efe2d633 100644 --- a/matlab/src/IceMatlab/icematlab.h +++ b/matlab/src/IceMatlab/icematlab.h @@ -26,10 +26,19 @@ typedef struct mxArray_tag mxArray; // Forward declaration to avoid importing me EXPORTED_FUNCTION mxArray* Ice_initialize(mxArray*, void*, void**); EXPORTED_FUNCTION mxArray* Ice_stringToIdentity(mxArray*); -EXPORTED_FUNCTION mxArray* Ice_identityToString(mxArray*); +EXPORTED_FUNCTION mxArray* Ice_identityToString(mxArray*, int); +EXPORTED_FUNCTION mxArray* Ice_stringVersion(); +EXPORTED_FUNCTION mxArray* Ice_intVersion(int*); +EXPORTED_FUNCTION mxArray* Ice_currentEncoding(); +EXPORTED_FUNCTION mxArray* Ice_currentProtocol(); +EXPORTED_FUNCTION mxArray* Ice_currentProtocolEncoding(); EXPORTED_FUNCTION mxArray* Ice_Communicator__release(void*); +EXPORTED_FUNCTION mxArray* Ice_Communicator_identityToString(void*, mxArray*); EXPORTED_FUNCTION mxArray* Ice_Communicator_stringToProxy(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_Communicator_propertyToProxy(void*, const char*, void**); +EXPORTED_FUNCTION mxArray* Ice_Communicator_proxyToProperty(void*, void*, const char*); +EXPORTED_FUNCTION mxArray* Ice_Communicator_proxyToString(void*, void*); EXPORTED_FUNCTION mxArray* Ice_Communicator_getProperties(void*, void**); EXPORTED_FUNCTION mxArray* Ice_Communicator_createOutputStream(void*, mxArray*, void**); EXPORTED_FUNCTION mxArray* Ice_Communicator_destroy(void*); @@ -41,12 +50,6 @@ typedef enum Idempotent } Ice_OperationMode; -typedef enum -{ - Random, - Ordered -} Ice_EndpointSelectionType; - EXPORTED_FUNCTION mxArray* Ice_ObjectPrx__release(void*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_equals(void*, void*, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_createOutputStream(void*, void**); @@ -58,7 +61,6 @@ EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invokeAsync(void*, const char*, Ice void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_invokeAsyncNC(void*, const char*, Ice_OperationMode, void*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_toString(void*); -EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getCommunicator(void*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getIdentity(void*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_identity(void*, mxArray*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getContext(void*); @@ -77,8 +79,8 @@ EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getConnectionId(void*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_connectionId(void*, const char*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isConnectionCached(void*, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_connectionCached(void*, unsigned char, void**); -EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEndpointSelection(void*, Ice_EndpointSelectionType*); -EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_endpointSelection(void*, Ice_EndpointSelectionType, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEndpointSelection(void*, int*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_endpointSelection(void*, int, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getEncodingVersion(void*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_encodingVersion(void*, mxArray*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getRouter(void*, void**); @@ -97,6 +99,8 @@ EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isBatchOneway(void*, unsigned char* EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_batchOneway(void*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isDatagram(void*, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_datagram(void*, void**); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_isBatchDatagram(void*, unsigned char*); +EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_batchDatagram(void*, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_compress(void*, unsigned char, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_timeout(void*, int, void**); EXPORTED_FUNCTION mxArray* Ice_ObjectPrx_ice_getConnection(void*, void**); @@ -128,114 +132,59 @@ EXPORTED_FUNCTION mxArray* Ice_SentFuture_state(void*); EXPORTED_FUNCTION mxArray* Ice_SentFuture_cancel(void*); EXPORTED_FUNCTION mxArray* Ice_SentFuture_check(void*); -typedef enum -{ - DefaultFormat, - CompactFormat, - SlicedFormat -} Ice_FormatType; - -typedef enum -{ - OptionalFormatF1 = 0, - OptionalFormatF2 = 1, - OptionalFormatF4 = 2, - OptionalFormatF8 = 3, - OptionalFormatSize = 4, - OptionalFormatVSize = 5, - OptionalFormatFSize = 6, - OptionalFormatClass = 7 -} Ice_OptionalFormat; - EXPORTED_FUNCTION mxArray* Ice_OutputStream__release(void*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBool(void*, unsigned char); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolOpt(void*, int, unsigned char); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolSeq(void*, const unsigned char*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBoolSeqOpt(void*, int, const unsigned char*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByte(void*, unsigned char); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteOpt(void*, int, unsigned char); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteSeq(void*, const unsigned char*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeByteSeqOpt(void*, int, const unsigned char*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShort(void*, short); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortOpt(void*, int, short); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortSeq(void*, const short*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeShortSeqOpt(void*, int, const short*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeInt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntOpt(void*, int, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntSeq(void*, const int*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeIntSeqOpt(void*, int, const int*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLong(void*, long long); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongOpt(void*, int, long long); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongSeq(void*, const long long*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeLongSeqOpt(void*, int, const long long*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloat(void*, float); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatOpt(void*, int, float); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatSeq(void*, const float*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeFloatSeqOpt(void*, int, const float*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDouble(void*, double); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleOpt(void*, int, double); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleSeq(void*, const double*, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeDoubleSeqOpt(void*, int, const double*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeString(void*, mxArray*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringOpt(void*, int, mxArray*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringSeq(void*, mxArray*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeStringSeqOpt(void*, int, mxArray*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeSize(void*, int); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeProxy(void*, void*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeProxyOpt(void*, int, void*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeEnum(void*, int, int); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeValue(void*, mxArray*, mxArray*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeValueOpt(void*, int, mxArray*, mxArray*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_startEncapsulation(void*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_startEncapsulationWithFormat(void*, Ice_FormatType); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_endEncapsulation(void*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_startSlice(void*, const char*, int, unsigned char); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_endSlice(void*); -EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeOptional(void*, int, Ice_OptionalFormat, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_startSize(void*, unsigned int*); EXPORTED_FUNCTION mxArray* Ice_OutputStream_endSize(void*, unsigned int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_pos(void*, unsigned int*); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_rewriteByte(void*, unsigned char, unsigned int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_rewriteInt(void*, int, unsigned int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_writeBlob(void*, const unsigned char*, int); +EXPORTED_FUNCTION mxArray* Ice_OutputStream_getEncoding(void*); EXPORTED_FUNCTION mxArray* Ice_InputStream__release(void*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readBool(void*, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readBoolSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readByte(void*, unsigned char*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readByteSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readShort(void*, short*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readShortSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readInt(void*, int*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readIntSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readLong(void*, long long*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readLongSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloat(void*, float*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readFloatSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readDouble(void*, double*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readDoubleSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_readString(void*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringSeq(void*); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringOpt(void*, int); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readStringSeqOpt(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_skip(void*, int); EXPORTED_FUNCTION mxArray* Ice_InputStream_skipSize(void*); EXPORTED_FUNCTION mxArray* Ice_InputStream_getEncoding(void*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readSize(void*, int*); EXPORTED_FUNCTION mxArray* Ice_InputStream_readProxy(void*, void**); -EXPORTED_FUNCTION mxArray* Ice_InputStream_readProxyOpt(void*, int, void**); EXPORTED_FUNCTION mxArray* Ice_InputStream_readEnum(void*, int, int*); EXPORTED_FUNCTION mxArray* Ice_InputStream_pos(void*, unsigned int*); +EXPORTED_FUNCTION mxArray* Ice_InputStream_setPos(void*, unsigned int); EXPORTED_FUNCTION mxArray* Ice_InputStream_size(void*, unsigned int*); EXPORTED_FUNCTION mxArray* Ice_InputStream_getBytes(void*, unsigned int, unsigned int); diff --git a/matlab/test/Ice/objects/AllTests.m b/matlab/test/Ice/objects/AllTests.m new file mode 100644 index 00000000000..67ab0a6239e --- /dev/null +++ b/matlab/test/Ice/objects/AllTests.m @@ -0,0 +1,219 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef AllTests + methods(Static) + function r = allTests(app) + communicator = app.communicator(); + ref = ['initial:', app.getTestEndpoint(0, '')]; + base = communicator.stringToProxy(ref); + initial = Test.InitialPrx.checkedCast(base); + + fprintf('getting B1... '); + b1 = initial.getB1(); + assert(~isempty(b1)); + fprintf('ok\n'); + + fprintf('getting B2... '); + b2 = initial.getB2(); + assert(~isempty(b2)); + fprintf('ok\n'); + + fprintf('getting C... '); + c = initial.getC(); + assert(~isempty(c)); + fprintf('ok\n'); + + fprintf('getting D... '); + d = initial.getD(); + assert(~isempty(d)); + fprintf('ok\n'); + + fprintf('checking consistency... '); + assert(b1 ~= b2); + assert(b1.theB == b1); + assert(isempty(b1.theC)); + assert(isa(b1.theA, 'Test.B')); + assert(b1.theA.theA == b1.theA); + assert(b1.theA.theB == b1); + assert(isa(b1.theA.theC, 'Test.C')); + assert(b1.theA.theC.theB == b1.theA); + assert(b1.preMarshalInvoked); + assert(b1.postUnmarshalInvoked); + assert(b1.theA.preMarshalInvoked); + assert(b1.theA.postUnmarshalInvoked); + assert(b1.theA.theC.preMarshalInvoked); + assert(b1.theA.theC.postUnmarshalInvoked); + + % More tests possible for b2 and d, but I think this is already sufficient. + assert(b2.theA == b2); + assert(isempty(d.theC)); + fprintf('ok\n'); + + fprintf('getting B1, B2, C, and D all at once... '); + [b1, b2, c, d] = initial.getAll(); + assert(~isempty(b1)); + assert(~isempty(b2)); + assert(~isempty(c)); + assert(~isempty(d)); + fprintf('ok\n'); + + fprintf('checking consistency... '); + assert(b1 ~= b2); + assert(b1.theA == b2); + assert(b1.theB == b1); + assert(isempty(b1.theC)); + assert(b2.theA == b2); + assert(b2.theB == b1); + assert(b2.theC == c); + assert(c.theB == b2); + assert(d.theA == b1); + assert(d.theB == b2); + assert(isempty(d.theC)); + assert(d.preMarshalInvoked); + assert(d.postUnmarshalInvoked); + assert(d.theA.preMarshalInvoked); + assert(d.theA.postUnmarshalInvoked); + assert(d.theB.preMarshalInvoked); + assert(d.theB.postUnmarshalInvoked); + assert(d.theB.theC.preMarshalInvoked); + assert(d.theB.theC.postUnmarshalInvoked); + fprintf('ok\n'); + + fprintf('testing protected members... '); + e = initial.getE(); + assert(e.checkValues()); + em = ?Test.E; + assert(strcmp(em.PropertyList(1).GetAccess, 'protected')); + assert(strcmp(em.PropertyList(2).GetAccess, 'protected')); + f = initial.getF(); + assert(f.checkValues()); + assert(f.e2.checkValues()); + fm = ?Test.F; + assert(strcmp(fm.PropertyList(1).GetAccess, 'public')); + assert(strcmp(fm.PropertyList(2).GetAccess, 'protected')); + fprintf('ok\n'); + + fprintf('getting I, J and H... '); + i = initial.getI(); + assert(~isempty(i) && strcmp(i.ice_id(), Test.IPrx.ice_staticId())); + j = initial.getJ(); + assert(~isempty(j) && strcmp(j.ice_id(), Test.JPrx.ice_staticId())); + h = initial.getH(); + assert(~isempty(h) && isa(h, 'Test.H')); + fprintf('ok\n'); + + fprintf('getting D1... '); + d1 = Test.D1(Test.A1('a1'), Test.A1('a2'), Test.A1('a3'), Test.A1('a4')); + d1 = initial.getD1(d1); + assert(strcmp(d1.a1.name, 'a1')); + assert(strcmp(d1.a2.name, 'a2')); + assert(strcmp(d1.a3.name, 'a3')); + assert(strcmp(d1.a4.name, 'a4')); + fprintf('ok\n'); + + fprintf('throw EDerived... '); + try + initial.throwEDerived(); + assert(false); + catch ederived + assert(isa(ederived, 'Test.EDerived')); + assert(strcmp(ederived.a1.name, 'a1')); + assert(strcmp(ederived.a2.name, 'a2')); + assert(strcmp(ederived.a3.name, 'a3')); + assert(strcmp(ederived.a4.name, 'a4')); + end + fprintf('ok\n'); + + fprintf('setting I... '); + initial.setI(i); + initial.setI(j); + initial.setI(h); + fprintf('ok\n'); + + fprintf('testing sequences... '); + try + inS = Test.BaseSeq.new(); + [r, outS] = initial.opBaseSeq(inS); + assert(length(r) == 0 && length(outS) == 0); + + inS = Test.BaseSeq.new(); + inS(1) = Test.Base(Test.S(), ''); + [r, outS] = initial.opBaseSeq(inS); + assert(length(r) == 1 && length(outS) == 1); + catch ex + if ~isa(ex, 'Ice.OperationNotExistException') + rethrow(ex); + end + end + fprintf('ok\n'); + + fprintf('testing recursive type... '); + top = Test.Recursive(); + p = top; + depth = 0; + try + for depth = 0:20000 + p.v = Test.Recursive(); + p = p.v; + if (depth < 10 && mod(depth, 10) == 0) || ... + (depth < 1000 && mod(depth, 100) == 0) || ... + (depth < 10000 && mod(depth, 1000) == 0) || ... + mod(depth, 10000) == 0 + initial.setRecursive(top); + end + end + assert(~initial.supportsClassGraphDepthMax()); + catch ex + if isa(ex, 'Ice.UnknownLocalException') + % Expected marshal exception from the server (max class graph depth reached) + elseif isa(ex, 'Ice.UnknownException') + % Expected stack overflow from the server (Java only) + else + rethrow(ex); + end + end + initial.setRecursive(Test.Recursive()); + fprintf('ok\n'); + + fprintf('testing compact ID... '); + try + assert(~isempty(initial.getCompact())); + catch ex + if ~isa(ex, 'Ice.OperationNotExistException') + rethrow(ex); + end + end + fprintf('ok\n'); + + fprintf('testing UnexpectedObjectException... '); + ref = ['uoet:', app.getTestEndpoint(0, '')]; + base = communicator.stringToProxy(ref); + assert(~isempty(base)); + uoet = Test.UnexpectedObjectExceptionTestPrx.uncheckedCast(base); + assert(~isempty(uoet)); + try + uoet.op(); + assert(false); + catch ex + if isa(ex, 'Ice.UnexpectedObjectException') + assert(strcmp(ex.type_, 'Test.AlsoEmpty')); + assert(strcmp(ex.expectedType, 'Test.Empty')); + else + rethrow(ex); + end + end + fprintf('ok\n'); + + r = initial; + end + end +end diff --git a/matlab/test/Ice/objects/Application.m b/matlab/test/Ice/objects/Application.m new file mode 100644 index 00000000000..003eea46ea4 --- /dev/null +++ b/matlab/test/Ice/objects/Application.m @@ -0,0 +1,157 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Application < handle + methods(Sealed) + % + % main() initializes the Communicator, calls run(), and destroys + % the Communicator upon return from run(). It thereby handles + % all exceptions properly, i.e., error messages are printed + % if exceptions propagate to main(), and the Communicator is + % always destroyed, regardless of exceptions. + % + function r = main(obj, appName, varargin) + if ~isempty(obj.communicator_) + printf('%s: only one instance of the Application class can be used', appName); + r = 1; + return; + end + + obj.testName_ = appName; + + args = {}; + initializationData = []; + + if length(varargin) >= 1 + args = varargin{1}; + end + if length(varargin) >= 2 + initializationData = varargin{2}; + end + + % + % We parse the properties here to extract Ice.ProgramName. + % + if isempty(initializationData) + [initializationData, args] = obj.getInitData(args); + end + + if ~isempty(initializationData) + initData = initializationData.clone(); + else + initData = Ice.InitializationData(); + end + + [initData.properties_, args] = Ice.createProperties(args, initData.properties_); + + %TBD + % If the process logger is the default logger, we replace it with a + % a logger that uses the program name as the prefix. + % + %if(Util.getProcessLogger() instanceof LoggerI) + %{ + % Util.setProcessLogger(new LoggerI(initData.properties_.getProperty('Ice.ProgramName'), '')); + %} + + status = 0; + + try + [communicator, args] = Ice.initialize(args, initData); + obj.communicator_ = communicator; + + status = obj.run(args); + catch ex + fprintf('%s: caught %s', obj.testName_, ex.identifier); + disp(getReport(ex, 'extended')); + status = 1; + end + obj.communicator_.destroy(); + obj.communicator_ = []; + + r = status; + end + function r = initialize(obj, varargin) + assert(length(varargin) <= 1); + if length(varargin) == 0 + r = Ice.initialize(); + else + r = Ice.initialize(varargin{1}); + end + end + function setLogger(obj, logger) + obj.logger_ = logger; + end + function r = appName(obj) + r = obj.testName_; + end + function r = communicator(obj) + r = obj.communicator_; + end + function r = createInitializationData(obj) + initData = Ice.InitializationData(); + initData.logger = obj.logger_; + r = initData; + end + function r = getTestEndpoint(obj, num, prot) + r = Application.getTestEndpointWithProperties(obj.communicator_.getProperties(), num, prot); + end + function r = getTestHost(obj) + r = Application.getTestHostWithProperties(obj.communicator_.getProperties()); + end + function r = getTestProtocol(obj) + r = Application.getTestProtocolWithProperties(obj.communicator_.getProperties()); + end + function r = getTestPort(obj, num) + r = Application.getTestPortWithProperties(obj.communicator_.getProperties(), num); + end + end + methods(Static) + function r = getTestEndpointWithProperties(props, num, prot) + protocol = prot; + if length(protocol) == 0 + protocol = props.getPropertyWithDefault('Ice.Default.Protocol', 'default'); + end + + basePort = props.getPropertyAsIntWithDefault('Test.BasePort', 12010); + + r = sprintf('%s -p %d', protocol, basePort + num); + end + function r = getTestHostWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Host', '127.0.0.1'); + end + function r = getTestProtocolWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Protocol', 'tcp'); + end + function r = getTestPortWithProperties(props, num) + r = props.getPropertyAsIntWithDefault('Test.BasePort', 12010) + num; + end + end + methods(Abstract) + r = run(obj, args) + end + methods(Access=protected) + % + % Hook to override the initialization data. This hook is + % necessary because some properties must be set prior to + % communicator initialization. + % + function [initData, remArgs] = getInitData(obj, args) + initData = obj.createInitializationData(); + [initData.properties_, remArgs] = Ice.createProperties(args); + remArgs = initData.properties_.parseCommandLineOptions('Test', remArgs); + end + end + properties(Access=private) + testName_ + communicator_ + logger_ + end +end diff --git a/matlab/test/Ice/objects/BI.m b/matlab/test/Ice/objects/BI.m new file mode 100644 index 00000000000..c14d0ee20ae --- /dev/null +++ b/matlab/test/Ice/objects/BI.m @@ -0,0 +1,22 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef BI < Test.B + methods + function ice_preMarshal(obj) + obj.preMarshalInvoked = true; + end + + function ice_postUnmarshal(obj) + obj.postUnmarshalInvoked = true; + end + end +end diff --git a/matlab/test/Ice/objects/CI.m b/matlab/test/Ice/objects/CI.m new file mode 100644 index 00000000000..db350dc1975 --- /dev/null +++ b/matlab/test/Ice/objects/CI.m @@ -0,0 +1,22 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef CI < Test.C + methods + function ice_preMarshal(obj) + obj.preMarshalInvoked = true; + end + + function ice_postUnmarshal(obj) + obj.postUnmarshalInvoked = true; + end + end +end diff --git a/matlab/test/Ice/objects/Client.m b/matlab/test/Ice/objects/Client.m new file mode 100644 index 00000000000..4f48f36ee60 --- /dev/null +++ b/matlab/test/Ice/objects/Client.m @@ -0,0 +1,41 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Client < Application + methods + function r = run(obj, args) + communicator = obj.communicator(); + vfm = communicator.getValueFactoryManager(); + vfm.add(@(id) BI(), Test.B.ice_staticId()); + vfm.add(@(id) CI(), Test.C.ice_staticId()); + vfm.add(@(id) DI(), Test.D.ice_staticId()); + vfm.add(@(id) EI(), Test.E.ice_staticId()); + vfm.add(@(id) FI(), Test.F.ice_staticId()); + vfm.add(@(id) II(), Test.IPrx.ice_staticId()); + vfm.add(@(id) JI(), Test.JPrx.ice_staticId()); + vfm.add(@(id) HI(), Test.H.ice_staticId()); + + initial = AllTests.allTests(obj); + initial.shutdown(); + r = 0; + end + end + methods(Static) + function start(args) + addpath('generated'); + if ~libisloaded('icematlab') + loadlibrary('icematlab') + end + c = Client(); + status = c.main('Client', args); + end + end +end diff --git a/matlab/test/Ice/objects/DI.m b/matlab/test/Ice/objects/DI.m new file mode 100644 index 00000000000..ecbde0552fa --- /dev/null +++ b/matlab/test/Ice/objects/DI.m @@ -0,0 +1,22 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef DI < Test.D + methods + function ice_preMarshal(obj) + obj.preMarshalInvoked = true; + end + + function ice_postUnmarshal(obj) + obj.postUnmarshalInvoked = true; + end + end +end diff --git a/matlab/test/Ice/objects/EI.m b/matlab/test/Ice/objects/EI.m new file mode 100644 index 00000000000..efb0ee9ea65 --- /dev/null +++ b/matlab/test/Ice/objects/EI.m @@ -0,0 +1,22 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef EI < Test.E + methods + function obj = EI() + obj = obj@Test.E(1, 'hello'); + end + + function r = checkValues(obj) + r = obj.i == 1 && strcmp(obj.s, 'hello'); + end + end +end diff --git a/matlab/test/Ice/objects/FI.m b/matlab/test/Ice/objects/FI.m new file mode 100644 index 00000000000..9facec621a6 --- /dev/null +++ b/matlab/test/Ice/objects/FI.m @@ -0,0 +1,25 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef FI < Test.F + methods + function obj = FI(e) + if nargin == 0 + e = []; + end + obj = obj@Test.F(e, e); + end + + function r = checkValues(obj) + r = ~isempty(obj.e1) && obj.e1 == obj.e2; + end + end +end diff --git a/matlab/test/Ice/objects/HI.m b/matlab/test/Ice/objects/HI.m new file mode 100644 index 00000000000..8dd4757d07d --- /dev/null +++ b/matlab/test/Ice/objects/HI.m @@ -0,0 +1,13 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef HI < Test.H +end diff --git a/matlab/test/Ice/objects/II.m b/matlab/test/Ice/objects/II.m new file mode 100644 index 00000000000..3296eae0608 --- /dev/null +++ b/matlab/test/Ice/objects/II.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef II < Ice.InterfaceByValue + methods + function obj = II() + obj = obj@Ice.InterfaceByValue(Test.IPrx.ice_staticId()); + end + end +end diff --git a/matlab/test/Ice/objects/JI.m b/matlab/test/Ice/objects/JI.m new file mode 100644 index 00000000000..dbc90556cca --- /dev/null +++ b/matlab/test/Ice/objects/JI.m @@ -0,0 +1,18 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef JI < Ice.InterfaceByValue + methods + function obj = JI() + obj = obj@Ice.InterfaceByValue(Test.JPrx.ice_staticId()); + end + end +end diff --git a/matlab/test/Ice/objects/Test.ice b/matlab/test/Ice/objects/Test.ice new file mode 100644 index 00000000000..8526225deb6 --- /dev/null +++ b/matlab/test/Ice/objects/Test.ice @@ -0,0 +1,261 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +[["suppress-warning:deprecated"]] // For classes with operations + +module Test +{ + +struct S +{ + string str; +} + +class Base +{ + S theS; + string str; +} + +class AbstractBase extends Base +{ + void op(); +} + +class B; +class C; + +class A +{ + B theB; + C theC; + + bool preMarshalInvoked; + bool postUnmarshalInvoked; +} + +class B extends A +{ + A theA; +} + +class C +{ + B theB; + + bool preMarshalInvoked; + bool postUnmarshalInvoked; +} + +class D +{ + A theA; + B theB; + C theC; + + bool preMarshalInvoked; + bool postUnmarshalInvoked; +} + +["protected"] class E +{ + int i; + string s; +} + +class F +{ + ["protected"] E e1; + E e2; +} + +interface I +{ +} + +interface J extends I +{ +} + +class H implements I +{ +} + +sequence<Base> BaseSeq; + +class CompactExt; + +class Compact(1) +{ +} + +const int CompactExtId = 789; + +class CompactExt(CompactExtId) extends Compact +{ +} + +module Inner +{ + +class A +{ + ::Test::A theA; +} + +exception Ex +{ + string reason; +} + +module Sub +{ + +class A +{ + ::Test::Inner::A theA; +} + +exception Ex +{ + string reason; +} + +} + +} + +class A1 +{ + string name; +} + +class B1 +{ + A1 a1; + A1 a2; +} + +class D1 extends B1 +{ + A1 a3; + A1 a4; +} + +exception EBase +{ + A1 a1; + A1 a2; +} + +exception EDerived extends EBase +{ + A1 a3; + A1 a4; +} + +class Recursive +{ + Recursive v; +} + +interface Initial +{ + void shutdown(); + B getB1(); + B getB2(); + C getC(); + D getD(); + E getE(); + F getF(); + + void setRecursive(Recursive p); + bool supportsClassGraphDepthMax(); + + ["marshaled-result"] B getMB(); + ["amd", "marshaled-result"] B getAMDMB(); + + void getAll(out B b1, out B b2, out C theC, out D theD); + + I getI(); + I getJ(); + I getH(); + + D1 getD1(D1 d1); + void throwEDerived() throws EDerived; + + void setI(I theI); + + BaseSeq opBaseSeq(BaseSeq inSeq, out BaseSeq outSeq); + + Compact getCompact(); + + Inner::A getInnerA(); + Inner::Sub::A getInnerSubA(); + + void throwInnerEx() throws Inner::Ex; + void throwInnerSubEx() throws Inner::Sub::Ex; +} + +class Empty +{ +} + +class AlsoEmpty +{ +} + +interface UnexpectedObjectExceptionTest +{ + Empty op(); +} + +// +// Remaining definitions are here to ensure that the generated code compiles. +// + +class COneMember +{ + Empty e; +} + +class CTwoMembers +{ + Empty e1; + Empty e2; +} + +exception EOneMember +{ + Empty e; +} + +exception ETwoMembers +{ + Empty e1; + Empty e2; +} + +struct SOneMember +{ + Empty e; +} + +struct STwoMembers +{ + Empty e1; + Empty e2; +} + +dictionary<int, COneMember> DOneMember; +dictionary<int, CTwoMembers> DTwoMembers; + +} diff --git a/matlab/test/Ice/objects/generated/.gitignore b/matlab/test/Ice/objects/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/matlab/test/Ice/objects/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/matlab/test/Ice/optional/AllTests.m b/matlab/test/Ice/optional/AllTests.m new file mode 100644 index 00000000000..7342cf707e0 --- /dev/null +++ b/matlab/test/Ice/optional/AllTests.m @@ -0,0 +1,840 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef AllTests + methods(Static) + function r = allTests(app) + communicator = app.communicator(); + + ref = ['initial:', app.getTestEndpoint(0, '')]; + base = communicator.stringToProxy(ref); + initial = Test.InitialPrx.checkedCast(base); + + fprintf('testing optional data members... '); + + oo1 = Test.OneOptional(); + assert(oo1.a == Ice.Unset); + oo1.a = 15; + + oo2 = Test.OneOptional(16); + assert(oo2.a == 16); + + mo1 = Test.MultiOptional(); + assert(mo1.a == Ice.Unset); + assert(mo1.b == Ice.Unset); + assert(mo1.c == Ice.Unset); + assert(mo1.d == Ice.Unset); + assert(mo1.e == Ice.Unset); + assert(mo1.f == Ice.Unset); + assert(mo1.g == Ice.Unset); + assert(mo1.h == Ice.Unset); + assert(mo1.i == Ice.Unset); + assert(mo1.j == Ice.Unset); + assert(mo1.k == Ice.Unset); + assert(mo1.bs == Ice.Unset); + assert(mo1.ss == Ice.Unset); + assert(mo1.iid == Ice.Unset); + assert(mo1.sid == Ice.Unset); + assert(mo1.fs == Ice.Unset); + assert(mo1.vs == Ice.Unset); + + assert(mo1.shs == Ice.Unset); + assert(mo1.es == Ice.Unset); + assert(mo1.fss == Ice.Unset); + assert(mo1.vss == Ice.Unset); + assert(mo1.oos == Ice.Unset); + assert(mo1.oops == Ice.Unset); + + assert(mo1.ied == Ice.Unset); + assert(mo1.ifsd == Ice.Unset); + assert(mo1.ivsd == Ice.Unset); + assert(mo1.iood == Ice.Unset); + assert(mo1.ioopd == Ice.Unset); + + assert(mo1.bos == Ice.Unset); + + ss = Test.SmallStruct(); + fs = Test.FixedStruct(78); + vs = Test.VarStruct('hello'); + iid = Test.IntIntDict.new(); + iid(4) = 3; + sid = Test.StringIntDict.new(); + sid('test') = 10; + ied = Test.IntEnumDict.new(); + ied(4) = Test.MyEnum.MyEnumMember; + oos = Test.OneOptionalSeq.new(); + oos(1) = oo1; + ifsd = Test.IntFixedStructDict.new(); + ifsd(4) = fs; + ivsd = Test.IntVarStructDict.new(); + ivsd(5) = vs; + iood = Test.IntOneOptionalDict.new(); + iood(5) = Test.OneOptional(15); + ioopd = Test.IntOneOptionalPrxDict.new(); + ioopd(5) = communicator.stringToProxy('test'); + mo1 = Test.MultiOptional(15, true, 19, 78, 99, 5.5, 1.0, 'test', Test.MyEnum.MyEnumMember, ... + communicator.stringToProxy('test'), ... + [], [5], {'test', 'test2'}, iid, sid, fs, vs, [1], ... + {Test.MyEnum.MyEnumMember, Test.MyEnum.MyEnumMember}, ... + { fs }, { vs }, oos, { communicator.stringToProxy('test') }, ... + ied, ifsd, ivsd, iood, ioopd, [false, true, false], []); + + assert(mo1.a == 15); + assert(mo1.b == true); + assert(mo1.c == 19); + assert(mo1.d == 78); + assert(mo1.e == 99); + assert(mo1.f == 5.5); + assert(mo1.g == 1.0); + assert(strcmp(mo1.h, 'test')); + assert(mo1.i == Test.MyEnum.MyEnumMember); + assert(mo1.j == communicator.stringToProxy('test')); + assert(isempty(mo1.k)); + assert(mo1.bs == [5]) + assert(isequal(mo1.ss, {'test', 'test2'})); + assert(mo1.iid(4) == 3); + assert(mo1.sid('test') == 10); + assert(isequal(mo1.fs, Test.FixedStruct(78))); + assert(isequal(mo1.vs, Test.VarStruct('hello'))); + + assert(mo1.shs(1) == 1); + assert(mo1.es{1} == Test.MyEnum.MyEnumMember && mo1.es{2} == Test.MyEnum.MyEnumMember); + assert(isequal(mo1.fss{1}, Test.FixedStruct(78))); + assert(isequal(mo1.vss{1}, Test.VarStruct('hello'))); + assert(isequal(mo1.oos(1), oo1)); + assert(mo1.oops{1} == communicator.stringToProxy('test')); + + assert(mo1.ied(4) == Test.MyEnum.MyEnumMember); + assert(isequal(mo1.ifsd(4), Test.FixedStruct(78))); + assert(isequal(mo1.ivsd(5), Test.VarStruct('hello'))); + assert(mo1.iood(5).a == 15); + assert(mo1.ioopd(5) == communicator.stringToProxy('test')); + + assert(isequal(mo1.bos, [false, true, false])); + + % + % Test generated struct and classes compare with Ice.Unset + % + assert(ss ~= Ice.Unset); + assert(fs ~= Ice.Unset); + assert(vs ~= Ice.Unset); + assert(mo1 ~= Ice.Unset); + + fprintf('ok\n'); + + fprintf('testing marshaling... '); + + oo4 = initial.pingPong(Test.OneOptional()); + assert(oo4.a == Ice.Unset); + + oo5 = initial.pingPong(oo1); + assert(oo1.a == oo5.a); + + mo4 = initial.pingPong(Test.MultiOptional()); + assert(mo4.a == Ice.Unset); + assert(mo4.b == Ice.Unset); + assert(mo4.c == Ice.Unset); + assert(mo4.d == Ice.Unset); + assert(mo4.e == Ice.Unset); + assert(mo4.f == Ice.Unset); + assert(mo4.g == Ice.Unset); + assert(mo4.h == Ice.Unset); + assert(mo4.i == Ice.Unset); + assert(mo4.j == Ice.Unset); + assert(mo4.k == Ice.Unset); + assert(mo4.bs == Ice.Unset); + assert(mo4.ss == Ice.Unset); + assert(mo4.iid == Ice.Unset); + assert(mo4.sid == Ice.Unset); + assert(mo4.fs == Ice.Unset); + assert(mo4.vs == Ice.Unset); + + assert(mo4.shs == Ice.Unset); + assert(mo4.es == Ice.Unset); + assert(mo4.fss == Ice.Unset); + assert(mo4.vss == Ice.Unset); + assert(mo4.oos == Ice.Unset); + assert(mo4.oops == Ice.Unset); + + assert(mo4.ied == Ice.Unset); + assert(mo4.ifsd == Ice.Unset); + assert(mo4.ivsd == Ice.Unset); + assert(mo4.iood == Ice.Unset); + assert(mo4.ioopd == Ice.Unset); + + assert(mo4.bos == Ice.Unset); + + mo5 = initial.pingPong(mo1); + assert(mo5.a == mo1.a); + assert(mo5.b == mo1.b); + assert(mo5.c == mo1.c); + assert(mo5.d == mo1.d); + assert(mo5.e == mo1.e); + assert(mo5.f == mo1.f); + assert(mo5.g == mo1.g); + assert(strcmp(mo5.h, mo1.h)); + assert(mo5.i == mo1.i); + assert(mo5.j == mo1.j); + assert(isempty(mo5.k)); + assert(mo5.bs(1) == 5); + assert(isequal(mo5.ss, mo1.ss)); + assert(mo5.iid(4) == 3); + assert(mo5.sid('test') == 10); + assert(mo5.fs == mo1.fs); + assert(mo5.vs == mo1.vs); + assert(isequal(mo5.shs, mo1.shs)); + assert(mo5.es{1} == Test.MyEnum.MyEnumMember && mo1.es{2} == Test.MyEnum.MyEnumMember); + assert(mo5.fss{1} == Test.FixedStruct(78)); + assert(mo5.vss{1} == Test.VarStruct('hello')); + assert(mo5.oos(1).a == 15); + assert(mo5.oops{1} == communicator.stringToProxy('test')); + + assert(mo5.ied(4) == Test.MyEnum.MyEnumMember); + assert(mo5.ifsd(4) == Test.FixedStruct(78)); + assert(mo5.ivsd(5) == Test.VarStruct('hello')); + assert(mo5.iood(5).a == 15); + assert(mo5.ioopd(5) == communicator.stringToProxy('test')); + + assert(isequal(mo5.bos, mo1.bos)); + + % Clear the first half of the optional members + mo6 = Test.MultiOptional(); + mo6.b = mo5.b; + mo6.d = mo5.d; + mo6.f = mo5.f; + mo6.h = mo5.h; + mo6.j = mo5.j; + mo6.bs = mo5.bs; + mo6.iid = mo5.iid; + mo6.fs = mo5.fs; + mo6.shs = mo5.shs; + mo6.fss = mo5.fss; + mo6.oos = mo5.oos; + mo6.ifsd = mo5.ifsd; + mo6.iood = mo5.iood; + mo6.bos = mo5.bos; + + mo7 = initial.pingPong(mo6); + assert(mo7.a == Ice.Unset); + assert(mo7.b == mo1.b); + assert(mo7.c == Ice.Unset); + assert(mo7.d == mo1.d); + assert(mo7.e == Ice.Unset); + assert(mo7.f == mo1.f); + assert(mo7.g == Ice.Unset); + assert(strcmp(mo7.h, mo1.h)); + assert(mo7.i == Ice.Unset); + assert(mo7.j == mo1.j); + assert(mo7.k == Ice.Unset); + assert(mo7.bs(1) == 5); + assert(mo7.ss == Ice.Unset); + assert(mo7.iid(4) == 3); + assert(mo7.sid == Ice.Unset); + assert(mo7.fs == mo1.fs); + assert(mo7.vs == Ice.Unset); + + assert(isequal(mo7.shs, mo1.shs)); + assert(mo7.es == Ice.Unset); + assert(mo7.fss{1} == Test.FixedStruct(78)); + assert(mo7.vss == Ice.Unset); + assert(mo7.oos(1).a == 15); + assert(mo7.oops == Ice.Unset); + + assert(mo7.ied == Ice.Unset); + assert(mo7.ifsd(4) == Test.FixedStruct(78)); + assert(mo7.ivsd == Ice.Unset); + assert(mo7.iood(5).a == 15); + assert(mo7.ioopd == Ice.Unset); + + assert(isequal(mo7.bos, [false, true, false])); + + % Clear the second half of the optional members + mo8 = Test.MultiOptional(); + mo8.a = mo5.a; + mo8.c = mo5.c; + mo8.e = mo5.e; + mo8.g = mo5.g; + mo8.i = mo5.i; + mo8.k = mo8; + mo8.ss = mo5.ss; + mo8.sid = mo5.sid; + mo8.vs = mo5.vs; + + mo8.es = mo5.es; + mo8.vss = mo5.vss; + mo8.oops = mo5.oops; + + mo8.ied = mo5.ied; + mo8.ivsd = mo5.ivsd; + mo8.ioopd = mo5.ioopd; + + mo9 = initial.pingPong(mo8); + assert(mo9.a == mo1.a); + assert(mo9.b == Ice.Unset); + assert(mo9.c == mo1.c); + assert(mo9.d == Ice.Unset); + assert(mo9.e == mo1.e); + assert(mo9.f == Ice.Unset); + assert(mo9.g == mo1.g); + assert(mo9.h == Ice.Unset); + assert(mo9.i == mo1.i); + assert(mo9.j == Ice.Unset); + assert(mo9.k == mo9); + assert(mo9.bs == Ice.Unset); + assert(isequal(mo9.ss, mo1.ss)); + assert(mo9.iid == Ice.Unset); + assert(mo9.sid('test') == 10); + assert(mo9.fs == Ice.Unset); + assert(mo9.vs == mo1.vs); + + assert(mo9.shs == Ice.Unset); + assert(mo9.es{1} == Test.MyEnum.MyEnumMember && mo1.es{2} == Test.MyEnum.MyEnumMember); + assert(mo9.fss == Ice.Unset); + assert(mo9.vss{1} == Test.VarStruct('hello')); + assert(mo9.oos == Ice.Unset); + assert(mo9.oops{1} == communicator.stringToProxy('test')); + + assert(mo9.ied(4) == Test.MyEnum.MyEnumMember); + assert(mo9.ifsd == Ice.Unset); + assert(mo9.ivsd(5) == Test.VarStruct('hello')); + assert(mo9.iood == Ice.Unset); + assert(mo9.ioopd(5) == communicator.stringToProxy('test')); + + assert(mo9.bos == Ice.Unset); + + % + % Use the 1.0 encoding with operations whose only class parameters are optional. + % + initial.sendOptionalClass(true, Test.OneOptional(53)); + initial.ice_encodingVersion(Ice.EncodingVersion(1, 0)).sendOptionalClass(true, Test.OneOptional(53)); + + r = initial.returnOptionalClass(true); + assert(r ~= Ice.Unset) + r = initial.ice_encodingVersion(Ice.EncodingVersion(1, 0)).returnOptionalClass(true); + assert(r == Ice.Unset); + + recursive1 = Test.RecursiveSeq.new(); + recursive2 = Test.RecursiveSeq.new(); + r1 = Test.Recursive(); + r2 = Test.Recursive(); + r1.value = recursive2; + recursive1(1) = r1; + recursive2(1) = r2; + + outer = Test.Recursive(); + outer.value = recursive1; + initial.pingPong(outer); + + g = Test.G(); + g.gg1Opt = Test.G1('gg1Opt'); + g.gg2 = Test.G2(10); + g.gg2Opt = Test.G2(20); + g.gg1 = Test.G1('gg1'); + r = initial.opG(g); + assert(strcmp(r.gg1Opt.a, 'gg1Opt')); + assert(r.gg2.a == 10); + assert(r.gg2Opt.a == 20); + assert(strcmp(r.gg1.a, 'gg1')); + + initial2 = Test.Initial2Prx.uncheckedCast(base); + initial2.opVoid(15, 'test'); + + fprintf('ok\n'); + + fprintf('testing marshaling of large containers with fixed size elements... '); + + mc = Test.MultiOptional(); + + mc.bs = uint8(zeros(1, 1000)); + mc.shs = int16(zeros(1, 300)); + + mc.fss = cell(1, 300); + for i = 1:300 + mc.fss{i} = Test.FixedStruct(); + end + + mc.ifsd = Test.IntFixedStructDict.new(); + for i = 1:300 + mc.ifsd(i) = Test.FixedStruct(); + end + + mc = initial.pingPong(mc); + assert(length(mc.bs) == 1000); + assert(length(mc.shs) == 300); + assert(length(mc.fss) == 300); + assert(length(mc.ifsd) == 300); + + fprintf('ok\n'); + + fprintf('testing tag marshaling... '); + + b = Test.B(); + b2 = initial.pingPong(b); + assert(b2.ma == Ice.Unset); + assert(b2.mb == Ice.Unset); + assert(b2.mc == Ice.Unset); + + b.ma = 10; + b.mb = 11; + b.mc = 12; + b.md = 13; + + b2 = initial.pingPong(b); + assert(b2.ma == 10); + assert(b2.mb == 11); + assert(b2.mc == 12); + assert(b2.md == 13); + + fprintf('ok\n'); + + fprintf('testing marshalling of objects with optional objects... '); + + f = Test.F(); + + f.af = Test.A(); + f.ae = f.af; + + rf = initial.pingPong(f); + assert(rf.ae == rf.af); + + fprintf('ok\n'); + + fprintf('testing optional with default values... '); + + wd = initial.pingPong(Test.WD()); + assert(wd.a == 5); + assert(strcmp(wd.s, 'test')); + wd.a = Ice.Unset; + wd.s = Ice.Unset; + wd = initial.pingPong(wd); + assert(wd.a == Ice.Unset); + assert(wd.s == Ice.Unset); + + fprintf('ok\n'); + + if communicator.getProperties().getPropertyAsInt('Ice.Default.SlicedFormat') > 0 + fprintf('testing marshaling with unknown class slices... '); + + c = Test.C(); + c.ss = 'test'; + c.ms = 'testms'; + c = initial.pingPong(c); + test(c.ma == Ice.Unset); + test(c.mb == Ice.Unset); + test(c.mc == Ice.Unset); + test(c.md == Ice.Unset); + test(strcmp(c.ss, 'test')); + test(strcmp(c.ms, 'testms')); + + fprintf('ok\n'); + + fprintf('testing optionals with unknown classes... '); + + initial2 = Test.Initial2Prx.uncheckedCast(base); + d = Test.D(); + d.ds = 'test'; + d.seq = {'test1', 'test2', 'test3', 'test4'}; + d.ao = Test.A(18); + d.requiredB = 14; + d.requiredA = 14; + initial2.opClassAndUnknownOptional(Test.A(), d); + + fprintf('ok\n'); + end + + fprintf('testing optional parameters... '); + + [p2, p3] = initial.opByte(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opByte(56); + assert(p2 == 56 && p3 == 56); + f = initial.opByteAsync(56); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 56 && p3 == 56); + + [p2, p3] = initial.opBool(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opBool(true); + assert(p2 == true && p3 == true); + f = initial.opBoolAsync(true); + [p2, p3] = f.fetchOutputs(); + assert(p2 == true && p3 == true); + + [p2, p3] = initial.opShort(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opShort(56); + assert(p2 == 56 && p3 == 56); + f = initial.opShortAsync(56); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 56 && p3 == 56); + + [p2, p3] = initial.opInt(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opInt(56); + assert(p2 == 56 && p3 == 56); + f = initial.opIntAsync(56); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 56 && p3 == 56); + + [p2, p3] = initial.opLong(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opLong(56); + assert(p2 == 56 && p3 == 56); + f = initial.opLongAsync(56); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 56 && p3 == 56); + + [p2, p3] = initial.opFloat(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opFloat(1.0); + assert(p2 == 1.0 && p3 == 1.0); + f = initial.opFloatAsync(1.0); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 1.0 && p3 == 1.0); + + [p2, p3] = initial.opDouble(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opDouble(1.0); + assert(p2 == 1.0 && p3 == 1.0); + f = initial.opDoubleAsync(1.0); + [p2, p3] = f.fetchOutputs(); + assert(p2 == 1.0 && p3 == 1.0); + + [p2, p3] = initial.opString(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opString('test'); + assert(strcmp(p2, 'test') && strcmp(p3, 'test')); + f = initial.opStringAsync('test'); + [p2, p3] = f.fetchOutputs(); + assert(strcmp(p2, 'test') && strcmp(p3, 'test')); + + [p2, p3] = initial.opMyEnum(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + [p2, p3] = initial.opMyEnum(Test.MyEnum.MyEnumMember); + assert(p2 == Test.MyEnum.MyEnumMember && p3 == Test.MyEnum.MyEnumMember); + f = initial.opMyEnumAsync(Test.MyEnum.MyEnumMember); + [p2, p3] = f.fetchOutputs(); + assert(p2 == Test.MyEnum.MyEnumMember && p3 == Test.MyEnum.MyEnumMember); + + [p2, p3] = initial.opSmallStruct(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.SmallStruct(56); + [p2, p3] = initial.opSmallStruct(p1); + assert(p2 == p1 && p3 == p1); + [p2, p3] = initial.opSmallStruct([]); % Test null struct + assert(p2.m == 0 && p3.m == 0); + f = initial.opSmallStructAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2 == p1 && p3 == p1); + + [p2, p3] = initial.opFixedStruct(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.FixedStruct(56); + [p2, p3] = initial.opFixedStruct(p1); + assert(p2 == p1 && p3 == p1); + f = initial.opFixedStructAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2 == p1 && p3 == p1); + + [p2, p3] = initial.opVarStruct(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.VarStruct('test'); + [p2, p3] = initial.opVarStruct(p1); + assert(p2 == p1 && p3 == p1); + f = initial.opVarStructAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2 == p1 && p3 == p1); + + [p2, p3] = initial.opOneOptional(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + if initial.supportsNullOptional() + [p2, p3] = initial.opOneOptional([]); + assert(isempty(p2) && isempty(p3)); + end + p1 = Test.OneOptional(58); + [p2, p3] = initial.opOneOptional(p1); + assert(p2.a == p1.a && p3.a == p1.a); + f = initial.opOneOptionalAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2.a == p1.a && p3.a == p1.a); + + [p2, p3] = initial.opOneOptionalProxy(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = communicator.stringToProxy('test'); + [p2, p3] = initial.opOneOptionalProxy(p1); + assert(p2 == p1 && p3 == p1); + f = initial.opOneOptionalProxyAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2 == p1 && p3 == p1); + + [p2, p3] = initial.opByteSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 56; + [p2, p3] = initial.opByteSeq(p1); + assert(length(p2) == length(p1) && length(p3) == length(p1)); + assert(p2(1) == 56); + assert(p3(1) == 56); + f = initial.opByteSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(length(p2) == length(p1) && length(p3) == length(p1)); + assert(p2(1) == 56); + assert(p3(1) == 56); + + [p2, p3] = initial.opBoolSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = true; + [p2, p3] = initial.opBoolSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opBoolSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opShortSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 56; + [p2, p3] = initial.opShortSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opShortSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opIntSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 56; + [p2, p3] = initial.opIntSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opIntSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opLongSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 56; + [p2, p3] = initial.opLongSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opLongSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opFloatSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 1.0; + [p2, p3] = initial.opFloatSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opFloatSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opDoubleSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = []; + p1(1:100) = 1.0; + [p2, p3] = initial.opDoubleSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opDoubleSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opStringSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = 'test'; + end + [p2, p3] = initial.opStringSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opStringSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opSmallStructSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = Test.SmallStruct(1); + end + [p2, p3] = initial.opSmallStructSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opSmallStructSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opSmallStructList(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = Test.SmallStruct(1); + end + [p2, p3] = initial.opSmallStructList(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opSmallStructListAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opFixedStructSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = Test.FixedStruct(1); + end + [p2, p3] = initial.opFixedStructSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opFixedStructSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opFixedStructList(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = Test.FixedStruct(1); + end + [p2, p3] = initial.opFixedStructList(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opFixedStructListAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opVarStructSeq(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = cell(1, 100); + for i = 1:length(p1) + p1{i} = Test.VarStruct('test'); + end + [p2, p3] = initial.opVarStructSeq(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opVarStructSeqAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opIntIntDict(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.IntIntDict.new(); + p1(1) = 2; + p1(2) = 3; + [p2, p3] = initial.opIntIntDict(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opIntIntDictAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opStringIntDict(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.StringIntDict.new(); + p1('1') = 2; + p1('2') = 3; + [p2, p3] = initial.opStringIntDict(p1); + assert(isequal(p2, p1) && isequal(p3, p1)); + f = initial.opStringIntDictAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(isequal(p2, p1) && isequal(p3, p1)); + + [p2, p3] = initial.opIntOneOptionalDict(Ice.Unset); + assert(p2 == Ice.Unset && p3 == Ice.Unset); + p1 = Test.IntOneOptionalDict.new(); + p1(1) = Test.OneOptional(58); + p1(2) = Test.OneOptional(59); + [p2, p3] = initial.opIntOneOptionalDict(p1); + assert(p2(1).a == 58 && p3(1).a == 58); + f = initial.opIntOneOptionalDictAsync(p1); + [p2, p3] = f.fetchOutputs(); + assert(p2(1).a == 58 && p3(1).a == 58); + + fprintf('ok\n'); + + fprintf('testing exception optionals... '); + + try + initial.opOptionalException(Ice.Unset, Ice.Unset, Ice.Unset); + catch ex + assert(isa(ex, 'Test.OptionalException')); + assert(ex.a == Ice.Unset); + assert(ex.b == Ice.Unset); + assert(ex.o == Ice.Unset); + end + + try + initial.opOptionalException(30, 'test', Test.OneOptional(53)); + catch ex + assert(isa(ex, 'Test.OptionalException')); + assert(ex.a == 30); + assert(strcmp(ex.b, 'test')); + assert(ex.o.a == 53); + end + + try + % + % Use the 1.0 encoding with an exception whose only class members are optional. + % + initial.ice_encodingVersion(Ice.EncodingVersion(1, 0)).opOptionalException(30, 'test', Test.OneOptional(53)); + catch ex + assert(isa(ex, 'Test.OptionalException')); + assert(ex.a == Ice.Unset); + assert(ex.b == Ice.Unset); + assert(ex.o == Ice.Unset); + end + + try + initial.opDerivedException(Ice.Unset, Ice.Unset, Ice.Unset); + catch ex + assert(isa(ex, 'Test.DerivedException')); + assert(ex.a == Ice.Unset); + assert(ex.b == Ice.Unset); + assert(ex.o == Ice.Unset); + assert(ex.ss == Ice.Unset); + assert(ex.o2 == Ice.Unset); + end + + try + initial.opDerivedException(30, 'test2', Test.OneOptional(53)); + catch ex + assert(isa(ex, 'Test.DerivedException')); + assert(ex.a == 30); + assert(strcmp(ex.b, 'test2')); + assert(ex.o.a == 53); + assert(strcmp(ex.ss, 'test2')); + assert(ex.o2 == ex.o); + end + + try + initial.opRequiredException(Ice.Unset, Ice.Unset, Ice.Unset); + catch ex + assert(isa(ex, 'Test.RequiredException')); + assert(ex.a == Ice.Unset); + assert(ex.b == Ice.Unset); + assert(ex.o == Ice.Unset); + assert(strcmp(ex.ss, 'test')); + assert(isempty(ex.o2)); + end + + try + initial.opRequiredException(30, 'test2', Test.OneOptional(53)); + catch ex + assert(isa(ex, 'Test.RequiredException')); + assert(ex.a == 30); + assert(strcmp(ex.b, 'test2')); + assert(ex.o.a == 53); + assert(strcmp(ex.ss, 'test2')); + assert(ex.o2 == ex.o); + end + + fprintf('ok\n'); + + r = initial; + end + end +end diff --git a/matlab/test/Ice/optional/Application.m b/matlab/test/Ice/optional/Application.m new file mode 100644 index 00000000000..003eea46ea4 --- /dev/null +++ b/matlab/test/Ice/optional/Application.m @@ -0,0 +1,157 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Application < handle + methods(Sealed) + % + % main() initializes the Communicator, calls run(), and destroys + % the Communicator upon return from run(). It thereby handles + % all exceptions properly, i.e., error messages are printed + % if exceptions propagate to main(), and the Communicator is + % always destroyed, regardless of exceptions. + % + function r = main(obj, appName, varargin) + if ~isempty(obj.communicator_) + printf('%s: only one instance of the Application class can be used', appName); + r = 1; + return; + end + + obj.testName_ = appName; + + args = {}; + initializationData = []; + + if length(varargin) >= 1 + args = varargin{1}; + end + if length(varargin) >= 2 + initializationData = varargin{2}; + end + + % + % We parse the properties here to extract Ice.ProgramName. + % + if isempty(initializationData) + [initializationData, args] = obj.getInitData(args); + end + + if ~isempty(initializationData) + initData = initializationData.clone(); + else + initData = Ice.InitializationData(); + end + + [initData.properties_, args] = Ice.createProperties(args, initData.properties_); + + %TBD + % If the process logger is the default logger, we replace it with a + % a logger that uses the program name as the prefix. + % + %if(Util.getProcessLogger() instanceof LoggerI) + %{ + % Util.setProcessLogger(new LoggerI(initData.properties_.getProperty('Ice.ProgramName'), '')); + %} + + status = 0; + + try + [communicator, args] = Ice.initialize(args, initData); + obj.communicator_ = communicator; + + status = obj.run(args); + catch ex + fprintf('%s: caught %s', obj.testName_, ex.identifier); + disp(getReport(ex, 'extended')); + status = 1; + end + obj.communicator_.destroy(); + obj.communicator_ = []; + + r = status; + end + function r = initialize(obj, varargin) + assert(length(varargin) <= 1); + if length(varargin) == 0 + r = Ice.initialize(); + else + r = Ice.initialize(varargin{1}); + end + end + function setLogger(obj, logger) + obj.logger_ = logger; + end + function r = appName(obj) + r = obj.testName_; + end + function r = communicator(obj) + r = obj.communicator_; + end + function r = createInitializationData(obj) + initData = Ice.InitializationData(); + initData.logger = obj.logger_; + r = initData; + end + function r = getTestEndpoint(obj, num, prot) + r = Application.getTestEndpointWithProperties(obj.communicator_.getProperties(), num, prot); + end + function r = getTestHost(obj) + r = Application.getTestHostWithProperties(obj.communicator_.getProperties()); + end + function r = getTestProtocol(obj) + r = Application.getTestProtocolWithProperties(obj.communicator_.getProperties()); + end + function r = getTestPort(obj, num) + r = Application.getTestPortWithProperties(obj.communicator_.getProperties(), num); + end + end + methods(Static) + function r = getTestEndpointWithProperties(props, num, prot) + protocol = prot; + if length(protocol) == 0 + protocol = props.getPropertyWithDefault('Ice.Default.Protocol', 'default'); + end + + basePort = props.getPropertyAsIntWithDefault('Test.BasePort', 12010); + + r = sprintf('%s -p %d', protocol, basePort + num); + end + function r = getTestHostWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Host', '127.0.0.1'); + end + function r = getTestProtocolWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Protocol', 'tcp'); + end + function r = getTestPortWithProperties(props, num) + r = props.getPropertyAsIntWithDefault('Test.BasePort', 12010) + num; + end + end + methods(Abstract) + r = run(obj, args) + end + methods(Access=protected) + % + % Hook to override the initialization data. This hook is + % necessary because some properties must be set prior to + % communicator initialization. + % + function [initData, remArgs] = getInitData(obj, args) + initData = obj.createInitializationData(); + [initData.properties_, remArgs] = Ice.createProperties(args); + remArgs = initData.properties_.parseCommandLineOptions('Test', remArgs); + end + end + properties(Access=private) + testName_ + communicator_ + logger_ + end +end diff --git a/matlab/test/Ice/optional/Client.m b/matlab/test/Ice/optional/Client.m new file mode 100644 index 00000000000..fc10327540a --- /dev/null +++ b/matlab/test/Ice/optional/Client.m @@ -0,0 +1,30 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Client < Application + methods + function r = run(obj, args) + initial = AllTests.allTests(obj); + initial.shutdown(); + r = 0; + end + end + methods(Static) + function start(args) + addpath('generated'); + if ~libisloaded('icematlab') + loadlibrary('icematlab') + end + c = Client(); + status = c.main('Client', args); + end + end +end diff --git a/matlab/test/Ice/optional/ClientPrivate.ice b/matlab/test/Ice/optional/ClientPrivate.ice new file mode 100644 index 00000000000..e35c0d87ef8 --- /dev/null +++ b/matlab/test/Ice/optional/ClientPrivate.ice @@ -0,0 +1,39 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Test.ice> + +module Test +{ + +// +// The server doesn't know this class. +// +class D extends B +{ + string ds; + optional(990) StringSeq seq; + optional(1000) A ao; +} + +// +// This class is a hack that allows us to invoke the opClassAndUnknownOptional operation +// on the server and pass an optional argument. This isn't necessary in other language +// mappings where the public stream API is available. +// +interface Initial2 +{ + void opClassAndUnknownOptional(A p, optional(1) Object o); + + void opVoid(optional(1) int a, optional(2) string v); +} + +} diff --git a/matlab/test/Ice/optional/Test.ice b/matlab/test/Ice/optional/Test.ice new file mode 100644 index 00000000000..ecf69d164eb --- /dev/null +++ b/matlab/test/Ice/optional/Test.ice @@ -0,0 +1,359 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +[["java:package:test.Ice.optional", "suppress-warning:deprecated"]] +module Test +{ + +class OneOptional +{ + optional(1) int a; +} + +enum MyEnum +{ + MyEnumMember +} + +struct SmallStruct +{ + byte m; +} + +struct FixedStruct +{ + int m; +} + +struct VarStruct +{ + string m; +} + +struct ClassVarStruct +{ + int a; +} + +sequence<byte> ByteSeq; +sequence<bool> BoolSeq; +sequence<short> ShortSeq; +sequence<int> IntSeq; +sequence<long> LongSeq; +sequence<float> FloatSeq; +sequence<double> DoubleSeq; +sequence<string> StringSeq; +sequence<MyEnum> MyEnumSeq; +sequence<SmallStruct> SmallStructSeq; +["java:type:java.util.ArrayList<SmallStruct>"] sequence<SmallStruct> SmallStructList; +sequence<FixedStruct> FixedStructSeq; +["java:type:java.util.ArrayList<FixedStruct>"] sequence<FixedStruct> FixedStructList; +sequence<VarStruct> VarStructSeq; +sequence<OneOptional> OneOptionalSeq; +sequence<OneOptional*> OneOptionalPrxSeq; + +["java:serializable:test.Ice.optional.SerializableClass"] sequence<byte> Serializable; + +dictionary<int, int> IntIntDict; +dictionary<string, int> StringIntDict; +dictionary<int, MyEnum> IntEnumDict; +dictionary<int, FixedStruct> IntFixedStructDict; +dictionary<int, VarStruct> IntVarStructDict; +dictionary<int, OneOptional> IntOneOptionalDict; +dictionary<int, OneOptional*> IntOneOptionalPrxDict; + +class MultiOptional +{ + optional(1) byte a; + optional(2) bool b; + optional(3) short c; + optional(4) int d; + optional(5) long e; + optional(6) float f; + optional(7) double g; + optional(8) string h; + optional(9) MyEnum i; + optional(10) MultiOptional* j; + optional(11) MultiOptional k; + optional(12) ByteSeq bs; + optional(13) StringSeq ss; + optional(14) IntIntDict iid; + optional(15) StringIntDict sid; + optional(16) FixedStruct fs; + optional(17) VarStruct vs; + + optional(18) ShortSeq shs; + optional(19) MyEnumSeq es; + optional(20) FixedStructSeq fss; + optional(21) VarStructSeq vss; + optional(22) OneOptionalSeq oos; + optional(23) OneOptionalPrxSeq oops; + + optional(24) IntEnumDict ied; + optional(25) IntFixedStructDict ifsd; + optional(26) IntVarStructDict ivsd; + optional(27) IntOneOptionalDict iood; + optional(28) IntOneOptionalPrxDict ioopd; + + optional(29) BoolSeq bos; + + optional(30) Serializable ser; +} + +class A +{ + int requiredA; + optional(1) int ma; + optional(50) int mb; + optional(500) int mc; +} + +["preserve-slice"] +class B extends A +{ + int requiredB; + optional(10) int md; +} + +class C extends B +{ + string ss; + optional(890) string ms; +} + +class WD +{ + optional(1) int a = 5; + optional(2) string s = "test"; +} + +exception OptionalException +{ + bool req = false; + optional(1) int a = 5; + optional(2) string b; + optional(50) OneOptional o; +} + +exception DerivedException extends OptionalException +{ + optional(600) string ss = "test"; + optional(601) OneOptional o2; +} + +exception RequiredException extends OptionalException +{ + string ss = "test"; + OneOptional o2; +} + +class OptionalWithCustom +{ + optional(1) SmallStructList l; + ["protected"] optional(2) SmallStructList lp; + optional(3) ClassVarStruct s; +} + +class E +{ + A ae; +} + +class F extends E +{ + optional(1) A af; +} + +class G1 +{ + string a; +} + +class G2 +{ + long a; +} + +class G +{ + optional(1) G1 gg1Opt; + G2 gg2; + optional(0) G2 gg2Opt; + G1 gg1; +} + +class Recursive; +sequence<Recursive> RecursiveSeq; + +class Recursive +{ + optional(0) RecursiveSeq value; +} + +interface Initial +{ + void shutdown(); + + Object pingPong(Object o); + + void opOptionalException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opDerivedException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + void opRequiredException(optional(1) int a, optional(2) string b, optional(3) OneOptional o) + throws OptionalException; + + ["java:optional"] optional(1) byte opByte(optional(2) byte p1, out optional(3) byte p3); + optional(1) byte opByteReq(optional(2) byte p1, out optional(3) byte p3); + + ["java:optional"] optional(1) bool opBool(optional(2) bool p1, out optional(3) bool p3); + optional(1) bool opBoolReq(optional(2) bool p1, out optional(3) bool p3); + + ["java:optional"] optional(1) short opShort(optional(2) short p1, out optional(3) short p3); + optional(1) short opShortReq(optional(2) short p1, out optional(3) short p3); + + ["java:optional"] optional(1) int opInt(optional(2) int p1, out optional(3) int p3); + optional(1) int opIntReq(optional(2) int p1, out optional(3) int p3); + + ["java:optional"] optional(3) long opLong(optional(1) long p1, out optional(2) long p3); + optional(3) long opLongReq(optional(1) long p1, out optional(2) long p3); + + ["java:optional"] optional(1) float opFloat(optional(2) float p1, out optional(3) float p3); + optional(1) float opFloatReq(optional(2) float p1, out optional(3) float p3); + + ["java:optional"] optional(1) double opDouble(optional(2) double p1, out optional(3) double p3); + optional(1) double opDoubleReq(optional(2) double p1, out optional(3) double p3); + + ["java:optional"] optional(1) string opString(optional(2) string p1, out optional(3) string p3); + optional(1) string opStringReq(optional(2) string p1, out optional(3) string p3); + + ["java:optional"] optional(1) MyEnum opMyEnum(optional(2) MyEnum p1, out optional(3) MyEnum p3); + optional(1) MyEnum opMyEnumReq(optional(2) MyEnum p1, out optional(3) MyEnum p3); + + ["java:optional"] optional(1) SmallStruct opSmallStruct(optional(2) SmallStruct p1, out optional(3) SmallStruct p3); + optional(1) SmallStruct opSmallStructReq(optional(2) SmallStruct p1, out optional(3) SmallStruct p3); + + ["java:optional"] optional(1) FixedStruct opFixedStruct(optional(2) FixedStruct p1, out optional(3) FixedStruct p3); + optional(1) FixedStruct opFixedStructReq(optional(2) FixedStruct p1, out optional(3) FixedStruct p3); + + ["java:optional"] optional(1) VarStruct opVarStruct(optional(2) VarStruct p1, out optional(3) VarStruct p3); + optional(1) VarStruct opVarStructReq(optional(2) VarStruct p1, out optional(3) VarStruct p3); + + ["java:optional"] optional(1) OneOptional opOneOptional(optional(2) OneOptional p1, out optional(3) OneOptional p3); + optional(1) OneOptional opOneOptionalReq(optional(2) OneOptional p1, out optional(3) OneOptional p3); + + ["java:optional"] optional(1) OneOptional* opOneOptionalProxy(optional(2) OneOptional* p1, + out optional(3) OneOptional* p3); + optional(1) OneOptional* opOneOptionalProxyReq(optional(2) OneOptional* p1, out optional(3) OneOptional* p3); + + ["java:optional"] optional(1) ByteSeq opByteSeq(optional(2) ByteSeq p1, out optional(3) ByteSeq p3); + optional(1) ByteSeq opByteSeqReq(optional(2) ByteSeq p1, out optional(3) ByteSeq p3); + + ["java:optional"] optional(1) BoolSeq opBoolSeq(optional(2) BoolSeq p1, out optional(3) BoolSeq p3); + optional(1) BoolSeq opBoolSeqReq(optional(2) BoolSeq p1, out optional(3) BoolSeq p3); + + ["java:optional"] optional(1) ShortSeq opShortSeq(optional(2) ShortSeq p1, out optional(3) ShortSeq p3); + optional(1) ShortSeq opShortSeqReq(optional(2) ShortSeq p1, out optional(3) ShortSeq p3); + + ["java:optional"] optional(1) IntSeq opIntSeq(optional(2) IntSeq p1, out optional(3) IntSeq p3); + optional(1) IntSeq opIntSeqReq(optional(2) IntSeq p1, out optional(3) IntSeq p3); + + ["java:optional"] optional(1) LongSeq opLongSeq(optional(2) LongSeq p1, out optional(3) LongSeq p3); + optional(1) LongSeq opLongSeqReq(optional(2) LongSeq p1, out optional(3) LongSeq p3); + + ["java:optional"] optional(1) FloatSeq opFloatSeq(optional(2) FloatSeq p1, out optional(3) FloatSeq p3); + optional(1) FloatSeq opFloatSeqReq(optional(2) FloatSeq p1, out optional(3) FloatSeq p3); + + ["java:optional"] optional(1) DoubleSeq opDoubleSeq(optional(2) DoubleSeq p1, out optional(3) DoubleSeq p3); + optional(1) DoubleSeq opDoubleSeqReq(optional(2) DoubleSeq p1, out optional(3) DoubleSeq p3); + + ["java:optional"] optional(1) StringSeq opStringSeq(optional(2) StringSeq p1, out optional(3) StringSeq p3); + optional(1) StringSeq opStringSeqReq(optional(2) StringSeq p1, out optional(3) StringSeq p3); + + ["java:optional"] optional(1) SmallStructSeq opSmallStructSeq(optional(2) SmallStructSeq p1, + out optional(3) SmallStructSeq p3); + optional(1) SmallStructSeq opSmallStructSeqReq(optional(2) SmallStructSeq p1, out optional(3) SmallStructSeq p3); + + ["java:optional"] optional(1) SmallStructList opSmallStructList(optional(2) SmallStructList p1, + out optional(3) SmallStructList p3); + optional(1) SmallStructList opSmallStructListReq(optional(2) SmallStructList p1, + out optional(3) SmallStructList p3); + + ["java:optional"] optional(1) FixedStructSeq opFixedStructSeq(optional(2) FixedStructSeq p1, + out optional(3) FixedStructSeq p3); + optional(1) FixedStructSeq opFixedStructSeqReq(optional(2) FixedStructSeq p1, out optional(3) FixedStructSeq p3); + + ["java:optional"] optional(1) FixedStructList opFixedStructList(optional(2) FixedStructList p1, + out optional(3) FixedStructList p3); + optional(1) FixedStructList opFixedStructListReq(optional(2) FixedStructList p1, + out optional(3) FixedStructList p3); + + ["java:optional"] optional(1) VarStructSeq opVarStructSeq(optional(2) VarStructSeq p1, + out optional(3) VarStructSeq p3); + optional(1) VarStructSeq opVarStructSeqReq(optional(2) VarStructSeq p1, out optional(3) VarStructSeq p3); + + ["java:optional"] optional(1) Serializable opSerializable(optional(2) Serializable p1, + out optional(3) Serializable p3); + optional(1) Serializable opSerializableReq(optional(2) Serializable p1, out optional(3) Serializable p3); + + ["java:optional"] optional(1) IntIntDict opIntIntDict(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); + optional(1) IntIntDict opIntIntDictReq(optional(2) IntIntDict p1, out optional(3) IntIntDict p3); + + ["java:optional"] optional(1) StringIntDict opStringIntDict(optional(2) StringIntDict p1, + out optional(3) StringIntDict p3); + optional(1) StringIntDict opStringIntDictReq(optional(2) StringIntDict p1, out optional(3) StringIntDict p3); + + ["java:optional"] optional(1) IntOneOptionalDict opIntOneOptionalDict(optional(2) IntOneOptionalDict p1, + out optional(3) IntOneOptionalDict p3); + + optional(1) IntOneOptionalDict opIntOneOptionalDictReq(optional(2) IntOneOptionalDict p1, + out optional(3) IntOneOptionalDict p3); + + void opClassAndUnknownOptional(A p); + + void sendOptionalClass(bool req, optional(1) OneOptional o); + + ["java:optional"] + void returnOptionalClass(bool req, out optional(1) OneOptional o); + + G opG(G g); + + void opVoid(); + + ["marshaled-result"] optional(1) SmallStruct opMStruct1(); + ["marshaled-result"] optional(1) SmallStruct opMStruct2(optional(2) SmallStruct p1, + out optional(3)SmallStruct p2); + + ["marshaled-result"] optional(1) StringSeq opMSeq1(); + ["marshaled-result"] optional(1) StringSeq opMSeq2(optional(2) StringSeq p1, + out optional(3) StringSeq p2); + + ["marshaled-result"] optional(1) StringIntDict opMDict1(); + ["marshaled-result"] optional(1) StringIntDict opMDict2(optional(2) StringIntDict p1, + out optional(3) StringIntDict p2); + + ["marshaled-result"] optional(1) G opMG1(); + ["marshaled-result"] optional(1) G opMG2(optional(2) G p1, out optional(3) G p2); + + bool supportsRequiredParams(); + + bool supportsJavaSerializable(); + + bool supportsCsharpSerializable(); + + bool supportsCppStringView(); + + bool supportsNullOptional(); +} + +} diff --git a/matlab/test/Ice/optional/generated/.gitignore b/matlab/test/Ice/optional/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/matlab/test/Ice/optional/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/matlab/test/Ice/proxy/AllTests.m b/matlab/test/Ice/proxy/AllTests.m new file mode 100644 index 00000000000..ce6c543c412 --- /dev/null +++ b/matlab/test/Ice/proxy/AllTests.m @@ -0,0 +1,851 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef AllTests + methods(Static) + function r = allTests(app) + communicator = app.communicator(); + + fprintf('testing stringToProxy... '); + + % + % Test nil proxies. + % + p = communicator.stringToProxy(''); + assert(isempty(p)); + p = communicator.propertyToProxy('bogus'); + assert(isempty(p)); + + ref = 'test:default -p 12010'; + base = communicator.stringToProxy(ref); + assert(~isempty(base)); + + b1 = communicator.stringToProxy('test'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getAdapterId()) && isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy('test '); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy(' test '); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy(' test'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy('''test -f facet'''); + assert(strcmp(b1.ice_getIdentity().name, 'test -f facet') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getFacet())); + try + b1 = communicator.stringToProxy('"test -f facet'''); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + b1 = communicator.stringToProxy('"test -f facet"'); + assert(strcmp(b1.ice_getIdentity().name, 'test -f facet') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy('"test -f facet@test"'); + assert(strcmp(b1.ice_getIdentity().name, 'test -f facet@test') && ... + isempty(b1.ice_getIdentity().category) && isempty(b1.ice_getFacet())); + b1 = communicator.stringToProxy('"test -f facet@test @test"'); + assert(strcmp(b1.ice_getIdentity().name, 'test -f facet@test @test') && ... + isempty(b1.ice_getIdentity().category) && isempty(b1.ice_getFacet())); + try + b1 = communicator.stringToProxy('test test'); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + b1 = communicator.stringToProxy('test\040test'); + assert(strcmp(b1.ice_getIdentity().name, 'test test') && isempty(b1.ice_getIdentity().category)); + try + b1 = communicator.stringToProxy('test\777'); + assert(false); + catch ex + assert(isa(ex, 'Ice.IdentityParseException')); + end + b1 = communicator.stringToProxy('test\40test'); + assert(strcmp(b1.ice_getIdentity().name, 'test test')); + + % Test some octal and hex corner cases. + b1 = communicator.stringToProxy('test\4test'); + assert(strcmp(b1.ice_getIdentity().name, sprintf('test\4test'))); + b1 = communicator.stringToProxy('test\04test'); + assert(strcmp(b1.ice_getIdentity().name, sprintf('test\4test'))); + b1 = communicator.stringToProxy('test\004test'); + assert(strcmp(b1.ice_getIdentity().name, sprintf('test\4test'))); + % + % In other languages this test is written as: + % + % b1 = communicator.stringToProxy('test\1114test') + % + % But the MATLAB parser consumes all of the octal digits. + % + b1 = communicator.stringToProxy('test\111\064test'); + assert(strcmp(b1.ice_getIdentity().name, sprintf('test\111\064test'))); + + b1 = communicator.stringToProxy('test\b\f\n\r\t''"\test'); + assert(strcmp(b1.ice_getIdentity().name, sprintf('test\b\f\n\r\t''"\test')) && ... + isempty(b1.ice_getIdentity().category)); + + b1 = communicator.stringToProxy('category/test'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category') && isempty(b1.ice_getAdapterId())); + + b1 = communicator.stringToProxy('test@adapter'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getAdapterId(), 'adapter')); + try + b1 = communicator.stringToProxy('id@adapter test'); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + b1 = communicator.stringToProxy('category/test@adapter'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category') && strcmp(b1.ice_getAdapterId(), 'adapter')); + b1 = communicator.stringToProxy('category/test@adapter:tcp'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category') && strcmp(b1.ice_getAdapterId(), 'adapter:tcp')); + b1 = communicator.stringToProxy('''category 1/test''@adapter'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category 1') && ... + strcmp(b1.ice_getAdapterId(), 'adapter')); + b1 = communicator.stringToProxy('''category/test 1''@adapter'); + assert(strcmp(b1.ice_getIdentity().name, 'test 1') && ... + strcmp(b1.ice_getIdentity().category, 'category') && ... + strcmp(b1.ice_getAdapterId(), 'adapter')); + b1 = communicator.stringToProxy('''category/test''@''adapter 1'''); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category') && ... + strcmp(b1.ice_getAdapterId(), 'adapter 1')); + b1 = communicator.stringToProxy('"category \/test@foo/test"@adapter'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category /test@foo') && ... + strcmp(b1.ice_getAdapterId(), 'adapter')); + b1 = communicator.stringToProxy('"category \/test@foo/test"@"adapter:tcp"'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && ... + strcmp(b1.ice_getIdentity().category, 'category /test@foo') && ... + strcmp(b1.ice_getAdapterId(), 'adapter:tcp')); + + b1 = communicator.stringToProxy('id -f facet'); + assert(strcmp(b1.ice_getIdentity().name, 'id') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet')); + b1 = communicator.stringToProxy('id -f ''facet x'''); + assert(strcmp(b1.ice_getIdentity().name, 'id') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet x')); + b1 = communicator.stringToProxy('id -f "facet x"'); + assert(strcmp(b1.ice_getIdentity().name, 'id') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet x')); + try + b1 = communicator.stringToProxy('id -f "facet x'); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + try + b1 = communicator.stringToProxy('id -f ''facet x'); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + b1 = communicator.stringToProxy('test -f facet:tcp'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet') && isempty(b1.ice_getAdapterId())); + b1 = communicator.stringToProxy('test -f "facet:tcp"'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet:tcp') && isempty(b1.ice_getAdapterId())); + b1 = communicator.stringToProxy('test -f facet@test'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet') && strcmp(b1.ice_getAdapterId(), 'test')); + b1 = communicator.stringToProxy('test -f ''facet@test'''); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet@test') && isempty(b1.ice_getAdapterId())); + b1 = communicator.stringToProxy('test -f ''facet@test''@test'); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + strcmp(b1.ice_getFacet(), 'facet@test') && strcmp(b1.ice_getAdapterId(), 'test')); + try + b1 = communicator.stringToProxy('test -f facet@test @test'); + assert(false); + catch ex + assert(isa(ex, 'Ice.ProxyParseException')); + end + b1 = communicator.stringToProxy('test'); + assert(b1.ice_isTwoway()); + b1 = communicator.stringToProxy('test -t'); + assert(b1.ice_isTwoway()); + b1 = communicator.stringToProxy('test -o'); + assert(b1.ice_isOneway()); + b1 = communicator.stringToProxy('test -O'); + assert(b1.ice_isBatchOneway()); + b1 = communicator.stringToProxy('test -d'); + assert(b1.ice_isDatagram()); + b1 = communicator.stringToProxy('test -D'); + assert(b1.ice_isBatchDatagram()); + b1 = communicator.stringToProxy('test'); + assert(~b1.ice_isSecure()); + b1 = communicator.stringToProxy('test -s'); + assert(b1.ice_isSecure()); + + try + b1 = communicator.stringToProxy('test:tcp@adapterId'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + % This is an unknown endpoint warning, not a parse exception. + % + %try + % b1 = communicator.stringToProxy('test -f the:facet:tcp'); + % assert(false); + %catch ex + % assert(isa(ex, 'Ice.EndpointParseException')); + %end + try + b1 = communicator.stringToProxy('test::tcp'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + fprintf('ok\n'); + + fprintf('testing propertyToProxy... '); + prop = communicator.getProperties(); + propertyPrefix = 'Foo.Proxy'; + prop.setProperty(propertyPrefix, 'test:default -p 12010'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(strcmp(b1.ice_getIdentity().name, 'test') && isempty(b1.ice_getIdentity().category) && ... + isempty(b1.ice_getAdapterId()) && isempty(b1.ice_getFacet())); + + property = [propertyPrefix, '.Locator']; + assert(isempty(b1.ice_getLocator())); + prop.setProperty(property, 'locator:default -p 10000'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(~isempty(b1.ice_getLocator()) && strcmp(b1.ice_getLocator().ice_getIdentity().name, 'locator')); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.LocatorCacheTimeout']; + assert(b1.ice_getLocatorCacheTimeout() == -1) + prop.setProperty(property, '1'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_getLocatorCacheTimeout() == 1); + prop.setProperty(property, ''); + + % Now retest with an indirect proxy. + prop.setProperty(propertyPrefix, 'test'); + property = [propertyPrefix, '.Locator']; + prop.setProperty(property, 'locator:default -p 10000'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(~isempty(b1.ice_getLocator()) && strcmp(b1.ice_getLocator().ice_getIdentity().name, 'locator')); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.LocatorCacheTimeout']; + assert(b1.ice_getLocatorCacheTimeout() == -1); + prop.setProperty(property, '1'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_getLocatorCacheTimeout() == 1); + prop.setProperty(property, ''); + + % This cannot be tested so easily because the property is cached + % on communicator initialization. + % + %prop.setProperty('Ice.Default.LocatorCacheTimeout', '60'); + %b1 = communicator.propertyToProxy(propertyPrefix); + %assert(b1.ice_getLocatorCacheTimeout() == 60); + %prop.setProperty('Ice.Default.LocatorCacheTimeout', ''); + + prop.setProperty(propertyPrefix, 'test:default -p 12010'); + + property = [propertyPrefix, '.Router']; + assert(isempty(b1.ice_getRouter())); + prop.setProperty(property, 'router:default -p 10000'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(~isempty(b1.ice_getRouter()) && strcmp(b1.ice_getRouter().ice_getIdentity().name, 'router')); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.PreferSecure']; + assert(~b1.ice_isPreferSecure()); + prop.setProperty(property, '1'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_isPreferSecure()); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.ConnectionCached']; + assert(b1.ice_isConnectionCached()); + prop.setProperty(property, '0'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(~b1.ice_isConnectionCached()); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.InvocationTimeout']; + assert(b1.ice_getInvocationTimeout() == -1); + prop.setProperty(property, '1000'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_getInvocationTimeout() == 1000); + prop.setProperty(property, ''); + + property = [propertyPrefix, '.EndpointSelection']; + assert(b1.ice_getEndpointSelection() == Ice.EndpointSelectionType.Random); + prop.setProperty(property, 'Random'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_getEndpointSelection() == Ice.EndpointSelectionType.Random); + prop.setProperty(property, 'Ordered'); + b1 = communicator.propertyToProxy(propertyPrefix); + assert(b1.ice_getEndpointSelection() == Ice.EndpointSelectionType.Ordered); + prop.setProperty(property, ''); + + fprintf('ok\n'); + + fprintf('testing proxyToProperty... '); + + b1 = communicator.stringToProxy('test'); + b1 = b1.ice_connectionCached(true); + b1 = b1.ice_preferSecure(false); + b1 = b1.ice_endpointSelection(Ice.EndpointSelectionType.Ordered); + b1 = b1.ice_locatorCacheTimeout(100); + b1 = b1.ice_invocationTimeout(1234); + b1 = b1.ice_encodingVersion(Ice.EncodingVersion(1, 0)); + + router = communicator.stringToProxy('router'); + router = router.ice_connectionCached(true); + router = router.ice_preferSecure(true); + router = router.ice_endpointSelection(Ice.EndpointSelectionType.Random); + router = router.ice_locatorCacheTimeout(200); + router = router.ice_invocationTimeout(1500); + + locator = communicator.stringToProxy('locator'); + locator = locator.ice_connectionCached(false); + locator = locator.ice_preferSecure(true); + locator = locator.ice_endpointSelection(Ice.EndpointSelectionType.Random); + locator = locator.ice_locatorCacheTimeout(300); + locator = locator.ice_invocationTimeout(1500); + + locator = locator.ice_router(Ice.RouterPrx.uncheckedCast(router)); + b1 = b1.ice_locator(Ice.LocatorPrx.uncheckedCast(locator)); + + proxyProps = communicator.proxyToProperty(b1, 'Test'); + assert(length(proxyProps) == 21); + + assert(strcmp(proxyProps('Test'), 'test -t -e 1.0')); + %assert(strcmp(proxyProps('Test.CollocationOptimized'), '1')); + assert(strcmp(proxyProps('Test.ConnectionCached'), '1')); + assert(strcmp(proxyProps('Test.PreferSecure'), '0')); + assert(strcmp(proxyProps('Test.EndpointSelection'), 'Ordered')); + assert(strcmp(proxyProps('Test.LocatorCacheTimeout'), '100')); + assert(strcmp(proxyProps('Test.InvocationTimeout'), '1234')); + + assert(strcmp(proxyProps('Test.Locator'), ... + ['locator -t -e ', Ice.encodingVersionToString(Ice.currentEncoding())])); + %assert(strcmp(proxyProps('Test.Locator.CollocationOptimized'), '1')); + assert(strcmp(proxyProps('Test.Locator.ConnectionCached'), '0')); + assert(strcmp(proxyProps('Test.Locator.PreferSecure'), '1')); + assert(strcmp(proxyProps('Test.Locator.EndpointSelection'), 'Random')); + assert(strcmp(proxyProps('Test.Locator.LocatorCacheTimeout'), '300')); + assert(strcmp(proxyProps('Test.Locator.InvocationTimeout'), '1500')); + + assert(strcmp(proxyProps('Test.Locator.Router'), ... + ['router -t -e ', Ice.encodingVersionToString(Ice.currentEncoding())])); + %assert(strcmp(proxyProps('Test.Locator.Router.CollocationOptimized'), '0')); + assert(strcmp(proxyProps('Test.Locator.Router.ConnectionCached'), '1')); + assert(strcmp(proxyProps('Test.Locator.Router.PreferSecure'), '1')); + assert(strcmp(proxyProps('Test.Locator.Router.EndpointSelection'), 'Random')); + assert(strcmp(proxyProps('Test.Locator.Router.LocatorCacheTimeout'), '200')); + assert(strcmp(proxyProps('Test.Locator.Router.InvocationTimeout'), '1500')); + + fprintf('ok\n'); + + fprintf('testing ice_getCommunicator... '); + + assert(base.ice_getCommunicator() == communicator); + + fprintf('ok\n'); + + fprintf('testing proxy methods... '); + + assert(strcmp(communicator.identityToString(base.ice_identity(Ice.stringToIdentity('other')).ice_getIdentity()), 'other')); + + %{ + % TODO + % + % Verify that ToStringMode is passed correctly + % + euroStr = sprintf('\x7F\xE2\x82\xAC'); + ident = Ice.Identity('test', euroStr); + + idStr = Ice.identityToString(ident, Ice.ToStringMode.Unicode); + assert(strcmp(idStr, sprintf('\x007f\xe2\x82\xac/test'))); + ident2 = Ice.stringToIdentity(idStr); + assert(ident == ident2); + assert(strcmp(Ice.identityToString(ident), idStr)); + + idStr = Ice.identityToString(ident, Ice.ToStringMode.ASCII) + assert(idStr == "\\u007f\\u20ac/test") + ident2 = Ice.stringToIdentity(idStr) + assert(ident == ident2) + + idStr = Ice.identityToString(ident, Ice.ToStringMode.Compat) + assert(idStr == "\\177\\342\\202\\254/test") + ident2 = Ice.stringToIdentity(idStr) + assert(ident == ident2) + + ident2 = Ice.stringToIdentity(communicator.identityToString(ident)) + assert(ident == ident2) + %} + + assert(strcmp(base.ice_facet('facet').ice_getFacet(), 'facet')); + assert(strcmp(base.ice_adapterId('id').ice_getAdapterId(), 'id')); + assert(base.ice_twoway().ice_isTwoway()); + assert(base.ice_oneway().ice_isOneway()); + assert(base.ice_batchOneway().ice_isBatchOneway()); + assert(base.ice_datagram().ice_isDatagram()); + assert(base.ice_batchDatagram().ice_isBatchDatagram()); + assert(base.ice_secure(true).ice_isSecure()); + assert(~base.ice_secure(false).ice_isSecure()); + %assert(base.ice_collocationOptimized(true).ice_isCollocationOptimized()); + %assert(~base.ice_collocationOptimized(false).ice_isCollocationOptimized()); + assert(base.ice_preferSecure(true).ice_isPreferSecure()); + assert(~base.ice_preferSecure(false).ice_isPreferSecure()); + assert(base.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_getEncodingVersion() == Ice.EncodingVersion(1, 0)); + assert(base.ice_encodingVersion(Ice.EncodingVersion(1, 1)).ice_getEncodingVersion() == Ice.EncodingVersion(1, 1)); + assert(base.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_getEncodingVersion() ~= Ice.EncodingVersion(1, 1)); + + try + base.ice_timeout(0); + assert(false); + catch ex + end + + try + base.ice_timeout(-1); + catch ex + assert(false); + end + + try + base.ice_timeout(-2); + assert(false); + catch ex + end + + try + base.ice_invocationTimeout(0); + assert(false); + catch ex + end + + try + base.ice_invocationTimeout(-1); + catch ex + assert(false); + end + + try + base.ice_invocationTimeout(-2); + assert(false); + catch ex + end + + try + base.ice_locatorCacheTimeout(0); + catch ex + assert(false); + end + + try + base.ice_locatorCacheTimeout(-1); + catch ex + assert(false); + end + + try + base.ice_locatorCacheTimeout(-2); + assert(false); + catch ex + end + + fprintf('ok\n'); + + fprintf('testing proxy comparison... '); + + assert(communicator.stringToProxy('foo') == communicator.stringToProxy('foo')); + assert(communicator.stringToProxy('foo') ~= communicator.stringToProxy('foo2')); + %assert(communicator.stringToProxy('foo') < communicator.stringToProxy('foo2')); + %assert(~(communicator.stringToProxy('foo2') < communicator.stringToProxy('foo'))); + + compObj = communicator.stringToProxy('foo'); + + assert(compObj.ice_facet('facet') == compObj.ice_facet('facet')); + assert(compObj.ice_facet('facet') ~= compObj.ice_facet('facet1')); + %assert(compObj.ice_facet('facet') < compObj.ice_facet('facet1')); + %assert(~(compObj.ice_facet('facet') < compObj.ice_facet('facet'))); + + assert(compObj.ice_oneway() == compObj.ice_oneway()); + assert(compObj.ice_oneway() ~= compObj.ice_twoway()); + %assert(compObj.ice_twoway() < compObj.ice_oneway()); + %assert(~(compObj.ice_oneway() < compObj.ice_twoway())); + + assert(compObj.ice_secure(true) == compObj.ice_secure(true)); + assert(compObj.ice_secure(false) ~= compObj.ice_secure(true)); + %assert(compObj.ice_secure(false) < compObj.ice_secure(true)); + %assert(~(compObj.ice_secure(true) < compObj.ice_secure(false))); + + %assert(compObj.ice_collocationOptimized(true) == compObj.ice_collocationOptimized(true)); + %assert(compObj.ice_collocationOptimized(false) ~= compObj.ice_collocationOptimized(true)); + %assert(compObj.ice_collocationOptimized(false) < compObj.ice_collocationOptimized(true)); + %assert(~(compObj.ice_collocationOptimized(true) < compObj.ice_collocationOptimized(false))); + + assert(compObj.ice_connectionCached(true) == compObj.ice_connectionCached(true)); + assert(compObj.ice_connectionCached(false) ~= compObj.ice_connectionCached(true)); + %assert(compObj.ice_connectionCached(false) < compObj.ice_connectionCached(true)); + %assert(~(compObj.ice_connectionCached(true) < compObj.ice_connectionCached(false))); + + assert(compObj.ice_endpointSelection(Ice.EndpointSelectionType.Random) == ... + compObj.ice_endpointSelection(Ice.EndpointSelectionType.Random)); + assert(compObj.ice_endpointSelection(Ice.EndpointSelectionType.Random) ~= ... + compObj.ice_endpointSelection(Ice.EndpointSelectionType.Ordered)); + %assert(compObj.ice_endpointSelection(Ice.EndpointSelectionType.Random) < ... + % compObj.ice_endpointSelection(Ice.EndpointSelectionType.Ordered)); + %assert(~(compObj.ice_endpointSelection(Ice.EndpointSelectionType.Ordered) < ... + % compObj.ice_endpointSelection(Ice.EndpointSelectionType.Random))); + + assert(compObj.ice_connectionId('id2') == compObj.ice_connectionId('id2')); + assert(compObj.ice_connectionId('id1') ~= compObj.ice_connectionId('id2')); + %assert(compObj.ice_connectionId('id1') < compObj.ice_connectionId('id2')); + %assert(~(compObj.ice_connectionId('id2') < compObj.ice_connectionId('id1'))); + assert(strcmp(compObj.ice_connectionId('id1').ice_getConnectionId(), 'id1')); + assert(strcmp(compObj.ice_connectionId('id2').ice_getConnectionId(), 'id2')); + + assert(compObj.ice_compress(true) == compObj.ice_compress(true)); + assert(compObj.ice_compress(false) ~= compObj.ice_compress(true)); + %assert(compObj.ice_compress(false) < compObj.ice_compress(true)); + %assert(~(compObj.ice_compress(true) < compObj.ice_compress(false))); + + assert(compObj.ice_timeout(20) == compObj.ice_timeout(20)); + assert(compObj.ice_timeout(10) ~= compObj.ice_timeout(20)); + %assert(compObj.ice_timeout(10) < compObj.ice_timeout(20)); + %assert(~(compObj.ice_timeout(20) < compObj.ice_timeout(10))); + + loc1 = Ice.LocatorPrx.uncheckedCast(communicator.stringToProxy('loc1:default -p 10000')); + loc2 = Ice.LocatorPrx.uncheckedCast(communicator.stringToProxy('loc2:default -p 10000')); + assert(compObj.ice_locator([]) == compObj.ice_locator([])); + assert(compObj.ice_locator(loc1) == compObj.ice_locator(loc1)); + assert(compObj.ice_locator(loc1) ~= compObj.ice_locator([])); + assert(compObj.ice_locator([]) ~= compObj.ice_locator(loc2)); + assert(compObj.ice_locator(loc1) ~= compObj.ice_locator(loc2)); + %assert(compObj.ice_locator([]) < compObj.ice_locator(loc1)); + %assert(~(compObj.ice_locator(loc1) < compObj.ice_locator([]))); + %assert(compObj.ice_locator(loc1) < compObj.ice_locator(loc2)); + %assert(~(compObj.ice_locator(loc2) < compObj.ice_locator(loc1))); + + rtr1 = Ice.RouterPrx.uncheckedCast(communicator.stringToProxy('rtr1:default -p 10000')); + rtr2 = Ice.RouterPrx.uncheckedCast(communicator.stringToProxy('rtr2:default -p 10000')); + assert(compObj.ice_router([]) == compObj.ice_router([])); + assert(compObj.ice_router(rtr1) == compObj.ice_router(rtr1)); + assert(compObj.ice_router(rtr1) ~= compObj.ice_router([])); + assert(compObj.ice_router([]) ~= compObj.ice_router(rtr2)); + assert(compObj.ice_router(rtr1) ~= compObj.ice_router(rtr2)); + %assert(compObj.ice_router([]) < compObj.ice_router(rtr1)); + %assert(~(compObj.ice_router(rtr1) < compObj.ice_router([]))); + %assert(compObj.ice_router(rtr1) < compObj.ice_router(rtr2)); + %assert(~(compObj.ice_router(rtr2) < compObj.ice_router(rtr1))); + + ctx1 = Ice.Context.new(); + ctx1('ctx1') = 'v1'; + ctx2 = Ice.Context.new(); + ctx2('ctx2') = 'v2'; + assert(compObj.ice_context(Ice.Context.new()) == compObj.ice_context(Ice.Context.new())); + assert(compObj.ice_context(ctx1) == compObj.ice_context(ctx1)); + assert(compObj.ice_context(ctx1) ~= compObj.ice_context(Ice.Context.new())); + assert(compObj.ice_context(Ice.Context.new()) ~= compObj.ice_context(ctx2)); + assert(compObj.ice_context(ctx1) ~= compObj.ice_context(ctx2)); + %assert(compObj.ice_context(ctx1) < compObj.ice_context(ctx2)); + %assert(~(compObj.ice_context(ctx2) < compObj.ice_context(ctx1))); + + assert(compObj.ice_preferSecure(true) == compObj.ice_preferSecure(true)); + assert(compObj.ice_preferSecure(true) ~= compObj.ice_preferSecure(false)); + %assert(compObj.ice_preferSecure(false) < compObj.ice_preferSecure(true)); + %assert(~(compObj.ice_preferSecure(true) < compObj.ice_preferSecure(false))); + + compObj1 = communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 10000'); + compObj2 = communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 10001'); + assert(compObj1 ~= compObj2); + %assert(compObj1 < compObj2); + %assert(~(compObj2 < compObj1)); + + compObj1 = communicator.stringToProxy('foo@MyAdapter1'); + compObj2 = communicator.stringToProxy('foo@MyAdapter2'); + assert(compObj1 ~= compObj2); + %assert(compObj1 < compObj2); + %assert(~(compObj2 < compObj1)); + + assert(compObj1.ice_locatorCacheTimeout(20) == compObj1.ice_locatorCacheTimeout(20)); + assert(compObj1.ice_locatorCacheTimeout(10) ~= compObj1.ice_locatorCacheTimeout(20)); + %assert(compObj1.ice_locatorCacheTimeout(10) < compObj1.ice_locatorCacheTimeout(20)); + %assert(~(compObj1.ice_locatorCacheTimeout(20) < compObj1.ice_locatorCacheTimeout(10))); + + assert(compObj1.ice_invocationTimeout(20) == compObj1.ice_invocationTimeout(20)); + assert(compObj1.ice_invocationTimeout(10) ~= compObj1.ice_invocationTimeout(20)); + %assert(compObj1.ice_invocationTimeout(10) < compObj1.ice_invocationTimeout(20)); + %assert(~(compObj1.ice_invocationTimeout(20) < compObj1.ice_invocationTimeout(10))); + + compObj1 = communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 1000'); + compObj2 = communicator.stringToProxy('foo@MyAdapter1'); + assert(compObj1 ~= compObj2); + %assert(compObj1 < compObj2); + %assert(~(compObj2 < compObj1)); + + %{ + TODO: ice_getEndpoints + endpts1 = communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 10000').ice_getEndpoints(); + endpts2 = communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 10001').ice_getEndpoints(); + assert(endpts1 ~= endpts2); + assert(endpts1 < endpts2); + assert(~(endpts2 < endpts1)); + assert(endpts1 == communicator.stringToProxy('foo:tcp -h 127.0.0.1 -p 10000').ice_getEndpoints()); + %} + + assert(compObj1.ice_encodingVersion(Ice.EncodingVersion(1, 0)) == compObj1.ice_encodingVersion(Ice.EncodingVersion(1, 0))); + assert(compObj1.ice_encodingVersion(Ice.EncodingVersion(1, 0)) ~= compObj1.ice_encodingVersion(Ice.EncodingVersion(1, 1))); + %assert(compObj.ice_encodingVersion(Ice.EncodingVersion(1, 0)) < compObj.ice_encodingVersion(Ice.EncodingVersion(1, 1))); + %assert(~(compObj.ice_encodingVersion(Ice.EncodingVersion(1, 1)) < compObj.ice_encodingVersion(Ice.EncodingVersion(1, 0)))); + + % + % TODO: Ideally we should also test comparison of fixed proxies. + % + + fprintf('ok\n'); + + fprintf('testing checked cast... '); + cl = Test.MyClassPrx.checkedCast(base); + assert(~isempty(cl)); + + derived = Test.MyDerivedClassPrx.checkedCast(cl); + assert(~isempty(derived)); + assert(cl == base); + assert(derived == base); + assert(cl == derived); + + loc = Ice.LocatorPrx.checkedCast(base); + assert(isempty(loc)); + + % + % Upcasting + % + cl2 = Test.MyClassPrx.checkedCast(derived); + obj = Ice.ObjectPrx.checkedCast(derived); + assert(~isempty(cl2)); + assert(~isempty(obj)); + assert(cl2 == obj); + assert(cl2 == derived); + + fprintf('ok\n'); + + fprintf('testing checked cast with context... '); + tccp = Test.MyClassPrx.checkedCast(base); + c = tccp.getContext(); + assert(isempty(c)); + + c = Ice.Context.new(); + c('one') = 'hello'; + c('two') = 'world'; + tccp = Test.MyClassPrx.checkedCast(base, c); + c2 = tccp.getContext(); + assert(isequal(c, c2)); + fprintf('ok\n'); + + fprintf('testing encoding versioning... '); + ref20 = 'test -e 2.0:default -p 12010'; + cl20 = Test.MyClassPrx.uncheckedCast(communicator.stringToProxy(ref20)); + try + cl20.ice_ping(); + assert(false); + catch ex + % Server 2.0 endpoint doesn't support 1.1 version. + assert(isa(ex, 'Ice.UnsupportedEncodingException')); + end + + ref10 = 'test -e 1.0:default -p 12010'; + cl10 = Test.MyClassPrx.uncheckedCast(communicator.stringToProxy(ref10)); + cl10.ice_ping(); + cl10.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_ping(); + cl.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_ping(); + + % 1.3 isn't supported but since a 1.3 proxy supports 1.1, the + % call will use the 1.1 encoding + ref13 = 'test -e 1.3:default -p 12010'; + cl13 = Test.MyClassPrx.uncheckedCast(communicator.stringToProxy(ref13)); + cl13.ice_ping(); + + fprintf('ok\n'); + + fprintf('testing opaque endpoints... '); + + try + % Invalid -x option + p = communicator.stringToProxy('id:opaque -t 99 -v abc -x abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Missing -t and -v + p = communicator.stringToProxy('id:opaque'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Repeated -t + p = communicator.stringToProxy('id:opaque -t 1 -t 1 -v abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Repeated -v + p = communicator.stringToProxy('id:opaque -t 1 -v abc -v abc') + assert(false) + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Missing -t + p = communicator.stringToProxy('id:opaque -v abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Missing -v + p = communicator.stringToProxy('id:opaque -t 1'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Missing arg for -t + p = communicator.stringToProxy('id:opaque -t -v abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Missing arg for -v + p = communicator.stringToProxy('id:opaque -t 1 -v'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Not a number for -t + p = communicator.stringToProxy('id:opaque -t x -v abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % < 0 for -t + p = communicator.stringToProxy('id:opaque -t -1 -v abc'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + try + % Invalid char for -v + p = communicator.stringToProxy('id:opaque -t 99 -v x?c'); + assert(false); + catch ex + assert(isa(ex, 'Ice.EndpointParseException')); + end + + % Legal TCP endpoint expressed as opaque endpoint + p1 = communicator.stringToProxy('test -e 1.1:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMeouAAAQJwAAAA=='); + pstr = communicator.proxyToString(p1); + assert(strcmp(pstr, 'test -t -e 1.1:tcp -h 127.0.0.1 -p 12010 -t 10000')); + + % Opaque endpoint encoded with 1.1 encoding. + p2 = communicator.stringToProxy('test -e 1.1:opaque -e 1.1 -t 1 -v CTEyNy4wLjAuMeouAAAQJwAAAA=='); + assert(strcmp(communicator.proxyToString(p2), 'test -t -e 1.1:tcp -h 127.0.0.1 -p 12010 -t 10000')); + + if communicator.getProperties().getPropertyAsInt('Ice.IPv6') == 0 + % Working? + ssl = strcmp(communicator.getProperties().getProperty('Ice.Default.Protocol'), 'ssl'); + tcp = strcmp(communicator.getProperties().getProperty('Ice.Default.Protocol'), 'tcp'); + if tcp + p1.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_ping(); + end + + % Two legal TCP endpoints expressed as opaque endpoints + p1 = communicator.stringToProxy('test -e 1.0:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMeouAAAQJwAAAA==:opaque -t 1 -e 1.0 -v CTEyNy4wLjAuMusuAAAQJwAAAA=='); + pstr = communicator.proxyToString(p1); + assert(strcmp(pstr, 'test -t -e 1.0:tcp -h 127.0.0.1 -p 12010 -t 10000:tcp -h 127.0.0.2 -p 12011 -t 10000')); + + % + % Test that an SSL endpoint and a nonsense endpoint get written + % back out as an opaque endpoint. + % + p1 = communicator.stringToProxy('test -e 1.0:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch'); + pstr = communicator.proxyToString(p1); + if ssl + assert(strcmp(pstr, 'test -t -e 1.0:ssl -h 127.0.0.1 -p 10001 -t infinite:opaque -t 99 -e 1.0 -v abch')); + elseif tcp + assert(strcmp(pstr, 'test -t -e 1.0:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch')); + end + + % + % Try to invoke on the SSL endpoint to verify that we get a + % NoEndpointException (or ConnectionRefusedException when + % running with SSL). + % + try + p1.ice_encodingVersion(Ice.EncodingVersion(1, 0)).ice_ping(); + assert(false); + catch ex + if isa(ex, 'Ice.NoEndpointException') + assert(~ssl); + elseif isa(ex, 'Ice.ConnectFailedException') + assert(~tcp); + else + rethrow(ex); + end + end + + % + % Test that the proxy with an SSL endpoint and a nonsense + % endpoint (which the server doesn't understand either) can be + % sent over the wire and returned by the server without losing + % the opaque endpoints. + % + p2 = derived.echo(p1); + pstr = communicator.proxyToString(p2); + if ssl + assert(strcmp(pstr, 'test -t -e 1.0:ssl -h 127.0.0.1 -p 10001 -t infinite:opaque -t 99 -e 1.0 -v abch')); + elseif tcp + assert(strcmp(pstr, 'test -t -e 1.0:opaque -t 2 -e 1.0 -v CTEyNy4wLjAuMREnAAD/////AA==:opaque -t 99 -e 1.0 -v abch')); + end + end + + fprintf('ok\n'); + + r = cl; + end + end +end diff --git a/matlab/test/Ice/proxy/Application.m b/matlab/test/Ice/proxy/Application.m new file mode 100644 index 00000000000..003eea46ea4 --- /dev/null +++ b/matlab/test/Ice/proxy/Application.m @@ -0,0 +1,157 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef (Abstract) Application < handle + methods(Sealed) + % + % main() initializes the Communicator, calls run(), and destroys + % the Communicator upon return from run(). It thereby handles + % all exceptions properly, i.e., error messages are printed + % if exceptions propagate to main(), and the Communicator is + % always destroyed, regardless of exceptions. + % + function r = main(obj, appName, varargin) + if ~isempty(obj.communicator_) + printf('%s: only one instance of the Application class can be used', appName); + r = 1; + return; + end + + obj.testName_ = appName; + + args = {}; + initializationData = []; + + if length(varargin) >= 1 + args = varargin{1}; + end + if length(varargin) >= 2 + initializationData = varargin{2}; + end + + % + % We parse the properties here to extract Ice.ProgramName. + % + if isempty(initializationData) + [initializationData, args] = obj.getInitData(args); + end + + if ~isempty(initializationData) + initData = initializationData.clone(); + else + initData = Ice.InitializationData(); + end + + [initData.properties_, args] = Ice.createProperties(args, initData.properties_); + + %TBD + % If the process logger is the default logger, we replace it with a + % a logger that uses the program name as the prefix. + % + %if(Util.getProcessLogger() instanceof LoggerI) + %{ + % Util.setProcessLogger(new LoggerI(initData.properties_.getProperty('Ice.ProgramName'), '')); + %} + + status = 0; + + try + [communicator, args] = Ice.initialize(args, initData); + obj.communicator_ = communicator; + + status = obj.run(args); + catch ex + fprintf('%s: caught %s', obj.testName_, ex.identifier); + disp(getReport(ex, 'extended')); + status = 1; + end + obj.communicator_.destroy(); + obj.communicator_ = []; + + r = status; + end + function r = initialize(obj, varargin) + assert(length(varargin) <= 1); + if length(varargin) == 0 + r = Ice.initialize(); + else + r = Ice.initialize(varargin{1}); + end + end + function setLogger(obj, logger) + obj.logger_ = logger; + end + function r = appName(obj) + r = obj.testName_; + end + function r = communicator(obj) + r = obj.communicator_; + end + function r = createInitializationData(obj) + initData = Ice.InitializationData(); + initData.logger = obj.logger_; + r = initData; + end + function r = getTestEndpoint(obj, num, prot) + r = Application.getTestEndpointWithProperties(obj.communicator_.getProperties(), num, prot); + end + function r = getTestHost(obj) + r = Application.getTestHostWithProperties(obj.communicator_.getProperties()); + end + function r = getTestProtocol(obj) + r = Application.getTestProtocolWithProperties(obj.communicator_.getProperties()); + end + function r = getTestPort(obj, num) + r = Application.getTestPortWithProperties(obj.communicator_.getProperties(), num); + end + end + methods(Static) + function r = getTestEndpointWithProperties(props, num, prot) + protocol = prot; + if length(protocol) == 0 + protocol = props.getPropertyWithDefault('Ice.Default.Protocol', 'default'); + end + + basePort = props.getPropertyAsIntWithDefault('Test.BasePort', 12010); + + r = sprintf('%s -p %d', protocol, basePort + num); + end + function r = getTestHostWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Host', '127.0.0.1'); + end + function r = getTestProtocolWithProperties(props) + r = props.getPropertyWithDefault('Ice.Default.Protocol', 'tcp'); + end + function r = getTestPortWithProperties(props, num) + r = props.getPropertyAsIntWithDefault('Test.BasePort', 12010) + num; + end + end + methods(Abstract) + r = run(obj, args) + end + methods(Access=protected) + % + % Hook to override the initialization data. This hook is + % necessary because some properties must be set prior to + % communicator initialization. + % + function [initData, remArgs] = getInitData(obj, args) + initData = obj.createInitializationData(); + [initData.properties_, remArgs] = Ice.createProperties(args); + remArgs = initData.properties_.parseCommandLineOptions('Test', remArgs); + end + end + properties(Access=private) + testName_ + communicator_ + logger_ + end +end diff --git a/matlab/test/Ice/proxy/Client.m b/matlab/test/Ice/proxy/Client.m new file mode 100644 index 00000000000..684304656c7 --- /dev/null +++ b/matlab/test/Ice/proxy/Client.m @@ -0,0 +1,30 @@ +%{ +********************************************************************** + +Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. + +This copy of Ice is licensed to you under the terms described in the +ICE_LICENSE file included in this distribution. + +********************************************************************** +%} + +classdef Client < Application + methods + function r = run(obj, args) + myClass = AllTests.allTests(obj); + %myClass.shutdown(); TODO + r = 0; + end + end + methods(Static) + function start(args) + addpath('generated'); + if ~libisloaded('icematlab') + loadlibrary('icematlab') + end + c = Client(); + status = c.main('Client', args); + end + end +end diff --git a/matlab/test/Ice/proxy/Test.ice b/matlab/test/Ice/proxy/Test.ice new file mode 100644 index 00000000000..711ed0289f1 --- /dev/null +++ b/matlab/test/Ice/proxy/Test.ice @@ -0,0 +1,29 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#pragma once + +#include <Ice/Current.ice> + +module Test +{ + +interface MyClass +{ + void shutdown(); + + Ice::Context getContext(); +} + +interface MyDerivedClass extends MyClass +{ + Object* echo(Object* obj); +} + +} diff --git a/matlab/test/Ice/proxy/generated/.gitignore b/matlab/test/Ice/proxy/generated/.gitignore new file mode 100644 index 00000000000..39af5887579 --- /dev/null +++ b/matlab/test/Ice/proxy/generated/.gitignore @@ -0,0 +1 @@ +# Dummy file, so that git retains this otherwise empty directory. diff --git a/slice/Ice/Communicator.ice b/slice/Ice/Communicator.ice index a9037733c66..7887ec8ebbd 100644 --- a/slice/Ice/Communicator.ice +++ b/slice/Ice/Communicator.ice @@ -55,7 +55,7 @@ module Ice * @see ValueFactory * **/ -["clr:implements:_System.IDisposable", "java:implements:java.lang.AutoCloseable", "php:internal"] +["clr:implements:_System.IDisposable", "java:implements:java.lang.AutoCloseable", "php:internal", "matlab:internal"] local interface Communicator { |