summaryrefslogtreecommitdiff
path: root/cpp/src/Slice/CPlusPlusUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/Slice/CPlusPlusUtil.cpp')
-rw-r--r--cpp/src/Slice/CPlusPlusUtil.cpp1419
1 files changed, 1419 insertions, 0 deletions
diff --git a/cpp/src/Slice/CPlusPlusUtil.cpp b/cpp/src/Slice/CPlusPlusUtil.cpp
new file mode 100644
index 00000000000..f0d6a514e75
--- /dev/null
+++ b/cpp/src/Slice/CPlusPlusUtil.cpp
@@ -0,0 +1,1419 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <Slice/CPlusPlusUtil.h>
+#include <Slice/Util.h>
+#include <cstring>
+
+#ifndef _WIN32
+# include <fcntl.h>
+#endif
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtil;
+using namespace IceUtilInternal;
+
+Slice::FeatureProfile Slice::featureProfile = Slice::Ice;
+
+char
+Slice::ToIfdef::operator()(char c)
+{
+ if(!isalnum(static_cast<unsigned char>(c)))
+ {
+ return '_';
+ }
+ else
+ {
+ return c;
+ }
+}
+
+
+void
+Slice::printHeader(Output& out)
+{
+ static const char* header =
+"// **********************************************************************\n"
+"//\n"
+"// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.\n"
+"//\n"
+"// This copy of Ice is licensed to you under the terms described in the\n"
+"// ICE_LICENSE file included in this distribution.\n"
+"//\n"
+"// **********************************************************************\n"
+ ;
+
+ out << header;
+ out << "//\n";
+ out << "// Ice version " << ICE_STRING_VERSION << "\n";
+ out << "//\n";
+}
+
+void
+Slice::printVersionCheck(Output& out)
+{
+ out << "\n";
+ out << "\n#ifndef ICE_IGNORE_VERSION";
+ int iceVersion = ICE_INT_VERSION; // Use this to prevent warning with C++Builder
+ if(iceVersion % 100 > 50)
+ {
+ //
+ // Beta version: exact match required
+ //
+ out << "\n# if ICE_INT_VERSION != " << ICE_INT_VERSION;
+ out << "\n# error Ice version mismatch: an exact match is required for beta generated code";
+ out << "\n# endif";
+ }
+ else
+ {
+ out << "\n# if ICE_INT_VERSION / 100 != " << ICE_INT_VERSION / 100;
+ out << "\n# error Ice version mismatch!";
+ out << "\n# endif";
+
+ //
+ // Generated code is release; reject beta header
+ //
+ out << "\n# if ICE_INT_VERSION % 100 > 50";
+ out << "\n# error Beta header file detected";
+ out << "\n# endif";
+
+ out << "\n# if ICE_INT_VERSION % 100 < " << ICE_INT_VERSION % 100;
+ out << "\n# error Ice patch level mismatch!";
+ out << "\n# endif";
+ }
+ out << "\n#endif";
+}
+
+void
+Slice::printDllExportStuff(Output& out, const string& dllExport)
+{
+ if(dllExport.size())
+ {
+ out << sp;
+ out << "\n#ifndef " << dllExport;
+ out << "\n# ifdef " << dllExport << "_EXPORTS";
+ out << "\n# define " << dllExport << " ICE_DECLSPEC_EXPORT";
+ out << "\n# else";
+ out << "\n# define " << dllExport << " ICE_DECLSPEC_IMPORT";
+ out << "\n# endif";
+ out << "\n#endif";
+ }
+}
+
+namespace
+{
+
+string
+sequenceTypeToString(const SequencePtr& seq, const StringList& metaData, int typeCtx)
+{
+ string seqType = findMetaData(metaData, typeCtx);
+ if(!seqType.empty())
+ {
+ if(seqType == "array" || seqType == "range:array")
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type());
+ if(typeCtx & TypeContextAMIPrivateEnd)
+ {
+ if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)
+ {
+ seqType = findMetaData(seq->getMetaData());
+ if(seqType.empty())
+ {
+ return typeToString(seq);
+ }
+ else
+ {
+ return "::std::vector< " + typeToString(seq->type()) + ">";
+ }
+ }
+ else if(builtin->kind() == Builtin::KindByte)
+ {
+ string s = typeToString(seq->type());
+ return "::std::pair<const " + s + "*, const " + s + "*>";
+ }
+ else if(builtin->kind() != Builtin::KindString &&
+ builtin->kind() != Builtin::KindObject &&
+ builtin->kind() != Builtin::KindObjectProxy)
+ {
+ string s = typeToString(builtin);
+ if(s[0] == ':')
+ {
+ s = " " + s;
+ }
+ return "::std::pair< ::IceUtil::ScopedArray<" + s + ">," +
+ " ::std::pair<const " + s + "*, const " + s + "*> >";
+ }
+ else
+ {
+ return "::std::vector< " + typeToString(seq->type(),
+ seq->typeMetaData(),
+ inWstringModule(seq) ? TypeContextUseWstring : 0) + ">";
+ }
+ }
+ string s = typeToString(seq->type(), seq->typeMetaData(), inWstringModule(seq) ? TypeContextUseWstring : 0);
+ return "::std::pair<const " + s + "*, const " + s + "*>";
+ }
+ else if(seqType.find("range") == 0)
+ {
+ string s;
+ if(seqType.find("range:") == 0)
+ {
+ s = seqType.substr(strlen("range:"));
+ }
+ else
+ {
+ s = fixKwd(seq->scoped());
+ }
+ if(typeCtx & TypeContextAMIPrivateEnd)
+ {
+ return s;
+ }
+ if(s[0] == ':')
+ {
+ s = " " + s;
+ }
+ return "::std::pair<" + s + "::const_iterator, " + s + "::const_iterator>";
+ }
+ else
+ {
+ return seqType;
+ }
+ }
+ else
+ {
+ // Get the metadata associated at the point of definition.
+ bool protobuf;
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf, typeCtx);
+ if(protobuf && !seqType.empty())
+ {
+ return seqType;
+ }
+ return fixKwd(seq->scoped());
+ }
+}
+
+}
+
+string
+Slice::typeToString(const TypePtr& type, const StringList& metaData, int typeCtx)
+{
+ static const char* builtinTable[] =
+ {
+ "::Ice::Byte",
+ "bool",
+ "::Ice::Short",
+ "::Ice::Int",
+ "::Ice::Long",
+ "::Ice::Float",
+ "::Ice::Double",
+ "::std::string",
+ "::Ice::ObjectPtr",
+ "::Ice::ObjectPrx",
+ "::Ice::LocalObjectPtr"
+ };
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindString)
+ {
+ string strType = findMetaData(metaData);
+ if(strType != "string" && (typeCtx & TypeContextUseWstring || strType == "wstring"))
+ {
+ if(featureProfile == IceE)
+ {
+ return "::Ice::Wstring";
+ }
+ else
+ {
+ return "::std::wstring";
+ }
+ }
+ }
+ return builtinTable[builtin->kind()];
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ return fixKwd(cl->scoped() + "Ptr");
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ if(findMetaData(st->getMetaData()) == "class")
+ {
+ return fixKwd(st->scoped() + "Ptr");
+ }
+ return fixKwd(st->scoped());
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ if(proxy)
+ {
+ return fixKwd(proxy->_class()->scoped() + "Prx");
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return sequenceTypeToString(seq, metaData, typeCtx);
+ }
+
+ ContainedPtr contained = ContainedPtr::dynamicCast(type);
+ if(contained)
+ {
+ return fixKwd(contained->scoped());
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ return fixKwd(en->scoped());
+ }
+
+ return "???";
+}
+
+string
+Slice::returnTypeToString(const TypePtr& type, const StringList& metaData, int typeCtx)
+{
+ if(!type)
+ {
+ return "void";
+ }
+
+ return typeToString(type, metaData, typeCtx);
+}
+
+string
+Slice::inputTypeToString(const TypePtr& type, const StringList& metaData, int typeCtx)
+{
+ static const char* inputBuiltinTable[] =
+ {
+ "::Ice::Byte",
+ "bool",
+ "::Ice::Short",
+ "::Ice::Int",
+ "::Ice::Long",
+ "::Ice::Float",
+ "::Ice::Double",
+ "const ::std::string&",
+ "const ::Ice::ObjectPtr&",
+ "const ::Ice::ObjectPrx&",
+ "const ::Ice::LocalObjectPtr&"
+ };
+
+ typeCtx |= TypeContextInParam;
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindString)
+ {
+ string strType = findMetaData(metaData);
+ if(strType != "string" && (typeCtx & TypeContextUseWstring || strType == "wstring"))
+ {
+ if(featureProfile == IceE)
+ {
+ return "const ::Ice::Wstring&";
+ }
+ else
+ {
+ return "const ::std::wstring&";
+ }
+ }
+ }
+ return inputBuiltinTable[builtin->kind()];
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ return "const " + fixKwd(cl->scoped() + "Ptr&");
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ if(findMetaData(st->getMetaData()) == "class")
+ {
+ return "const " + fixKwd(st->scoped() + "Ptr&");
+ }
+ return "const " + fixKwd(st->scoped()) + "&";
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ if(proxy)
+ {
+ return "const " + fixKwd(proxy->_class()->scoped() + "Prx&");
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(type);
+ if(en)
+ {
+ return fixKwd(en->scoped());
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return "const " + sequenceTypeToString(seq, metaData, typeCtx) + "&";
+ }
+
+ ContainedPtr contained = ContainedPtr::dynamicCast(type);
+ if(contained)
+ {
+ return "const " + fixKwd(contained->scoped()) + "&";
+ }
+
+ return "???";
+}
+
+string
+Slice::outputTypeToString(const TypePtr& type, const StringList& metaData, int typeCtx)
+{
+ static const char* outputBuiltinTable[] =
+ {
+ "::Ice::Byte&",
+ "bool&",
+ "::Ice::Short&",
+ "::Ice::Int&",
+ "::Ice::Long&",
+ "::Ice::Float&",
+ "::Ice::Double&",
+ "::std::string&",
+ "::Ice::ObjectPtr&",
+ "::Ice::ObjectPrx&",
+ "::Ice::LocalObjectPtr&"
+ };
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindString)
+ {
+ string strType = findMetaData(metaData);
+ if(strType != "string" && (typeCtx & TypeContextUseWstring || strType == "wstring"))
+ {
+ if(featureProfile == IceE)
+ {
+ return "::Ice::Wstring&";
+ }
+ else
+ {
+ return "::std::wstring&";
+ }
+ }
+ }
+ return outputBuiltinTable[builtin->kind()];
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ return fixKwd(cl->scoped() + "Ptr&");
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ if(findMetaData(st->getMetaData()) == "class")
+ {
+ return fixKwd(st->scoped() + "Ptr&");
+ }
+ return fixKwd(st->scoped()) + "&";
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(type);
+ if(proxy)
+ {
+ return fixKwd(proxy->_class()->scoped() + "Prx&");
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ return sequenceTypeToString(seq, metaData, typeCtx) + "&";
+ }
+
+ ContainedPtr contained = ContainedPtr::dynamicCast(type);
+ if(contained)
+ {
+ return fixKwd(contained->scoped()) + "&";
+ }
+
+ return "???";
+}
+
+string
+Slice::operationModeToString(Operation::Mode mode)
+{
+ switch(mode)
+ {
+ case Operation::Normal:
+ {
+ return "::Ice::Normal";
+ }
+
+ case Operation::Nonmutating:
+ {
+ return "::Ice::Nonmutating";
+ }
+
+ case Operation::Idempotent:
+ {
+ return "::Ice::Idempotent";
+ }
+
+ default:
+ {
+ assert(false);
+ }
+ }
+
+ return "???";
+}
+
+//
+// If the passed name is a keyword, return the name with a "_cxx_" prefix;
+// otherwise, return the name unchanged.
+//
+
+static string
+lookupKwd(const string& name)
+{
+ //
+ // Keyword list. *Must* be kept in alphabetical order.
+ //
+ // Note that this keyword list unnecessarily contains C++ keywords
+ // that are illegal Slice identifiers -- namely identifiers that
+ // are Slice keywords (class, int, etc.). They have not been removed
+ // so that the keyword list is kept complete.
+ //
+ static const string keywordList[] =
+ {
+ "and", "and_eq", "asm", "auto", "bit_and", "bit_or", "bool", "break", "case", "catch", "char",
+ "class", "compl", "const", "const_cast", "continue", "default", "delete", "do", "double",
+ "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false", "float", "for",
+ "friend", "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
+ "operator", "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
+ "return", "short", "signed", "sizeof", "static", "static_cast", "struct", "switch", "template",
+ "this", "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using",
+ "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
+ };
+ bool found = binary_search(&keywordList[0],
+ &keywordList[sizeof(keywordList) / sizeof(*keywordList)],
+ name);
+ return found ? "_cpp_" + name : name;
+}
+
+//
+// Split a scoped name into its components and return the components as a list of (unscoped) identifiers.
+//
+static StringList
+splitScopedName(const string& scoped)
+{
+ assert(scoped[0] == ':');
+ StringList ids;
+ string::size_type next = 0;
+ string::size_type pos;
+ while((pos = scoped.find("::", next)) != string::npos)
+ {
+ pos += 2;
+ if(pos != scoped.size())
+ {
+ string::size_type endpos = scoped.find("::", pos);
+ if(endpos != string::npos)
+ {
+ ids.push_back(scoped.substr(pos, endpos - pos));
+ }
+ }
+ next = pos;
+ }
+ if(next != scoped.size())
+ {
+ ids.push_back(scoped.substr(next));
+ }
+ else
+ {
+ ids.push_back("");
+ }
+
+ return ids;
+}
+
+//
+// If the passed name is a scoped name, return the identical scoped name,
+// but with all components that are C++ keywords replaced by
+// their "_cxx_"-prefixed version; otherwise, if the passed name is
+// not scoped, but a C++ keyword, return the "_cxx_"-prefixed name;
+// otherwise, return the name unchanged.
+//
+string
+Slice::fixKwd(const string& name)
+{
+ if(name[0] != ':')
+ {
+ return lookupKwd(name);
+ }
+ StringList ids = splitScopedName(name);
+ transform(ids.begin(), ids.end(), ids.begin(), ptr_fun(lookupKwd));
+ stringstream result;
+ for(StringList::const_iterator i = ids.begin(); i != ids.end(); ++i)
+ {
+ result << "::" + *i;
+ }
+ return result.str();
+}
+
+void
+Slice::writeMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& param, bool marshal,
+ const string& str, bool pointer, const StringList& metaData, int typeCtx)
+{
+ string fixedParam = fixKwd(param);
+
+ string stream;
+ if(str.empty())
+ {
+ stream = marshal ? "__os" : "__is";
+ }
+ else
+ {
+ stream = str;
+ }
+
+ string deref;
+ if(pointer)
+ {
+ deref = "->";
+ }
+ else
+ {
+ deref = '.';
+ }
+
+ string func = marshal ? "write(" : "read(";
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindObject)
+ {
+ if(marshal)
+ {
+ out << nl << stream << deref << func << fixedParam << ");";
+ }
+ else
+ {
+ out << nl << stream << deref << func << "::Ice::__patch__ObjectPtr, &" << fixedParam << ");";
+ }
+ return;
+ }
+ else
+ {
+ out << nl << stream << deref << func << fixedParam << ");";
+ return;
+ }
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ string scope = fixKwd(cl->scope());
+ if(marshal)
+ {
+ out << nl << stream << deref << "write(::Ice::ObjectPtr(::IceInternal::upCast(" << fixedParam
+ << ".get())));";
+ }
+ else
+ {
+ out << nl << stream << deref << "read("
+ << scope << "__patch__" << cl->name() << "Ptr, &" << fixedParam << ");";
+ }
+
+ return;
+ }
+
+ ProxyPtr px = ProxyPtr::dynamicCast(type);
+ if(px)
+ {
+ string scope = fixKwd(px->_class()->scope());
+ if(marshal)
+ {
+ out << nl << stream << deref << "write(::Ice::ObjectPrx(::IceInternal::upCast(" << fixedParam
+ << ".get())));";
+ }
+ else
+ {
+ out << nl << scope << "__read(" << (pointer ? "" : "&") << stream << ", " << fixedParam << ");";
+ }
+ return;
+ }
+
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st)
+ {
+ string deref;
+ if(findMetaData(st->getMetaData()) == "class")
+ {
+ if(!marshal)
+ {
+ out << nl << fixedParam << " = new " << fixKwd(st->scoped()) << ";";
+ }
+ out << nl << fixedParam << "->__" << func << (pointer ? "" : "&") << stream << ");";
+ }
+ else
+ {
+ out << nl << fixedParam << ".__" << func << (pointer ? "" : "&") << stream << ");";
+ }
+ return;
+ }
+
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ builtin = BuiltinPtr::dynamicCast(seq->type());
+ string funcSeq = (marshal ? "write" : "read") + fixKwd(seq->name()) + "(";
+
+ if(marshal)
+ {
+ string seqType = findMetaData(metaData, typeCtx);
+ string scope = fixKwd(seq->scope());
+
+ if(seqType == "array" || seqType == "range:array")
+ {
+ //
+ // Use array (pair<const TYPE*, const TYPE*>). In parameters only.
+ //
+ if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)
+ {
+ //
+ // Sequence type in not handled by BasicStream functions. If the sequence is the
+ // default vector than we can use the sequences generated write function. Otherwise
+ // we need to generate marshal code to write each element.
+ //
+ seqType = findMetaData(seq->getMetaData());
+ if(seqType.empty())
+ {
+ out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", "
+ << fixedParam << ".first, " << fixedParam << ".second);";
+ }
+ else
+ {
+ out << nl << "::Ice::Int __sz_" << fixedParam << " = static_cast< ::Ice::Int>(" << fixedParam
+ << ".second - " << fixedParam << ".first);";
+ out << nl << stream << deref << "writeSize(__sz_" << fixedParam << ");";
+ out << nl << "for(int __i_" << fixedParam << " = 0; __i_" << fixedParam << " < __sz_"
+ << fixedParam << "; ++__i_" << fixedParam << ")";
+ out << sb;
+ writeMarshalUnmarshalCode(out, seq->type(), fixedParam + ".first[__i_" + fixedParam + "]",
+ true);
+ out << eb;
+ }
+ }
+ else
+ {
+ //
+ // Use BasicStream write functions.
+ //
+ out << nl << stream << deref << func << fixedParam << ".first, " << fixedParam << ".second);";
+ }
+ }
+ else if(seqType.find("range") == 0)
+ {
+ //
+ // Use range (pair<TYPE::const_iterator, TYPE::const_iterator). Only for in paramaters.
+ // Need to check if the range defines an iterator type other than the actual sequence
+ // type.
+ //
+ StringList l;
+ if(seqType.find("range:") == 0)
+ {
+ seqType = seqType.substr(strlen("range:"));
+ l.push_back("cpp:" + seqType);
+ }
+ else
+ {
+ seqType = fixKwd(seq->scoped());
+ }
+ out << nl << stream << deref << "writeSize(static_cast< ::Ice::Int>(IceUtilInternal::distance("
+ << fixedParam << ".first, " << fixedParam << ".second)));";
+ out << nl << "for(" << seqType << "::const_iterator ___" << fixedParam << " = "
+ << fixedParam << ".first; ___" << fixedParam << " != " << fixedParam << ".second; ++___"
+ << fixedParam << ")";
+ out << sb;
+ writeMarshalUnmarshalCode(out, seq->type(), "(*___" + fixedParam + ")", true, "", true, l, false);
+ out << eb;
+ }
+ else if(!seqType.empty())
+ {
+ out << nl << stream << deref << "writeSize(static_cast< ::Ice::Int>(" << fixedParam << ".size()));";
+ out << nl << seqType << "::const_iterator __p_" << fixedParam << ";";
+ out << nl << "for(__p_" << fixedParam << " = " << fixedParam << ".begin(); __p_" << fixedParam
+ << " != " << fixedParam << ".end(); ++__p_" << fixedParam << ")";
+ out << sb;
+ writeMarshalUnmarshalCode(out, seq->type(), "(*__p_" + fixedParam + ")", true);
+ out << eb;
+ }
+ else
+ {
+ //
+ // No modifying metadata specified. Use appropriate write methods for type.
+ //
+ bool protobuf;
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf);
+ if(protobuf || !seqType.empty())
+ {
+ out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", " << fixedParam
+ << ");";
+ }
+ else if(!builtin ||
+ builtin->kind() == Builtin::KindObject ||
+ builtin->kind() == Builtin::KindObjectProxy)
+ {
+ out << nl << "if(" << fixedParam << ".size() == 0)";
+ out << sb;
+ out << nl << stream << deref << "writeSize(0);";
+ out << eb;
+ out << nl << "else";
+ out << sb;
+ out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", &"
+ << fixedParam << "[0], &" << fixedParam << "[0] + " << fixedParam << ".size());";
+ out << eb;
+ }
+ else if(builtin->kind() == Builtin::KindBool)
+ {
+ out << nl << stream << deref << func << fixedParam << ");";
+ }
+ else
+ {
+ out << nl << "if(" << fixedParam << ".size() == 0)";
+ out << sb;
+ out << nl << stream << deref << "writeSize(0);";
+ out << eb;
+ out << nl << "else";
+ out << sb;
+ out << nl << stream << deref << func << "&" << fixedParam << "[0], &" << fixedParam
+ << "[0] + " << fixedParam << ".size());";
+ out << eb;
+ }
+ }
+ }
+ else
+ {
+ string seqType = findMetaData(metaData, typeCtx);
+ string scope = fixKwd(seq->scope());
+ if(seqType == "array" || seqType == "range:array")
+ {
+ //
+ // Use array (pair<const TYPE*, const TYPE*>). In parameters only.
+ //
+ if(!builtin || builtin->kind() == Builtin::KindObject || builtin->kind() == Builtin::KindObjectProxy)
+ {
+ seqType = findMetaData(seq->getMetaData());
+ if(seqType.empty())
+ {
+ out << nl << typeToString(type) << " ___" << fixedParam << ";";
+ out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", ___"
+ << fixedParam << ");";
+ }
+ else
+ {
+ seqType = "::std::vector< " + typeToString(seq->type()) + ">";
+ StringList l;
+ l.push_back("cpp:type:" + seqType);
+ out << nl << seqType << " ___" << fixedParam << ";";
+ writeMarshalUnmarshalCode(out, seq, "___" + fixedParam, false, "", true, l, false);
+ }
+ }
+ else if(builtin->kind() == Builtin::KindByte)
+ {
+ out << nl << stream << deref << func << fixedParam << ");";
+ }
+ else if(builtin->kind() != Builtin::KindString && builtin->kind() != Builtin::KindObject &&
+ builtin->kind() != Builtin::KindObjectProxy)
+ {
+ string s = typeToString(builtin);
+ if(s[0] == ':')
+ {
+ s = " " + s;
+ }
+
+ if(typeCtx & TypeContextAMIPrivateEnd)
+ {
+ out << nl << fixedParam << ".first.reset(" << stream << deref << func << fixedParam
+ << ".second));";
+ }
+ else
+ {
+ out << nl << "::IceUtil::ScopedArray<" << s << "> ___" << fixedParam << '('
+ << stream << deref << func << fixedParam << "));";
+ }
+ }
+ else
+ {
+ out << nl << "::std::vector< "
+ << typeToString(seq->type(), seq->typeMetaData(),
+ inWstringModule(seq) ? TypeContextUseWstring : 0) << "> ___"
+ << fixedParam << ";";
+ out << nl << stream << deref << func << "___" << fixedParam << ");";
+ }
+
+ if(!builtin || builtin->kind() == Builtin::KindString || builtin->kind() == Builtin::KindObject ||
+ builtin->kind() == Builtin::KindObjectProxy)
+ {
+ if(typeCtx & TypeContextAMIPrivateEnd)
+ {
+ out << nl << fixedParam << ".swap(" << "___" << fixedParam << ");";
+ }
+ else
+ {
+ out << nl << fixedParam << ".first" << " = &___" << fixedParam << "[0];";
+ out << nl << fixedParam << ".second" << " = " << fixedParam << ".first + " << "___"
+ << fixedParam << ".size();";
+ }
+ }
+ }
+ else if(seqType.find("range") == 0)
+ {
+ //
+ // Use range (pair<TYPE::const_iterator, TYPE::const_iterator>). In paramters only.
+ // Need to check if iterator type other than default is specified.
+ //
+ StringList md;
+ if(seqType.find("range:") == 0)
+ {
+ md.push_back("cpp:type:" + seqType.substr(strlen("range:")));
+ }
+ if(typeCtx & TypeContextAMIPrivateEnd)
+ {
+ writeMarshalUnmarshalCode(out, seq, fixedParam, false, "", true, md, false);
+ }
+ else
+ {
+ writeMarshalUnmarshalCode(out, seq, "___" + fixedParam, false, "", true, md, false);
+ out << nl << fixedParam << ".first = ___" << fixedParam << ".begin();";
+ out << nl << fixedParam << ".second = ___" << fixedParam << ".end();";
+ }
+ }
+ else if(!seqType.empty())
+ {
+ //
+ // Using alternate sequence type.
+ //
+ out << nl << "::Ice::Int __sz_" << fixedParam << ";";
+ out << nl << stream << deref << "readAndCheckSeqSize(" << seq->type()->minWireSize() << ", __sz_"
+ << fixedParam << ");";
+ out << nl << seqType << "(__sz_" << fixedParam << ").swap(" << fixedParam << ");";
+ out << nl << seqType << "::iterator __p_" << fixedParam << ";";
+ out << nl << "for(__p_" << fixedParam << " = " << fixedParam << ".begin(); __p_" << fixedParam
+ << " != " << fixedParam << ".end(); ++__p_" << fixedParam << ")";
+ out << sb;
+ writeMarshalUnmarshalCode(out, seq->type(), "(*__p_" + fixedParam + ")", false);
+ out << eb;
+ }
+ else
+ {
+ //
+ // No modifying metadata supplied. Just use
+ // appropriate read function.
+ //
+ bool protobuf;
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf);
+ if(protobuf ||
+ !seqType.empty() ||
+ !builtin ||
+ builtin->kind() == Builtin::KindObject ||
+ builtin->kind() == Builtin::KindObjectProxy)
+ {
+ out << nl << scope << "__" << funcSeq << (pointer ? "" : "&") << stream << ", "
+ << fixedParam << ");";
+ }
+ else if(builtin->kind() == Builtin::KindByte)
+ {
+ StringList md;
+ md.push_back("cpp:array");
+ string tmpParam = "___";
+
+ //
+ // Catch some case in which it is not possible to just prepend
+ // underscores to param to use as temporary variable.
+ //
+ if(fixedParam.find("(*") == 0)
+ {
+ tmpParam += fixedParam.substr(2, fixedParam.length() - 3);
+ }
+ else if(fixedParam.find("[i]") != string::npos)
+ {
+ tmpParam += fixedParam.substr(0, fixedParam.length() - 3);
+ }
+ else if(fixedParam.find("->second") != string::npos)
+ {
+ tmpParam += fixedParam.substr(0, fixedParam.length() - 8);
+ }
+ else
+ {
+ tmpParam += fixedParam;
+ }
+ out << nl << typeToString(type, md, TypeContextInParam) << " " << tmpParam << ";";
+ out << nl << stream << deref << func << tmpParam << ");";
+ out << nl << "::std::vector< ::Ice::Byte>(" << tmpParam << ".first, " << tmpParam
+ << ".second).swap(" << fixedParam << ");";
+ }
+ else
+ {
+ out << nl << stream << deref << func << fixedParam << ");";
+ }
+ }
+ }
+ return;
+ }
+
+ DictionaryPtr dict = DictionaryPtr::dynamicCast(type);
+ if(dict)
+ {
+ string scope = fixKwd(dict->scope());
+ string funcDict = (marshal ? "write" : "read") + fixKwd(dict->name()) + "(";
+ out << nl << scope << "__" << funcDict << (pointer ? "" : "&") << stream << ", " << fixedParam << ");";
+ return;
+ }
+
+ ConstructedPtr constructed = ConstructedPtr::dynamicCast(type);
+ assert(constructed);
+
+ out << nl << fixKwd(constructed->scope()) << "__" << func << (pointer ? "" : "&") << stream << ", "
+ << fixedParam << ");";
+}
+
+void
+Slice::writeMarshalCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData,
+ int typeCtx)
+{
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ writeMarshalUnmarshalCode(out, (*p)->type(), fixKwd((*p)->name()), true, "", true, (*p)->getMetaData(),
+ typeCtx);
+ }
+ if(ret)
+ {
+ writeMarshalUnmarshalCode(out, ret, "__ret", true, "", true, metaData, false);
+ }
+}
+
+void
+Slice::writeUnmarshalCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData,
+ int typeCtx)
+{
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ writeMarshalUnmarshalCode(out, (*p)->type(), fixKwd((*p)->name()), false, "", true, (*p)->getMetaData(),
+ typeCtx);
+ }
+ if(ret)
+ {
+ writeMarshalUnmarshalCode(out, ret, "__ret", false, "", true, metaData, typeCtx);
+ }
+}
+
+namespace
+{
+
+void
+writeParamAllocateCode(Output& out, const TypePtr& type, const string& fixedName, const StringList& metaData,
+ int typeCtx)
+{
+ out << nl << typeToString(type, metaData, typeCtx) << ' ' << fixedName;
+ StructPtr st = StructPtr::dynamicCast(type);
+ if(st && findMetaData(st->getMetaData()) == "class")
+ {
+ out << " = new " << fixKwd(st->scoped());
+ }
+ out << ';';
+
+ if(!(typeCtx & TypeContextInParam))
+ {
+ return; // We're done.
+ }
+
+ //
+ // If using a range or array we need to allocate the range container, or
+ // array as well now to ensure they are always in the same scope.
+ //
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ bool protobuf;
+ string seqType = findMetaData(seq, metaData, protobuf, typeCtx);
+ if(!protobuf && seqType.empty())
+ {
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf, typeCtx);
+ }
+ if(protobuf)
+ {
+ return;
+ }
+ if(seqType == "array" || seqType == "range:array")
+ {
+ if(typeCtx & TypeContextAMICallPrivateEnd)
+ {
+ out << nl << typeToString(seq, metaData, TypeContextAMIPrivateEnd) << " ___" << fixedName << ";";
+// BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type());
+// if(builtin &&
+// builtin->kind() != Builtin::KindByte &&
+// builtin->kind() != Builtin::KindString &&
+// builtin->kind() != Builtin::KindObject &&
+// builtin->kind() != Builtin::KindObjectProxy)
+// {
+// out << nl << typeToString(seq, metaData, TypeContextAMIPrivateEnd) << " ___" << fixedName << ";";
+// }
+// else if(!builtin || builtin->kind() != Builtin::KindByte)
+// {
+// out << nl << typeToString(seq, metaData) << " ___" << fixedName << ";";
+// }
+ }
+ }
+ else if(seqType.find("range") == 0)
+ {
+ StringList md;
+ if(seqType.find("range:") == 0)
+ {
+ md.push_back("cpp:type:" + seqType.substr(strlen("range:")));
+ }
+ out << nl << typeToString(seq, md) << " ___" << fixedName << ";";
+ }
+ }
+}
+
+}
+
+void
+Slice::writeAllocateCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData,
+ int typeCtx)
+{
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ writeParamAllocateCode(out, (*p)->type(), fixKwd((*p)->name()), (*p)->getMetaData(), typeCtx);
+ }
+ if(ret)
+ {
+ writeParamAllocateCode(out, ret, "__ret", metaData, typeCtx);
+ }
+}
+
+void
+Slice::writeStreamMarshalUnmarshalCode(Output& out, const TypePtr& type, const string& param, bool marshal,
+ const string& str, const StringList& metaData, int typeCtx)
+{
+ string fixedParam = fixKwd(param);
+
+ string stream;
+ if(str.empty())
+ {
+ stream = marshal ? "__outS" : "__inS";
+ }
+ else
+ {
+ stream = str;
+ }
+
+ if(marshal)
+ {
+ out << nl << stream << "->write(" << fixedParam << ");";
+ }
+ else
+ {
+ out << nl << stream << "->read(" << fixedParam << ");";
+ }
+}
+
+string
+Slice::getEndArg(const TypePtr& type, const StringList& metaData, const string& arg)
+{
+ string endArg = arg;
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ bool protobuf;
+ string seqType = findMetaData(seq, metaData, protobuf, TypeContextInParam);
+ if(!protobuf && seqType.empty())
+ {
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf, TypeContextInParam);
+ }
+ if(!protobuf)
+ {
+ if(seqType == "array" || seqType == "range:array")
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type());
+ if(builtin &&
+ builtin->kind() != Builtin::KindByte &&
+ builtin->kind() != Builtin::KindString &&
+ builtin->kind() != Builtin::KindObject &&
+ builtin->kind() != Builtin::KindObjectProxy)
+ {
+ endArg = "___" + endArg;
+ }
+ else if(!builtin || builtin->kind() != Builtin::KindByte)
+ {
+ endArg = "___" + endArg;
+ }
+ }
+ else if(seqType.find("range") == 0)
+ {
+ StringList md;
+ if(seqType.find("range:") == 0)
+ {
+ md.push_back("cpp:type:" + seqType.substr(strlen("range:")));
+ }
+ endArg = "___" + endArg;
+ }
+ }
+ }
+ return endArg;
+}
+
+namespace
+{
+
+void
+writeParamEndCode(Output& out, const TypePtr& type, const string& fixedName, const StringList& metaData)
+{
+ SequencePtr seq = SequencePtr::dynamicCast(type);
+ if(seq)
+ {
+ bool protobuf;
+ string seqType = findMetaData(seq, metaData, protobuf, TypeContextInParam);
+ if(!protobuf && seqType.empty())
+ {
+ seqType = findMetaData(seq, seq->getMetaData(), protobuf, TypeContextInParam);
+ }
+ if(!protobuf)
+ {
+ if(seqType == "array" || seqType == "range:array")
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type());
+ if(builtin &&
+ builtin->kind() != Builtin::KindByte &&
+ builtin->kind() != Builtin::KindString &&
+ builtin->kind() != Builtin::KindObject &&
+ builtin->kind() != Builtin::KindObjectProxy)
+ {
+ out << nl << fixedName << " = ___" << fixedName << ".second;";
+ }
+ else if(!builtin || builtin->kind() == Builtin::KindString || builtin->kind() == Builtin::KindObject ||
+ builtin->kind() == Builtin::KindObjectProxy)
+ {
+ out << nl << fixedName << ".first" << " = &___" << fixedName << "[0];";
+ out << nl << fixedName << ".second" << " = " << fixedName << ".first + " << "___"
+ << fixedName << ".size();";
+ }
+ }
+ else if(seqType.find("range") == 0)
+ {
+ out << nl << fixedName << ".first = ___" << fixedName << ".begin();";
+ out << nl << fixedName << ".second = ___" << fixedName << ".end();";
+ }
+ }
+ }
+}
+
+}
+
+void
+Slice::writeEndCode(Output& out, const ParamDeclList& params, const TypePtr& ret, const StringList& metaData)
+{
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ writeParamEndCode(out, (*p)->type(), fixKwd((*p)->name()), (*p)->getMetaData());
+ }
+ if(ret)
+ {
+ writeParamEndCode(out, ret, "__ret", metaData);
+ }
+}
+
+// Accepted metadata.
+//
+// cpp:type:<typename>
+// cpp:const
+// cpp:array
+// cpp:range:<typename>
+// cpp:protobuf<:typename>
+//
+// For the new AMI mapping, we ignore the array and range directives because they don't apply.
+//
+// This form is for sequences definitions only.
+//
+string
+Slice::findMetaData(const SequencePtr& seq, const StringList& metaData, bool& isProtobuf, int typeCtx)
+{
+ 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 = str.substr(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.find("protobuf") == 0 || pos != string::npos)
+ {
+ if(ss.find("type:") == 0)
+ {
+ return str.substr(pos + 1);
+ }
+ else if(ss.find("protobuf:") == 0)
+ {
+ 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((typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd)) &&
+ !(typeCtx & TypeContextAMIEnd) && ss.find("range:") == 0)
+ {
+ return str.substr(prefix.size());
+ }
+ else if((typeCtx & TypeContextAMIPrivateEnd) && ss == "range:array")
+ {
+ 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(typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd) && !(typeCtx & TypeContextAMIEnd))
+ {
+ if(ss == "array")
+ {
+ return ss;
+ }
+ else if((typeCtx & TypeContextInParam) && 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, int typeCtx)
+{
+ 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());
+ //
+ // If the form is cpp:type:<...> the data after cpp:type:
+ // is returned. If the form is cpp:range:<...> the data
+ // after cpp: is returned.
+ //
+ if(pos != string::npos)
+ {
+ string ss = str.substr(prefix.size());
+ if(ss.find("type:") == 0)
+ {
+ return str.substr(pos + 1);
+ }
+ else if((typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd)) &&
+ !(typeCtx & TypeContextAMIEnd) && ss.find("range:") == 0)
+ {
+ return str.substr(prefix.size());
+ }
+ else if((typeCtx & TypeContextAMIPrivateEnd) && ss == "range:array")
+ {
+ return str.substr(prefix.size());
+ }
+ }
+ else if(typeCtx & (TypeContextInParam | TypeContextAMIPrivateEnd) && !(typeCtx & TypeContextAMIEnd))
+ {
+ string ss = str.substr(prefix.size());
+ if(ss == "array")
+ {
+ return ss;
+ }
+ else if((typeCtx & TypeContextInParam) && ss == "range")
+ {
+ return ss;
+ }
+ }
+ //
+ // Otherwise if the data is "class" it is returned.
+ //
+ else
+ {
+ string ss = str.substr(prefix.size());
+ if(ss == "class")
+ {
+ return ss;
+ }
+ }
+ }
+ }
+
+ return "";
+}
+
+bool
+Slice::inWstringModule(const SequencePtr& seq)
+{
+ ContainerPtr cont = seq->container();
+ while(cont)
+ {
+ ModulePtr mod = ModulePtr::dynamicCast(cont);
+ if(!mod)
+ {
+ break;
+ }
+ StringList metaData = mod->getMetaData();
+ if(find(metaData.begin(), metaData.end(), "cpp:type:wstring") != metaData.end())
+ {
+ return true;
+ }
+ else if(find(metaData.begin(), metaData.end(), "cpp:type:string") != metaData.end())
+ {
+ return false;
+ }
+ cont = mod->container();
+ }
+ return false;
+}