summaryrefslogtreecommitdiff
path: root/cpp/src/slice2objc/Gen.cpp
diff options
context:
space:
mode:
authorBenoit Foucher <benoit@zeroc.com>2015-01-07 15:11:14 +0100
committerBenoit Foucher <benoit@zeroc.com>2015-01-07 15:11:14 +0100
commitc126ec03755c9cea578c3b6584ed64c7ba065232 (patch)
tree453ad5f807fdca1deaa8b16ee62853b414ba1e58 /cpp/src/slice2objc/Gen.cpp
parentICE-6082 added sndBufSize and rcvBufSize to UDPEndpointInfo (diff)
downloadice-c126ec03755c9cea578c3b6584ed64c7ba065232.tar.bz2
ice-c126ec03755c9cea578c3b6584ed64c7ba065232.tar.xz
ice-c126ec03755c9cea578c3b6584ed64c7ba065232.zip
Added Objective-C mapping
Diffstat (limited to 'cpp/src/slice2objc/Gen.cpp')
-rw-r--r--cpp/src/slice2objc/Gen.cpp3139
1 files changed, 3139 insertions, 0 deletions
diff --git a/cpp/src/slice2objc/Gen.cpp b/cpp/src/slice2objc/Gen.cpp
new file mode 100644
index 00000000000..763f3f5661a
--- /dev/null
+++ b/cpp/src/slice2objc/Gen.cpp
@@ -0,0 +1,3139 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2014 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 <IceUtil/DisableWarnings.h>
+#include <IceUtil/Functional.h>
+#include <Gen.h>
+#include <limits>
+#include <sys/stat.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <direct.h>
+#endif
+#include <IceUtil/Iterator.h>
+#include <IceUtil/UUID.h>
+#include <Slice/Checksum.h>
+#include <Slice/FileTracker.h>
+#include <Slice/Util.h>
+#include <string.h>
+
+using namespace std;
+using namespace Slice;
+using namespace IceUtilInternal;
+
+namespace
+{
+
+string
+sliceModeToIceMode(Operation::Mode opMode)
+{
+ string mode;
+ switch(opMode)
+ {
+ case Operation::Normal:
+ {
+ mode = "ICENormal";
+ break;
+ }
+ case Operation::Nonmutating:
+ {
+ mode = "ICENonmutating";
+ break;
+ }
+ case Operation::Idempotent:
+ {
+ mode = "ICEIdempotent";
+ break;
+ }
+ default:
+ {
+ assert(false);
+ break;
+ }
+ }
+ return mode;
+}
+
+string
+opFormatTypeToString(const OperationPtr& op)
+{
+ switch(op->format())
+ {
+ case DefaultFormat:
+ {
+ return "ICEDefaultFormat";
+ break;
+ }
+ case CompactFormat:
+ {
+ return "ICECompactFormat";
+ break;
+ }
+ case SlicedFormat:
+ {
+ return "ICESlicedFormat";
+ break;
+ }
+ default:
+ {
+ assert(false);
+ }
+ }
+
+ return "???";
+}
+
+class SortParamDeclByTagFn
+{
+public:
+
+ static bool compare(const ParamDeclPtr& lhs, const ParamDeclPtr& rhs)
+ {
+ return lhs->tag() < rhs->tag();
+ }
+};
+
+}
+
+Slice::ObjCVisitor::ObjCVisitor(Output& h, Output& m) : _H(h), _M(m)
+{
+}
+
+Slice::ObjCVisitor::~ObjCVisitor()
+{
+}
+
+void
+Slice::ObjCVisitor::writeMarshalUnmarshalParams(const ParamDeclList& params, const OperationPtr& op, bool marshal,
+ bool reference)
+{
+ ParamDeclList optionals;
+ for(ParamDeclList::const_iterator p = params.begin(); p != params.end(); ++p)
+ {
+ if((*p)->optional())
+ {
+ optionals.push_back(*p);
+ }
+ else
+ {
+ string name = reference ? "*" + fixId((*p)->name()) : fixId((*p)->name());
+ writeMarshalUnmarshalCode(_M, (*p)->type(), name, marshal, true);
+ }
+ }
+ if(op && op->returnType())
+ {
+ if(!op->returnIsOptional())
+ {
+ writeMarshalUnmarshalCode(_M, op->returnType(), "ret_", marshal, true);
+ }
+ }
+
+ optionals.sort(SortParamDeclByTagFn::compare);
+ bool checkReturnType = op && op->returnIsOptional();
+ for(ParamDeclList::const_iterator p = optionals.begin(); p != optionals.end(); ++p)
+ {
+ if(checkReturnType && op->returnTag() < (*p)->tag())
+ {
+ writeOptParamMarshalUnmarshalCode(_M, op->returnType(), "ret_", op->returnTag(), marshal);
+ checkReturnType = false;
+ }
+ string name = reference ? "*" + fixId((*p)->name()) : fixId((*p)->name());
+ writeOptParamMarshalUnmarshalCode(_M, (*p)->type(), name, (*p)->tag(), marshal);
+ }
+ if(checkReturnType)
+ {
+ writeOptParamMarshalUnmarshalCode(_M, op->returnType(), "ret_", op->returnTag(), marshal);
+ }
+}
+
+void
+Slice::ObjCVisitor::writeDispatchAndMarshalling(const ClassDefPtr& p)
+{
+ string name = fixName(p);
+ string scoped = p->scoped();
+ ClassList allBases = p->allBases();
+ StringList ids;
+
+ transform(allBases.begin(), allBases.end(), back_inserter(ids), ::IceUtil::constMemFun(&Contained::scoped));
+
+ StringList other;
+ other.push_back(p->scoped());
+ other.push_back("::Ice::Object");
+ other.sort();
+ ids.merge(other);
+ ids.unique();
+
+ StringList::const_iterator firstIter = ids.begin();
+ StringList::const_iterator scopedIter = find(ids.begin(), ids.end(), scoped);
+ assert(scopedIter != ids.end());
+ StringList::difference_type scopedPos = IceUtilInternal::distance(firstIter, scopedIter);
+
+ _M << sp << nl << "static NSString *" << name << "_ids__[] = ";
+ _M << sb;
+ {
+ StringList::const_iterator q = ids.begin();
+ while(q != ids.end())
+ {
+ _M << nl << "@\"" << *q << '"';
+ if(++q != ids.end())
+ {
+ _M << ',';
+ }
+ }
+ }
+ _M << eb << ";";
+
+ OperationList ops = p->operations();
+ OperationList::const_iterator r;
+ for(r = ops.begin(); r != ops.end(); ++r)
+ {
+ OperationPtr op = *r;
+ ContainerPtr container = op->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ assert(cl);
+
+ string opName = getName(op);
+ _M << sp << nl << "+(BOOL)" << op->name() << "___:(id<" << name << ">)target_ current:(ICECurrent *)current "
+ << "is:(id<ICEInputStream>)is_ os:(id<ICEOutputStream>)os_";
+ _M << sb;
+
+ _M << nl << "ICEInternalCheckModeAndSelector(target_, " << sliceModeToIceMode(op->mode()) << ", @selector(";
+ string selector = getSelector(op);
+ if(!selector.empty())
+ {
+ _M << selector << "current:";
+ }
+ else
+ {
+ _M << opName << ":";
+ }
+ _M << "), current);";
+
+ _M << nl << "ICEEncodingVersion* encoding = [is_ startEncapsulation];";
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli)
+ {
+ if(!(*pli)->isOutParam())
+ {
+ inParams.push_back(*pli);
+ }
+ else
+ {
+ outParams.push_back(*pli);
+ }
+ }
+ ExceptionList throws = op->throws();
+ throws.sort();
+ throws.unique();
+ throws.sort(Slice::DerivedToBaseCompare());
+
+ for(ParamDeclList::const_iterator inp = inParams.begin(); inp != inParams.end(); ++inp)
+ {
+ TypePtr type = (*inp)->type();
+ string name = (*inp)->name();
+ _M << nl << outTypeToString(type, (*inp)->optional(), true) << " " << fixId(name);
+ if(!isValueType(type))
+ {
+ _M << " = nil";
+ }
+ _M << ";";
+ }
+ writeMarshalUnmarshalParams(inParams, 0, false);
+ if(op->sendsClasses(false))
+ {
+ _M << nl << "[is_ readPendingObjects];";
+ }
+ _M << nl << "[is_ endEncapsulation];";
+ if(!throws.empty())
+ {
+ _M << nl << "@try";
+ _M << sb;
+ }
+ for(ParamDeclList::const_iterator outp = outParams.begin(); outp != outParams.end(); ++outp)
+ {
+ TypePtr type = (*outp)->type();
+ string name = (*outp)->name();
+ _M << nl << inTypeToString(type, (*outp)->optional(), true) << " " << fixId(name);
+ if((*outp)->optional())
+ {
+ _M << " = ICENone";
+ }
+ _M << ";";
+ }
+ _M << nl << "[os_ startEncapsulation:encoding format:" << opFormatTypeToString(*r) << "];";
+ TypePtr returnType = op->returnType();
+ if(returnType)
+ {
+ _M << nl << inTypeToString(returnType, op->returnIsOptional(), true) << " ret_ = ";
+ }
+ else
+ {
+ _M << nl;
+ }
+ string args = getServerArgs(op);
+ _M << "[target_ " << opName << args;
+ if(!args.empty())
+ {
+ _M << " current";
+ }
+ _M << ":current];";
+ writeMarshalUnmarshalParams(outParams, op, true);
+ if(op->returnsClasses(false))
+ {
+ _M << nl << "[os_ writePendingObjects];";
+ }
+ if(!throws.empty())
+ {
+ _M << eb;
+ ExceptionList::const_iterator t;
+ for(t = throws.begin(); t != throws.end(); ++t)
+ {
+ string exS = fixName(*t);
+ _M << nl << "@catch(" << exS << " *ex)";
+ _M << sb;
+ _M << nl << "[os_ writeException:ex];";
+ _M << nl << "return NO;";
+ _M << eb;
+ }
+ _M << nl << "@finally";
+ _M << sb;
+ _M << nl << "[os_ endEncapsulation];";
+ _M << eb;
+ }
+ else
+ {
+ _M << nl << "[os_ endEncapsulation];";
+ }
+ _M << nl << "return YES;";
+ _M << eb;
+ }
+
+ OperationList allOps = p->allOperations();
+ if(!allOps.empty())
+ {
+ map<string, string> allOpNames;
+ for(OperationList::const_iterator p = allOps.begin(); p != allOps.end(); ++p)
+ {
+ allOpNames.insert(make_pair((*p)->name(), fixName(ClassDefPtr::dynamicCast((*p)->container()))));
+ }
+
+ allOpNames["ice_id"] = "ICEObject";
+ allOpNames["ice_ids"] = "ICEObject";
+ allOpNames["ice_isA"] = "ICEObject";
+ allOpNames["ice_ping"] = "ICEObject";
+
+ map<string, string>::const_iterator q;
+
+ _M << sp << nl << "static NSString *" << name << "_all__[] =";
+ _M << sb;
+ q = allOpNames.begin();
+ while(q != allOpNames.end())
+ {
+ _M << nl << "@\"" << q->first << '"';
+ if(++q != allOpNames.end())
+ {
+ _M << ',';
+ }
+ }
+ _M << eb << ';';
+
+ _M << sp << nl << "-(BOOL) dispatch__:(ICECurrent *)current is:(id<ICEInputStream>)is "
+ << "os:(id<ICEOutputStream>)os";
+ _M << sb;
+ _M << nl << "id target__ = [self target__];";
+ _M << nl << "switch(ICEInternalLookupString(" << name << "_all__, sizeof(" << name
+ << "_all__) / sizeof(NSString*), current.operation))";
+ _M << sb;
+ int i = 0;
+ for(q = allOpNames.begin(); q != allOpNames.end(); ++q)
+ {
+ _M << nl << "case " << i++ << ':';
+ _M.inc();
+ string target = (q->second == "ICEObject") ? "self" : "target__";
+ _M << nl << "return [" << q->second << " " << q->first << "___:(id<" << q->second
+ << ">)" << target << " current:current is:is os:os];";
+ _M.dec();
+ }
+ _M << nl << "default:";
+ _M.inc();
+ _M << nl << "@throw [ICEOperationNotExistException operationNotExistException:";
+ _M.useCurrentPosAsIndent();
+ _M << "__FILE__";
+ _M << nl << "line:__LINE__";
+ _M << nl << "id_:current.id_";
+ _M << nl << "facet:current.facet";
+ _M << nl << "operation:current.operation];";
+ _M.restoreIndent();
+ _M.dec();
+ _M << eb;
+ _M << eb;
+ }
+
+ _M << sp << nl << "+(NSString * const*) staticIds__:(int*)count idIndex:(int*)idx";
+ _M << sb;
+ _M << nl << "*count = sizeof(" << name << "_ids__) / sizeof(NSString *);";
+ _M << nl << "*idx = " << scopedPos << ";";
+ _M << nl << "return " << name << "_ids__;";
+ _M << eb;
+}
+
+string
+Slice::ObjCVisitor::getName(const OperationPtr& op) const
+{
+ if(!op->parameters().empty())
+ {
+ return fixId(op->name(), BaseTypeNone);
+ }
+ else
+ {
+ return fixId(op->name(), BaseTypeObject);
+ }
+}
+
+string
+Slice::ObjCVisitor::getSelector(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(q == paramList.begin())
+ {
+ result += getName(op) + ":";
+ }
+ else
+ {
+ result += fixId((*q)->name()) + ":";
+ }
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getParams(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = outTypeToString(type, (*q)->optional(), false, true);
+ }
+ else
+ {
+ typeString = inTypeToString(type, (*q)->optional());
+ }
+ string name = fixId((*q)->name());
+ if(q != paramList.begin())
+ {
+ result += " " + name;
+ }
+ result += ":(" + typeString + ")" + name;
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getMarshalParams(const OperationPtr& op) const
+{
+ ParamDeclList paramList = op->parameters();
+ string result;
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(!(*q)->isOutParam())
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name());
+ if(!result.empty())
+ {
+ result += " " + name;
+ }
+ result += ":(" + inTypeToString(type, (*q)->optional()) + ")" + name;
+ }
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getUnmarshalParams(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name());
+ if(!result.empty())
+ {
+ result += " " + name;
+ }
+ result += ":(" + outTypeToString(type, (*q)->optional(), false, true) + ")" + name;
+ }
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getServerParams(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string typeString;
+ if((*q)->isOutParam())
+ {
+ typeString = inTypeToString(type, (*q)->optional(), false, true);
+ }
+ else
+ {
+ typeString = outTypeToString(type, (*q)->optional());
+ }
+ string name = fixId((*q)->name());
+ if(q != paramList.begin())
+ {
+ result += " " + name;
+ }
+ result += ":(" + typeString + ")" + name;
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getResponseCBSig(const OperationPtr& op) const
+{
+ string result;
+ TypePtr returnType = op->returnType();
+ if(returnType)
+ {
+ result = outTypeToString(returnType, op->returnIsOptional());
+ }
+
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name());
+ if(!result.empty())
+ {
+ result += ", ";
+ }
+ result += outTypeToString(type, (*q)->optional());
+ }
+ }
+ return "void(^)(" + result + ")";
+}
+
+string
+Slice::ObjCVisitor::getArgs(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string name = fixId((*q)->name());
+ if(q != paramList.begin())
+ {
+ result += " " + name;
+ }
+ result += ":" + name;
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getMarshalArgs(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if(!(*q)->isOutParam())
+ {
+ string name = fixId((*q)->name());
+ if(!result.empty())
+ {
+ result += " " + name;
+ }
+ result += ":" + name;
+ }
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getUnmarshalArgs(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ if((*q)->isOutParam())
+ {
+ string name = fixId((*q)->name());
+ if(!result.empty())
+ {
+ result += " " + name;
+ }
+ result += ":" + name;
+ }
+ }
+ return result;
+}
+
+string
+Slice::ObjCVisitor::getServerArgs(const OperationPtr& op) const
+{
+ string result;
+ ParamDeclList paramList = op->parameters();
+ for(ParamDeclList::const_iterator q = paramList.begin(); q != paramList.end(); ++q)
+ {
+ string name = fixId((*q)->name());
+ if(q != paramList.begin())
+ {
+ result += " " + name;
+ }
+ result += ":";
+ if((*q)->isOutParam())
+ {
+ result += "&";
+ }
+ result += name;
+ }
+ return result;
+}
+
+Slice::Gen::Gen(const string& name, const string& base, const string& include, const vector<string>& includePaths,
+ const string& dir)
+ : _base(base),
+ _include(include),
+ _includePaths(includePaths)
+{
+ for(vector<string>::iterator p = _includePaths.begin(); p != _includePaths.end(); ++p)
+ {
+ *p = fullPath(*p);
+ }
+
+ string::size_type pos = _base.find_last_of("/\\");
+ if(pos != string::npos)
+ {
+ _base.erase(0, pos + 1);
+ }
+
+ string fileH = _base + ".h";
+ string fileM = _base + ".m";
+ string fileImplH = _base + "I.h";
+ string fileImplM = _base + "I.m";
+
+ if(!dir.empty())
+ {
+ fileH = dir + '/' + fileH;
+ fileM = dir + '/' + fileM;
+ fileImplH = dir + '/' + fileImplH;
+ fileImplM = dir + '/' + fileImplM;
+ }
+
+ _H.open(fileH.c_str());
+ if(!_H)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileH << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileH);
+ printHeader(_H);
+ _H << nl << "// Generated from file `" << _base << ".ice'";
+
+ _H << sp << nl << "#import <objc/Ice/Config.h>";
+ _H << nl << "#import <objc/Ice/Proxy.h>";
+ _H << nl << "#import <objc/Ice/Object.h>";
+ _H << nl << "#import <objc/Ice/Current.h>";
+ _H << nl << "#import <objc/Ice/Exception.h>";
+ _H << nl << "#import <objc/Ice/Stream.h>";
+
+ _M.open(fileM.c_str());
+ if(!_M)
+ {
+ ostringstream os;
+ os << "cannot open `" << fileM << "': " << strerror(errno);
+ throw FileException(__FILE__, __LINE__, os.str());
+ }
+ FileTracker::instance()->addFile(fileM);
+ printHeader(_M);
+ _M << nl << "// Generated from file `" << _base << ".ice'";
+}
+
+Slice::Gen::~Gen()
+{
+ if(_H.isOpen())
+ {
+ _H << '\n';
+ _M << '\n';
+ }
+}
+
+bool
+Slice::Gen::operator!() const
+{
+ if(!_H || !_M)
+ {
+ return true;
+ }
+ return false;
+}
+
+void
+Slice::Gen::generate(const UnitPtr& p)
+{
+ ObjCGenerator::validateMetaData(p);
+
+ _M << nl << "\n#import <objc/Ice/LocalException.h>";
+ _M << nl << "#import <objc/Ice/Stream.h>";
+ if(p->hasContentsWithMetaData("preserve-slice"))
+ {
+ _H << "\n#import <objc/Ice/SlicedData.h>";
+ }
+ _M << nl << "#import <";
+ if(!_include.empty())
+ {
+ _M << _include << "/";
+ }
+ _M << _base << ".h>";
+
+ // Necessary for objc_getClass use when marshalling/unmarshalling proxies.
+ _M << nl << "#import <objc/runtime.h>";
+
+ _M << nl;
+
+ StringList includes = p->includeFiles();
+ for(StringList::const_iterator q = includes.begin(); q != includes.end(); ++q)
+ {
+ static const string headerDirPrefix = "objc:header-dir:";
+ DefinitionContextPtr dc = p->findDefinitionContext(*q);
+ assert(dc);
+ string meta = dc->findMetaData(headerDirPrefix);
+ string headerDir;
+ if(meta.size() > headerDirPrefix.size())
+ {
+ headerDir = meta.substr(headerDirPrefix.size());
+ }
+ _H << "\n#import <";
+ if(!headerDir.empty())
+ {
+ _H << headerDir << "/";
+ }
+ _H << changeInclude(*q, _includePaths) << ".h>";
+ }
+
+ UnitVisitor unitVisitor(_H, _M);
+ p->visit(&unitVisitor, false);
+
+ ObjectDeclVisitor objectDeclVisitor(_H, _M);
+ p->visit(&objectDeclVisitor, false);
+
+ ProxyDeclVisitor proxyDeclVisitor(_H, _M);
+ p->visit(&proxyDeclVisitor, false);
+
+ TypesVisitor typesVisitor(_H, _M);
+ p->visit(&typesVisitor, false);
+
+ ProxyVisitor proxyVisitor(_H, _M);
+ p->visit(&proxyVisitor, false);
+
+ DelegateMVisitor delegateMVisitor(_H, _M);
+ p->visit(&delegateMVisitor, false);
+
+ HelperVisitor HelperVisitor(_H, _M);
+ p->visit(&HelperVisitor, false);
+}
+
+void
+Slice::Gen::closeOutput()
+{
+ _H.close();
+ _M.close();
+}
+
+void
+Slice::Gen::printHeader(Output& o)
+{
+ static const char* header =
+"// **********************************************************************\n"
+"//\n"
+"// Copyright (c) 2003-2014 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"
+ ;
+
+ o << header;
+ o << "\n// Ice version " << ICE_STRING_VERSION;
+}
+
+Slice::Gen::UnitVisitor::UnitVisitor(Output& H, Output& M) :
+ ObjCVisitor(H, M)
+{
+}
+
+bool
+Slice::Gen::UnitVisitor::visitModuleStart(const ModulePtr& p)
+{
+ string dummy;
+ if(p->findMetaData("objc:prefix", dummy))
+ {
+ _prefixes.push_back(modulePrefix(p));
+ }
+ return true;
+}
+
+void
+Slice::Gen::UnitVisitor::visitUnitEnd(const UnitPtr& unit)
+{
+ string uuid = IceUtil::generateUUID();
+ for(string::size_type pos = 0; pos < uuid.size(); ++pos)
+ {
+ if(!isalnum(uuid[pos]))
+ {
+ uuid[pos] = '_';
+ }
+ }
+
+ if(!_prefixes.empty())
+ {
+ _M << sp << nl << "@implementation ICEInternalPrefixTable(C" << uuid << ")";
+ _M << nl << "-(void)addPrefixes_C" << uuid << ":(NSMutableDictionary*)prefixTable";
+ _M << sb;
+ for(vector<Slice::ObjCGenerator::ModulePrefix>::const_iterator p = _prefixes.begin(); p != _prefixes.end(); ++p)
+ {
+ _M << nl << "[prefixTable setObject:@\"" << p->name << "\" forKey:@\"" << p->m->scoped() << "\"];";
+ }
+ _M << eb;
+ _M << nl << "@end";
+ }
+}
+
+Slice::Gen::ObjectDeclVisitor::ObjectDeclVisitor(Output& H, Output& M)
+ : ObjCVisitor(H, M)
+{
+}
+
+void
+Slice::Gen::ObjectDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ _H << sp << nl << "@class " << fixName(p) << ";";
+ _H << nl << "@protocol " << fixName(p) << ";";
+}
+
+Slice::Gen::ProxyDeclVisitor::ProxyDeclVisitor(Output& H, Output& M)
+ : ObjCVisitor(H, M)
+{
+}
+
+void
+Slice::Gen::ProxyDeclVisitor::visitClassDecl(const ClassDeclPtr& p)
+{
+ _H << sp << nl << "@class " << fixName(p) << "Prx;";
+ _H << nl << "@protocol " << fixName(p) << "Prx;";
+}
+
+Slice::Gen::TypesVisitor::TypesVisitor(Output& H, Output& M)
+ : ObjCVisitor(H, M)
+{
+}
+
+bool
+Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p)
+{
+ string suffix;
+ StringList names = splitScopedName(p->scoped());
+ for(StringList::const_iterator i = names.begin(); i != names.end(); ++i)
+ {
+ if(i != names.begin())
+ {
+ suffix += "_";
+ }
+ suffix += *i;
+ }
+ string symbol = "ICE_MODULE_PREFIX_";
+ symbol += suffix;
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitModuleEnd(const ModulePtr&)
+{
+}
+
+bool
+Slice::Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ string name = fixName(p);
+ ClassList bases = p->bases();
+
+ _H << sp << nl << "@protocol " << name;
+ if(!bases.empty())
+ {
+ _H << " <";
+ for(ClassList::const_iterator i = bases.begin(); i != bases.end(); ++i)
+ {
+ string baseName = fixName(*i);
+ if(i != bases.begin())
+ {
+ _H << ", ";
+ }
+ _H << baseName;
+ }
+ _H << ">";
+ }
+
+ _M << sp << nl << "@implementation " << name;
+
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ string name = fixName(p);
+ ClassList bases = p->bases();
+ bool basePreserved = p->inheritsMetaData("preserve-slice");
+ bool preserved = p->hasMetaData("preserve-slice");
+ bool hasBaseClass = !bases.empty() && !bases.front()->isInterface();
+ string baseName = hasBaseClass ? fixName(bases.front()) : "ICEObject";
+ DataMemberList baseDataMembers;
+ if(hasBaseClass)
+ {
+ baseDataMembers = bases.front()->allDataMembers();
+ }
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList optionalMembers = p->orderedOptionalDataMembers();
+ DataMemberList allDataMembers = p->allDataMembers();
+
+ _H << nl << "@end";
+
+ _H << sp << nl << "@interface " << name << " : " << baseName;
+
+ if(!dataMembers.empty() || (preserved && !basePreserved))
+ {
+ //
+ // Data member declarations.
+ //
+ _H << sb;
+
+ if(!dataMembers.empty())
+ {
+ writeMembers(dataMembers, BaseTypeObject);
+ }
+
+ if(preserved && !basePreserved)
+ {
+ _H << nl << "id<ICESlicedData> slicedData__;";
+ }
+
+ _H << eb;
+ _H << sp;
+
+ _M << sp;
+ }
+
+ //
+ // @property and @synthesize for each data member.
+ //
+ writeProperties(dataMembers, BaseTypeObject);
+ writeSynthesize(dataMembers, BaseTypeObject);
+
+ //
+ // Constructor.
+ //
+ if(!dataMembers.empty())
+ {
+ _H << sp;
+ }
+ if(!p->isInterface() && !dataMembers.empty())
+ {
+ if(p->hasDefaultValues())
+ {
+ _H << nl << "-(id) init;";
+ _M << sp << nl << "-(id) init";
+ _M << sb;
+ _M << nl << "self = [super init];";
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ writeMemberDefaultValueInit(dataMembers, BaseTypeObject);
+ _M << nl << "return self;";
+ _M << eb;
+ }
+ _H << nl << "-(id) init";
+ _M << sp << nl << "-(id) init";
+ writeMemberSignature(allDataMembers, BaseTypeObject, Other);
+ _H << ";";
+ _M << sb;
+ _M << nl << "self = [super init";
+ writeMemberCall(baseDataMembers, BaseTypeObject, Other, WithEscape);
+ _M << "];";
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ writeMemberInit(dataMembers, BaseTypeObject);
+ _M << nl << "return self;";
+ _M << eb;
+ }
+
+ //
+ // Convenience constructors.
+ //
+ if(!allDataMembers.empty())
+ {
+ string lowerCaseName = fixId(p->name());
+ *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin());
+
+ _H << nl << "+(id) " << lowerCaseName;
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ writeMemberSignature(allDataMembers, BaseTypeObject, Other);
+ _H << ";";
+ _M << sb;
+
+ //
+ // The cast avoids a compiler warning that is emitted if different structs
+ // have members with the same name but different types.
+ //
+ _M << nl << name << " *s__ = [(" << name << " *)[" << name << " alloc] init";
+ writeMemberCall(allDataMembers, BaseTypeObject, Other, WithEscape);
+ _M << "];";
+
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+
+ _M << nl << "return s__;";
+ _M << eb;
+
+ _H << nl << "+(id) " << lowerCaseName << ";";
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ _M << sb;
+ _M << nl << name << " *s__ = [[" << name << " alloc] init];";
+
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+
+ _M << nl << "return s__;";
+ _M << eb;
+ }
+
+ if(!p->isInterface())
+ {
+ //
+ // copyWithZone and dealloc
+ //
+ if(!dataMembers.empty())
+ {
+ _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p";
+ _M << sb;
+ _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init";
+ writeMemberCall(allDataMembers, BaseTypeObject, Other, NoEscape);
+ _M << "];";
+ _M << eb;
+ _H << nl << "// This class also overrides copyWithZone:.";
+
+ writeMemberDealloc(dataMembers, BaseTypeObject, preserved && !basePreserved);
+ }
+ }
+
+ //
+ // Setter, has, clear selectors for optionals
+ //
+ writeOptionalDataMemberSelectors(dataMembers, BaseTypeObject);
+
+ //
+ // If the class uses a compact id we generate a +load method to register the compact id
+ // with the compact id resolver.
+ //
+ if(p->compactId() >= 0)
+ {
+ _M << sp << nl << "+(void) load";
+ _M << sb;
+ _M << nl << "[CompactIdMapHelper registerClass:@\"" << p->scoped() << "\" value:" << p->compactId() << "];";
+ _M << eb;
+ }
+
+ //
+ // Operations
+ //
+ OperationList ops = p->operations();
+ OperationList::const_iterator r;
+ for(r = ops.begin(); r != ops.end(); ++r)
+ {
+ OperationPtr op = *r;
+ _H << nl << "+(BOOL)" << op->name() << "___:(id<" << name
+ << ">)target current:(ICECurrent *)current "
+ << "is:(id<ICEInputStream>)is_ os:(id<ICEOutputStream>)os_;";
+ }
+
+ _M << sp << nl << "+(id)objectWithDelegate:(id)delegate";
+ _M << sb;
+ _M.zeroIndent();
+ _M << sp << nl << "#if defined(__clang__) && __has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "return [[" << name << " alloc] initWithDelegate:delegate];";
+ _M.zeroIndent();
+ _M << nl << "#else";
+ _M.restoreIndent();
+ _M << nl << "return [[[" << name << " alloc] initWithDelegate:delegate] autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _M << eb;
+
+ //
+ // Marshaling/unmarshaling
+ //
+
+ _M << sp << nl << "-(void) writeImpl__:(id<ICEOutputStream>)os_";
+ _M << sb;
+ _M << nl << "[os_ startSlice:@\"" << p->scoped() << "\" compactId: " << p->compactId() << " lastSlice:"
+ << (!hasBaseClass ? "YES" : "NO") << "];";
+ writeMemberMarshal(dataMembers, optionalMembers, BaseTypeObject);
+ _M << nl << "[os_ endSlice];";
+ if(hasBaseClass)
+ {
+ _M << nl << "[super writeImpl__:os_];";
+ }
+ _M << eb;
+
+ _H << nl << "@end";
+
+ _M << sp << nl << "-(void) readImpl__:(id<ICEInputStream>)is_";
+ _M << sb;
+ _M << nl << "[is_ startSlice];";
+ writeMemberUnmarshal(dataMembers, optionalMembers, BaseTypeObject);
+ _M << nl << "[is_ endSlice];";
+ if(hasBaseClass)
+ {
+ _M << nl << "[super readImpl__:is_];";
+ }
+ _M << eb;
+
+ writeDispatchAndMarshalling(p);
+
+ if(preserved && !basePreserved)
+ {
+ _M << nl << "-(void) write__:(id<ICEOutputStream>)os";
+ _M << sb;
+ _M << nl << "[os startObject:slicedData__];";
+ _M << nl << "[self writeImpl__:os];";
+ _M << nl << "[os endObject];";
+ _M << eb;
+
+ _M << nl << "-(void) read__:(id<ICEInputStream>)is";
+ _M << sb;
+ _M << nl << "[is startObject];";
+ _M << nl << "[self readImpl__:is];";
+ _M << nl << "slicedData__ = [is endObject:YES];";
+ _M << eb;
+ }
+
+ _M << nl << "@end";
+}
+
+void
+Slice::Gen::TypesVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = getName(p);
+ TypePtr returnType = p->returnType();
+ string retString = typeToString(returnType);
+ string params = getServerParams(p);
+
+
+ _H << nl << "-(" << inTypeToString(returnType, p->returnIsOptional()) << ") " << name << params;
+ if(!params.empty())
+ {
+ _H << " current";
+ }
+ _H << ":(ICECurrent *)current;";
+}
+
+void
+Slice::Gen::TypesVisitor::visitSequence(const SequencePtr& p)
+{
+ string prefix = moduleName(findModule(p));
+ string name = fixName(p);
+
+ if(isValueType(p->type()))
+ {
+ _H << sp << nl << "typedef NSData " << name << ";";
+ _H << nl << "typedef NSMutableData " << prefix << "Mutable" << p->name() << ";";
+ }
+ else
+ {
+ _H << sp << nl << "typedef NSArray " << name << ";";
+ _H << nl << "typedef NSMutableArray " << prefix << "Mutable" << p->name() << ";";
+ }
+}
+
+bool
+Slice::Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
+{
+ string name = fixName(p);
+ ExceptionPtr base = p->base();
+ DataMemberList dataMembers = p->dataMembers();
+ bool basePreserved = p->inheritsMetaData("preserve-slice");
+ bool preserved = p->hasMetaData("preserve-slice");
+
+ _H << sp;
+
+ _H << nl << "@interface " << name << " : ";
+ if(base)
+ {
+ _H << fixName(base);
+ }
+ else
+ {
+ _H << (p->isLocal() ? "ICELocalException" : "ICEUserException");
+ }
+ if(!dataMembers.empty() || (preserved && !basePreserved))
+ {
+ _H << sb;
+ }
+
+ _M << sp << nl << "@implementation " << name;
+
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitExceptionEnd(const ExceptionPtr& p)
+{
+ string name = fixName(p);
+
+ string lowerCaseName = fixId(p->name());
+ *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin());
+ bool basePreserved = p->inheritsMetaData("preserve-slice");
+ bool preserved = p->hasMetaData("preserve-slice");
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList optionalMembers = p->orderedOptionalDataMembers();
+ DataMemberList allDataMembers = p->allDataMembers();
+ DataMemberList::const_iterator q;
+
+ DataMemberList baseDataMembers;
+ if(p->base())
+ {
+ baseDataMembers = p->base()->allDataMembers();
+ }
+
+ if(!dataMembers.empty() || (preserved && !basePreserved))
+ {
+ //
+ // Data member declarations.
+ //
+ if(!dataMembers.empty())
+ {
+ writeMembers(dataMembers, BaseTypeException);
+ }
+
+ if(preserved && !basePreserved)
+ {
+ _H << nl << "id<ICESlicedData> slicedData__;";
+ }
+
+ _H << eb;
+ _H << sp;
+ _M << sp;
+
+ //
+ // @property and @synthesize for each data member.
+ //
+ if(!dataMembers.empty())
+ {
+ writeProperties(dataMembers, BaseTypeException);
+ writeSynthesize(dataMembers, BaseTypeException);
+ }
+ _H << sp;
+ }
+
+ //
+ // ice_name
+ //
+ _H << nl << "-(NSString *) ice_name;";
+ _M << sp << nl << "-(NSString *) ice_name";
+ _M << sb;
+ _M << nl << "return @\"" << p->scoped().substr(2) << "\";";
+ _M << eb;
+
+ //
+ // Constructors.
+ //
+ if(p->isLocal() && !dataMembers.empty())
+ {
+ _H << nl << "-(id) init:(const char*)file__p line:(int)line__p;";
+ _M << sp << nl << "-(id) init:(const char*)file__p line:(int)line__p";
+ _M << sb;
+ _M << nl << "self = [super init:file__p line:line__p];";
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ _M << nl << "return self;";
+ _M << eb;
+ }
+ if(!dataMembers.empty())
+ {
+ if(!p->base() || p->hasDefaultValues())
+ {
+ _H << sp << nl << "-(id) init;";
+ _M << sp << nl << "-(id) init";
+ _M << sb;
+ _M << nl << "self = ";
+ if(!p->base())
+ {
+ _M << "[super initWithName:[self ice_name] reason:nil userInfo:nil];";
+ }
+ else
+ {
+ _M << nl << "[super init];";
+ }
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ if(p->hasDefaultValues())
+ {
+ writeMemberDefaultValueInit(dataMembers, BaseTypeObject);
+ }
+ _M << nl << "return self;";
+ _M << eb;
+ }
+
+ _H << nl << "-(id) init";
+ _M << sp << nl << "-(id) init";
+ writeMemberSignature(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other);
+ _H << ";";
+ _M << sb;
+ _M << nl << "self = ";
+ if(!p->base())
+ {
+ _M << nl << "[super initWithName:[self ice_name] reason:nil userInfo:nil];";
+ }
+ else
+ {
+ _M << nl << "[super init";
+ if(p->isLocal())
+ {
+ _M << ":file__p line:line__p ";
+ }
+ writeMemberCall(baseDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, WithEscape);
+ _M << "];";
+ }
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ if(!dataMembers.empty())
+ {
+ writeMemberInit(dataMembers, BaseTypeException);
+ }
+ _M << nl << "return self;";
+ _M << eb;
+ }
+
+ //
+ // Convenience constructors.
+ //
+ _H << nl << "+(id) " << lowerCaseName;
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ writeMemberSignature(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other);
+ _H << ";";
+
+ //
+ // The cast avoids a compiler warning that is emitted if different exceptions
+ // have members with the same name but different types.
+ //
+ _M << sb;
+ _M << nl << name << " *s__ = [(" << name << " *)[" << name << " alloc] init";
+ if(p->isLocal())
+ {
+ _M << ":file__p line:line__p";
+ }
+ writeMemberCall(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, WithEscape);
+ _M << "];";
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _M << nl << "return s__;";
+ _M << eb;
+
+ if(!allDataMembers.empty())
+ {
+ _H << nl << "+(id) " << lowerCaseName;
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ if(p->isLocal())
+ {
+ _H << ":(const char*)file__p line:(int)line__p";
+ _M << ":(const char*)file__p line:(int)line__p";
+ }
+ _H << ";";
+ _M << sb;
+ _M << nl << name << " *s__ = [[" << name << " alloc] init";
+ if(p->isLocal())
+ {
+ _M << ":file__p line:line__p";
+ }
+ _M << "];";
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _M << nl << "return s__;";
+ _M << eb;
+ }
+
+ //
+ // copyWithZone and dealloc
+ //
+ if(!dataMembers.empty())
+ {
+ _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p";
+ _M << sb;
+ _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init";
+ if(p->isLocal())
+ {
+ _M << ":file line:line";
+ }
+ writeMemberCall(allDataMembers, BaseTypeException, p->isLocal() ? LocalException : Other, NoEscape);
+ _M << "];";
+ _M << eb;
+ _H << nl << "// This class also overrides copyWithZone:.";
+
+ writeMemberDealloc(dataMembers, BaseTypeException, preserved && !basePreserved);
+ }
+
+ //
+ // Setter, has, clear selectors for optionals
+ //
+ writeOptionalDataMemberSelectors(dataMembers, BaseTypeObject);
+
+ //
+ // Marshaling/unmarshaling
+ //
+ ExceptionPtr base = p->base();
+ if(!p->allClassDataMembers().empty())
+ {
+ if(!base || (base && !base->usesClasses(false)))
+ {
+ _M << sp << nl << "-(BOOL) usesClasses__";
+ _M << sb;
+ _M << nl << "return YES;";
+ _M << eb;
+ }
+ }
+
+ if(!p->isLocal())
+ {
+ _M << sp << nl << "-(void) writeImpl__:(id<ICEOutputStream>)os_";
+ _M << sb;
+ _M << nl << "[os_ startSlice:@\"" << p->scoped() << "\" compactId:-1 lastSlice:"
+ << (!base ? "YES" : "NO") << "];";
+ writeMemberMarshal(dataMembers, optionalMembers, BaseTypeException);
+ _M << nl << "[os_ endSlice];";
+ if(base)
+ {
+ _M << nl << "[super writeImpl__:os_];";
+ }
+ _M << eb;
+
+ _M << sp << nl << "-(void) readImpl__:(id<ICEInputStream>)is_";
+ _M << sb;
+ _M << nl << "[is_ startSlice];";
+ writeMemberUnmarshal(dataMembers, optionalMembers, BaseTypeException);
+ _M << nl << "[is_ endSlice];";
+ if(base)
+ {
+ _M << nl << "[super readImpl__:is_];";
+ }
+ _M << eb;
+
+ if(preserved && !basePreserved)
+ {
+ _M << nl << nl << "-(void) write__:(id<ICEOutputStream>)os";
+ _M << sb;
+ _M << nl << "[os startException:slicedData__];";
+ _M << nl << "[self writeImpl__:os];";
+ _M << nl << "[os endException];";
+ _M << eb;
+
+ _M << nl << nl << "-(void) read__:(id<ICEInputStream>)is";
+ _M << sb;
+ _M << nl << "[is startException];";
+ _M << nl << "[self readImpl__:is];";
+ _M << nl << "slicedData__ = [is endException:YES];";
+ _M << eb;
+ }
+ }
+
+ _H << nl << "@end";
+ _M << nl << "@end";
+}
+
+bool
+Slice::Gen::TypesVisitor::visitStructStart(const StructPtr& p)
+{
+ string name = fixName(p);
+
+ _H << sp;
+
+ _H << nl << "@interface " << name << " : NSObject <NSCopying>";
+ _H << sb;
+ _H << nl << "@private";
+ _H.inc();
+
+ _M << sp << nl << "@implementation " << name << sp;
+
+ return true;
+}
+
+void
+Slice::Gen::TypesVisitor::visitStructEnd(const StructPtr& p)
+{
+ string name = fixName(p);
+ DataMemberList dataMembers = p->dataMembers();
+ DataMemberList::const_iterator q;
+
+ //
+ // Data member declarations.
+ //
+ writeMembers(dataMembers, BaseTypeObject);
+
+ _H.dec();
+ _H << eb;
+
+ _H << sp;
+
+ //
+ // @property and @synthesize for each data member.
+ //
+ writeProperties(dataMembers, BaseTypeObject);
+ writeSynthesize(dataMembers, BaseTypeObject);
+
+ //
+ // Constructor.
+ //
+ if(p->hasDefaultValues())
+ {
+ _H << sp << nl << "-(id) init;";
+ _M << sp << nl << "-(id) init";
+ _M << sb;
+ _M << nl << "self = [super init];";
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ writeMemberDefaultValueInit(dataMembers, BaseTypeObject);
+ _M << nl << "return self;";
+ _M << eb;
+ }
+ _H << sp << nl << "-(id) init";
+ _M << sp << nl << "-(id) init";
+ writeMemberSignature(dataMembers, BaseTypeObject, Other);
+ _H << ";";
+ _M << sb;
+ _M << nl << "self = [super init];";
+ _M << nl << "if(!self)";
+ _M << sb;
+ _M << nl << "return nil;";
+ _M << eb;
+ writeMemberInit(dataMembers, BaseTypeObject);
+ _M << nl << "return self;";
+ _M << eb;
+
+ //
+ // Convenience constructor.
+ //
+ string lowerCaseName = fixId(p->name());
+ *(lowerCaseName.begin()) = tolower(*lowerCaseName.begin());
+
+ _H << nl << "+(id) " << lowerCaseName;
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ writeMemberSignature(dataMembers, BaseTypeObject, Other);
+ _H << ";";
+ _M << sb;
+
+ //
+ // The cast avoids a compiler warning that is emitted if different structs
+ // have members with the same name but different types.
+ //
+ _M << nl << name << " *s__ = [(" << name << "* )[" << name << " alloc] init";
+ writeMemberCall(dataMembers, BaseTypeObject, Other, WithEscape);
+ _M << "];";
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _M << nl << "return s__;";
+ _M << eb;
+
+ _H << nl << "+(id) " << lowerCaseName << ";";
+ _M << sp << nl << "+(id) " << lowerCaseName;
+ _M << sb;
+ _M << nl << name << " *s__ = [[" << name << " alloc] init];";
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "[s__ autorelease];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _M << nl << "return s__;";
+ _M << eb;
+
+ //
+ // copyWithZone
+ //
+ _M << sp << nl << "-(id) copyWithZone:(NSZone *)zone_p";
+ _M << sb;
+ _M << nl << "return [(" << name << " *)[[self class] allocWithZone:zone_p] init";
+ writeMemberCall(dataMembers, BaseTypeObject, Other, NoEscape);
+ _M << "];";
+ _M << eb;
+
+ //
+ // hash
+ //
+ writeMemberHashCode(dataMembers, BaseTypeObject);
+
+ //
+ // isEqual
+ //
+ _M << sp << nl << "-(BOOL) isEqual:(id)o_";
+ _M << sb;
+ _M << nl << "if(self == o_)";
+ _M << sb;
+ _M << nl << "return YES;";
+ _M << eb;
+ _M << nl << "if(!o_ || ![o_ isKindOfClass:[self class]])";
+ _M << sb;
+ _M << nl << "return NO;";
+ _M << eb;
+ writeMemberEquals(dataMembers, BaseTypeObject);
+ _M << eb;
+
+ _H << nl << "// This class also overrides copyWithZone:, hash, and isEqual:";
+
+ //
+ // dealloc
+ //
+ writeMemberDealloc(dataMembers, BaseTypeObject);
+
+ //
+ // Marshaling/unmarshaling
+ //
+ _H << nl << "-(void) write__:(id<ICEOutputStream>)os_;";
+ _H << nl << "-(void) read__:(id<ICEInputStream>)is_;";
+
+ _M << sp << nl << "-(void) write__:(id<ICEOutputStream>)os_";
+ _M << sb;
+ writeMemberMarshal(dataMembers, DataMemberList(), BaseTypeObject);
+ _M << eb;
+
+ _M << sp << nl << "-(void) read__:(id<ICEInputStream>)is_";
+ _M << sb;
+ writeMemberUnmarshal(dataMembers, DataMemberList(), BaseTypeObject);
+ _M << eb;
+
+ _H << nl << "@end";
+ _M << nl << "@end";
+}
+
+void
+Slice::Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ string prefix = moduleName(findModule(p));
+ string name = fixName(p);
+
+ _H << sp << nl << "typedef NSDictionary " << name << ";";
+ _H << nl << "typedef NSMutableDictionary " << prefix << "Mutable" << p->name() << ";";
+}
+
+void
+Slice::Gen::TypesVisitor::visitEnum(const EnumPtr& p)
+{
+ string name = fixName(p);
+ EnumeratorList enumerators = p->getEnumerators();
+ _H << sp;
+
+ //
+ // Check if any of the enumerators were assigned an explicit value.
+ //
+ const bool explicitValue = p->explicitValue();
+
+ _H << nl << "typedef enum : ICEInt";
+ _H << sb;
+ EnumeratorList::const_iterator en = enumerators.begin();
+ while(en != enumerators.end())
+ {
+ _H << nl << fixName(*en);
+ //
+ // If any of the enumerators were assigned an explicit value, we emit
+ // an explicit value for *all* enumerators.
+ //
+ if(explicitValue)
+ {
+ _H << " = " << int64ToString((*en)->value());
+ }
+ if(++en != enumerators.end())
+ {
+ _H << ',';
+ }
+ }
+ _H << eb << " " << name << ";";
+}
+
+void
+Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p)
+{
+ _H << sp;
+ if(isString(p->type()))
+ {
+ _H << nl << "static NSString * const";
+ }
+ else
+ {
+ _H << nl << "static const " << typeToString(p->type());
+ }
+ _H << " " << fixName(p) << " = ";
+ writeConstantValue(_H, p->type(), p->value());
+ _H << ';';
+}
+
+void
+Slice::Gen::TypesVisitor::writeConstantValue(IceUtilInternal::Output& out, const TypePtr& type, const string& val) const
+{
+ if(isString(type))
+ {
+ //
+ // Expand strings into the basic source character set. We can't use isalpha() and the like
+ // here because they are sensitive to the current locale.
+ //
+ static const string basicSourceChars = "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789"
+ "_{}[]#()<>%:;.?*+-/^&|~!=,\\\"' ";
+ static const set<char> charSet(basicSourceChars.begin(), basicSourceChars.end());
+
+ out << "@\""; // Opening @"
+
+ for(string::const_iterator c = val.begin(); c != val.end(); ++c)
+ {
+ if(charSet.find(*c) == charSet.end())
+ {
+ unsigned char uc = *c; // char may be signed, so make it positive
+ ostringstream s;
+ s << "\\"; // Print as octal if not in basic source character set
+ s.width(3);
+ s.fill('0');
+ s << oct;
+ s << static_cast<unsigned>(uc);
+ out << s.str();
+ }
+ else
+ {
+ out << *c; // Print normally if in basic source character set
+ }
+ }
+
+ out << "\""; // Closing "
+ }
+ else
+ {
+ EnumPtr ep = EnumPtr::dynamicCast(type);
+ if(ep)
+ {
+ out << moduleName(findModule(ep)) << val;
+ }
+ else
+ {
+ if(val == "true")
+ {
+ out << "YES";
+ }
+ else if(val == "false")
+ {
+ out << "NO";
+ }
+ else
+ {
+ out << val;
+ }
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMembers(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name(), baseType);
+
+ _H << nl << typeToString(type) << " ";
+ if(mapsToPointerType(type))
+ {
+ _H << "*";
+ }
+ _H << name << ";";
+
+ if((*q)->optional())
+ {
+ _H << nl << "BOOL has_" << name << "__;";
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberSignature(const DataMemberList& dataMembers, int baseType,
+ ContainerType ct) const
+{
+ if(ct == LocalException)
+ {
+ _H << ":(const char*)file__p line:(int)line__p";
+ _M << ":(const char*)file__p line:(int)line__p";
+ }
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string typeString = inTypeToString(type, (*q)->optional());
+ string name = fixId((*q)->name(), baseType);
+
+ if(q != dataMembers.begin() || ct == LocalException)
+ {
+ _H << " " << name;
+ _M << " " << name;
+ }
+ _H << ":(" << typeString << ")" << fixId((*q)->name());
+ _M << ":(" << typeString << ")" << fixId((*q)->name()) << "_p";
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberCall(const DataMemberList& dataMembers, int baseType,
+ ContainerType ct, Escape esc) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string name = (*q)->name();
+
+ if(q != dataMembers.begin() || ct == LocalException)
+ {
+ _M << " " << fixId(name, baseType);
+ }
+
+ name = esc == NoEscape ? fixId(name, baseType) : fixId(name);
+ if(esc == NoEscape)
+ {
+ if((*q)->optional())
+ {
+ if(isValueType((*q)->type()))
+ {
+ _M << ":" << "(self->has_" << name << "__ ? @(self->" << name << ") : ICENone)";
+ }
+ else
+ {
+ _M << ":" << "(self->has_" << name << "__ ? self->" << name << " : ICENone)";
+ }
+ }
+ else
+ {
+ _M << ":" << name;
+ }
+ }
+ else
+ {
+ _M << ":" << name << "_p";
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberDefaultValueInit(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator p = dataMembers.begin(); p != dataMembers.end(); ++p)
+ {
+ if((*p)->defaultValueType())
+ {
+ string name = fixId((*p)->name(), baseType);
+ if((*p)->optional())
+ {
+ _M << nl << "self->has_" << name << "__ = YES;";
+ }
+ _M << nl << "self->" << name << " = ";
+ writeConstantValue(_M, (*p)->type(), (*p)->defaultValue());
+ _M << ";";
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberInit(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name());
+ if((*q)->optional())
+ {
+ if(isValueType(type))
+ {
+ _M << nl << "self->has_" << name << "__ = [ICEOptionalGetter " << getOptionalHelperGetter(type) << ":";
+ _M << name << "_p value:&self->" << fixId((*q)->name(), baseType) << "];";
+ }
+ else
+ {
+ _M << nl << "self->has_" << name << "__ = [ICEOptionalGetter getRetained:";
+ _M << name << "_p value:&self->" << fixId((*q)->name(), baseType);
+ _M << " type:[" << typeToObjCTypeString(type) << " class]];";
+ }
+ }
+ else
+ {
+ if(isValueType(type))
+ {
+ _M << nl << "self->" << fixId((*q)->name(), baseType) << " = " << name << "_p;";
+ }
+ else
+ {
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "self->" << fixId((*q)->name(), baseType) << " = " << name << "_p;";
+ _M.zeroIndent();
+ _M << nl << "#else";
+ _M.restoreIndent();
+ _M << nl << "self->" << fixId((*q)->name(), baseType) << " = [" << name << "_p retain];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ }
+ }
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeProperties(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name(), baseType);
+
+ string typeString = typeToString(type);
+ bool isValue = isValueType(type);
+
+ _H << nl << "@property(nonatomic, ";
+ if(isValue)
+ {
+ _H << "assign";
+ }
+ else
+ {
+ _H << "ICE_STRONG_ATTR";
+ }
+ _H << ") " << typeString << " ";
+ if(mapsToPointerType(type))
+ {
+ _H << "*";
+ }
+ _H << name << ";";
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeSynthesize(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ string name = fixId((*q)->name(), baseType);
+ _M << nl << "@synthesize " << name << ";";
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeOptionalDataMemberSelectors(const DataMemberList& dataMembers, int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ if(!(*q)->optional())
+ {
+ continue;
+ }
+
+ TypePtr type = (*q)->type();
+ string typeString = inTypeToString(type, false);
+
+ string name = fixId((*q)->name(), baseType);
+
+ string capName = (*q)->name();
+ capName[0] = toupper(static_cast<unsigned char>(capName[0]));
+
+ _H << nl << "-(void)set" << capName << ":(" << typeString << ")" << name << "_p;";
+
+ _M << nl << "-(void)set" << capName << ":(" << typeString << ")" << name << "_p";
+ _M << sb;
+ _M << nl << "self->has_" << name << "__ = YES;";
+ bool isValue = isValueType(type);
+ if(isValue)
+ {
+ _M << nl << "self->" << name << " = " << name << "_p;";
+ }
+ else
+ {
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "self->" << name << " = " << name << "_p;";
+ _M.zeroIndent();
+ _M << nl << "#else";
+ _M.restoreIndent();
+ _M << nl << "[self->" << name << " release];";
+ _M << nl << "self->" << name << " = [" << name << "_p retain];";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ }
+ _M << eb;
+
+ _H << nl << "-(BOOL)has" << capName << ";";
+ _M << nl << "-(BOOL)has" << capName;
+ _M << sb;
+ _M << nl << "return self->has_" << name << "__;";
+ _M << eb;
+
+ _H << nl << "-(void)clear" << capName << ";";
+ _M << nl << "-(void)clear" << capName;
+ _M << sb;
+ _M << nl << "self->has_" << name << "__ = NO;";
+ if(!isValue)
+ {
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && __has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "self->" << name << " = nil;";
+ _M.zeroIndent();
+ _M << nl << "#else";
+ _M.restoreIndent();
+ _M << nl << "[self->" << name << " release];";
+ _M << nl << "self->" << name << " = nil;";
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ }
+ _M << eb;
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberHashCode(const DataMemberList& dataMembers, int baseType) const
+{
+ _M << sp << nl << "-(NSUInteger) hash";
+ _M << sb;
+ _M << nl << "NSUInteger h_ = 5381;";
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name(), baseType);
+
+ _M << nl << "h_ = ((h_ << 5) + h_) ^ ";
+ if(isValueType(type))
+ {
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(type);
+ if(builtin)
+ {
+ if(builtin->kind() == Builtin::KindFloat || builtin->kind() == Builtin::KindDouble)
+ {
+ _M << "(2654435761u * (uint)" << name << ");";
+ }
+ else
+ {
+ _M << "(2654435761u * " << name << ");";
+ }
+ }
+ else
+ {
+ _M << name << ";";
+ }
+ }
+ else
+ {
+ _M << "[self->" << name << " hash];";
+ }
+ }
+ _M << nl << "return h_;";
+ _M << eb;
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberEquals(const DataMemberList& dataMembers, int baseType) const
+{
+ if(!dataMembers.empty())
+ {
+ ContainerPtr container = (*dataMembers.begin())->container();
+ ContainedPtr contained = ContainedPtr::dynamicCast(container);
+ string containerName = fixName(contained);
+ _M << nl << containerName << " *obj_ = (" << containerName << " *)o_;";
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ string name = fixId((*q)->name(), baseType);
+
+ if(isValueType(type))
+ {
+ _M << nl << "if(" << name << " != obj_->" << name << ")";
+ _M << sb;
+ _M << nl << "return NO;";
+ _M << eb;
+ }
+ else
+ {
+ _M << nl << "if(!" << name << ")";
+ _M << sb;
+ _M << nl << "if(obj_->" << name << ")";
+ _M << sb;
+ _M << nl << "return NO;";
+ _M << eb;
+ _M << eb;
+ _M << nl << "else";
+ _M << sb;
+ _M << nl << "if(![self." << name << " ";
+ _M << (isString(type) ? "isEqualToString" : "isEqual");
+ _M << ":obj_->" << name << "])";
+ _M << sb;
+ _M << nl << "return NO;";
+ _M << eb;
+ _M << eb;
+ }
+ }
+ }
+ _M << nl << "return YES;";
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberDealloc(const DataMemberList& dataMembers, int baseType, bool slicedData) const
+{
+ bool once = false;
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ TypePtr type = (*q)->type();
+ if(!isValueType(type))
+ {
+ if(!once)
+ {
+ once = true;
+ _M << sp;
+ _M.zeroIndent();
+ _M << nl << "#if defined(__clang__) && !__has_feature(objc_arc)";
+ _M.restoreIndent();
+ _M << nl << "-(void) dealloc";
+ _M << sb;
+ }
+
+ bool isValue = isValueType(type);
+ if(!isValue)
+ {
+ _M << nl << "[self->" << fixId((*q)->name(), baseType) << " release];";
+ }
+ }
+ }
+ if(once)
+ {
+ if(slicedData)
+ {
+ _M << nl << "[(NSObject*)slicedData__ release];";
+ }
+ _M << nl << "[super dealloc];";
+ _M << eb;
+ _M.zeroIndent();
+ _M << nl << "#endif";
+ _M.restoreIndent();
+ _H << nl << "// This class also overrides dealloc.";
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberMarshal(const DataMemberList& dataMembers, const DataMemberList& optionalMembers,
+ int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ if(!(*q)->optional())
+ {
+ writeMarshalUnmarshalCode(_M, (*q)->type(), "self->" + fixId((*q)->name(), baseType), true, false);
+ }
+ }
+ for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ string name = fixId((*q)->name(), baseType);
+ string frmt = getOptionalFormat((*q)->type());
+ _M << nl << "if(self->has_" << name << "__ && [os_ writeOptional:" << (*q)->tag() << " format:" << frmt << "])";
+ _M << sb;
+ writeOptMemberMarshalUnmarshalCode(_M, (*q)->type(), "self->" + name, true);
+ _M << eb;
+ }
+}
+
+void
+Slice::Gen::TypesVisitor::writeMemberUnmarshal(const DataMemberList& dataMembers, const DataMemberList& optionalMembers,
+ int baseType) const
+{
+ for(DataMemberList::const_iterator q = dataMembers.begin(); q != dataMembers.end(); ++q)
+ {
+ if(!(*q)->optional())
+ {
+ writeMarshalUnmarshalCode(_M, (*q)->type(), "self->" + fixId((*q)->name(), baseType), false, false);
+ }
+ }
+ for(DataMemberList::const_iterator q = optionalMembers.begin(); q != optionalMembers.end(); ++q)
+ {
+ string name = fixId((*q)->name(), baseType);
+ string frmt = getOptionalFormat((*q)->type());
+ _M << nl << "if([is_ readOptional:" << (*q)->tag() << " format:" << frmt << "])";
+ _M << sb;
+ _M << nl << "self->has_" << name << "__ = YES;";
+ writeOptMemberMarshalUnmarshalCode(_M, (*q)->type(), "self->" + name, false);
+ _M << eb;
+ _M << nl << "else";
+ _M << sb;
+ _M << nl << "self->has_" << name << "__ = NO;";
+ _M << eb;
+ }
+}
+
+Slice::Gen::ProxyVisitor::ProxyVisitor(Output& H, Output& M)
+ : ObjCVisitor(H, M)
+{
+}
+
+bool
+Slice::Gen::ProxyVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ string name = fixName(p);
+ ClassList bases = p->bases();
+
+ _H << sp << nl << "@protocol " << name << "Prx <";
+ if(bases.empty())
+ {
+ _H << "ICEObjectPrx";
+ }
+ else
+ {
+ ClassList::const_iterator q = bases.begin();
+ while(q != bases.end())
+ {
+ _H << fixName(*q) + "Prx";
+ if(++q != bases.end())
+ {
+ _H << ", ";
+ }
+ }
+ }
+ _H << ">";
+
+ return true;
+}
+
+void
+Slice::Gen::ProxyVisitor::visitClassDefEnd(const ClassDefPtr&)
+{
+ _H << nl << "@end";
+}
+
+void
+Slice::Gen::ProxyVisitor::visitOperation(const OperationPtr& p)
+{
+ string name = getName(p);
+ TypePtr returnType = p->returnType();
+ string retString = outTypeToString(returnType, p->returnIsOptional());
+ string params = getParams(p);
+ string marshalParams = getMarshalParams(p);
+ string unmarshalParams = getUnmarshalParams(p);
+
+ //
+ // Write two versions of the operation--with and without a
+ // context parameter.
+ //
+ _H << nl << "-(" << retString << ") " << name << params << ";";
+
+ _H << nl << "-(" << retString << ") " << name << params;
+ if(!params.empty())
+ {
+ _H << " context";
+ }
+ _H << ":(ICEContext *)context;";
+
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams << ";";
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " context";
+ }
+ _H << ":(ICEContext *)context;";
+
+ _H << nl << "-(" << retString << ") end_" << p->name() << unmarshalParams;
+ if(!unmarshalParams.empty())
+ {
+ _H << " result";
+ }
+ _H << ":(id<ICEAsyncResult>)result;";
+
+ string responseCBSig = getResponseCBSig(p);
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " response";
+ }
+ _H << ":(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_;";
+
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " context";
+ }
+ _H << ":(ICEContext *)context";
+ _H << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_;";
+
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " response";
+ }
+ _H << ":(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_;";
+
+ _H << nl << "-(id<ICEAsyncResult>) begin_" << p->name() << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " context";
+ }
+ _H << ":(ICEContext *)context";
+ _H << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_;";
+}
+
+Slice::Gen::HelperVisitor::HelperVisitor(Output& H, Output& M) :
+ ObjCVisitor(H, M)
+{
+}
+
+bool
+Slice::Gen::HelperVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ //
+ // Proxy helper
+ //
+ {
+ string name = moduleName(findModule(p)) + p->name() + "PrxHelper";
+ _H << sp << nl << "@interface " << name << " : ICEProxyHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream";
+ _M << sb;
+ _M << nl << "return [stream newProxy:[" << fixName(p) << "Prx class]];";
+ _M << eb;
+ _M << nl << "@end";
+ }
+
+ //
+ // Class helper
+ //
+ {
+ string name = moduleName(findModule(p)) + p->name() + "Helper";
+ if(p->isInterface())
+ {
+ _H << sp << nl << "typedef ICEObjectHelper " << name << ";";
+ }
+ else
+ {
+ _H << sp << nl << "@interface " << name << " : ICEObjectHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(void) readRetained:(ICEObject*ICE_STRONG_QUALIFIER*)obj stream:(id<ICEInputStream>)stream";
+ _M << sb;
+ _M << nl << "[stream newObject:obj expectedType:[" << fixName(p) << " class]];";
+ _M << eb;
+ _M << nl << "@end";
+ }
+ }
+ return false;
+}
+
+void
+Slice::Gen::HelperVisitor::visitEnum(const EnumPtr& p)
+{
+ string name = moduleName(findModule(p)) + p->name() + "Helper";
+
+ _H << sp << nl << "@interface " << name << " : ICEEnumHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(ICEInt) getMinValue";
+ _M << sb;
+ _M << nl << "return " << p->minValue() << ";";
+ _M << eb;
+ _M << nl << "+(ICEInt) getMaxValue";
+ _M << sb;
+ _M << nl << "return " << p->maxValue() << ";";
+ _M << eb;
+ _M << nl << "@end";
+}
+
+void
+Slice::Gen::HelperVisitor::visitSequence(const SequencePtr& p)
+{
+ string name = moduleName(findModule(p)) + p->name() + "Helper";
+
+ BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type());
+ if(builtin)
+ {
+ _H << sp << nl << "typedef ICE" << getBuiltinName(builtin) << "SequenceHelper " << name << ";";
+ return;
+ }
+
+ EnumPtr en = EnumPtr::dynamicCast(p->type());
+ if(en)
+ {
+ _H << sp << nl << "@interface " << name << " : ICEEnumSequenceHelper";
+ _H << nl << "@end";
+
+ string typeS = typeToString(en);
+ int min = en->minValue();
+ int max = en->maxValue();
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream";
+ _M << sb;
+ _M << nl << "return [stream newEnumSeq:" << min << " max:" << max << "];";
+ _M << eb;
+ _M << nl << "+(void) write:(id)obj stream:(id<ICEOutputStream>)stream";
+ _M << sb;
+ _M << nl << "[stream writeEnumSeq:obj min:" << min << " max:" << max << "];";
+ _M << eb;
+ _M << nl << "@end";
+ return;
+ }
+
+ ClassDeclPtr cl = ClassDeclPtr::dynamicCast(p->type());
+ if(cl)
+ {
+ _H << sp << nl << "@interface " << name << " : ICEObjectSequenceHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream";
+ _M << sb;
+ _M << nl << "return [stream newObjectSeq:[" << fixName(cl) << " class]];";
+ _M << eb;
+ _M << nl << "@end";
+ return;
+ }
+
+ ProxyPtr proxy = ProxyPtr::dynamicCast(p->type());
+ ContainedPtr contained = ContainedPtr::dynamicCast(p->type());
+ _H << sp << nl << "@interface " << name << " : ICEArraySequenceHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(Class) getElementHelper";
+ _M << sb;
+ if(proxy)
+ {
+ string name = moduleName(findModule(proxy->_class())) + proxy->_class()->name();
+ _M << nl << "return [" << name << "PrxHelper class];";
+ }
+ else
+ {
+ assert(contained);
+ _M << nl << "return [" << moduleName(findModule(contained)) + contained->name() + "Helper class];";
+ }
+ _M << eb;
+ _M << nl << "+(Class) getOptionalHelper";
+ _M << sb;
+ if(p->type()->isVariableLength())
+ {
+ _M << nl << "return [ICEVarLengthOptionalHelper class];";
+ }
+ else if(p->type()->minWireSize() == 1)
+ {
+ _M << nl << "return [ICEFixedSize1SequenceOptionalHelper class];";
+ }
+ else
+ {
+ _M << nl << "return [ICEFixedSequenceOptionalHelper class];";
+ }
+ _M << eb;
+ _M << nl << "@end";
+}
+
+void
+Slice::Gen::HelperVisitor::visitDictionary(const DictionaryPtr& p)
+{
+ string name = moduleName(findModule(p)) + p->name() + "Helper";
+
+ TypePtr keyType = p->keyType();
+ string keyS;
+ BuiltinPtr keyBuiltin = BuiltinPtr::dynamicCast(keyType);
+ if(keyBuiltin)
+ {
+ keyS = "ICE" + getBuiltinName(BuiltinPtr::dynamicCast(keyType)) + "Helper";
+ }
+ else
+ {
+ ContainedPtr contained = ContainedPtr::dynamicCast(keyType);
+ keyS = moduleName(findModule(contained)) + contained->name() + "Helper";
+ }
+
+ string valueS;
+ TypePtr valueType = p->valueType();
+ BuiltinPtr valueBuiltin = BuiltinPtr::dynamicCast(valueType);
+ ClassDeclPtr valueClass = ClassDeclPtr::dynamicCast(valueType);
+ if((valueBuiltin && valueBuiltin->kind() == Builtin::KindObject) || valueClass)
+ {
+ _H << sp << nl << "@interface " << name << " : ICEObjectDictionaryHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(id) readRetained:(id<ICEInputStream>)stream";
+ _M << sb;
+ if(valueClass && !valueClass->isInterface())
+ {
+ valueS = fixName(valueClass);
+ _M << nl << "return [stream newObjectDict:[" << keyS << " class] expectedType:[" << valueS << " class]];";
+ }
+ else
+ {
+ _M << nl << "return [stream newObjectDict:[" << keyS << " class] expectedType:[ICEObject class]];";
+ }
+ _M << eb;
+ _M << nl << "+(void) write:(id)obj stream:(id<ICEOutputStream>)stream";
+ _M << sb;
+ _M << nl << "[stream writeObjectDict:obj helper:[" << keyS << " class]];";
+ _M << eb;
+ _M << nl << "@end";
+ return;
+ }
+
+ ProxyPtr valueProxy = ProxyPtr::dynamicCast(valueType);
+ if(valueBuiltin)
+ {
+ valueS = "ICE" + getBuiltinName(BuiltinPtr::dynamicCast(valueType)) + "Helper";
+ }
+ else if(valueProxy)
+ {
+ valueS = moduleName(findModule(valueProxy->_class())) + valueProxy->_class()->name() + "PrxHelper";
+ }
+ else
+ {
+ ContainedPtr contained = ContainedPtr::dynamicCast(valueType);
+ valueS = moduleName(findModule(contained)) + contained->name() + "Helper";
+ }
+ _H << sp << nl << "@interface " << name << " : ICEDictionaryHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name;
+ _M << nl << "+(ICEKeyValueTypeHelper) getKeyValueHelper";
+ _M << sb;
+ _M << nl << "ICEKeyValueTypeHelper c;";
+ _M << nl << "c.key = [" << keyS << " class];";
+ _M << nl << "c.value = [" << valueS << " class];";
+ _M << nl << "return c;";
+ _M << eb;
+ _M << nl << "+(Class) getOptionalHelper";
+ _M << sb;
+ if(keyType->isVariableLength() || valueType->isVariableLength())
+ {
+ _M << nl << "return [ICEVarLengthOptionalHelper class];";
+ }
+ else
+ {
+ _M << nl << "return [ICEFixedDictionaryOptionalHelper class];";
+ }
+ _M << eb;
+ _M << nl << "@end";
+}
+
+
+bool
+Slice::Gen::HelperVisitor::visitStructStart(const StructPtr& p)
+{
+ string name = fixName(p);
+
+ _H << sp << nl << "@interface " << name << "Helper : ICEStructHelper";
+ _H << nl << "@end";
+
+ _M << sp << nl << "@implementation " << name << "Helper";
+
+ _M << nl << "+(Class) getType";
+ _M << sb;
+ _M << nl << "return [" << name << " class];";
+ _M << eb;
+ _M << nl << "+(Class) getOptionalHelper";
+ _M << sb;
+ if(p->isVariableLength())
+ {
+ _M << nl << "return [ICEVarLengthOptionalHelper class];";
+ }
+ else
+ {
+ _M << nl << "return [ICEFixedLengthOptionalHelper class];";
+ }
+ _M << eb;
+
+ _M << nl << "+(ICEInt) minWireSize";
+ _M << sb;
+ _M << nl << "return " << p->minWireSize() << ";";
+ _M << eb;
+
+ _M << nl << "@end";
+ return false;
+}
+
+Slice::Gen::DelegateMVisitor::DelegateMVisitor(Output& H, Output& M)
+ : ObjCVisitor(H, M)
+{
+}
+
+bool
+Slice::Gen::DelegateMVisitor::visitModuleStart(const ModulePtr& p)
+{
+ return true;
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitModuleEnd(const ModulePtr&)
+{
+}
+
+bool
+Slice::Gen::DelegateMVisitor::visitClassDefStart(const ClassDefPtr& p)
+{
+ string name = fixName(p);
+ ClassList bases = p->bases();
+ OperationList ops = p->allOperations();
+ OperationList::const_iterator r;
+
+ _H << sp << nl << "@interface " << name << "Prx : ICEObjectPrx <" << name << "Prx>";
+ _H << nl << "+(NSString *) ice_staticId;";
+
+ _M << sp << nl << "@implementation " << name << "Prx";
+ for(r = ops.begin(); r != ops.end(); ++r)
+ {
+ string opName = getName(*r);
+ TypePtr returnType = (*r)->returnType();
+ string retString = outTypeToString(returnType, (*r)->returnIsOptional());
+ string params = getParams(*r);
+ string args = getArgs(*r);
+
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = (*r)->parameters();
+ for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli)
+ {
+ if((*pli)->isOutParam())
+ {
+ outParams.push_back(*pli);
+ }
+ else
+ {
+ inParams.push_back(*pli);
+ }
+ }
+
+ ContainerPtr container = (*r)->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ string className = fixName(cl);
+
+ //
+ // Write context-less operation that forwards to the version with a context.
+ //
+ _M << sp << nl << "-(" << retString << ") " << opName << params;
+ _M << sb;
+ _M << nl;
+ if(returnType)
+ {
+ _M << "return ";
+ }
+ _M << "[self " << opName << args << (args.empty() ? ":nil" : " context:nil") << "];";
+ _M << eb;
+
+ //
+ // Write version with context.
+ //
+ _M << sp << nl << "-(" << retString << ") " << opName << params;
+ if(!params.empty())
+ {
+ _M << " context";
+ }
+ _M << ":(ICEContext *)ctx_";
+ _M << sb;
+ if(returnType)
+ {
+ _M << nl << "__block " << retString << " ret_";
+ if(!isValueType(returnType))
+ {
+ _M << " = nil;";
+ }
+ else
+ {
+ _M << ";";
+ }
+ }
+
+ string marshal;
+ string marshalArgs = getMarshalArgs(*r);
+ string marshalParams = getMarshalParams(*r);
+ if(!inParams.empty())
+ {
+ _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) ";
+ _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs;
+ _M << (marshalArgs.empty() ? ":os_" : " os:os_") << "]; };";
+ marshal = "marshal_";
+ }
+ else
+ {
+ marshal = "nil";
+ }
+
+ string unmarshal;
+ string unmarshalArgs = getUnmarshalArgs(*r);
+ string unmarshalParams = getUnmarshalParams(*r);
+ if((*r)->returnsData())
+ {
+ _M << nl << "ICEUnmarshalCB unmarshal_ = ^(id<ICEInputStream> is_, BOOL ok_) ";
+ if(returnType)
+ {
+ _M << "{ ret_ = ";
+ }
+ else
+ {
+ _M << "{ ";
+ }
+ _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalArgs;
+ _M << (unmarshalArgs.empty() ? ":is_" : " is:is_") << " ok:ok_]; };";
+ unmarshal = "unmarshal_";
+ }
+ else
+ {
+ unmarshal = "nil";
+ }
+
+ _M << nl << "[self invoke__:@\"" << (*r)->name() << "\" mode:" << sliceModeToIceMode((*r)->sendMode())
+ << " format:" << opFormatTypeToString(*r) << " marshal:" << marshal
+ << " unmarshal:" << unmarshal << " context:ctx_];";
+ if(returnType)
+ {
+ _M << nl << "return ret_;";
+ }
+ _M << eb;
+
+ //
+ // Write begin_ context-less operation that forwards to the version with a context.
+ //
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << sb;
+ _M << nl << "return [self begin_" << (*r)->name() << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " context") << ":nil];";
+ _M << eb;
+
+ //
+ // Write begin_ version with context.
+ //
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext *)ctx_";
+ _M << sb;
+ if(!inParams.empty())
+ {
+ _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) ";
+ _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " os") << ":os_]; };";
+ }
+ _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:"
+ << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r)
+ << " marshal:" << marshal
+ << " returnsData:" << ((*r)->returnsData() ? "YES" : "NO")
+ << " context:ctx_];";
+ _M << eb;
+
+ //
+ // Write end_ operation
+ //
+ _M << sp << nl << "-(" << retString << ") end_" << (*r)->name() << unmarshalParams;
+ if(!unmarshalParams.empty())
+ {
+ _M << " result";
+ }
+ _M << ":(id<ICEAsyncResult>)result_";
+ _M << sb;
+ if(returnType)
+ {
+ _M << nl << "__block " << retString << " ret_";
+ if(!isValueType(returnType))
+ {
+ _M << " = nil;";
+ }
+ else
+ {
+ _M << ";";
+ }
+ }
+ if((*r)->returnsData())
+ {
+ _M << nl << "ICEUnmarshalCB unmarshal_ = ^(id<ICEInputStream> is_, BOOL ok_) ";
+ if(returnType)
+ {
+ _M << "{ ret_ = ";
+ }
+ else
+ {
+ _M << "{ ";
+ }
+ _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalArgs;
+ _M << (unmarshalArgs.empty() ? ":is_" : " is:is_") << " ok:ok_]; };";
+ }
+ _M << nl << "[self end_invoke__:@\"" << (*r)->name() << "\" unmarshal:" << unmarshal << " result:result_];";
+ if(returnType)
+ {
+ _M << nl << "return ret_;";
+ }
+ _M << eb;
+
+ //
+ // Write begin_ operations with callbacks
+ //
+ string responseCBSig = getResponseCBSig(*r);
+
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << (marshalParams.empty() ? "" : " response") << ":(" << responseCBSig << ")response_";
+ _M << " exception:(void(^)(ICEException*))exception_";
+ _M << sb;
+ _M << nl << "return [self begin_" << (*r)->name() << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " context") << ":nil response:response_ exception:exception_ sent:nil];";
+ _M << eb;
+
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << (marshalParams.empty() ? "" : " response") << ":(" << responseCBSig << ")response_";
+ _M << " exception:(void(^)(ICEException*))exception_ sent:(void(^)(BOOL))sent_";
+ _M << sb;
+ _M << nl << "return [self begin_" << (*r)->name() << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " context") << ":nil response:response_ exception:exception_ sent:sent_];";
+ _M << eb;
+
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext*)ctx_";
+ _M << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ ";
+ _M << sb;
+ _M << nl << "return [self begin_" << (*r)->name() << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " context") << ":ctx_ response:response_ exception:exception_ sent:nil];";
+ _M << eb;
+
+ _M << sp << nl << "-(id<ICEAsyncResult>) begin_" << (*r)->name() << marshalParams;
+ _M << (marshalParams.empty() ? "" : " context") << ":(ICEContext*)ctx_";
+ _M << " response:(" << responseCBSig << ")response_ exception:(void(^)(ICEException*))exception_ ";
+ _M << " sent:(void(^)(BOOL))sent_";
+ _M << sb;
+ if(!inParams.empty())
+ {
+ _M << nl << "ICEMarshalCB marshal_ = ^(id<ICEOutputStream> os_) ";
+ _M << "{ [" << className << "Prx " << (*r)->name() << "_marshal___" << marshalArgs;
+ _M << (marshalArgs.empty() ? "" : " os") << ":os_]; };";
+ }
+ if((*r)->returnsData())
+ {
+ _M << nl << "void(^completed_)(id<ICEInputStream>, BOOL) = ^(id<ICEInputStream> is_, BOOL ok_)";
+ _M << sb;
+ string responseCallArgs;
+ string unmarshalCallArgs;
+ if(!outParams.empty() || returnType)
+ {
+ if(returnType)
+ {
+ responseCallArgs += "ret_";
+ }
+
+ for(ParamDeclList::const_iterator op = outParams.begin(); op != outParams.end(); ++op)
+ {
+ string name = fixId((*op)->name());
+ _M << nl << outTypeToString((*op)->type(), (*op)->optional(), true) << " " << name;
+ if(!isValueType((*op)->type()))
+ {
+ _M << " = nil";
+ }
+ _M << ";";
+
+ if(!unmarshalCallArgs.empty())
+ {
+ unmarshalCallArgs += " " + name;
+ }
+ unmarshalCallArgs += ":&" + name;
+
+ if(!responseCallArgs.empty())
+ {
+ responseCallArgs += ", ";
+ }
+ responseCallArgs += name;
+ }
+ if(returnType)
+ {
+ _M << nl << outTypeToString(returnType, (*r)->returnIsOptional(), true) << " ret_";
+ if(!isValueType(returnType))
+ {
+ _M << " = nil";
+ }
+ _M << ";";
+ }
+ }
+ _M << nl << "@try";
+ _M << sb;
+ _M << nl;
+ if(returnType)
+ {
+ _M << "ret_ = ";
+ }
+ _M << "[" << className << "Prx " << (*r)->name() << "_unmarshal___" << unmarshalCallArgs;
+ _M << (unmarshalCallArgs.empty() ? ":is_" : " is:is_") << " ok:ok_];";
+ _M << eb;
+ _M << nl << "@catch(ICEException* ex)";
+ _M << sb;
+ _M << nl << "if(exception_)";
+ _M << sb;
+ _M << nl << "exception_(ex);";
+ _M << eb;
+ _M << nl << "return;";
+ _M << eb;
+ _M << nl << "if(response_)";
+ _M << sb;
+ _M << nl << "response_(" << responseCallArgs << ");";
+ _M << eb;
+ _M << eb << ";";
+ if(returnType || !outParams.empty())
+ {
+ _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:"
+ << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r)
+ << " marshal:" << marshal
+ << " completed:completed_ response:(response_ != nil) exception:exception_ sent:sent_ context:ctx_];";
+ }
+ else
+ {
+ _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:"
+ << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r)
+ << " marshal:" << marshal << " completed:completed_ response:YES exception:exception_ sent:sent_ context:ctx_];";
+ }
+ }
+ else
+ {
+ _M << nl << "return [self begin_invoke__:@\"" << (*r)->name() << "\" mode:"
+ << sliceModeToIceMode((*r)->sendMode()) << " format:" << opFormatTypeToString(*r)
+ << " marshal:" << marshal << " response:response_ exception:exception_ sent:sent_ context:ctx_];";
+ }
+ _M << eb;
+ }
+
+ _M << sp << nl << "+(NSString *) ice_staticId";
+ _M << sb;
+ _M << nl << "return @\"" << p->scoped() << "\";";
+ _M << eb;
+
+ return true;
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitClassDefEnd(const ClassDefPtr& p)
+{
+ _H << nl << "@end";
+ _M << nl << "@end";
+}
+
+void
+Slice::Gen::DelegateMVisitor::visitOperation(const OperationPtr& p)
+{
+ TypePtr returnType = p->returnType();
+ string retString = outTypeToString(returnType, p->returnIsOptional());
+ string params = getParams(p);
+ string args = getParams(p);
+ string marshalParams = getMarshalParams(p);
+ string unmarshalParams = getUnmarshalParams(p);
+
+ ParamDeclList inParams;
+ ParamDeclList outParams;
+ ParamDeclList paramList = p->parameters();
+ for(ParamDeclList::const_iterator pli = paramList.begin(); pli != paramList.end(); ++pli)
+ {
+ if((*pli)->isOutParam())
+ {
+ outParams.push_back(*pli);
+ }
+ else
+ {
+ inParams.push_back(*pli);
+ }
+ }
+
+ //
+ // Write class method to invoke each operation.
+ //
+ ContainerPtr container = p->container();
+ ClassDefPtr cl = ClassDefPtr::dynamicCast(container);
+ string className = fixName(cl);
+ if(!inParams.empty())
+ {
+ _H << nl << "+(void) " << p->name() << "_marshal___" << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _H << " os";
+ }
+ _H << ":(id<ICEOutputStream>)os_;";
+
+ _M << sp << nl << "+(void) " << p->name() << "_marshal___" << marshalParams;
+ if(!marshalParams.empty())
+ {
+ _M << " os";
+ }
+ _M << ":(id<ICEOutputStream>)os_";
+ _M << sb;
+ writeMarshalUnmarshalParams(inParams, 0, true);
+ if(p->sendsClasses(false))
+ {
+ _M << nl << "[os_ writePendingObjects];";
+ }
+ _M << eb;
+ }
+
+ if(p->returnsData())
+ {
+ _H << nl << "+(" << retString << ")" << p->name() << "_unmarshal___" << unmarshalParams;
+ if(!unmarshalParams.empty())
+ {
+ _H << " is";
+ }
+ _H << ":(id<ICEInputStream>)is_ ok:(BOOL)ok_;";
+
+ _M << nl << "+(" << retString << ")" << p->name() << "_unmarshal___" << unmarshalParams;
+ if(!unmarshalParams.empty())
+ {
+ _M << " is";
+ }
+ _M << ":(id<ICEInputStream>)is_ ok:(BOOL)ok_";
+ _M << sb;
+ if(returnType)
+ {
+ _M << nl << outTypeToString(returnType, p->returnIsOptional(), true) << " ret_";
+ if(!isValueType(returnType))
+ {
+ _M << " = nil;";
+ }
+ else
+ {
+ _M << ";";
+ }
+ }
+ if(p->returnsData())
+ {
+ for(ParamDeclList::const_iterator op = outParams.begin(); op != outParams.end(); ++op)
+ {
+ if(!isValueType((*op)->type()))
+ {
+ _M << nl << "*" << fixId((*op)->name()) << " = nil;";
+ }
+ }
+ }
+ _M << nl << "if(!ok_)";
+ _M << sb;
+ _M << nl << "@try";
+ _M << sb;
+ _M << nl << "[is_ startEncapsulation];";
+ _M << nl << "[is_ throwException];";
+ _M << eb;
+ //
+ // Arrange exceptions into most-derived to least-derived order. If we don't
+ // do this, a base exception handler can appear before a derived exception
+ // handler, causing compiler warnings and resulting in the base exception
+ // being marshaled instead of the derived exception.
+ //
+ ExceptionList throws = p->throws();
+ throws.sort();
+ throws.unique();
+ throws.sort(Slice::DerivedToBaseCompare());
+
+ for(ExceptionList::const_iterator e = throws.begin(); e != throws.end(); ++e)
+ {
+ _M << nl << "@catch(" << fixName(*e) << " *ex_)";
+ _M << sb;
+ _M << nl << "[is_ endEncapsulation];";
+ _M << nl << "@throw;";
+ _M << eb;
+ }
+ _M << nl << "@catch(ICEUserException *ex_)";
+ _M << sb;
+ _M << nl << "[is_ endEncapsulation];";
+ _M << nl << "@throw [ICEUnknownUserException unknownUserException:__FILE__ line:__LINE__ "
+ << "unknown:[ex_ ice_name]];";
+ _M << eb;
+ _M << eb;
+
+ if(returnType || !outParams.empty())
+ {
+ _M << nl << "else";
+ _M << sb;
+ _M << nl << "[is_ startEncapsulation];";
+ writeMarshalUnmarshalParams(outParams, p, false, true);
+ if(p->returnsClasses(false))
+ {
+ _M << nl << "[is_ readPendingObjects];";
+ }
+ _M << nl << "[is_ endEncapsulation];";
+ _M << eb;
+ }
+
+ if(returnType)
+ {
+ _M << nl << "return ret_;";
+ }
+ _M << eb;
+ }
+}
+