in thrift/compiler/generate/t_cocoa_generator.cc [1989:2173]
void t_cocoa_generator::generate_cocoa_service_server_implementation(
std::ofstream& out, const t_service* tservice) {
out << "@implementation " << cocoa_prefix_ << tservice->name() << "Processor"
<< std::endl;
indent_up();
// initializer
out << std::endl;
out << "- (id) initWith" << tservice->name() << ": (id <" << cocoa_prefix_
<< tservice->name() << ">) service" << std::endl;
scope_up(out);
out << indent() << "self = [super init];" << std::endl;
out << indent() << "if (!self) {" << std::endl;
out << indent() << " return nil;" << std::endl;
out << indent() << "}" << std::endl;
// out << indent() << "mService = [service retain_stub];" << std::endl;
// out << indent() << "mMethodMap = [[NSMutableDictionary dictionary]
// retain_stub];" << std::endl;
// generate method std::map for routing incoming calls
for (const auto* function : tservice->get_functions()) {
const std::string& funname = function->name();
scope_up(out);
out << indent() << "SEL s = @selector(process_" << funname
<< "_withSequenceID:inProtocol:outProtocol:);" << std::endl;
out << indent()
<< "NSMethodSignature * sig = [self methodSignatureForSelector: s];"
<< std::endl;
out << indent()
<< "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];"
<< std::endl;
out << indent() << "[invocation setSelector: s];" << std::endl;
out << indent() << "[invocation retainArguments];" << std::endl;
out << indent() << "[mMethodMap setValue: invocation forKey: @\"" << funname
<< "\"];" << std::endl;
scope_down(out);
}
out << indent() << "return self;" << std::endl;
scope_down(out);
// implementation of the 'service' method which returns the service associated
// with this processor
out << std::endl;
out << indent() << "- (id<" << cocoa_prefix_ << tservice->name()
<< ">) service" << std::endl;
out << indent() << "{" << std::endl;
out << indent() << " return [[mService retain_stub] autorelease_stub];"
<< std::endl;
out << indent() << "}" << std::endl;
// implementation of the TProcess method, which dispatches the incoming call
// using the method std::map
out << std::endl;
out << indent()
<< "- (BOOL) processOnInputProtocol: (id <TProtocol>) inProtocol"
<< std::endl;
out << indent()
<< " outputProtocol: (id <TProtocol>) outProtocol"
<< std::endl;
out << indent() << "{" << std::endl;
out << indent() << " NSString * messageName;" << std::endl;
out << indent() << " int messageType;" << std::endl;
out << indent() << " int seqID;" << std::endl;
out << indent() << " [inProtocol readMessageBeginReturningName: &messageName"
<< std::endl;
out << indent() << " type: &messageType"
<< std::endl;
out << indent() << " sequenceID: &seqID];"
<< std::endl;
out << indent()
<< " NSInvocation * invocation = [mMethodMap valueForKey: messageName];"
<< std::endl;
out << indent() << " if (invocation == nil) {" << std::endl;
out << indent()
<< " [TProtocolUtil skipType: TType_STRUCT onProtocol: inProtocol];"
<< std::endl;
out << indent() << " [inProtocol readMessageEnd];" << std::endl;
out << indent()
<< " TApplicationException * x = [TApplicationException exceptionWithType: TApplicationException_UNKNOWN_METHOD reason: [NSString stringWithFormat: @\"Invalid method name: '%@'\", messageName]];"
<< std::endl;
out << indent() << " [outProtocol writeMessageBeginWithName: messageName"
<< std::endl;
out << indent()
<< " type: TMessageType_EXCEPTION"
<< std::endl;
out << indent() << " sequenceID: seqID];"
<< std::endl;
out << indent() << " [x write: outProtocol];" << std::endl;
out << indent() << " [outProtocol writeMessageEnd];" << std::endl;
out << indent() << " [[outProtocol transport] flush];" << std::endl;
out << indent() << " return YES;" << std::endl;
out << indent() << " }" << std::endl;
out << indent() << " // NSInvocation does not conform to NSCopying protocol"
<< std::endl;
out << indent()
<< " NSInvocation * i = [NSInvocation invocationWithMethodSignature: [invocation methodSignature]];"
<< std::endl;
out << indent() << " [i setSelector: [invocation selector]];" << std::endl;
out << indent() << " [i setArgument: &seqID atIndex: 2];" << std::endl;
out << indent() << " [i setArgument: &inProtocol atIndex: 3];" << std::endl;
out << indent() << " [i setArgument: &outProtocol atIndex: 4];" << std::endl;
out << indent() << " [i setTarget: self];" << std::endl;
out << indent() << " [i invoke];" << std::endl;
out << indent() << " return YES;" << std::endl;
out << indent() << "}" << std::endl;
// generate a process_XXXX method for each service function, which reads args,
// calls the service, and writes results
for (const auto* function : tservice->get_functions()) {
out << std::endl;
const std::string& funname = function->name();
out << indent() << "- (void) process_" << funname
<< "_withSequenceID: (int32_t) seqID inProtocol: (id<TProtocol>) inProtocol outProtocol: (id<TProtocol>) outProtocol"
<< std::endl;
scope_up(out);
std::string argstype =
cocoa_prefix_ + function_args_helper_struct_type(function);
out << indent() << argstype << " * args = [[" << argstype
<< " alloc] init];" << std::endl;
out << indent() << "[args read: inProtocol];" << std::endl;
out << indent() << "[inProtocol readMessageEnd];" << std::endl;
// prepare the result if not oneway
if (function->qualifier() != t_function_qualifier::one_way) {
std::string resulttype =
cocoa_prefix_ + function_result_helper_struct_type(function);
out << indent() << resulttype << " * result = [[" << resulttype
<< " alloc] init];" << std::endl;
}
// make the call to the actual service object
out << indent();
if (!function->get_returntype()->is_void()) {
out << "[result setSuccess: ";
}
out << "[mService " << funname;
bool first = true;
for (const auto& param : function->get_paramlist()->fields()) {
const std::string& fieldName = param.name();
if (first) {
first = false;
out << ": [args " << fieldName << "]";
} else {
out << " " << fieldName << ": [args " << fieldName << "]";
}
}
out << "]";
if (!function->get_returntype()->is_void()) {
out << "]";
}
out << ";" << std::endl;
// write out the result if not oneway
if (function->qualifier() != t_function_qualifier::one_way) {
out << indent() << "[outProtocol writeMessageBeginWithName: @\""
<< funname << "\"" << std::endl;
out << indent()
<< " type: TMessageType_REPLY"
<< std::endl;
out << indent() << " sequenceID: seqID];"
<< std::endl;
out << indent() << "[result write: outProtocol];" << std::endl;
out << indent() << "[outProtocol writeMessageEnd];" << std::endl;
out << indent() << "[[outProtocol transport] flush];" << std::endl;
out << indent() << "[result release_stub];" << std::endl;
}
out << indent() << "[args release_stub];" << std::endl;
scope_down(out);
}
// dealloc
out << std::endl;
out << "- (void) dealloc" << std::endl;
scope_up(out);
out << indent() << "[mService release_stub];" << std::endl;
out << indent() << "[mMethodMap release_stub];" << std::endl;
out << indent() << "[super dealloc_stub];" << std::endl;
scope_down(out);
out << std::endl;
indent_down();
out << "@end" << std::endl << std::endl;
}