diff options
author | Benoit Foucher <benoit@zeroc.com> | 2009-02-09 19:20:38 +0100 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2009-02-09 19:20:38 +0100 |
commit | 124b43c7bd718655556bd3cba2a554293bf63d16 (patch) | |
tree | 5c3138e3c96e9f3a4763e1b6eea92018d892b241 /cpp/src | |
parent | Bug 3519 - fix use of tolower in slice2freeze (diff) | |
download | ice-124b43c7bd718655556bd3cba2a554293bf63d16.tar.bz2 ice-124b43c7bd718655556bd3cba2a554293bf63d16.tar.xz ice-124b43c7bd718655556bd3cba2a554293bf63d16.zip |
Support for serializable and protobuf metadata (from cs_serial branch)
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Slice/CPlusPlusUtil.cpp | 142 | ||||
-rw-r--r-- | cpp/src/Slice/CsUtil.cpp | 38 | ||||
-rw-r--r-- | cpp/src/Slice/JavaUtil.cpp | 200 | ||||
-rw-r--r-- | cpp/src/Slice/PythonUtil.cpp | 64 | ||||
-rw-r--r-- | cpp/src/slice2cpp/Gen.cpp | 235 | ||||
-rw-r--r-- | cpp/src/slice2cs/Gen.cpp | 23 | ||||
-rw-r--r-- | cpp/src/slice2java/Gen.cpp | 17 |
7 files changed, 617 insertions, 102 deletions
diff --git a/cpp/src/Slice/CPlusPlusUtil.cpp b/cpp/src/Slice/CPlusPlusUtil.cpp index 6997b9b436c..e09e622ea41 100644 --- a/cpp/src/Slice/CPlusPlusUtil.cpp +++ b/cpp/src/Slice/CPlusPlusUtil.cpp @@ -215,6 +215,13 @@ Slice::typeToString(const TypePtr& type, bool useWstring, const StringList& meta } else { + // Get the metadata associated at the point of definition. + bool protobuf; + seqType = findMetaData(seq, seq->getMetaData(), true, protobuf); + if(protobuf && !seqType.empty()) + { + return seqType; + } return fixKwd(seq->scoped()); } } @@ -348,6 +355,13 @@ Slice::inputTypeToString(const TypePtr& type, bool useWstring, const StringList& } else { + // Get the metadata associated at the point of definition. + bool protobuf; + seqType = findMetaData(seq, seq->getMetaData(), true, protobuf); + if(protobuf && !seqType.empty()) + { + return "const " + seqType + "&"; + } return "const " + fixKwd(seq->scoped()) + "&"; } } @@ -432,6 +446,12 @@ Slice::outputTypeToString(const TypePtr& type, bool useWstring, const StringList } else { + bool protobuf; + seqType = findMetaData(seq, seq->getMetaData(), true, protobuf); + if(protobuf && !seqType.empty()) + { + return seqType + "&"; + } return fixKwd(seq->scoped()) + "&"; } } @@ -679,6 +699,7 @@ Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& if(marshal) { string scope = fixKwd(seq->scope()); + if(seqType == "array" || seqType == "range:array") { // @@ -758,11 +779,13 @@ Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& else { // - // No modifying metadata specified. Use appropriate write methods for type. + // No modifying metadata specified. Use appropriate + // write methods for type. // StringList l = seq->getMetaData(); - seqType = findMetaData(l, false); - if(!seqType.empty()) + bool protobuf; + seqType = findMetaData(seq, l, false, protobuf); + if(protobuf || !seqType.empty()) { out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; @@ -911,12 +934,14 @@ Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& else { // - // No modifying metadata supplied. Just use appropriate read function. + // No modifying metadata supplied. Just use + // appropriate read function. // StringList l = seq->getMetaData(); - seqType = findMetaData(l, false); - if(!seqType.empty() || !builtin || builtin->kind() == Builtin::KindObject || - builtin->kind() == Builtin::KindObjectProxy) + bool protobuf; + seqType = findMetaData(seq, l, false, protobuf); + if(protobuf || !seqType.empty() || !builtin || builtin->kind() == Builtin::KindObject || + builtin->kind() == Builtin::KindObjectProxy) { out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam << ");"; @@ -1019,8 +1044,13 @@ writeRangeAllocateCode(Output& out, const TypePtr& type, const string& fixedName SequencePtr seq = SequencePtr::dynamicCast(type); if(seq) { - string seqType = findMetaData(metaData, true); - if(seqType.find("range") == 0 && seqType != "range:array") + bool protobuf; + string seqType = findMetaData(seq, metaData, true, protobuf); + if(!protobuf && seqType.empty()) + { + seqType = findMetaData(seq, seq->getMetaData(), true, protobuf); + } + if(!protobuf && seqType.find("range") == 0 && seqType != "range:array") { StringList md; if(seqType.find("range:") == 0) @@ -1305,9 +1335,10 @@ Slice::writeStreamMarshalUnmarshalCode(Output& out, const TypePtr& type, const s } else { - seqType = findMetaData(seq->getMetaData(), false); + bool protobuf; + seqType = findMetaData(seq, seq->getMetaData(), false, protobuf); builtin = BuiltinPtr::dynamicCast(seq->type()); - if(!seqType.empty() || !builtin || (builtin->kind() == Builtin::KindObject || + if(protobuf || !seqType.empty() || !builtin || (builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)) { string scope = fixKwd(seq->scope()); @@ -1501,6 +1532,95 @@ Slice::writeStreamMarshalUnmarshalCode(Output& out, const TypePtr& type, const s assert(false); } +// Accepted metadata. +// +// cpp:type:<typename> +// cpp:const +// cpp:array +// cpp:range:<typename> +// cpp:protobuf<:typename> +// + +// This form is for sequences definitions only. +string +Slice::findMetaData(const SequencePtr& seq, const StringList& metaData, bool inParam, bool& isProtobuf) +{ + isProtobuf = false; + static const string prefix = "cpp:"; + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) + { + string str = *q; + if(str.find(prefix) == 0) + { + string::size_type pos = str.find(':', prefix.size()); + string ss; + if(pos == string::npos) + { + ss = str.substr(prefix.size()); + } + else + { + ss = str.substr(prefix.size(), pos - prefix.size()); + } + // + // If the form is cpp:type:<...> the data after cpp:type: + // is returned. If the form is cpp:range:<...> (and this + // is an inParam) the data after cpp: is returned. + // + if(ss == "protobuf" || pos != string::npos) + { + string ss = str.substr(prefix.size(), pos - prefix.size()); + if(ss == "type") + { + return str.substr(pos + 1); + } + else if(ss == "protobuf") + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + continue; + } + isProtobuf = true; + if(pos != string::npos) + { + return str.substr(pos + 1); + } + return ""; + } + else if(inParam && ss == "range") + { + return str.substr(prefix.size()); + } + } + // + // If the data is an inParam and the metadata is cpp:array + // or cpp:range then array or range is returned. + // + else if(inParam) + { + if(ss == "array" || ss == "range") + { + return ss; + } + } + // + // Otherwise if the data is "class" it is returned. + // + else + { + if(ss == "class") + { + return ss; + } + } + } + } + + return ""; +} + +// Does not handle cpp:protobuf string Slice::findMetaData(const StringList& metaData, bool inParam) { diff --git a/cpp/src/Slice/CsUtil.cpp b/cpp/src/Slice/CsUtil.cpp index a2f722b2dcb..58b41e7045c 100644 --- a/cpp/src/Slice/CsUtil.cpp +++ b/cpp/src/Slice/CsUtil.cpp @@ -214,6 +214,13 @@ Slice::CsGenerator::typeToString(const TypePtr& type) } } + prefix = "clr:serializable:"; + if(seq->findMetaData(prefix, meta)) + { + string type = meta.substr(prefix.size()); + return global() + type; + } + return typeToString(seq->type()) + "[]"; } @@ -888,6 +895,21 @@ Slice::CsGenerator::writeSequenceMarshalUnmarshalCode(Output& out, } default: { + string prefix = "clr:serializable:"; + string meta; + if(seq->findMetaData(prefix, meta)) + { + if(marshal) + { + out << nl << stream << ".writeSerializable(" << param << ");"; + } + else + { + out << nl << param << " = (" << typeToString(seq) << ")" << stream << ".readSerializable();"; + } + break; + } + typeS[0] = toupper(static_cast<unsigned char>(typeS[0])); if(marshal) { @@ -1688,6 +1710,22 @@ Slice::CsGenerator::MetaDataVisitor::validate(const ContainedPtr& cont) continue; // Custom type or List<T> } } + if(s.substr(prefix.size(), 13) == "serializable:") + { + string meta; + if(cont->findMetaData(prefix + "collection", meta) + || cont->findMetaData(prefix + "generic:", meta)) + { + emitWarning(file, cont->line(), msg + " `" + meta + "':\n" + + "serialization can only be used with the array mapping for byte sequences"); + } + string type = s.substr(prefix.size() + 13); + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(!type.empty() && builtin && builtin->kind() == Builtin::KindByte) + { + continue; + } + } } else if(StructPtr::dynamicCast(cont)) { diff --git a/cpp/src/Slice/JavaUtil.cpp b/cpp/src/Slice/JavaUtil.cpp index 99b617e2146..5c4b2420f90 100644 --- a/cpp/src/Slice/JavaUtil.cpp +++ b/cpp/src/Slice/JavaUtil.cpp @@ -551,6 +551,22 @@ Slice::JavaGenerator::typeToString(const TypePtr& type, } else { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string prefix = "java:serializable:"; + string meta; + if(seq->findMetaData(prefix, meta)) + { + return string("Ice.Holder<") + meta.substr(prefix.size()) + " >"; + } + prefix = "java:protobuf:"; + if(seq->findMetaData(prefix, meta)) + { + return string("Ice.Holder<") + meta.substr(prefix.size()) + " >"; + } + } + // // Only use the type's generated holder if the instance and // formal types match. @@ -595,6 +611,22 @@ Slice::JavaGenerator::typeToString(const TypePtr& type, } else { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string prefix = "java:serializable:"; + string meta; + if(seq->findMetaData(prefix, meta)) + { + return meta.substr(prefix.size()); + } + prefix = "java:protobuf:"; + if(seq->findMetaData(prefix, meta)) + { + return meta.substr(prefix.size()); + } + } + string instanceType, formalType; getSequenceTypes(seq, package, metaData, instanceType, formalType); return formal ? formalType : instanceType; @@ -1241,15 +1273,64 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode(Output& out, { string stream = marshal ? "__os" : "__is"; string v = param; + bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; + + // + // If the sequence is a byte sequence, check if there's the serializable or protobuf metadata to + // get rid of these two easy cases first. + // + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string meta; + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; + if(seq->findMetaData(serializable, meta)) + { + if(marshal) + { + out << nl << stream << ".writeSerializable(" << v << ");"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << v << " = (" << type << ")" << stream << ".readSerializable();"; + } + return; + } + else if(seq->findMetaData(protobuf, meta)) + { + if(marshal) + { + out << nl << "if(!" << v << ".isInitialized())"; + out << sb; + out << nl << "throw new Ice.MarshalException(\"type not fully initialized\");"; + out << eb; + out << nl << stream << ".writeByteSeq(" << v << ".toByteArray());"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << "try"; + out << sb; + out << nl << v << " = " << type << ".parseFrom(" << stream << ".readByteSeq());"; + out << eb; + out << nl << "catch(com.google.protobuf.InvalidProtocolBufferException __ex)"; + out << sb; + out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();"; + out << nl << "__mex.initCause(__ex);"; + out << nl << "throw __mex;"; + out << eb; + } + return; + } + } - bool java2 = false; bool customType = false; string instanceType; if(_featureProfile != Slice::IceE) { - java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; - // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal @@ -1300,7 +1381,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode(Output& out, while(s) { // - // Stop if the inner sequence type has a custom type. + // Stop if the inner sequence type has a custom, serializable or protobuf type. // if(hasTypeMetaData(s) && _featureProfile != Slice::IceE) { @@ -2496,10 +2577,60 @@ Slice::JavaGenerator::writeStreamSequenceMarshalUnmarshalCode(Output& out, { string stream = marshal ? "__outS" : "__inS"; string v = param; - bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // + // If the sequence is a byte sequence, check if there's the serializable or protobuf metadata to + // get rid of these two easy cases first. + // + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string meta; + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; + if(seq->findMetaData(serializable, meta)) + { + if(marshal) + { + out << nl << stream << ".writeSerializable(" << v << ");"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << v << " = (" << type << ")" << stream << ".readSerializable();"; + } + return; + } + else if(seq->findMetaData(protobuf, meta)) + { + if(marshal) + { + out << nl << "if(!" << v << ".isInitialized())"; + out << sb; + out << nl << "throw new Ice.MarshalException(\"type not fully initialized\");"; + out << eb; + out << nl << stream << ".writeByteSeq(" << v << ".toByteArray());"; + } + else + { + string type = meta.substr(protobuf.size()); + out << nl << "try"; + out << sb; + out << nl << v << " = " << type << ".parseFrom(" << stream << ".readByteSeq());"; + out << eb; + out << nl << "catch(com.google.protobuf.InvalidProtocolBufferException __ex)"; + out << sb; + out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();"; + out << nl << "__mex.initCause(__ex);"; + out << nl << "throw __mex;"; + out << eb; + } + return; + } + } + + // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in @@ -2548,7 +2679,7 @@ Slice::JavaGenerator::writeStreamSequenceMarshalUnmarshalCode(Output& out, while(s) { // - // Stop if the inner sequence type has a custom type. + // Stop if the inner sequence type has a custom, serializable or protobuf type. // if(hasTypeMetaData(s)) { @@ -3145,6 +3276,18 @@ Slice::JavaGenerator::hasTypeMetaData(const TypePtr& type, const StringList& loc { return true; } + else if(str.find("java:protobuf:") == 0 || str.find("java:serializable:") == 0) + { + SequencePtr seq = SequencePtr::dynamicCast(cont); + if(seq) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + return true; + } + } + } } } @@ -3533,9 +3676,33 @@ Slice::JavaGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) void Slice::JavaGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) { + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + const string file = p->definitionContext()->filename(); + const string line = p->line(); + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ) + { + string s = *q++; + if(s.find(protobuf) == 0 || s.find(serializable) == 0) + { + // + // Remove from list so validateType does not try to handle as well. + // + metaData.remove(s); + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + _history.insert(s); + emitWarning(file, line, "ignoring invalid metadata `" + s + "':\n" + + "this metadata can only be used with a byte sequence"); + } + } + } + + validateType(p, metaData, file, line); + validateGetSet(p, metaData, file, line); } void @@ -3598,6 +3765,16 @@ Slice::JavaGenerator::MetaDataVisitor::getMetaData(const ContainedPtr& cont) result.push_back(s); continue; } + else if(s.substr(prefix.size(), pos - prefix.size()) == "serializable") + { + result.push_back(s); + continue; + } + else if(s.substr(prefix.size(), pos - prefix.size()) == "protobuf") + { + result.push_back(s); + continue; + } emitWarning(file, cont->line(), "ignoring invalid metadata `" + s + "'"); } @@ -3634,6 +3811,13 @@ Slice::JavaGenerator::MetaDataVisitor::validateType(const SyntaxTreeBasePtr& p, } emitWarning(file, line, "invalid metadata for " + str); } + else if(i->find("java:protobuf:") == 0 || i->find("java:serializable:") == 0) + { + // + // Only valid in sequence defintion which is checked in visitSequence + // + emitWarning(file, line, "ignoring invalid metadata `" + *i + "'"); + } } } diff --git a/cpp/src/Slice/PythonUtil.cpp b/cpp/src/Slice/PythonUtil.cpp index c1c91b3f289..7dc251b25df 100644 --- a/cpp/src/Slice/PythonUtil.cpp +++ b/cpp/src/Slice/PythonUtil.cpp @@ -1204,17 +1204,46 @@ Slice::Python::CodeVisitor::visitStructStart(const StructPtr& p) void Slice::Python::CodeVisitor::visitSequence(const SequencePtr& p) { + static const string protobuf = "python:protobuf:"; + StringList metaData = p->getMetaData(); + bool isCustom = false; + string customType; + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ++q) + { + if(q->find(protobuf) == 0) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + continue; + } + isCustom = true; + customType = q->substr(protobuf.size()); + break; + } + } + // // Emit the type information. // string scoped = p->scoped(); _out << sp << nl << "if not " << getDictLookup(p, "_t_") << ':'; _out.inc(); - _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineSequence('" << scoped << "', "; - writeMetaData(p->getMetaData()); - _out << ", "; - writeType(p->type()); - _out << ")"; + if(isCustom) + { + string package = customType.substr(0, customType.find('.')); + _out << nl << "import " << package; + _out << nl << "_M_" << getAbsolute(p, "_t_") + << " = IcePy.defineCustom('" << scoped << "', " << customType << ")"; + } + else + { + _out << nl << "_M_" << getAbsolute(p, "_t_") << " = IcePy.defineSequence('" << scoped << "', "; + writeMetaData(metaData); + _out << ", "; + writeType(p->type()); + _out << ")"; + } _out.dec(); } @@ -2032,7 +2061,30 @@ Slice::Python::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) void Slice::Python::MetaDataVisitor::visitSequence(const SequencePtr& p) { - validateSequence(p->definitionContext(), p->line(), p, p->getMetaData()); + static const string protobuf = "python:protobuf:"; + StringList metaData = p->getMetaData(); + const string file = p->definitionContext()->filename(); + const string line = p->line(); + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ) + { + string s = *q++; + if(s.find(protobuf) == 0) + { + // + // Remove from list so validateSequence does not try to handle as well. + // + metaData.remove(s); + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + emitWarning(file, line, "ignoring invalid metadata `" + s + ":\n" + + "`protobuf' encoding must be a byte sequence"); + } + } + } + + validateSequence(p->definitionContext(), line, p, metaData); } void diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 3ab5e21fcd4..513b9f684ee 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -1151,14 +1151,20 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) TypePtr type = p->type(); string s = typeToString(type, _useWstring, p->typeMetaData()); StringList metaData = p->getMetaData(); - string seqType = findMetaData(metaData, false); - if(!seqType.empty()) - { - H << sp << nl << "typedef " << seqType << ' ' << name << ';'; - } - else + + bool protobuf; + string seqType = findMetaData(p, metaData, false, protobuf); + H << sp; + if(!protobuf) { - H << sp << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';'; + if(!seqType.empty()) + { + H << nl << "typedef " << seqType << ' ' << name << ';'; + } + else + { + H << nl << "typedef ::std::vector<" << (s[0] == ':' ? " " : "") << s << "> " << name << ';'; + } } BuiltinPtr builtin = BuiltinPtr::dynamicCast(type); @@ -1167,100 +1173,163 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) string scoped = fixKwd(p->scoped()); string scope = fixKwd(p->scope()); - if(!seqType.empty()) + if(protobuf || !seqType.empty()) { - H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " << name << "&);"; - H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " << name << "&);"; + string typeName = name; + string scopedName = scoped; + if(protobuf && !seqType.empty()) + { + typeName = seqType; + scopedName = seqType; + } + H << nl << _dllExport << "void __write" << name << "(::IceInternal::BasicStream*, const " + << typeName << "&);"; + H << nl << _dllExport << "void __read" << name << "(::IceInternal::BasicStream*, " + << typeName << "&);"; if(_stream) { H << nl << _dllExport << "void ice_write" << p->name() << "(const ::Ice::OutputStreamPtr&, const " - << name << "&);"; - H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << name + << typeName << "&);"; + H << nl << _dllExport << "void ice_read" << p->name() << "(const ::Ice::InputStreamPtr&, " << typeName << "&);"; } C << sp << nl << "void" << nl << scope.substr(2) << "__write" << name << - "(::IceInternal::BasicStream* __os, const " << scoped << "& v)"; - C << sb; - C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());"; - C << nl << "__os->writeSize(size);"; - C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)"; + "(::IceInternal::BasicStream* __os, const " << scopedName << "& v)"; C << sb; - writeMarshalUnmarshalCode(C, type, "(*p)", true); - C << eb; + if(protobuf) + { + C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());"; + C << nl << "if(!v.IsInitialized())"; + C << sb; + C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());"; + C << eb; + C << nl << "if(!v.SerializeToArray(&data[0], data.size()))"; + C << sb; + C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"SerializeToArray failed\");"; + C << eb; + C << nl << "__os->write(&data[0], &data[0] + data.size());"; + } + else + { + C << nl << "::Ice::Int size = static_cast< ::Ice::Int>(v.size());"; + C << nl << "__os->writeSize(size);"; + C << nl << "for(" << name << "::const_iterator p = v.begin(); p != v.end(); ++p)"; + C << sb; + writeMarshalUnmarshalCode(C, type, "(*p)", true); + C << eb; + } C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "__read" << name - << "(::IceInternal::BasicStream* __is, " << scoped << "& v)"; + << "(::IceInternal::BasicStream* __is, " << scopedName << "& v)"; C << sb; - C << nl << "::Ice::Int sz;"; - C << nl << "__is->readSize(sz);"; - C << nl << name << "(sz).swap(v);"; - if(type->isVariableLength()) + if(protobuf) { - // Protect against bogus sequence sizes. - C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");"; + C << nl << "::std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;"; + C << nl << "__is->read(data);"; + C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))"; + C << sb; + C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");"; + C << eb; } else { - C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");"; - } - C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)"; - C << sb; - writeMarshalUnmarshalCode(C, type, "(*p)", false); + C << nl << "::Ice::Int sz;"; + C << nl << "__is->readSize(sz);"; + C << nl << name << "(sz).swap(v);"; + if(type->isVariableLength()) + { + // Protect against bogus sequence sizes. + C << nl << "__is->startSeq(sz, " << type->minWireSize() << ");"; + } + else + { + C << nl << "__is->checkFixedSeq(sz, " << type->minWireSize() << ");"; + } + C << nl << "for(" << name << "::iterator p = v.begin(); p != v.end(); ++p)"; + C << sb; + writeMarshalUnmarshalCode(C, type, "(*p)", false); - // - // After unmarshaling each element, check that there are still enough bytes left in the stream - // to unmarshal the remainder of the sequence, and decrement the count of elements - // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences - // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to - // abort unmarshaling for bogus sequence sizes at the earliest possible moment. - // (For fixed-length sequences, we don't need to do this because the prediction of how many - // bytes will be taken up by the sequence is accurate.) - // - if(type->isVariableLength()) - { - if(!SequencePtr::dynamicCast(type)) + // + // After unmarshaling each element, check that there are still enough bytes left in the stream + // to unmarshal the remainder of the sequence, and decrement the count of elements + // yet to be unmarshaled for sequences with variable-length element type (that is, for sequences + // of classes, structs, dictionaries, sequences, strings, or proxies). This allows us to + // abort unmarshaling for bogus sequence sizes at the earliest possible moment. + // (For fixed-length sequences, we don't need to do this because the prediction of how many + // bytes will be taken up by the sequence is accurate.) + // + if(type->isVariableLength()) { - // - // No need to check for directly nested sequences because, at the start of each - // sequence, we check anyway. - // - C << nl << "__is->checkSeq();"; + if(!SequencePtr::dynamicCast(type)) + { + // + // No need to check for directly nested sequences because, at the start of each + // sequence, we check anyway. + // + C << nl << "__is->checkSeq();"; + } + C << nl << "__is->endElement();"; + } + C << eb; + if(type->isVariableLength()) + { + C << nl << "__is->endSeq(sz);"; } - C << nl << "__is->endElement();"; - } - C << eb; - if(type->isVariableLength()) - { - C << nl << "__is->endSeq(sz);"; } C << eb; if(_stream) { C << sp << nl << "void" << nl << scope.substr(2) << "ice_write" << p->name() - << "(const ::Ice::OutputStreamPtr& __outS, const " << scoped << "& v)"; - C << sb; - C << nl << "__outS->writeSize(::Ice::Int(v.size()));"; - C << nl << scoped << "::const_iterator p;"; - C << nl << "for(p = v.begin(); p != v.end(); ++p)"; + << "(const ::Ice::OutputStreamPtr& __outS, const " << scopedName << "& v)"; C << sb; - writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", _useWstring); - C << eb; + if(protobuf) + { + C << nl << "std::vector< ::Ice::Byte> data(v.ByteSize());"; + C << nl << "if(!v.IsInitialized())"; + C << sb; + C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"type not fully initialized: \" + v.InitializationErrorString());"; + C << eb; + C << nl << "v.SerializeToArray(&data[0], data.size());"; + + C << nl << "__outS->writeByteSeq(data);"; + } + else + { + C << nl << "__outS->writeSize(::Ice::Int(v.size()));"; + C << nl << scopedName << "::const_iterator p;"; + C << nl << "for(p = v.begin(); p != v.end(); ++p)"; + C << sb; + writeStreamMarshalUnmarshalCode(C, type, "(*p)", true, "", _useWstring); + C << eb; + } C << eb; C << sp << nl << "void" << nl << scope.substr(2) << "ice_read" << p->name() - << "(const ::Ice::InputStreamPtr& __inS, " << scoped << "& v)"; - C << sb; - C << nl << "::Ice::Int sz = __inS->readSize();"; - C << nl << scoped << "(sz).swap(v);"; - C << nl << scoped << "::iterator p;"; - C << nl << "for(p = v.begin(); p != v.end(); ++p)"; + << "(const ::Ice::InputStreamPtr& __inS, " << scopedName << "& v)"; C << sb; - writeStreamMarshalUnmarshalCode(C, type, "(*p)", false, "", _useWstring); - C << eb; + if(protobuf) + { + C << nl << "std::pair<const ::Ice::Byte*, const ::Ice::Byte*> data;"; + C << nl << "__inS->readByteSeq(data);"; + C << nl << "if(!v.ParseFromArray(data.first, data.second - data.first))"; + C << sb; + C << nl << "throw ::Ice::MarshalException(__FILE__, __LINE__, \"ParseFromArray failed\");"; + C << eb; + } + else + { + C << nl << "::Ice::Int sz = __inS->readSize();"; + C << nl << scopedName << "(sz).swap(v);"; + C << nl << scopedName << "::iterator p;"; + C << nl << "for(p = v.begin(); p != v.end(); ++p)"; + C << sb; + writeStreamMarshalUnmarshalCode(C, type, "(*p)", false, "", _useWstring); + C << eb; + } C << eb; } } @@ -5749,6 +5818,7 @@ Slice::Gen::MetaDataVisitor::visitStructEnd(const StructPtr&) void Slice::Gen::MetaDataVisitor::visitOperation(const OperationPtr& p) { + bool ami = false; ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container()); if(cl->hasMetaData("ami") || p->hasMetaData("ami") || cl->hasMetaData("amd") || p->hasMetaData("amd")) @@ -5814,7 +5884,31 @@ Slice::Gen::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) void Slice::Gen::MetaDataVisitor::visitSequence(const SequencePtr& p) { - validate(p, p->getMetaData(), p->definitionContext()->filename(), p->line()); + StringList metaData = p->getMetaData(); + const string file = p->definitionContext()->filename(); + const string line = p->line(); + static const string prefix = "cpp:protobuf"; + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ) + { + string s = *q++; + if(s.find(prefix) == 0) + { + // + // Remove from list so validate does not try to handle as well. + // + metaData.remove(s); + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + _history.insert(s); + emitWarning(file, line, "ignoring invalid metadata `" + s + "':\n"+ + "`protobuf' encoding must be a byte sequence."); + } + } + } + + validate(p, metaData, file, line); } void @@ -5871,7 +5965,6 @@ Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const Strin { continue; } - emitWarning(file, line, "ignoring invalid metadata `" + s + "'"); } _history.insert(s); diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 9a2a4ae2f08..a2420094869 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -1666,6 +1666,15 @@ Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p) return; } + // + // No need to generate anything for serializable sequences. + // + prefix = "clr:serializable:"; + if(p->findMetaData(prefix, meta)) + { + return; + } + string name = fixId(p->name()); string s = typeToString(p->type()); @@ -2732,9 +2741,10 @@ Slice::Gen::TypesVisitor::writeMemberHashCode(const DataMemberList& dataMembers, SequencePtr seq = SequencePtr::dynamicCast(memberType); if(seq) { - string genericType; - bool isGeneric = seq->findMetaData("clr:generic:", genericType); - bool isArray = !isGeneric && !seq->hasMetaData("clr:collection"); + string meta; + bool isSerializable = seq->findMetaData("clr:serializable", meta); + bool isGeneric = seq->findMetaData("clr:generic:", meta); + bool isArray = !isSerializable && !isGeneric && !seq->hasMetaData("clr:collection"); if(isArray) { // @@ -2811,9 +2821,10 @@ Slice::Gen::TypesVisitor::writeMemberEquals(const DataMemberList& dataMembers, i SequencePtr seq = SequencePtr::dynamicCast(memberType); if(seq) { - string genericType; - bool isGeneric = seq->findMetaData("clr:generic:", genericType); - bool isArray = !isGeneric && !seq->hasMetaData("clr:collection"); + string meta; + bool isSerializable = seq->findMetaData("clr:serializable:", meta); + bool isGeneric = seq->findMetaData("clr:generic:", meta); + bool isArray = !isSerializable && !isGeneric && !seq->hasMetaData("clr:collection"); if(isArray) { // diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index 9142e4b6e05..4289a6ae5a9 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -3185,6 +3185,23 @@ Slice::Gen::HolderVisitor::visitStructStart(const StructPtr& p) void Slice::Gen::HolderVisitor::visitSequence(const SequencePtr& p) { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string prefix = "java:serializable:"; + string meta; + if(p->findMetaData(prefix, meta)) + { + return; // No holders for serializable types. + } + prefix = "java:protobuf:"; + if(p->findMetaData(prefix, meta)) + { + return; // No holders for protobuf types. + + } + } + writeHolder(p); } |