summaryrefslogtreecommitdiff
path: root/cpp/src/slice2matlab/Main.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2017-09-22 15:12:38 -0700
committerMark Spruiell <mes@zeroc.com>2017-09-22 15:12:38 -0700
commit19ac82fcfd16262542775f054473f985f499a859 (patch)
tree2adc51ee0b04d6d586c8b8f83193c1b1038b23ff /cpp/src/slice2matlab/Main.cpp
parentFix for release build (diff)
downloadice-19ac82fcfd16262542775f054473f985f499a859.tar.bz2
ice-19ac82fcfd16262542775f054473f985f499a859.tar.xz
ice-19ac82fcfd16262542775f054473f985f499a859.zip
Revising the mapping for sequence<struct> and sequence<enum>
Diffstat (limited to 'cpp/src/slice2matlab/Main.cpp')
-rw-r--r--cpp/src/slice2matlab/Main.cpp181
1 files changed, 136 insertions, 45 deletions
diff --git a/cpp/src/slice2matlab/Main.cpp b/cpp/src/slice2matlab/Main.cpp
index 0f85509bd5b..34603cb9d5d 100644
--- a/cpp/src/slice2matlab/Main.cpp
+++ b/cpp/src/slice2matlab/Main.cpp
@@ -505,6 +505,14 @@ isClass(const TypePtr& type)
}
bool
+isProxy(const TypePtr& type)
+{
+ BuiltinPtr b = BuiltinPtr::dynamicCast(type);
+ ProxyPtr p = ProxyPtr::dynamicCast(type);
+ return (b && b->kind() == Builtin::KindObjectProxy) || p;
+}
+
+bool
needsConversion(const TypePtr& type)
{
SequencePtr seq = SequencePtr::dynamicCast(type);
@@ -634,6 +642,9 @@ private:
void marshal(IceUtilInternal::Output&, const string&, const string&, const TypePtr&, bool, int);
void unmarshal(IceUtilInternal::Output&, const string&, const string&, const TypePtr&, bool, int);
+ void unmarshalStruct(IceUtilInternal::Output&, const StructPtr&, const string&);
+ void convertStruct(IceUtilInternal::Output&, const StructPtr&, const string&);
+
const string _dir;
};
@@ -1961,16 +1972,7 @@ CodeVisitor::visitStructStart(const StructPtr& p)
{
out << nl << "function obj = ice_convert(obj)";
out.inc();
- for(DataMemberList::const_iterator q = convertMembers.begin(); q != convertMembers.end(); ++q)
- {
- string m = "obj." + fixIdent((*q)->name());
- convertValueType(out, m, m, (*q)->type(), (*q)->optional());
- }
- for(DataMemberList::const_iterator q = classMembers.begin(); q != classMembers.end(); ++q)
- {
- string m = "obj." + fixIdent((*q)->name());
- out << nl << m << " = " << m << ".value;";
- }
+ convertStruct(out, p, "obj");
out.dec();
out << nl << "end";
}
@@ -1985,19 +1987,7 @@ CodeVisitor::visitStructStart(const StructPtr& p)
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()))
- {
- string m = fixIdent((*q)->name());
- out << nl << "r." << m << " = Ice.ValueHolder();";
- unmarshal(out, "is", "@(v) r." + m + ".set(v)", (*q)->type(), false, 0);
- }
- else
- {
- unmarshal(out, "is", "r." + fixIdent((*q)->name()), (*q)->type(), false, 0);
- }
- }
+ unmarshalStruct(out, p, "r");
out.dec();
out << nl << "end";
@@ -2079,10 +2069,10 @@ CodeVisitor::visitSequence(const SequencePtr& p)
const TypePtr content = p->type();
- const BuiltinPtr bp = BuiltinPtr::dynamicCast(content);
- if(bp)
+ const BuiltinPtr b = BuiltinPtr::dynamicCast(content);
+ if(b)
{
- switch(bp->kind())
+ switch(b->kind())
{
case Builtin::KindBool:
case Builtin::KindByte:
@@ -2108,10 +2098,16 @@ CodeVisitor::visitSequence(const SequencePtr& p)
}
}
+ EnumPtr enumContent = EnumPtr::dynamicCast(content);
+ SequencePtr seqContent = SequencePtr::dynamicCast(content);
+ StructPtr structContent = StructPtr::dynamicCast(content);
+ DictionaryPtr dictContent = DictionaryPtr::dynamicCast(content);
+
const string name = fixIdent(p->name());
const string scoped = p->scoped();
const string abs = getAbsolute(p);
const bool cls = isClass(content);
+ const bool proxy = isProxy(content);
const bool convert = needsConversion(content);
IceUtilInternal::Output out;
@@ -2128,7 +2124,18 @@ CodeVisitor::visitSequence(const SequencePtr& p)
out << nl << "os.writeSize(sz);";
out << nl << "for i = 1:sz";
out.inc();
- marshal(out, "os", "seq{i}", content, false, 0);
+ //
+ // Aside from the primitive types, only enum and struct sequences are mapped to arrays. The rest are mapped
+ // to cell arrays. We can't use the same subscript syntax for both.
+ //
+ if(enumContent || structContent)
+ {
+ marshal(out, "os", "seq(i)", content, false, 0);
+ }
+ else
+ {
+ marshal(out, "os", "seq{i}", content, false, 0);
+ }
out.dec();
out << nl << "end";
out.dec();
@@ -2176,33 +2183,62 @@ CodeVisitor::visitSequence(const SequencePtr& p)
if(cls)
{
//
- // For a sequence<class>, read() returns an instance of Ice.CellArrayHandle that we later replace with
- // the cell array. See convert().
+ // For a sequence<class>, read() returns an instance of IceInternal.CellArrayHandle that we later replace
+ // with the cell array. See convert().
//
- out << nl << "r = Ice.CellArrayHandle();";
+ out << nl << "r = IceInternal.CellArrayHandle();";
out << nl << "r.array = cell(1, sz);";
+ out << nl << "for i = 1:sz";
+ out.inc();
+ //
+ // Ice.CellArrayHandle defines a set() method that we call from the lambda.
+ //
+ unmarshal(out, "is", "@(v) r.set(i, v)", content, false, 0);
+ out.dec();
+ out << nl << "end";
}
- else
+ else if((b && b->kind() == Builtin::KindString) || dictContent || seqContent || proxy)
{
+ //
+ // These types require a cell array.
+ //
out << nl << "r = cell(1, sz);";
+ out << nl << "for i = 1:sz";
+ out.inc();
+ unmarshal(out, "is", "r{i}", content, false, 0);
+ out.dec();
+ out << nl << "end";
}
- out << nl << "for i = 1:sz";
- out.inc();
- if(cls)
+ else if(enumContent)
+ {
+ const EnumeratorList enumerators = enumContent->enumerators();
+ out << nl << "r(1, sz) = " << getAbsolute(*enumerators.begin()) << ";";
+ out << nl << "for i = 1:sz";
+ out.inc();
+ unmarshal(out, "is", "r(i)", content, false, 0);
+ out.dec();
+ out << nl << "end";
+ }
+ else if(structContent)
{
//
- // Ice.CellArrayHandle defines a set() method that we call from the lambda.
+ // The most efficient way to build a sequence of structs is to pre-allocate the array using the
+ // syntax "arr(1, sz) = Type()". Additionally, we also have to inline the unmarshaling code for
+ // the struct members.
//
- unmarshal(out, "is", "@(v) r.set(i, v)", content, false, 0);
+ out << nl << "r(1, sz) = " << getAbsolute(structContent) << "();";
+ out << nl << "for i = 1:sz";
+ out.inc();
+ unmarshalStruct(out, structContent, "r(i)");
+ out.dec();
+ out << nl << "end";
}
else
{
- unmarshal(out, "is", "r{i}", content, false, 0);
+ assert(false);
}
out.dec();
out << nl << "end";
- out.dec();
- out << nl << "end";
out << nl << "function r = readOpt(is, tag)";
out.inc();
@@ -2236,12 +2272,28 @@ CodeVisitor::visitSequence(const SequencePtr& p)
}
else
{
- out << nl << "r = cell(1, length(seq));";
- out << nl << "for i = 1:length(seq)";
- out.inc();
- convertValueType(out, "r{i}", "seq{i}", content, false);
- out.dec();
- out << nl << "end";
+ assert(structContent || seqContent || dictContent);
+ if(structContent)
+ {
+ //
+ // Inline the conversion.
+ //
+ out << nl << "r = seq;";
+ out << nl << "for i = 1:length(seq)";
+ out.inc();
+ convertStruct(out, structContent, "r(i)");
+ out.dec();
+ out << nl << "end";
+ }
+ else
+ {
+ out << nl << "r = cell(1, length(seq));";
+ out << nl << "for i = 1:length(seq)";
+ out.inc();
+ convertValueType(out, "r{i}", "seq{i}", content, false);
+ out.dec();
+ out << nl << "end";
+ }
}
out.dec();
out << nl << "end";
@@ -3510,6 +3562,45 @@ CodeVisitor::unmarshal(IceUtilInternal::Output& out, const string& stream, const
assert(false);
}
+void
+CodeVisitor::unmarshalStruct(IceUtilInternal::Output& out, const StructPtr& p, const string& v)
+{
+ const DataMemberList members = p->dataMembers();
+
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
+ {
+ if(isClass((*q)->type()))
+ {
+ string m = fixIdent((*q)->name());
+ out << nl << v << "." << m << " = Ice.ValueHolder();";
+ unmarshal(out, "is", "@(v_) " + v + "." + m + ".set(v_)", (*q)->type(), false, 0);
+ }
+ else
+ {
+ unmarshal(out, "is", v + "." + fixIdent((*q)->name()), (*q)->type(), false, 0);
+ }
+ }
+}
+
+void
+CodeVisitor::convertStruct(IceUtilInternal::Output& out, const StructPtr& p, const string& v)
+{
+ const DataMemberList members = p->dataMembers();
+
+ for(DataMemberList::const_iterator q = members.begin(); q != members.end(); ++q)
+ {
+ string m = fixIdent((*q)->name());
+ if(needsConversion((*q)->type()))
+ {
+ convertValueType(out, v + "." + m, v + "." + m, (*q)->type(), false);
+ }
+ else if(isClass((*q)->type()))
+ {
+ out << nl << v << "." << m << " = " << v << "." << m << ".value;";
+ }
+ }
+}
+
static void
generate(const UnitPtr& un, const string& dir, bool all, bool checksum, const vector<string>& includePaths)
{