diff options
author | Mark Spruiell <mes@zeroc.com> | 2012-08-28 16:45:46 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2012-08-28 16:45:46 -0700 |
commit | b942ffebc2089adaa90233d69472c3289824a1c4 (patch) | |
tree | ae3c9e8c5af49b9c7800ae8f303ec8c723ed0d62 /cpp/src/Slice/CsUtil.cpp | |
parent | missing filter properties (diff) | |
download | ice-b942ffebc2089adaa90233d69472c3289824a1c4.tar.bz2 ice-b942ffebc2089adaa90233d69472c3289824a1c4.tar.xz ice-b942ffebc2089adaa90233d69472c3289824a1c4.zip |
initial support for optional params in C#
Diffstat (limited to 'cpp/src/Slice/CsUtil.cpp')
-rw-r--r-- | cpp/src/Slice/CsUtil.cpp | 684 |
1 files changed, 631 insertions, 53 deletions
diff --git a/cpp/src/Slice/CsUtil.cpp b/cpp/src/Slice/CsUtil.cpp index 482ee8a11b1..05e50fc201c 100644 --- a/cpp/src/Slice/CsUtil.cpp +++ b/cpp/src/Slice/CsUtil.cpp @@ -138,7 +138,7 @@ Slice::CsGenerator::fixId(const ContainedPtr& cont, int baseTypes, bool mangleCa ContainedPtr contained = ContainedPtr::dynamicCast(container); if(contained && contained->hasMetaData("clr:property")) { - return cont->name() + "_prop"; + return cont->name() + "__prop"; } else { @@ -147,13 +147,123 @@ Slice::CsGenerator::fixId(const ContainedPtr& cont, int baseTypes, bool mangleCa } string -Slice::CsGenerator::typeToString(const TypePtr& type) +Slice::CsGenerator::getOptionalType(const TypePtr& type) +{ + BuiltinPtr bp = BuiltinPtr::dynamicCast(type); + if(bp) + { + switch(bp->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + { + return "Ice.OptionalType.F1"; + } + case Builtin::KindShort: + { + return "Ice.OptionalType.F2"; + } + case Builtin::KindInt: + case Builtin::KindFloat: + { + return "Ice.OptionalType.F4"; + } + case Builtin::KindLong: + case Builtin::KindDouble: + { + return "Ice.OptionalType.F8"; + } + case Builtin::KindString: + { + return "Ice.OptionalType.VSize"; + } + case Builtin::KindObject: + { + return "Ice.OptionalType.Size"; + } + case Builtin::KindObjectProxy: + { + return "Ice.OptionalType.FSize"; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + } + + if(EnumPtr::dynamicCast(type)) + { + return "Ice.OptionalType.Size"; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + return seq->type()->isVariableLength() ? "Ice.OptionalType.FSize" : "Ice.OptionalType.VSize"; + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + if(d) + { + return (d->keyType()->isVariableLength() || d->valueType()->isVariableLength()) ? + "Ice.OptionalType.FSize" : "Ice.OptionalType.VSize"; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + return st->isVariableLength() ? "Ice.OptionalType.FSize" : "Ice.OptionalType.VSize"; + } + + if(ProxyPtr::dynamicCast(type)) + { + return "Ice.OptionalType.FSize"; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + assert(cl); + return "Ice.OptionalType.Size"; +} + +string +Slice::CsGenerator::getStaticId(const TypePtr& type) +{ + BuiltinPtr b = BuiltinPtr::dynamicCast(type); + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + + assert((b && b->kind() == Builtin::KindObject) || cl); + + if(b) + { + return "Ice.ObjectImpl.ice_staticId()"; + } + else if(cl->isInterface()) + { + ContainedPtr cont = ContainedPtr::dynamicCast(cl->container()); + assert(cont); + return fixId(cont->scoped(), DotNet::ICloneable) + "." + cl->name() + "Disp_.ice_staticId()"; + } + else + { + return fixId(cl->scoped(), DotNet::ICloneable) + ".ice_staticId()"; + } +} + +string +Slice::CsGenerator::typeToString(const TypePtr& type, bool optional) { if(!type) { return "void"; } + if(optional) + { + return "Ice.Optional<" + typeToString(type, false) + ">"; + } + static const char* builtinTable[] = { "byte", @@ -299,9 +409,7 @@ Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, const string& param, bool marshal, bool streamingAPI, - bool isOutParam, - const string& patchParams, - bool newAMI) + const string& patchParams) { string stream; @@ -423,26 +531,7 @@ Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, } else { - if(isOutParam) - { - out << nl << "IceInternal.ParamPatcher<Ice.Object> " << param - << "_PP = new IceInternal.ParamPatcher<Ice.Object>(\"::Ice::Object\");"; - out << nl << stream << ".readObject("; - if(streamingAPI) - { - out << "(Ice.ReadObjectCallback)"; - } - out << param << "_PP);"; - } - else - { - out << nl << stream << ".readObject("; - if(streamingAPI) - { - out << "(Ice.ReadObjectCallback)"; - } - out << "new Patcher__(\"::Ice::Object\", " << patchParams << "));"; - } + out << nl << stream << ".readObject(" << patchParams << ");"; } break; } @@ -502,27 +591,7 @@ Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, } else { - if(isOutParam) - { - out << nl << "IceInternal.ParamPatcher<" << typeToString(type) << ">" << param - << "_PP = new IceInternal.ParamPatcher<" << typeToString(type) << ">(\"" - << cl->scoped() << "\");"; - out << nl << stream << ".readObject("; - if(streamingAPI) - { - out << "(Ice.ReadObjectCallback)"; - } - out << param << "_PP);"; - } - else - { - out << nl << stream << ".readObject("; - if(streamingAPI) - { - out << "(Ice.ReadObjectCallback)"; - } - out << "new Patcher__(\"" << cl->scoped() << "\", " << patchParams << "));"; - } + out << nl << stream << ".readObject(" << patchParams << ");"; } return; } @@ -611,7 +680,7 @@ Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { - writeSequenceMarshalUnmarshalCode(out, seq, param, marshal, streamingAPI); + writeSequenceMarshalUnmarshalCode(out, seq, param, marshal, streamingAPI, true); return; } @@ -637,11 +706,324 @@ Slice::CsGenerator::writeMarshalUnmarshalCode(Output &out, } void +Slice::CsGenerator::writeOptionalMarshalUnmarshalCode(Output &out, + const TypePtr& type, + const string& param, + int tag, + bool marshal, + bool streamingAPI, + const string& patchParams) +{ + string stream; + + if(marshal) + { + stream = streamingAPI ? "outS__" : "os__"; + } + else + { + stream = streamingAPI ? "inS__" : "is__"; + } + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindByte: + { + if(marshal) + { + out << nl << stream << ".writeByte(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readByte(" << tag << ");"; + } + break; + } + case Builtin::KindBool: + { + if(marshal) + { + out << nl << stream << ".writeBool(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readBool(" << tag << ");"; + } + break; + } + case Builtin::KindShort: + { + if(marshal) + { + out << nl << stream << ".writeShort(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readShort(" << tag << ");"; + } + break; + } + case Builtin::KindInt: + { + if(marshal) + { + out << nl << stream << ".writeInt(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readInt(" << tag << ");"; + } + break; + } + case Builtin::KindLong: + { + if(marshal) + { + out << nl << stream << ".writeLong(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readLong(" << tag << ");"; + } + break; + } + case Builtin::KindFloat: + { + if(marshal) + { + out << nl << stream << ".writeFloat(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readFloat(" << tag << ");"; + } + break; + } + case Builtin::KindDouble: + { + if(marshal) + { + out << nl << stream << ".writeDouble(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readDouble(" << tag << ");"; + } + break; + } + case Builtin::KindString: + { + if(marshal) + { + out << nl << stream << ".writeString(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readString(" << tag << ");"; + } + break; + } + case Builtin::KindObject: + { + if(marshal) + { + out << nl << stream << ".writeObject(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = new Ice.Optional<Ice.Object>();"; + out << nl << stream << ".readObject(" << tag << ", " << param + << ", Ice.ObjectImpl.ice_staticId());"; + } + break; + } + case Builtin::KindObjectProxy: + { + string typeS = typeToString(type); + if(marshal) + { + out << nl << stream << ".writeProxy(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = " << stream << ".readProxy(" << tag << ");"; + } + break; + } + case Builtin::KindLocalObject: + { + assert(false); + break; + } + } + return; + } + + ProxyPtr prx = ProxyPtr::dynamicCast(type); + if(prx) + { + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " << stream << ".writeOpt(" << tag + << ", Ice.OptionalType.FSize))"; + out << sb; + out << nl << stream << ".startSize();"; + writeMarshalUnmarshalCode(out, type, param + ".Value", marshal, streamingAPI, patchParams); + out << nl << stream << ".endSize();"; + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", Ice.OptionalType.FSize))"; + out << sb; + out << nl << stream << ".skip(4);"; + writeMarshalUnmarshalCode(out, type, param + ".Value", marshal, streamingAPI, patchParams); + out << eb; + } + return; + } + + ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type); + if(cl) + { + if(marshal) + { + out << nl << stream << ".writeObject(" << tag << ", " << param << ");"; + } + else + { + out << nl << param << " = new Ice.Optional<" << typeToString(type) << ">();"; + out << nl << stream << ".readObject(" << tag << ", " << param << ", " << getStaticId(cl) << ");"; + } + return; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " << stream << ".writeOpt(" << tag + << ", " << getOptionalType(st) << "))"; + out << sb; + if(st->isVariableLength()) + { + out << nl << stream << ".startSize();"; + } + else + { + out << nl << stream << ".writeSize(" << st->minWireSize() << ");"; + } + writeMarshalUnmarshalCode(out, type, param + ".Value", marshal, streamingAPI, patchParams); + if(st->isVariableLength()) + { + out << nl << stream << ".endSize();"; + } + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(st) << "))"; + out << sb; + if(st->isVariableLength()) + { + out << nl << stream << ".skip(4);"; + } + else + { + out << nl << stream << ".skipSize();"; + } + string typeS = typeToString(type); + string tmp = "tmp__" + param; + out << nl << typeS << ' ' << tmp << " = new " << typeS << "();"; + writeMarshalUnmarshalCode(out, type, tmp, marshal, streamingAPI, patchParams); + out << nl << param << " = " << tmp << ';'; + out << eb; + } + return; + } + + EnumPtr en = EnumPtr::dynamicCast(type); + if(en) + { + size_t sz = en->getEnumerators().size(); + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue)"; + out << sb; + out << nl << stream << ".writeEnum(" << tag << ", (int)" << param << ".Value, " << sz << ");"; + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", Ice.OptionalType.Size))"; + out << sb; + writeMarshalUnmarshalCode(out, type, param, marshal, streamingAPI, patchParams); + out << eb; + } + return; + } + + SequencePtr seq = SequencePtr::dynamicCast(type); + if(seq) + { + writeOptionalSequenceMarshalUnmarshalCode(out, seq, param, tag, marshal, streamingAPI); + return; + } + + DictionaryPtr d = DictionaryPtr::dynamicCast(type); + assert(d); + TypePtr keyType = d->keyType(); + TypePtr valueType = d->valueType(); + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " << stream << ".writeOpt(" << tag + << ", " << getOptionalType(d) << "))"; + out << sb; + if(keyType->isVariableLength() || valueType->isVariableLength()) + { + out << nl << stream << ".startSize();"; + } + else + { + out << nl << stream << ".writeSize(" << param << ".Value == null ? 1 : " << param << ".Value.Count * " + << (keyType->minWireSize() + valueType->minWireSize()) << " + (" << param + << ".Value.Count > 254 ? 5 : 1));"; + } + writeMarshalUnmarshalCode(out, type, param + ".Value", marshal, streamingAPI, patchParams); + if(keyType->isVariableLength() || valueType->isVariableLength()) + { + out << nl << stream << ".endSize();"; + } + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(d) << "))"; + out << sb; + if(keyType->isVariableLength() || valueType->isVariableLength()) + { + out << nl << stream << ".skip(4);"; + } + else + { + out << nl << stream << ".skipSize();"; + } + writeMarshalUnmarshalCode(out, type, param + ".Value", marshal, streamingAPI, patchParams); + out << eb; + } +} + +void Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, const SequencePtr& seq, const string& param, bool marshal, - bool streamingAPI) + bool streamingAPI, + bool useHelper) { string stream; if(marshal) @@ -653,13 +1035,29 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, stream = streamingAPI ? "inS__" : "is__"; } + if(useHelper) + { + ContainedPtr cont = ContainedPtr::dynamicCast(seq->container()); + assert(cont); + string helperName = fixId(cont->scoped(), DotNet::ICloneable) + "." + seq->name() + "Helper"; + if(marshal) + { + out << nl << helperName << ".write(" << stream << ", " << param << ");"; + } + else + { + out << nl << param << " = " << helperName << ".read(" << stream << ");"; + } + return; + } + TypePtr type = seq->type(); string typeS = typeToString(type); - string genericPrefix = "clr:generic:"; + const string genericPrefix = "clr:generic:"; string genericType; string addMethod = "Add"; - bool isGeneric = seq->findMetaData(genericPrefix, genericType); + const bool isGeneric = seq->findMetaData(genericPrefix, genericType); bool isStack = false; bool isList = false; bool isLinkedList = false; @@ -690,9 +1088,9 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, isCustom = true; } } - bool isCollection = seq->hasMetaData("clr:collection"); - bool isArray = !isGeneric && !isCollection; - string limitID = isArray ? "Length" : "Count"; + const bool isCollection = seq->hasMetaData("clr:collection"); + const bool isArray = !isGeneric && !isCollection; + const string limitID = isArray ? "Length" : "Count"; BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); if(builtin) @@ -1404,6 +1802,186 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, return; } +void +Slice::CsGenerator::writeOptionalSequenceMarshalUnmarshalCode(Output& out, + const SequencePtr& seq, + const string& param, + int tag, + bool marshal, + bool streamingAPI) +{ + string stream; + if(marshal) + { + stream = streamingAPI ? "outS__" : "os__"; + } + else + { + stream = streamingAPI ? "inS__" : "is__"; + } + + const TypePtr type = seq->type(); + const string typeS = typeToString(type); + + string meta; + const bool isArray = !seq->findMetaData("clr:generic:", meta) && !seq->hasMetaData("clr:collection"); + const string length = isArray ? param + ".Value.Length" : param + ".Value.Count"; + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); + if(builtin) + { + switch(builtin->kind()) + { + case Builtin::KindByte: + case Builtin::KindBool: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindFloat: + case Builtin::KindLong: + case Builtin::KindDouble: + case Builtin::KindString: + { + string func = typeS; + func[0] = toupper(static_cast<unsigned char>(typeS[0])); + const bool isSerializable = seq->findMetaData("clr:serializable:", meta); + + if(marshal) + { + if(isSerializable) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " << stream << ".writeOpt(" + << tag << ", Ice.OptionalType.VSize))"; + out << sb; + out << nl << stream << ".writeSerializable(" << param << ".Value);"; + out << eb; + } + else if(isArray) + { + out << nl << stream << ".write" << func << "Seq(" << tag << ", " << param << ");"; + } + else + { + out << nl << "if(" << param << " != null && " << param << ".HasValue)"; + out << sb; + out << nl << stream << ".write" << func << "Seq(" << tag << ", " << param + << ".Value == null ? 0 : " << param << ".Value.Count, " << param << ".Value);"; + out << eb; + } + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + if(builtin->isVariableLength()) + { + out << nl << stream << ".skip(4);"; + } + else if(builtin->kind() != Builtin::KindByte && builtin->kind() != Builtin::KindBool) + { + out << nl << stream << ".skipSize();"; + } + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << eb; + } + break; + } + + case Builtin::KindObject: + case Builtin::KindObjectProxy: + { + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " + << stream << ".writeOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + out << nl << stream << ".startSize();"; + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << nl << stream << ".endSize();"; + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + out << nl << stream << ".skip(4);"; + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << eb; + } + break; + } + + case Builtin::KindLocalObject: + assert(false); + } + + return; + } + + StructPtr st = StructPtr::dynamicCast(type); + if(st) + { + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " + << stream << ".writeOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + if(st->isVariableLength()) + { + out << nl << stream << ".startSize();"; + } + else + { + out << nl << stream << ".writeSize(" << param << ".Value == null ? 1 : " << length << " * " + << st->minWireSize() << " + (" << length << " > 254 ? 5 : 1));"; + } + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + if(st->isVariableLength()) + { + out << nl << stream << ".endSize();"; + } + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + if(st->isVariableLength()) + { + out << nl << stream << ".skip(4);"; + } + else + { + out << nl << stream << ".skipSize();"; + } + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << eb; + } + return; + } + + // + // At this point, all remaining element types have variable size. + // + if(marshal) + { + out << nl << "if(" << param << " != null && " << param << ".HasValue && " + << stream << ".writeOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + out << nl << stream << ".startSize();"; + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << nl << stream << ".endSize();"; + out << eb; + } + else + { + out << nl << "if(" << stream << ".readOpt(" << tag << ", " << getOptionalType(seq) << "))"; + out << sb; + out << nl << stream << ".skip(4);"; + writeSequenceMarshalUnmarshalCode(out, seq, param + ".Value", marshal, streamingAPI, true); + out << eb; + } +} + string Slice::CsGenerator::toArrayAlloc(const string& decl, const string& sz) { |