diff --git a/cpp/src/slice2cpp/CPlusPlusUtil.cpp b/cpp/src/slice2cpp/CPlusPlusUtil.cpp index 7245af256e0..542c873ab92 100644 --- a/cpp/src/slice2cpp/CPlusPlusUtil.cpp +++ b/cpp/src/slice2cpp/CPlusPlusUtil.cpp @@ -20,63 +20,30 @@ using namespace IceUtilInternal; namespace { -string toTemplateArg(const string& arg) -{ - if(arg.empty()) - { - return arg; - } - string fixed = arg; - if(arg[0] == ':') - { - fixed = " " + fixed; - } - if(fixed[fixed.length() - 1] == '>') - { - fixed = fixed + " "; - } - return fixed; -} - string -toOptional(const TypePtr& type, const string& scope, const StringList& metaData, int typeCtx) +stringTypeToString(const TypePtr&, const StringList& metaData, TypeContext typeCtx) { - if (isProxyType(type)) + string strType = findMetaData(metaData, typeCtx); + + if (strType == "") { - // We map optional proxies like regular proxies, as optional. - return typeToString(type, scope, metaData, typeCtx); + strType = (typeCtx & TypeContext::UseWstring) != TypeContext::None ? "::std::wstring" : "::std::string"; } else { - return "::std::optional<" + typeToString(type, scope, metaData, typeCtx) + '>'; + assert(strType == "string" || strType == "wstring"); + strType = "::std::" + strType; } -} -string -stringTypeToString(const TypePtr&, const StringList& metaData, int typeCtx) -{ - string strType = findMetaData(metaData, typeCtx); - if(strType == "wstring" || (typeCtx & TypeContextUseWstring && strType == "")) - { - // TODO: if we're still using TypeContextAMIPrivateEnd, we should give it a better name. - // TODO: should be something like the following line but doesn't work currently - // return (typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd)) ? "::std::wstring_view" : "::std::wstring"; - return "::std::wstring"; - } - else if(strType != "" && strType != "string") + if ((typeCtx & TypeContext::MarshalParam) != TypeContext::None) { - // The user provided a type name, we use it as-is. - return strType; - } - else - { - return "::std::string"; - // return (typeCtx & TypeContextInParam) ? "::std::string_view" : "::std::string"; + strType += "_view"; } + return strType; } string -sequenceTypeToString(const SequencePtr& seq, const string& scope, const StringList& metaData, int typeCtx) +sequenceTypeToString(const SequencePtr& seq, const string& scope, const StringList& metaData, TypeContext typeCtx) { string seqType = findMetaData(metaData, typeCtx); if(!seqType.empty()) @@ -84,31 +51,8 @@ sequenceTypeToString(const SequencePtr& seq, const string& scope, const StringLi if(seqType == "%array") { BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); - if(typeCtx & TypeContextAMIPrivateEnd) - { - if(builtin && builtin->kind() == Builtin::KindByte) - { - string s = typeToString(seq->type(), scope); - return "::std::pair"; - } - else if(builtin && - builtin->kind() != Builtin::KindString && - builtin->kind() != Builtin::KindObject && - builtin->kind() != Builtin::KindObjectProxy) - { - string s = toTemplateArg(typeToString(builtin, scope)); - return "::std::pair< ::IceUtil::ScopedArray<" + s + ">, " + - "::std::pair >"; - } - else - { - string s = toTemplateArg(typeToString(seq->type(), scope, seq->typeMetaData(), - inWstringModule(seq) ? TypeContextUseWstring : 0)); - return "::std::vector<" + s + '>'; - } - } - string s = typeToString(seq->type(), scope, seq->typeMetaData(), - typeCtx | (inWstringModule(seq) ? TypeContextUseWstring : 0)); + string s = typeToString(seq->type(), false, scope, seq->typeMetaData(), + typeCtx | (inWstringModule(seq) ? TypeContext::UseWstring : TypeContext::None)); return "::std::pair"; } else @@ -123,7 +67,7 @@ sequenceTypeToString(const SequencePtr& seq, const string& scope, const StringLi } string -dictionaryTypeToString(const DictionaryPtr& dict, const string& scope, const StringList& metaData, int typeCtx) +dictionaryTypeToString(const DictionaryPtr& dict, const string& scope, const StringList& metaData, TypeContext typeCtx) { const string dictType = findMetaData(metaData, typeCtx); if(dictType.empty()) @@ -138,106 +82,20 @@ dictionaryTypeToString(const DictionaryPtr& dict, const string& scope, const Str void writeParamAllocateCode(Output& out, const TypePtr& type, bool optional, const string& scope, const string& fixedName, - const StringList& metaData, int typeCtx) + const StringList& metaData, TypeContext typeCtx) { string s = typeToString(type, optional, scope, metaData, typeCtx); out << nl << s << ' ' << fixedName << ';'; } void -writeParamEndCode(Output& out, const TypePtr& type, bool optional, const string& fixedName, const StringList& metaData, - const string& obj = "") +writeMarshalUnmarshalParams(Output& out, const ParamDeclList& params, const OperationPtr& op, bool marshal) { - string objPrefix = obj.empty() ? obj : obj + "."; - string paramName = objPrefix + fixedName; - string escapedParamName = objPrefix + fixedName + "_tmp_"; + const string returnValueS = "ret"; + const string stream = marshal ? "ostr" : "istr"; - SequencePtr seq = dynamic_pointer_cast(type); - if(seq) - { - string seqType = findMetaData(metaData, TypeContextInParam); - if(seqType.empty()) - { - seqType = findMetaData(seq->getMetaData(), TypeContextInParam); - } - - if(seqType == "%array") - { - BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); - if(builtin && - builtin->kind() != Builtin::KindByte && - builtin->kind() != Builtin::KindString && - builtin->kind() != Builtin::KindObject && - builtin->kind() != Builtin::KindObjectProxy) - { - if(optional) - { - out << nl << "if(" << escapedParamName << ")"; - out << sb; - out << nl << paramName << " = " << escapedParamName << "->second;"; - out << eb; - } - else - { - out << nl << paramName << " = " << escapedParamName << ".second;"; - } - } - else if(!builtin || - builtin->kind() == Builtin::KindString || - builtin->kind() == Builtin::KindObject || - builtin->kind() == Builtin::KindObjectProxy) - { - if(optional) - { - out << nl << "if(" << escapedParamName << ")"; - out << sb; - out << nl << paramName << ".emplace();"; - out << nl << "if(!" << escapedParamName << "->empty())"; - out << sb; - out << nl << paramName << "->first" << " = &(*" << escapedParamName << ")[0];"; - out << nl << paramName << "->second" << " = " << paramName << "->first + " << escapedParamName - << "->size();"; - out << eb; - out << nl << "else"; - out << sb; - out << nl << paramName << "->first" << " = " << paramName << "->second" << " = 0;"; - out << eb; - out << eb; - } - else - { - out << nl << "if(!" << escapedParamName << ".empty())"; - out << sb; - out << nl << paramName << ".first" << " = &" << escapedParamName << "[0];"; - out << nl << paramName << ".second" << " = " << paramName << ".first + " << escapedParamName - << ".size();"; - out << eb; - out << nl << "else"; - out << sb; - out << nl << paramName << ".first" << " = " << paramName << ".second" << " = 0;"; - out << eb; - } - } - } - } -} - -void -writeMarshalUnmarshalParams(Output& out, const ParamDeclList& params, const OperationPtr& op, bool marshal, - bool prepend, int typeCtx, const string& customStream = "", const string& retP = "", - const string& obj = "") -{ - string prefix = prepend ? paramPrefix : ""; - string returnValueS = retP.empty() ? string("ret") : retP; - string objPrefix = obj.empty() ? obj : obj + "."; - - string stream = customStream; - if(stream.empty()) - { - stream = marshal ? "ostr" : "istr"; - } - - bool tuple = (typeCtx & TypeContextTuple) != 0; + // True when unmarshaling a tuple response. + bool tuple = !marshal && op && (params.size() + (op->returnType() ? 1 : 0)) > 1; // // Marshal non optional parameters. @@ -275,22 +133,22 @@ writeMarshalUnmarshalParams(Output& out, const ParamDeclList& params, const Oper if (tuple) { auto index = std::distance(params.begin(), std::find(params.begin(), params.end(), *p)) + retOffset; - out << "::std::get<" + std::to_string(index) + ">(" + obj + ")"; + out << "::std::get<" + std::to_string(index) + ">(v)"; } else { - out << objPrefix + fixKwd(prefix + (*p)->name()); + out << fixKwd(paramPrefix + (*p)->name()); } } if(op && op->returnType() && !op->returnIsOptional()) { if (tuple) { - out << "::std::get<0>(" + obj + ")"; + out << "::std::get<0>(v)"; } else { - out << objPrefix + returnValueS; + out << returnValueS; } } out << epar << ";"; @@ -360,11 +218,11 @@ writeMarshalUnmarshalParams(Output& out, const ParamDeclList& params, const Oper { if (tuple) { - out << "::std::get<0>(" + obj + ")"; + out << "::std::get<0>(v)"; } else { - out << objPrefix + returnValueS; + out << returnValueS; } checkReturnType = false; } @@ -372,22 +230,22 @@ writeMarshalUnmarshalParams(Output& out, const ParamDeclList& params, const Oper if (tuple) { auto index = std::distance(params.begin(), std::find(params.begin(), params.end(), *p)) + retOffset; - out << "::std::get<" + std::to_string(index) + ">(" + obj + ")"; + out << "::std::get<" + std::to_string(index) + ">(v)"; } else { - out << objPrefix + fixKwd(prefix + (*p)->name()); + out << fixKwd(paramPrefix + (*p)->name()); } } if(checkReturnType) { if (tuple) { - out << "::std::get<0>(" + obj + ")"; + out << "::std::get<0>(v)"; } else { - out << objPrefix + returnValueS; + out << returnValueS; } } } @@ -532,9 +390,24 @@ Slice::getUnqualified(const std::string& type, const std::string& scope) } string -Slice::typeToString(const TypePtr& type, const string& scope, const StringList& metaData, int typeCtx) +Slice::typeToString(const TypePtr& type, bool optional, const string& scope, const StringList& metaData, TypeContext typeCtx) { - static const char* builtinTable[] = + assert(type); + + if (optional) + { + if (isProxyType(type)) + { + // We map optional proxies like regular proxies, as optional. + return typeToString(type, false, scope, metaData, typeCtx); + } + else + { + return "::std::optional<" + typeToString(type, false, scope, metaData, typeCtx) + '>'; + } + } + + static constexpr string_view builtinTable[] = { "::std::uint8_t", "bool", @@ -560,11 +433,11 @@ Slice::typeToString(const TypePtr& type, const string& scope, const StringList& { if(builtin->kind() == Builtin::KindObject) { - return getUnqualified(builtinTable[Builtin::KindValue], scope); + return getUnqualified(string{builtinTable[Builtin::KindValue]}, scope); } else { - return getUnqualified(builtinTable[builtin->kind()], scope); + return getUnqualified(string{builtinTable[builtin->kind()]}, scope); } } } @@ -608,203 +481,37 @@ Slice::typeToString(const TypePtr& type, const string& scope, const StringList& return "???"; } -string -Slice::typeToString(const TypePtr& type, bool optional, const string& scope, const StringList& metaData, int typeCtx) -{ - if(optional) - { - return toOptional(type, scope, metaData, typeCtx); - } - else - { - return typeToString(type, scope, metaData, typeCtx); - } -} - -string -Slice::returnTypeToString(const TypePtr& type, bool optional, const string& scope, const StringList& metaData, - int typeCtx) -{ - if(!type) - { - return "void"; - } - - if(optional) - { - return toOptional(type, scope, metaData, typeCtx); - } - - return typeToString(type, scope, metaData, typeCtx); -} - string Slice::inputTypeToString(const TypePtr& type, bool optional, const string& scope, const StringList& metaData, - int typeCtx) + TypeContext typeCtx) { - static const char* InputBuiltinTable[] = - { - "::std::uint8_t", - "bool", - "::std::int16_t", - "::std::int32_t", - "::std::int64_t", - "float", - "double", - "****", // string_view or wstring_view, see below - "const ::std::shared_ptr<::Ice::Value>&", - "const ::std::optional<::Ice::ObjectPrx>&", - "const ::std::shared_ptr<::Ice::Value>&" - }; - - typeCtx |= TypeContextInParam; - - if(optional) - { - return "const " + toOptional(type, scope, metaData, typeCtx) + '&'; - } + assert(type); + assert(typeCtx == TypeContext::None || typeCtx == TypeContext::UseWstring); + typeCtx = (typeCtx | TypeContext::MarshalParam); - BuiltinPtr builtin = dynamic_pointer_cast(type); - if(builtin) + if (!optional) { - if(builtin->kind() == Builtin::KindString) + BuiltinPtr builtin = dynamic_pointer_cast(type); + if ((builtin && (!builtin->isVariableLength() || builtin->kind() == Builtin::KindString)) || + dynamic_pointer_cast(type)) { - // TODO: temporary, stringTypeToString should return the correct string. - return stringTypeToString(type, metaData, typeCtx) + "_view"; + // pass by value + return typeToString(type, optional, scope, metaData, typeCtx); } - else - { - if(builtin->kind() == Builtin::KindObject) - { - return getUnqualified(InputBuiltinTable[Builtin::KindValue], scope); - } - else - { - return getUnqualified(InputBuiltinTable[builtin->kind()], scope); - } - } - } - - ClassDeclPtr cl = dynamic_pointer_cast(type); - if(cl) - { - return "const ::std::shared_ptr<" + getUnqualified(fixKwd(cl->scoped()), scope) + ">&"; } - StructPtr st = dynamic_pointer_cast(type); - if(st) - { - return "const " + getUnqualified(fixKwd(st->scoped()), scope) + "&"; - } - - InterfaceDeclPtr proxy = dynamic_pointer_cast(type); - if(proxy) - { - return "const ::std::optional<" + getUnqualified(fixKwd(proxy->scoped() + "Prx"), scope) + ">&"; - } - - EnumPtr en = dynamic_pointer_cast(type); - if(en) - { - return getUnqualified(fixKwd(en->scoped()), scope); - } - - SequencePtr seq = dynamic_pointer_cast(type); - if(seq) - { - return "const " + sequenceTypeToString(seq, scope, metaData, typeCtx) + "&"; - } - - DictionaryPtr dict = dynamic_pointer_cast(type); - if(dict) - { - return "const " + dictionaryTypeToString(dict, scope, metaData, typeCtx) + "&"; - } - - return "???"; + // For all other types, pass by const reference. + return "const " + typeToString(type, optional, scope, metaData, typeCtx) + '&'; } string Slice::outputTypeToString(const TypePtr& type, bool optional, const string& scope, const StringList& metaData, - int typeCtx) + TypeContext typeCtx) { - static const char* outputBuiltinTable[] = - { - "::std::uint8_t&", - "bool&", - "::std::int16_t&", - "::std::int32_t&", - "::std::int64_t&", - "float&", - "double&", - "****", // string& or wstring&, see below - "::std::shared_ptr<::Ice::Value>&", - "::std::optional<::Ice::ObjectPrx>&", - "::std::shared_ptr<::Ice::Value>&" - }; - - if(optional) - { - return toOptional(type, scope, metaData, typeCtx) + '&'; - } - - BuiltinPtr builtin = dynamic_pointer_cast(type); - if(builtin) - { - if(builtin->kind() == Builtin::KindString) - { - return stringTypeToString(type, metaData, typeCtx) + "&"; - } - else - { - if(builtin->kind() == Builtin::KindObject) - { - return getUnqualified(outputBuiltinTable[Builtin::KindValue], scope); - } - else - { - return getUnqualified(outputBuiltinTable[builtin->kind()], scope); - } - } - } - - ClassDeclPtr cl = dynamic_pointer_cast(type); - if(cl) - { - return "::std::shared_ptr<" + getUnqualified(fixKwd(cl->scoped()), scope) + ">&"; - } - - StructPtr st = dynamic_pointer_cast(type); - if(st) - { - return getUnqualified(fixKwd(st->scoped()), scope) + "&"; - } - - InterfaceDeclPtr proxy = dynamic_pointer_cast(type); - if(proxy) - { - return "::std::optional<" + getUnqualified(fixKwd(proxy->scoped() + "Prx"), scope) + ">&"; - } + assert(type); + assert(typeCtx == TypeContext::None || typeCtx == TypeContext::UseWstring); - EnumPtr en = dynamic_pointer_cast(type); - if(en) - { - return getUnqualified(fixKwd(en->scoped()), scope) + "&"; - } - - SequencePtr seq = dynamic_pointer_cast(type); - if(seq) - { - return sequenceTypeToString(seq, scope, metaData, typeCtx) + "&"; - } - - DictionaryPtr dict = dynamic_pointer_cast(type); - if(dict) - { - return dictionaryTypeToString(dict, scope, metaData, typeCtx) + "&"; - } - - return "???"; + return typeToString(type, optional, scope, metaData, typeCtx) + '&'; } string @@ -913,133 +620,33 @@ Slice::fixKwd(const string& name) } void -Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, bool optional, int tag, const string& param, - bool marshal, const StringList& metaData, int typeCtx, const string& customStream, - bool pointer, const string& obj) -{ - string objPrefix = obj.empty() ? obj : obj + "."; - - ostringstream os; - if(customStream.empty()) - { - os << (marshal ? "ostr" : "istr"); - } - else - { - os << customStream; - } - - if(pointer) - { - os << "->"; - } - else - { - os << '.'; - } - - if(marshal) - { - os << "write("; - } - else - { - os << "read("; - } - - if(optional) - { - os << tag << ", "; - } - - string func = os.str(); - if(!marshal) - { - SequencePtr seq = dynamic_pointer_cast(type); - if(seq && !(typeCtx & TypeContextAMIPrivateEnd)) - { - string seqType = findMetaData(metaData, typeCtx); - if(seqType == "%array") - { - BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); - if(builtin && builtin->kind() == Builtin::KindByte) - { - out << nl << func << objPrefix << param << ");"; - return; - } - - out << nl << func << objPrefix << param << "_tmp_);"; - writeParamEndCode(out, seq, optional, param, metaData, obj); - return; - } - } - } - - out << nl << func << objPrefix << param << ");"; -} - -void -Slice::writeMarshalCode(Output& out, const ParamDeclList& params, const OperationPtr& op, bool prepend, int typeCtx, - const string& customStream, const string& retP) +Slice::writeMarshalCode(Output& out, const ParamDeclList& params, const OperationPtr& op) { - writeMarshalUnmarshalParams(out, params, op, true, prepend, typeCtx, customStream, retP); + writeMarshalUnmarshalParams(out, params, op, true); } void -Slice::writeUnmarshalCode(Output& out, const ParamDeclList& params, const OperationPtr& op, bool prepend, int typeCtx, - const string& customStream, const string& retP, const string& obj) +Slice::writeUnmarshalCode(Output& out, const ParamDeclList& params, const OperationPtr& op) { - writeMarshalUnmarshalParams(out, params, op, false, prepend, typeCtx, customStream, retP, obj); + writeMarshalUnmarshalParams(out, params, op, false); } void -Slice::writeAllocateCode(Output& out, const ParamDeclList& params, const OperationPtr& op, bool prepend, - const string& clScope, int typeCtx, const string& customRet) +Slice::writeAllocateCode(Output& out, const ParamDeclList& params, const OperationPtr& op, const string& clScope, TypeContext typeCtx) { - string prefix = prepend ? paramPrefix : ""; - string returnValueS = customRet; - if(returnValueS.empty()) - { - returnValueS = "ret"; - } - for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) { - writeParamAllocateCode(out, (*p)->type(), (*p)->optional(), clScope, fixKwd(prefix + (*p)->name()), + writeParamAllocateCode(out, (*p)->type(), (*p)->optional(), clScope, fixKwd(paramPrefix + (*p)->name()), (*p)->getMetaData(), typeCtx); } if(op && op->returnType()) { - writeParamAllocateCode(out, op->returnType(), op->returnIsOptional(), clScope, returnValueS, op->getMetaData(), + writeParamAllocateCode(out, op->returnType(), op->returnIsOptional(), clScope, "ret", op->getMetaData(), typeCtx); } } -void -Slice::writeEndCode(Output& out, const ParamDeclList& params, const OperationPtr& op, bool prepend) -{ - string prefix = prepend ? paramPrefix : ""; - for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p) - { - writeParamEndCode(out, (*p)->type(), (*p)->optional(), fixKwd(prefix + (*p)->name()), (*p)->getMetaData()); - } - if(op && op->returnType()) - { - writeParamEndCode(out, op->returnType(), op->returnIsOptional(), "ret", op->getMetaData()); - } -} - -void -Slice::writeMarshalUnmarshalDataMemberInHolder(IceUtilInternal::Output& C, - const string& holder, - const DataMemberPtr& p, - bool marshal) -{ - writeMarshalUnmarshalCode(C, p->type(), p->optional(), p->tag(), holder + fixKwd(p->name()), marshal, - p->getMetaData()); -} - void Slice::writeMarshalUnmarshalAllInHolder(IceUtilInternal::Output& out, const string& holder, @@ -1182,7 +789,7 @@ Slice::writeStreamHelpers(Output& out, } void -Slice::writeIceTuple(::IceUtilInternal::Output& out, DataMemberList dataMembers, int typeCtx) +Slice::writeIceTuple(::IceUtilInternal::Output& out, DataMemberList dataMembers, TypeContext typeCtx) { // // Use an empty scope to get full qualified names from calls to typeToString. @@ -1241,7 +848,7 @@ Slice::findMetaData(const string& prefix, const StringList& metaData, string& va } string -Slice::findMetaData(const StringList& metaData, int typeCtx) +Slice::findMetaData(const StringList& metaData, TypeContext typeCtx) { static const string prefix = "cpp:"; @@ -1252,23 +859,15 @@ Slice::findMetaData(const StringList& metaData, int typeCtx) { string::size_type pos = str.find(':', prefix.size()); - // - // If the form is cpp:type:<...> the data after cpp:type: - // is returned. - // If the form is cpp:view-type:<...> the data after the - // cpp:view-type: is returned - // If the form is cpp:array, the return value is % followed by the string after cpp:. - // - // The priority of the metadata is as follows: - // 1: array view-type for "view" parameters - // 2: unscoped - // + // If a marshal param, we first check view-type then type. Otherwise, we check type. + // Then, if a marshal param or an unmarshal param where the underlying InputStream buffer remains valid for + // a while, we check for "array". if(pos != string::npos) { string ss = str.substr(prefix.size()); - if(typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd)) + if ((typeCtx & TypeContext::MarshalParam) != TypeContext::None) { if(ss.find("view-type:") == 0) { @@ -1281,7 +880,7 @@ Slice::findMetaData(const StringList& metaData, int typeCtx) return str.substr(pos + 1); } } - else if(typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd)) + else if ((typeCtx & (TypeContext::MarshalParam | TypeContext::UnmarshalParamZeroCopy)) != TypeContext::None) { string ss = str.substr(prefix.size()); if(ss == "array") @@ -1330,22 +929,3 @@ Slice::inWstringModule(const SequencePtr& seq) } return false; } - -string -Slice::getDataMemberRef(const DataMemberPtr& p) -{ - string name = fixKwd(p->name()); - if(!p->optional()) - { - return name; - } - - if(dynamic_pointer_cast(p->type())) - { - return "*" + name; - } - else - { - return "(*" + name + ")"; - } -} diff --git a/cpp/src/slice2cpp/CPlusPlusUtil.h b/cpp/src/slice2cpp/CPlusPlusUtil.h index 205ef38fa1b..9e70d3d4064 100644 --- a/cpp/src/slice2cpp/CPlusPlusUtil.h +++ b/cpp/src/slice2cpp/CPlusPlusUtil.h @@ -7,6 +7,7 @@ #include #include +#include "TypeContext.h" namespace Slice { @@ -22,49 +23,39 @@ void printHeader(::IceUtilInternal::Output&); void printVersionCheck(::IceUtilInternal::Output&); void printDllExportStuff(::IceUtilInternal::Output&, const std::string&); -const int TypeContextInParam = 1; -const int TypeContextAMIEnd = 2; -const int TypeContextAMIPrivateEnd = 4; -const int TypeContextAMICallPrivateEnd = 8; -const int TypeContextUseWstring = 16; -const int TypeContextTuple = 32; - bool isMovable(const TypePtr&); std::string getUnqualified(const std::string&, const std::string&); -std::string typeToString(const TypePtr&, const std::string& = "", const StringList& = StringList(), int = 0); -std::string typeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), int = 0); -std::string returnTypeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), int = 0); -std::string inputTypeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), int = 0); -std::string outputTypeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), int = 0); + +// Gets the C++ type for a Slice parameter or field. +std::string typeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), TypeContext = TypeContext::None); + +// TODO: find a better name. +// Gets the C++ type for a Slice parameter to be marshaled. +std::string inputTypeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), TypeContext = TypeContext::None); + +// TODO: find a better name. +// Gets the C++ type for a Slice out parameter when mapped to a C++ out parameter. +std::string outputTypeToString(const TypePtr&, bool, const std::string& = "", const StringList& = StringList(), TypeContext = TypeContext::None); + std::string operationModeToString(Operation::Mode); std::string opFormatTypeToString(const OperationPtr&); std::string fixKwd(const std::string&); -void writeMarshalUnmarshalCode(::IceUtilInternal::Output&, const TypePtr&, bool, int, const std::string&, - bool, const StringList& = StringList(), int = 0, const std::string& = "", - bool = true, const std::string& = ""); - -void writeMarshalCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&, bool, - int = 0, const std::string& = "", const std::string& = ""); -void writeUnmarshalCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&, bool, int = 0, - const std::string& = "", const std::string& = "", const std::string& = ""); -void writeAllocateCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&, bool, const std::string&, - int = 0, const std::string& = ""); +void writeMarshalCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&); +void writeUnmarshalCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&); +void writeAllocateCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&, const std::string&, TypeContext); -void writeEndCode(::IceUtilInternal::Output&, const ParamDeclList&, const OperationPtr&, bool = false); -void writeMarshalUnmarshalDataMemberInHolder(IceUtilInternal::Output&, const std::string&, const DataMemberPtr&, bool); void writeMarshalUnmarshalAllInHolder(IceUtilInternal::Output&, const std::string&, const DataMemberList&, bool, bool); void writeStreamHelpers(::IceUtilInternal::Output&, const ContainedPtr&, DataMemberList, bool); -void writeIceTuple(::IceUtilInternal::Output&, DataMemberList, int); +void writeIceTuple(::IceUtilInternal::Output&, DataMemberList, TypeContext); bool findMetaData(const std::string&, const ClassDeclPtr&, std::string&); bool findMetaData(const std::string&, const StringList&, std::string&); -std::string findMetaData(const StringList&, int = 0); +std::string findMetaData(const StringList&, TypeContext = TypeContext::None); bool inWstringModule(const SequencePtr&); -std::string getDataMemberRef(const DataMemberPtr&); } #endif diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index 39f54eb120c..7ed39b3a4d1 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -91,7 +91,7 @@ getDeprecateSymbol(const ContainedPtr& p1, const ContainedPtr& p2) void writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const SyntaxTreeBasePtr& valueType, - const string& value, int typeContext, const StringList& metaData, const string& scope) + const string& value, TypeContext typeContext, const StringList& metaData, const string& scope) { ConstPtr constant = dynamic_pointer_cast(valueType); if(constant) @@ -103,7 +103,7 @@ writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const Synt BuiltinPtr bp = dynamic_pointer_cast(type); if(bp && bp->kind() == Builtin::KindString) { - if ((typeContext & TypeContextUseWstring) || findMetaData(metaData) == "wstring") // wide strings + if ((typeContext & TypeContext::UseWstring) != TypeContext::None || findMetaData(metaData) == "wstring") // wide strings { out << "L\""; out << toStringLiteral(value, "\a\b\f\n\r\t\v", "?", UCN, 0); @@ -180,6 +180,7 @@ toDllMemberExport(const string& dllExport) } } +// Marshals the parameters of an outgoing request. void writeInParamsLambda(IceUtilInternal::Output& C, const OperationPtr& p, const ParamDeclList& inParams, const string& scope) @@ -192,7 +193,7 @@ writeInParamsLambda(IceUtilInternal::Output& C, const OperationPtr& p, const Par { C << "[&](" << getUnqualified("::Ice::OutputStream*", scope) << " ostr)"; C << sb; - writeMarshalCode(C, inParams, 0, true, TypeContextInParam); + writeMarshalCode(C, inParams, nullptr); if(p->sendsClasses(false)) { C << nl << "ostr->writePendingValues();"; @@ -568,13 +569,13 @@ createOutgoingAsyncTypeParam(const vector& elements) // Returns the C++ types that make up the client-side result type of an operation (first return type then out parameter // types, as per the future API). vector -createOutgoingAsyncParams(const OperationPtr& p, const string& scope, int typeContext) +createOutgoingAsyncParams(const OperationPtr& p, const string& scope, TypeContext typeContext) { vector elements; TypePtr ret = p->returnType(); if (ret) { - elements.push_back(returnTypeToString(ret, p->returnIsOptional(), scope, p->getMetaData(), typeContext)); + elements.push_back(typeToString(ret, p->returnIsOptional(), scope, p->getMetaData(), typeContext)); } for (const auto& param : p->outParameters()) { @@ -584,7 +585,7 @@ createOutgoingAsyncParams(const OperationPtr& p, const string& scope, int typeCo } string -createLambdaResponse(const OperationPtr& p, int typeContext) +createLambdaResponse(const OperationPtr& p, TypeContext typeContext) { ostringstream os; Output out(os); @@ -1204,26 +1205,26 @@ Slice::Gen::MetaDataVisitor::validate(const SyntaxTreeBasePtr& cont, const Strin return newMetaData; } -int -Slice::Gen::setUseWstring(ContainedPtr p, list& hist, int use) +TypeContext +Slice::Gen::setUseWstring(ContainedPtr p, list& hist, TypeContext typeCtx) { - hist.push_back(use); + hist.push_back(typeCtx); StringList metaData = p->getMetaData(); if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end()) { - use = TypeContextUseWstring; + typeCtx = TypeContext::UseWstring; } else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end()) { - use = 0; + typeCtx = TypeContext::None; } - return use; + return typeCtx; } -int -Slice::Gen::resetUseWstring(list& hist) +TypeContext +Slice::Gen::resetUseWstring(list& hist) { - int use = hist.back(); + TypeContext use = hist.back(); hist.pop_back(); return use; } @@ -1259,7 +1260,7 @@ Slice::Gen::getSourceExt(const string& file, const UnitPtr& ut) } Slice::Gen::ForwardDeclVisitor::ForwardDeclVisitor(Output& h) : - H(h), _useWstring(false) + H(h), _useWstring(TypeContext::None) { } @@ -1352,8 +1353,8 @@ Slice::Gen::ForwardDeclVisitor::visitSequence(const SequencePtr& p) string name = fixKwd(p->name()); string scope = fixKwd(p->scope()); TypePtr type = p->type(); - int typeCtx = _useWstring; - string s = typeToString(type, scope, p->typeMetaData(), typeCtx); + TypeContext typeCtx = _useWstring; + string s = typeToString(type, false, scope, p->typeMetaData(), typeCtx); StringList metaData = p->getMetaData(); string seqType = findMetaData(metaData, _useWstring); @@ -1376,7 +1377,7 @@ Slice::Gen::ForwardDeclVisitor::visitDictionary(const DictionaryPtr& p) string name = fixKwd(p->name()); string scope = fixKwd(p->scope()); string dictType = findMetaData(p->getMetaData()); - int typeCtx = _useWstring; + TypeContext typeCtx = _useWstring; H << sp; writeDocSummary(H, p); @@ -1388,8 +1389,8 @@ Slice::Gen::ForwardDeclVisitor::visitDictionary(const DictionaryPtr& p) // TypePtr keyType = p->keyType(); TypePtr valueType = p->valueType(); - string ks = typeToString(keyType, scope, p->keyMetaData(), typeCtx); - string vs = typeToString(valueType, scope, p->valueMetaData(), typeCtx); + string ks = typeToString(keyType, false, scope, p->keyMetaData(), typeCtx); + string vs = typeToString(valueType, false, scope, p->valueMetaData(), typeCtx); H << nl << "using " << name << " = ::std::map<" << ks << ", " << vs << ">;"; } @@ -1409,7 +1410,7 @@ Slice::Gen::ForwardDeclVisitor::visitConst(const ConstPtr& p) H << sp; writeDocSummary(H, p); H << nl << (isConstexprType(p->type()) ? "constexpr " : "const ") - << typeToString(p->type(), scope, p->typeMetaData(), _useWstring) << " " << fixKwd(p->name()) + << typeToString(p->type(), false, scope, p->typeMetaData(), _useWstring) << " " << fixKwd(p->name()) << " = "; writeConstantValue(H, p->type(), p->valueType(), p->value(), _useWstring, p->typeMetaData(), scope); @@ -1462,7 +1463,7 @@ Slice::Gen::DefaultFactoryVisitor::visitExceptionStart(const ExceptionPtr& p) } Slice::Gen::ProxyVisitor::ProxyVisitor(Output& h, Output& c, const string& dllExport) : - H(h), C(c), _dllExport(dllExport), _useWstring(false) + H(h), C(c), _dllExport(dllExport), _useWstring(TypeContext::None) { } @@ -1632,8 +1633,8 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) TypePtr ret = p->returnType(); bool retIsOpt = p->returnIsOptional(); - string retS = returnTypeToString(ret, retIsOpt, interfaceScope, p->getMetaData(), _useWstring); - string retSImpl = returnTypeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring); + string retS = ret ? typeToString(ret, retIsOpt, interfaceScope, p->getMetaData(), _useWstring) : "void"; + string retSImpl = ret ? typeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring) : "void"; // All parameters vector paramsDecl; @@ -1645,7 +1646,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) vector inParamsImpl; vector futureOutParams = createOutgoingAsyncParams(p, interfaceScope, _useWstring); - vector lambdaOutParams = createOutgoingAsyncParams(p, interfaceScope, _useWstring | TypeContextInParam); + vector lambdaOutParams = createOutgoingAsyncParams(p, interfaceScope, _useWstring | TypeContext::UnmarshalParamZeroCopy); const string futureImplPrefix = "_iceI_"; const string lambdaImplPrefix = futureOutParams == lambdaOutParams ? "_iceI_" : "_iceIL_"; @@ -1784,7 +1785,7 @@ Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p) const string responseParam = escapeParam(inParams, "response"); const string exParam = escapeParam(inParams, "ex"); const string sentParam = escapeParam(inParams, "sent"); - const string lambdaResponse = createLambdaResponse(p, _useWstring | TypeContextInParam); + const string lambdaResponse = createLambdaResponse(p, _useWstring | TypeContext::UnmarshalParamZeroCopy); H << sp; if(comment) @@ -1867,8 +1868,8 @@ Slice::Gen::ProxyVisitor::emitOperationImpl( TypePtr ret = p->returnType(); bool retIsOpt = p->returnIsOptional(); - string retS = returnTypeToString(ret, retIsOpt, interfaceScope, p->getMetaData(), _useWstring); - string retSImpl = returnTypeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring); + string retS = ret ? typeToString(ret, retIsOpt, interfaceScope, p->getMetaData(), _useWstring) : "void"; + string retSImpl = ret ? typeToString(ret, retIsOpt, "", p->getMetaData(), _useWstring) : "void"; vector inParamsS; vector inParamsImplDecl; @@ -1933,7 +1934,7 @@ Slice::Gen::ProxyVisitor::emitOperationImpl( C << "," << nl; throwUserExceptionLambda(C, p->throws(), interfaceScope); - if(outgoingAsyncParams.size() > 1) + if (outgoingAsyncParams.size() > 1) { // // Generate a read method if there are more than one ret/out parameter. If there's @@ -1943,8 +1944,8 @@ Slice::Gen::ProxyVisitor::emitOperationImpl( C << "," << nl << "[](" << getUnqualified("::Ice::InputStream*", interfaceScope) << " istr)"; C << sb; C << nl << returnT << " v;"; - // The "ret" parameter (the one before last) is not used with tuples. - writeUnmarshalCode(C, outParams, p, false, _useWstring | TypeContextTuple, "", "", "v"); + + writeUnmarshalCode(C, outParams, p); if(p->returnsClasses(false)) { @@ -1963,8 +1964,8 @@ Slice::Gen::ProxyVisitor::emitOperationImpl( C << "," << nl << "[](" << getUnqualified("::Ice::InputStream*", interfaceScope) << " istr)"; C << sb; - writeAllocateCode(C, outParams, p, true, interfaceScope, _useWstring); - writeUnmarshalCode(C, outParams, p, true, _useWstring); + writeAllocateCode(C, outParams, p, interfaceScope, _useWstring); + writeUnmarshalCode(C, outParams, p); if(p->returnsClasses(false)) { @@ -1995,7 +1996,7 @@ Slice::Gen::DataDefVisitor::DataDefVisitor( _dllExport(dllExport), _dllClassExport(toDllClassExport(dllExport)), _dllMemberExport(toDllMemberExport(dllExport)), _doneStaticSymbol(false), - _useWstring(false) + _useWstring(TypeContext::None) { } @@ -2714,7 +2715,7 @@ Slice::Gen::InterfaceVisitor::InterfaceVisitor(::IceUtilInternal::Output& h, H(h), C(c), _dllExport(dllExport), - _useWstring(false) + _useWstring(TypeContext::None) { } @@ -2976,7 +2977,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) } string retS; - if(amd) + if (amd || !ret) { retS = "void"; } @@ -2986,7 +2987,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) } else { - retS = returnTypeToString(ret, p->returnIsOptional(), interfaceScope, p->getMetaData(), _useWstring); + retS = typeToString(ret, p->returnIsOptional(), interfaceScope, p->getMetaData(), _useWstring); } for(ParamDeclList::iterator q = paramList.begin(); q != paramList.end(); ++q) @@ -2997,10 +2998,9 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) if(!isOutParam) { - // TODO: We need the TypeContextInParam for the view types. params.push_back(typeToString(type, (*q)->optional(), interfaceScope, (*q)->getMetaData(), - _useWstring | TypeContextInParam) + " " + paramName); - args.push_back(condMove(isMovable(type) && !isOutParam, paramPrefix + (*q)->name())); + _useWstring | TypeContext::UnmarshalParamZeroCopy) + " " + paramName); + args.push_back(condMove(isMovable(type), paramPrefix + (*q)->name())); } else { @@ -3082,7 +3082,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) C.dec(); C << sb; C << nl << "ostr->startEncapsulation(current.encoding, " << opFormatTypeToString(p) << ");"; - writeMarshalCode(C, outParams, p, true, 0, "ostr"); + writeMarshalCode(C, outParams, p); if(p->returnsClasses(false)) { C << nl << "ostr->writePendingValues();"; @@ -3136,8 +3136,8 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) if(!inParams.empty()) { C << nl << "auto istr = inS.startReadParams();"; - writeAllocateCode(C, inParams, 0, true, interfaceScope, _useWstring | TypeContextInParam); - writeUnmarshalCode(C, inParams, 0, true, _useWstring | TypeContextInParam); + writeAllocateCode(C, inParams, nullptr, interfaceScope, _useWstring | TypeContext::UnmarshalParamZeroCopy); + writeUnmarshalCode(C, inParams, nullptr); if(p->sendsClasses(false)) { C << nl << "istr->readPendingValues();"; @@ -3161,7 +3161,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) } else { - writeAllocateCode(C, outParams, 0, true, interfaceScope, _useWstring); + writeAllocateCode(C, outParams, nullptr, interfaceScope, _useWstring); if(ret) { C << nl << retS << " ret = "; @@ -3183,7 +3183,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) if(ret || !outParams.empty()) { C << nl << "auto ostr = inS.startWriteParams();"; - writeMarshalCode(C, outParams, p, true); + writeMarshalCode(C, outParams, p); if(p->returnsClasses(false)) { C << nl << "ostr->writePendingValues();"; @@ -3205,7 +3205,7 @@ Slice::Gen::InterfaceVisitor::visitOperation(const OperationPtr& p) C << nl << "auto responseCB = [inA]" << spar << responseParamsDecl << epar; C << sb; C << nl << "auto ostr = inA->startWriteParams();"; - writeMarshalCode(C, outParams, p, true); + writeMarshalCode(C, outParams, p); if(p->returnsClasses(false)) { C << nl << "ostr->writePendingValues();"; diff --git a/cpp/src/slice2cpp/Gen.h b/cpp/src/slice2cpp/Gen.h index 2280aeb1ae6..050b32eb117 100644 --- a/cpp/src/slice2cpp/Gen.h +++ b/cpp/src/slice2cpp/Gen.h @@ -7,6 +7,7 @@ #include "Slice/Parser.h" #include "IceUtil/OutputUtil.h" +#include "TypeContext.h" namespace Slice { @@ -30,8 +31,8 @@ class Gen void generate(const UnitPtr&); void closeOutput(); - static int setUseWstring(ContainedPtr, std::list&, int); - static int resetUseWstring(std::list&); + static TypeContext setUseWstring(ContainedPtr, std::list&, TypeContext); + static TypeContext resetUseWstring(std::list&); private: @@ -90,8 +91,8 @@ class Gen ::IceUtilInternal::Output& H; - int _useWstring; - std::list _useWstringHist; + TypeContext _useWstring; + std::list _useWstringHist; }; // Generates the code that registers the default class and exception factories. @@ -137,8 +138,8 @@ class Gen ::IceUtilInternal::Output& C; std::string _dllExport; - int _useWstring; - std::list _useWstringHist; + TypeContext _useWstring; + std::list _useWstringHist; }; // Generates code for definitions with data members - structs, classes and exceptions. @@ -172,8 +173,8 @@ class Gen std::string _dllClassExport; std::string _dllMemberExport; bool _doneStaticSymbol; - int _useWstring; - std::list _useWstringHist; + TypeContext _useWstring; + std::list _useWstringHist; }; // Generates the server-side classes that applications use to implement Ice objects. @@ -196,8 +197,8 @@ class Gen ::IceUtilInternal::Output& C; std::string _dllExport; - int _useWstring; - std::list _useWstringHist; + TypeContext _useWstring; + std::list _useWstringHist; }; // Generates internal StreamHelper template specializations for enums, structs, classes and exceptions. diff --git a/cpp/src/slice2cpp/TypeContext.h b/cpp/src/slice2cpp/TypeContext.h new file mode 100644 index 00000000000..17a824443db --- /dev/null +++ b/cpp/src/slice2cpp/TypeContext.h @@ -0,0 +1,36 @@ +// +// Copyright (c) ZeroC, Inc. All rights reserved. +// + +#ifndef TYPE_CONTEXT_H +#define TYPE_CONTEXT_H + +#include +#include + +namespace Slice +{ + enum class TypeContext : std::uint8_t + { + None = 0, + UseWstring = 1, + MarshalParam = 2, + UnmarshalParamZeroCopy = 4 + }; + + inline constexpr TypeContext operator|(TypeContext lhs, TypeContext rhs) noexcept + { + return static_cast( + static_cast>(lhs) | + static_cast>(rhs)); + } + + inline constexpr TypeContext operator&(TypeContext lhs, TypeContext rhs) noexcept + { + return static_cast( + static_cast>(lhs) & + static_cast>(rhs)); + } +} + +#endif diff --git a/cpp/test/Ice/optional/TestAMDI.cpp b/cpp/test/Ice/optional/TestAMDI.cpp index 8fedef0d21b..00fcc5c4d0a 100644 --- a/cpp/test/Ice/optional/TestAMDI.cpp +++ b/cpp/test/Ice/optional/TestAMDI.cpp @@ -130,7 +130,7 @@ InitialI::opDoubleAsync(optional p1, void InitialI::opStringAsync(optional<::std::string> p1, - ::std::function&, const optional<::std::string>&)> response, + ::std::function&, const optional<::std::string_view>&)> response, ::std::function, const Ice::Current&) { response(p1, p1); diff --git a/cpp/test/Ice/optional/TestAMDI.h b/cpp/test/Ice/optional/TestAMDI.h index 71c785ac5a8..d54ca6187ef 100644 --- a/cpp/test/Ice/optional/TestAMDI.h +++ b/cpp/test/Ice/optional/TestAMDI.h @@ -61,7 +61,7 @@ class InitialI : public Test::Initial ::std::function, const Ice::Current&) override; virtual void opStringAsync(std::optional<::std::string>, - ::std::function&, const std::optional<::std::string>&)>, + ::std::function&, const std::optional<::std::string_view>&)>, ::std::function, const Ice::Current&) override; virtual void opMyEnumAsync(std::optional<::Test::MyEnum>,