blob: 8003f1e7476b326f2fd8b2f4f552875a1cb74c2a [file] [log] [blame]
Marc Slemkob2039e72006-08-09 01:00:17 +00001import time
2import os
3import os.path
4from string import Template
5from parser import *
6from generator import *
7
8HEADER_COMMENT = """/**
9 * Autogenerated by Thrift
10 * ${date}
11 *
12 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
13 */
14 """
15
16CPP_TYPES_HEADER = Template(HEADER_COMMENT+"""
17#if !defined(${source}_types_h_)
18#define ${source}_types_h_ 1
19
Marc Slemkoc4eb9e82006-08-10 03:29:29 +000020#include <Thrift.h>
Marc Slemko17859852006-08-15 00:21:31 +000021${namespacePrefix}
Marc Slemkob2039e72006-08-09 01:00:17 +000022""")
23
24CPP_TYPES_FOOTER = Template("""
Marc Slemko17859852006-08-15 00:21:31 +000025${namespaceSuffix}
Marc Slemkob2039e72006-08-09 01:00:17 +000026#endif // !defined(${source}_types_h_)
27""")
28
29CPP_SERVICES_HEADER = Template(HEADER_COMMENT+"""
30#if !defined(${source}_h_)
31#define ${source}_h_ 1
32
Marc Slemkoc4eb9e82006-08-10 03:29:29 +000033#include <Thrift.h>
34#include <TProcessor.h>
35#include <protocol/TProtocol.h>
36#include <transport/TTransport.h>
Marc Slemkodb14e172006-08-09 23:36:18 +000037#include \"${source}_types.h\"
Marc Slemko17859852006-08-15 00:21:31 +000038
39${namespacePrefix}
Marc Slemkob2039e72006-08-09 01:00:17 +000040""")
41
42CPP_SERVICES_FOOTER = Template("""
Marc Slemko17859852006-08-15 00:21:31 +000043${namespaceSuffix}
Marc Slemkob2039e72006-08-09 01:00:17 +000044#endif // !defined(${source}_h_)""")
45
Marc Slemkodb14e172006-08-09 23:36:18 +000046CPP_IMPL_HEADER = Template(HEADER_COMMENT+"""
47#include \"${source}.h\"
Marc Slemko17859852006-08-15 00:21:31 +000048
49${namespacePrefix}
Marc Slemkodb14e172006-08-09 23:36:18 +000050""")
51
Marc Slemko17859852006-08-15 00:21:31 +000052CPP_IMPL_FOOTER = Template("""
53${namespaceSuffix}
54""")
Marc Slemkodb14e172006-08-09 23:36:18 +000055
Marc Slemkob2039e72006-08-09 01:00:17 +000056def cpp_debug(arg):
57 print(arg)
58
59class Indenter(object):
60 def __init__(self, level=0, step=4):
61 self.level = level
62 self.step = step
63 self.chunk = ""
64 for i in range(step):
65 self.chunk+= " "
66 self.prefix=""
67
68 def inc(self):
69 self.level+= self.step
70 self.prefix += self.chunk
71
72 def dec(self):
73 self.level-= self.step
74 if(self.level < 0):
75 raise Exception, "Illegal indent level"
76 self.prefix = self.prefix[:self.level]
77
78 def __call__(self):
79 return self.prefix
80
81class CFile(file):
82
83 def __init__(self, name, flags):
84 file.__init__(self, name, flags)
85 self.indent = Indenter()
86 self.newline = True
87
88 def rwrite(self, value):
89 file.write(self, value)
90
91 def write(self, value=""):
92 if self.newline:
93 self.rwrite(self.indent())
94 self.newline = False
95 self.rwrite(value)
96
97 def writeln(self, value=""):
98 self.write(value+"\n")
99 self.newline = True
100
101 def beginBlock(self):
102 self.writeln("{")
103 self.indent.inc();
104
105 def endBlock(self, suffix=""):
106 self.indent.dec();
107 self.writeln("}"+suffix)
108
109CPP_PRIMITIVE_MAP = {
110 "void" : "void",
111 "bool" : "bool",
112 "string": "std::string",
113 "utf7": "std::string",
114 "utf8": "std::wstring",
115 "utf16": "std::utf16",
116 "byte" : "uint8_t",
117 "i08": "int8_t",
118 "i16": "int16_t",
119 "i32": "int32_t",
120 "i64": "int64_t",
121 "u08": "uint8_t",
122 "u16": "uint16_t",
123 "u32": "uint32_t",
124 "u64": "uint64_t",
Marc Slemkod8b10512006-08-14 23:30:37 +0000125 "float": "float",
126 "double": "double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000127}
128
129CPP_CONTAINER_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000130 MapType : "std::map",
131 ListType: "std::list",
132 SetType : "std::set",
Marc Slemkob2039e72006-08-09 01:00:17 +0000133}
134
Marc Slemko17859852006-08-15 00:21:31 +0000135def toCNamespacePrefix(namespace):
136 if not namespace:
137 return ""
138 else:
139 return string.join(["namespace "+token + " {" for token in string.split(namespace, ".")], " ")
140
141def toCNamespaceSuffix(namespace):
142 if not namespace:
143 return ""
144 else:
145 return string.join(["}" for token in string.split(namespace, ".")], "")
146
147def toCTypeDeclaration(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000148 """ Converts the thrift IDL type to the corresponding C/C++ type. Note that if ttype is FieldType, this function c
149converts to type declaration followed by field name, i.e. \"string string_thing\""""
Marc Slemkob2039e72006-08-09 01:00:17 +0000150
151 if isinstance(ttype, PrimitiveType):
152 return CPP_PRIMITIVE_MAP[ttype.name]
153
154 elif isinstance(ttype, CollectionType):
155
156 result = CPP_CONTAINER_MAP[type(ttype)]+"<"
157
Marc Slemko5b126d62006-08-11 23:03:42 +0000158 if isinstance(ttype, MapType):
Marc Slemko17859852006-08-15 00:21:31 +0000159 result+= toCTypeDeclaration(ttype.keyType)+", "+ toCTypeDeclaration(ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000160
Marc Slemko5b126d62006-08-11 23:03:42 +0000161 elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
Marc Slemko17859852006-08-15 00:21:31 +0000162 result+= toCTypeDeclaration(ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000163
164 else:
165 raise Exception, "Unknown Collection Type "+str(ttype)
166
167 result+= "> "
168
169 return result
170
Marc Slemko5b126d62006-08-11 23:03:42 +0000171 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000172 return "struct "+ttype.name
173
Marc Slemko5b126d62006-08-11 23:03:42 +0000174 elif isinstance(ttype, TypedefType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000175 return ttype.name;
176
Marc Slemko5b126d62006-08-11 23:03:42 +0000177 elif isinstance(ttype, EnumType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000178 return ttype.name;
179
180 elif isinstance(ttype, Function):
Marc Slemko17859852006-08-15 00:21:31 +0000181 result = toCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([toCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
Marc Slemkod8b10512006-08-14 23:30:37 +0000182 if len(ttype.exceptions()):
Marc Slemko17859852006-08-15 00:21:31 +0000183 result+= " throw("+string.join([toCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
Marc Slemkod8b10512006-08-14 23:30:37 +0000184 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000185
186 elif isinstance(ttype, Field):
Marc Slemko17859852006-08-15 00:21:31 +0000187 return toCTypeDeclaration(ttype.type)+ " "+ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000188
189 else:
190 raise Exception, "Unknown type "+str(ttype)
191
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000192def toTypeDefDefinition(typedef):
Marc Slemkod8b10512006-08-14 23:30:37 +0000193 """ Converts a thrift typedef to a C/C++ typedef """
Marc Slemkob2039e72006-08-09 01:00:17 +0000194
Marc Slemko17859852006-08-15 00:21:31 +0000195 return "typedef "+toCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
Marc Slemkob2039e72006-08-09 01:00:17 +0000196
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000197def toEnumDefinition(enum):
Marc Slemkod8b10512006-08-14 23:30:37 +0000198 """ Converts a thrift enum to a C/C++ enum """
Marc Slemkob2039e72006-08-09 01:00:17 +0000199
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000200 result = "enum "+enum.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000201
202 first = True
203
204 for ed in enum.enumDefs:
205 if first:
206 first = False
207 else:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000208 result+= ",\n"
209 result+= " "+ed.name+" = "+str(ed.id)
Marc Slemkob2039e72006-08-09 01:00:17 +0000210
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000211 result+= "\n};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000212
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000213 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000214
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000215def toStructDefinition(struct):
Marc Slemkod8b10512006-08-14 23:30:37 +0000216 """Converts a thrift struct to a C/C++ struct"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000217
218 result = "struct "+struct.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000219
220 for field in struct.fieldList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000221 if toCanonicalType(field.type) != VOID_TYPE:
Marc Slemko17859852006-08-15 00:21:31 +0000222 result += " "+toCTypeDeclaration(field)+";\n"
Marc Slemko5b126d62006-08-11 23:03:42 +0000223
224 result+= " struct {\n"
225
226 for field in struct.fieldList:
227 result+= " bool "+field.name+";\n"
228 result+= " } __isset;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000229
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000230 result+= "};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000231
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000232 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000233
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000234CPP_DEFINITION_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000235 TypedefType : toTypeDefDefinition,
236 EnumType : toEnumDefinition,
237 StructType : toStructDefinition,
Marc Slemkod8b10512006-08-14 23:30:37 +0000238 ExceptionType : toStructDefinition,
Marc Slemkob2039e72006-08-09 01:00:17 +0000239 Service : None
240 }
241
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000242def toDefinitions(definitions):
Marc Slemkod8b10512006-08-14 23:30:37 +0000243 """Converts an arbitrafy thrift grammatical unit definition to the corresponding C/C++ definition"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000244
245 result = ""
246
Marc Slemkob2039e72006-08-09 01:00:17 +0000247 for definition in definitions:
248
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000249 writer = CPP_DEFINITION_MAP[type(definition)]
Marc Slemkob2039e72006-08-09 01:00:17 +0000250
251 if writer:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000252 result+= writer(definition)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000253
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000254 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000255
256CPP_THRIFT_NS = "facebook::thrift"
257
258CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
259""")
260
261CPP_INTERFACE_DECLARATION = Template("""
262class ${service}If {
263 public:
Marc Slemkoe6889de2006-08-12 00:32:53 +0000264 virtual ~${service}If() {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000265${functionDeclarations}};
266""")
267
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000268def toServiceInterfaceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000269 """Converts a thrift service definition into a C++ abstract base class"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000270
Marc Slemko17859852006-08-15 00:21:31 +0000271 functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
Marc Slemkob2039e72006-08-09 01:00:17 +0000272
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000273 return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000274
Marc Slemko5b126d62006-08-11 23:03:42 +0000275CPP_EXCEPTION = CPP_THRIFT_NS+"::Exception"
276
Marc Slemkob2039e72006-08-09 01:00:17 +0000277CPP_SP = Template("boost::shared_ptr<${klass}> ")
278
279CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
280CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
281
282CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000283CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
284CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
Marc Slemkob2039e72006-08-09 01:00:17 +0000285
286
287CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
288CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
289CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
290
Marc Slemkob2039e72006-08-09 01:00:17 +0000291CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
292CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000293CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
294CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
295CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000296
Marc Slemkodb14e172006-08-09 23:36:18 +0000297CPP_TTYPE_MAP = {
298 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
299 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
300 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
301 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
302 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
303 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
304 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
305 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
306 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
307 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
308 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
309 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
310 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
311 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
312 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
313 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
314 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000315 DOUBLE_TYPE : CPP_PROTOCOL_NS+"::T_DOUBLE",
Marc Slemko5b126d62006-08-11 23:03:42 +0000316 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000317 ExceptionType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000318 ListType : CPP_PROTOCOL_NS+"::T_LIST",
319 MapType : CPP_PROTOCOL_NS+"::T_MAP",
320 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000321}
322
Marc Slemko91f67482006-08-11 23:58:57 +0000323
324CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
325""")
326
327CPP_SERVER_FUNCTION_DEFINITION = Template("""
328void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
329
330 uint32_t xfer = 0;
331
332 ${argsStructDeclaration};
333
334 ${argsStructReader};
335
336 _iprot->readMessageEnd(itrans);
337
Marc Slemko91f67482006-08-11 23:58:57 +0000338 ${resultStructDeclaration};
339
Marc Slemkod8b10512006-08-14 23:30:37 +0000340 ${functionCall};
Marc Slemko91f67482006-08-11 23:58:57 +0000341
342 _oprot->writeMessageBegin(otrans, \"${function}\", """+CPP_PROTOCOL_REPLY+""", seqid);
343
344 ${resultStructWriter};
345
346 _oprot->writeMessageEnd(otrans);
347
348 otrans->flush();
349}
350""")
351
352CPP_SERVER_PROCESS_DEFINITION = Template("""
353bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
354
Marc Slemko91f67482006-08-11 23:58:57 +0000355 std::string name;
356
357 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
358
359 uint32_t seqid;
360
361 _iprot->readMessageBegin(itrans, name, messageType, seqid);
362
363 if(messageType == """+CPP_PROTOCOL_CALL+""") {
364${callProcessSwitch}
365 } else {
366 throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
367 }
Marc Slemkoe6889de2006-08-12 00:32:53 +0000368
369 return true;
Marc Slemko91f67482006-08-11 23:58:57 +0000370}
371""")
372
Marc Slemkodb14e172006-08-09 23:36:18 +0000373def toWireType(ttype):
Marc Slemko17859852006-08-15 00:21:31 +0000374 """Converts a thrift type to the corresponding wire type. This differs from toCTypeDeclaration in that it reduces typedefs
Marc Slemkod8b10512006-08-14 23:30:37 +0000375to their canonical form and converts enums to signedf 32 bit integers"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000376
377 if isinstance(ttype, PrimitiveType):
378 return CPP_TTYPE_MAP[ttype]
379
Marc Slemko5b126d62006-08-11 23:03:42 +0000380 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000381 return CPP_TTYPE_MAP[I32_TYPE]
382
Marc Slemko5b126d62006-08-11 23:03:42 +0000383 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000384 return toWireType(toCanonicalType(ttype))
385
Marc Slemko5b126d62006-08-11 23:03:42 +0000386 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000387 return CPP_TTYPE_MAP[type(ttype)]
388
389 else:
390 raise Exception, "No wire type for thrift type: "+str(ttype)
391
Marc Slemkob2039e72006-08-09 01:00:17 +0000392CPP_SERVER_DECLARATION = Template("""
393class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
394 public:
395 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
396 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
397 virtual ~${service}ServerIf() {}
398 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
399 protected:
400 """+CPP_PROTOCOLP+""" _iprot;
401 """+CPP_PROTOCOLP+""" _oprot;
402 private:
403${functionDeclarations}};
404""")
405
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000406def toServerDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000407 """Converts a thrift service definition to the Server skeleton class declaration."""
Marc Slemkob2039e72006-08-09 01:00:17 +0000408
409 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
410
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000411 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000412
413CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
414""")
415
Marc Slemko5b126d62006-08-11 23:03:42 +0000416
417CPP_CLIENT_FUNCTION_DEFINITION = Template("""
Marc Slemkod8b10512006-08-14 23:30:37 +0000418${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) ${exceptionDeclaration} {
Marc Slemko5b126d62006-08-11 23:03:42 +0000419
420 uint32_t xfer = 0;
Marc Slemko91f67482006-08-11 23:58:57 +0000421 std::string name;
Marc Slemko5b126d62006-08-11 23:03:42 +0000422 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
423 uint32_t cseqid = 0;
424 uint32_t rseqid = 0;
425
Marc Slemko91f67482006-08-11 23:58:57 +0000426 _oprot->writeMessageBegin(_otrans, \"${function}\", """+CPP_PROTOCOL_CALL+""", cseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000427
428 ${argsStructDeclaration};
429
430${argsToStruct};
431
432 ${argsStructWriter};
433
434 _otrans->flush();
435
Marc Slemko91f67482006-08-11 23:58:57 +0000436 _iprot->readMessageBegin(_itrans, name, messageType, rseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000437
438 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
439 rseqid != cseqid) {
440 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
441 }
442
443 ${resultStructDeclaration};
444
445 ${resultStructReader};
446
447 _iprot->readMessageEnd(_itrans);
448
449 if(__result.__isset.success) {
Marc Slemkod8b10512006-08-14 23:30:37 +0000450 ${success}
451 } ${error} else {
452 throw """+CPP_EXCEPTION+"""(\"${function} failed: unknown result");
Marc Slemko5b126d62006-08-11 23:03:42 +0000453 }
454}
455""")
456
Marc Slemkob2039e72006-08-09 01:00:17 +0000457CPP_CLIENT_DECLARATION = Template("""
458class ${service}Client : public ${service}If {
459
460 public:
461
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000462 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000463
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000464 ${service}Client("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans, """+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _itrans(itrans), _otrans(otrans), _iprot(iprot), _oprot(oprot) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000465
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000466${functionDeclarations}
467 private:
468 """+CPP_TRANSPORTP+""" _itrans;
469 """+CPP_TRANSPORTP+""" _otrans;
470 """+CPP_PROTOCOLP+""" _iprot;
471 """+CPP_PROTOCOLP+""" _oprot;
472};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000473
Marc Slemko5b126d62006-08-11 23:03:42 +0000474def toServerFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000475 """Converts a thrift service method declaration into a server method-call processoror function"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000476 result = ""
477
Marc Slemko17859852006-08-15 00:21:31 +0000478 argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
Marc Slemko5b126d62006-08-11 23:03:42 +0000479
480 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
481
Marc Slemko17859852006-08-15 00:21:31 +0000482 resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
Marc Slemko5b126d62006-08-11 23:03:42 +0000483
484 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
485
Marc Slemkod8b10512006-08-14 23:30:37 +0000486
Marc Slemko5b126d62006-08-11 23:03:42 +0000487
Marc Slemkod8b10512006-08-14 23:30:37 +0000488 if function.returnType() != VOID_TYPE:
489 functionCallPrefix= "__result.success = "
490 functionCallSuffix = "__result.__isset.success = true;"
491 else:
492 functionCallPrefix = ""
493 functionCallSuffix = ""
494
495 functionCall= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+");"
496
497 exceptions = function.exceptions()
498
499 if len(exceptions) > 0:
500 functionCallPrefix= "try {"+functionCallPrefix
501
Marc Slemko17859852006-08-15 00:21:31 +0000502 functionCallSuffix = functionCallSuffix+"} "+string.join(["catch("+toCTypeDeclaration(exceptions[ix].type)+"& e"+str(ix)+") {__result."+exceptions[ix].name+" = e"+str(ix)+"; __result.__isset."+exceptions[ix].name+" = true;}" for ix in range(len(exceptions))], "")
Marc Slemkod8b10512006-08-14 23:30:37 +0000503
504 functionCall = functionCallPrefix+functionCall+functionCallSuffix
Marc Slemko5b126d62006-08-11 23:03:42 +0000505
506 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
507 argsStructDeclaration=argsStructDeclaration,
508 argsStructReader=argsStructReader,
509 functionCall=functionCall,
Marc Slemko5b126d62006-08-11 23:03:42 +0000510 resultStructDeclaration=resultStructDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000511 resultStructWriter=resultStructWriter)
Marc Slemko5b126d62006-08-11 23:03:42 +0000512 return result
513
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000514def toServerServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000515 """Converts a thrift service definiton to a server skeleton implementation"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000516
517 result = ""
518
519 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000520
521 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko66d67d82006-08-11 23:33:08 +0000522
Marc Slemko91f67482006-08-11 23:58:57 +0000523 callProcessSwitch = " if"+string.join(["(name.compare(\""+function.name+"\") == 0) { process_"+function.name+"(seqid, itrans, otrans);}" for function in service.functionList], "\n else if")+"\n else {throw "+CPP_EXCEPTION+"(\"Unknown function name \\\"\"+name+\"\\\"\");}"
Marc Slemko66d67d82006-08-11 23:33:08 +0000524
Marc Slemko91f67482006-08-11 23:58:57 +0000525 result+= CPP_SERVER_PROCESS_DEFINITION.substitute(service=service.name, callProcessSwitch=callProcessSwitch)
Marc Slemko66d67d82006-08-11 23:33:08 +0000526
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000527 return result
528
529def toServerDefinition(program, debugp=None):
530
531 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
532
533def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000534
Marc Slemko17859852006-08-15 00:21:31 +0000535 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
Marc Slemkob2039e72006-08-09 01:00:17 +0000536
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000537 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000538
Marc Slemko5b126d62006-08-11 23:03:42 +0000539def toClientFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000540 """Converts a thrift service method declaration to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000541
Marc Slemko17859852006-08-15 00:21:31 +0000542 returnDeclaration = toCTypeDeclaration(function.returnType())
Marc Slemko5b126d62006-08-11 23:03:42 +0000543
Marc Slemko17859852006-08-15 00:21:31 +0000544 argsDeclaration = string.join([toCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
Marc Slemko5b126d62006-08-11 23:03:42 +0000545
Marc Slemko17859852006-08-15 00:21:31 +0000546 exceptionDeclaration = string.join([toCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
Marc Slemkod8b10512006-08-14 23:30:37 +0000547
548 if len(exceptionDeclaration)> 0:
549 exceptionDeclaration = "throw("+exceptionDeclaration+")"
550
Marc Slemko17859852006-08-15 00:21:31 +0000551 argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
Marc Slemko5b126d62006-08-11 23:03:42 +0000552
553 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
554
555 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
556
Marc Slemko17859852006-08-15 00:21:31 +0000557 resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
Marc Slemko5b126d62006-08-11 23:03:42 +0000558
559 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
560
561 if(toCanonicalType(function.returnType()) != VOID_TYPE):
562
563 success = "return __result.success;"
564 else:
565 success = ""
Marc Slemkod8b10512006-08-14 23:30:37 +0000566
567 exceptions = function.exceptions()
568
569 if len(exceptions) > 0:
570 error = "else if "+string.join(["(__result.__isset."+exception.name+") { throw __result."+exception.name+";}" for exception in exceptions], "else if")
571 else:
572 error = ""
Marc Slemko5b126d62006-08-11 23:03:42 +0000573
574 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
575 function=function.name,
576 returnDeclaration=returnDeclaration,
577 argsDeclaration=argsDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000578 exceptionDeclaration=exceptionDeclaration,
Marc Slemko5b126d62006-08-11 23:03:42 +0000579 argsStructDeclaration=argsStructDeclaration,
580 argsStructWriter=argsStructWriter,
581 argsToStruct=argsToStruct,
582 resultStructDeclaration=resultStructDeclaration,
583 resultStructReader=resultStructReader,
Marc Slemkod8b10512006-08-14 23:30:37 +0000584 success=success,
585 error=error)
Marc Slemko5b126d62006-08-11 23:03:42 +0000586
587def toClientServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000588 """Converts a thrift service definition to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000589
590 result = ""
591
592 for function in service.functionList:
593
594 result+= toClientFunctionDefinition(service.name, function)
595
596 return result
597
598def toClientDefinition(program, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000599 """Converts all services in a thrift program to client stub implementations"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000600
601 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
602
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000603def toServiceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000604 """Converts all services in a thrift program to service interface or abstract base class declarations"""
605
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000606 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000607
608def toGenDir(filename, suffix="cpp-gen", debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000609 """creates a generated-code subdirectory for C++ code based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000610
611 result = os.path.join(os.path.split(filename)[0], suffix)
612
613 if not os.path.exists(result):
614 os.mkdir(result)
615
616 return result
617
618def toBasename(filename, debugp=None):
619 """ Take the filename minus the path and\".thrift\" extension if present """
620
621 basename = os.path.split(filename)[1]
622
623 tokens = os.path.splitext(basename)
624
625 if tokens[1].lower() == ".thrift":
626 basename = tokens[0]
627
628 if debugp:
629 debugp("toBasename("+str(filename)+") => "+str(basename))
630
631 return basename
632
633def toDefinitionHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000634 """Creates a file name for the public thrift data types based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000635
636 if not genDir:
637 genDir = toGenDir(filename)
638
639 basename = toBasename(filename)
640
641 result = os.path.join(genDir, basename+"_types.h")
642
643 if debugp:
644 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
645
646 return result
647
648def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000649 """Writes public thrift data types defined in program into a public data types header file. Uses the name of the original
650thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000651
652 definitionHeader = toDefinitionHeaderName(filename, genDir)
653
654 if debugp:
655 debugp("definitionHeader: "+str(definitionHeader))
656
657 cfile = CFile(definitionHeader, "w")
658
659 basename = toBasename(filename)
660
Marc Slemko17859852006-08-15 00:21:31 +0000661 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000662
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000663 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000664
Marc Slemko17859852006-08-15 00:21:31 +0000665 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000666
667 cfile.close()
668
669def toServicesHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000670 """Creates a file name for the public thrift services based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000671
672 if not genDir:
673 genDir = toGenDir(filename)
674
675 basename = toBasename(filename)
676
677 result = os.path.join(genDir, basename+".h")
678
679 if debugp:
680 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
681
682 return result
683
Marc Slemkob2039e72006-08-09 01:00:17 +0000684def writeServicesHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000685 """Writes public thrift service abstract base class, client class, and server class for all services defined in program into a public services header file. Uses the name of the original thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000686
687 servicesHeader = toServicesHeaderName(filename, genDir)
688
689 if debugp:
690 debugp("servicesHeader: "+str(servicesHeader))
691
692 cfile = CFile(servicesHeader, "w")
693
694 basename = toBasename(filename)
695
Marc Slemko17859852006-08-15 00:21:31 +0000696 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000697
698 services = []
699
700 # Build orderered list of service definitions by scanning definitions list for services
701
702 for definition in program.definitions:
703 if isinstance(definition, Service) and definition.name in program.serviceMap:
704 services.append(definition)
705
706 for service in services:
707
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000708 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000709
Marc Slemko17859852006-08-15 00:21:31 +0000710 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000711
712 cfile.close()
713
714
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000715CPP_STRUCT_READ = Template("""
716uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
717
Marc Slemkob2039e72006-08-09 01:00:17 +0000718 std::string name;
719 uint32_t id;
720 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000721 uint32_t xfer = 0;
722
Marc Slemkob2039e72006-08-09 01:00:17 +0000723 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000724 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000725 if(type == """+CPP_PROTOCOL_TSTOP+""") {
726 break;
727 }
728 switch(id) {
729${readFieldListSwitch}
730 }
731 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000732
733 xfer+= _iprot->readStructEnd(_itrans);
734
735 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000736}
737""")
738
739CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000740 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000741 "bool" : "Bool",
742 "string": "String",
743 "utf7": "String",
744 "utf8": "String",
745 "utf16": "String",
746 "i08": "Byte",
747 "i16": "I16",
748 "i32": "I32",
749 "i64": "I64",
750 "u08": "Byte",
751 "u16": "U16",
752 "u32": "U32",
753 "u64": "U64",
Marc Slemkod8b10512006-08-14 23:30:37 +0000754 "float": "Float",
755 "double": "Double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000756}
757
758CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000759 MapType : "map",
760 ListType : "list",
761 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000762}
763
764def typeToIOMethodSuffix(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000765 """Converts type to a name suitable as a suffix with TProtocol primitive read and write methods or with a generated read or write
766method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000767
768 if isinstance(ttype, PrimitiveType):
769 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
770
771 elif isinstance(ttype, CollectionType):
772
773 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
774
Marc Slemko5b126d62006-08-11 23:03:42 +0000775 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000776 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
777
778 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
779
780 return result
781
Marc Slemko5b126d62006-08-11 23:03:42 +0000782 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000783 return "struct_"+ttype.name
784
Marc Slemko5b126d62006-08-11 23:03:42 +0000785 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000786 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000787
Marc Slemko5b126d62006-08-11 23:03:42 +0000788 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000789 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000790
791 else:
792 raise Exception, "Unknown type "+str(ttype)
793
Marc Slemko5b126d62006-08-11 23:03:42 +0000794def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000795 """Converts type to a name suitable as a suffix with TProtocol primitive read methods or with a generated read
796method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000797
798 suffix = typeToIOMethodSuffix(ttype)
799
800 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000801 if ttype != VOID_TYPE:
802 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
803 else:
804 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000805
806 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000807 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000808
Marc Slemko5b126d62006-08-11 23:03:42 +0000809 elif isinstance(ttype, StructType):
810 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000811
Marc Slemko5b126d62006-08-11 23:03:42 +0000812 elif isinstance(ttype, TypedefType):
Marc Slemko17859852006-08-15 00:21:31 +0000813 return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000814
Marc Slemko5b126d62006-08-11 23:03:42 +0000815 elif isinstance(ttype, EnumType):
Marc Slemko17859852006-08-15 00:21:31 +0000816 return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000817
818 else:
819 raise Exception, "Unknown type "+str(ttype)
820
Marc Slemko5b126d62006-08-11 23:03:42 +0000821def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000822 """Converts type to a name suitable as a suffix with TProtocol primitive write methods or with a generated write
823method for a complex type"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000824
825 suffix = typeToIOMethodSuffix(ttype)
826
827 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000828 if ttype != VOID_TYPE:
829 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
830 else:
831 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000832
833 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000834 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000835
Marc Slemko5b126d62006-08-11 23:03:42 +0000836 elif isinstance(ttype, StructType):
837 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000838
Marc Slemko5b126d62006-08-11 23:03:42 +0000839 elif isinstance(ttype, TypedefType):
Marc Slemko17859852006-08-15 00:21:31 +0000840 return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000841
Marc Slemko5b126d62006-08-11 23:03:42 +0000842 elif isinstance(ttype, EnumType):
Marc Slemko17859852006-08-15 00:21:31 +0000843 return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000844
845 else:
846 raise Exception, "Unknown type "+str(ttype)
847
848CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000849uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000850
851 uint32_t count;
852 ${keyType} key;
853 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000854 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000855
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000856 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000857
Marc Slemkoe6889de2006-08-12 00:32:53 +0000858 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000859 ${keyReaderCall};
860 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000861 value.insert(std::make_pair(key, elem));
862 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000863
864 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000865}
866""")
867
868CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000869uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000870
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000871 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000872
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000873 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000874
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000875 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000876 ${keyWriterCall};
877 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000878 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000879 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000880}
881""")
882
Marc Slemkob2039e72006-08-09 01:00:17 +0000883CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000884uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000885
886 uint32_t count;
887 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000888 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000889
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000890 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000891
Marc Slemkoe6889de2006-08-12 00:32:53 +0000892 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000893 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000894 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000895 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000896 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000897}
898""")
899
Marc Slemkodb14e172006-08-09 23:36:18 +0000900CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000901uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000902
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000903 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000904
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000905 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000906
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000907 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000908 ${valueWriterCall};
909 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000910 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000911}
912""")
913
Marc Slemkod8b10512006-08-14 23:30:37 +0000914def toCollectionReaderDefinition(collection):
915 """Converts collection type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000916
Marc Slemkod8b10512006-08-14 23:30:37 +0000917 suffix = typeToIOMethodSuffix(collection)
Marc Slemkob2039e72006-08-09 01:00:17 +0000918
Marc Slemkod8b10512006-08-14 23:30:37 +0000919 if isinstance(collection, MapType):
920 keyReaderCall = toReaderCall("key", collection.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000921
Marc Slemkod8b10512006-08-14 23:30:37 +0000922 valueReaderCall= toReaderCall("elem", collection.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000923
Marc Slemkod8b10512006-08-14 23:30:37 +0000924 if isinstance(collection, MapType):
Marc Slemko17859852006-08-15 00:21:31 +0000925 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
926 keyType=toCTypeDeclaration(collection.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000927 keyReaderCall=keyReaderCall,
Marc Slemko17859852006-08-15 00:21:31 +0000928 valueType=toCTypeDeclaration(collection.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000929 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000930
931 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000932 if isinstance(collection, ListType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000933 insert="push_back"
934 else:
935 insert="insert"
936
Marc Slemko17859852006-08-15 00:21:31 +0000937 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
Marc Slemkodb14e172006-08-09 23:36:18 +0000938 valueReaderCall=valueReaderCall,
Marc Slemko17859852006-08-15 00:21:31 +0000939 valueType=toCTypeDeclaration(collection.valueType),
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000940 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000941
942
Marc Slemkod8b10512006-08-14 23:30:37 +0000943def toCollectionWriterDefinition(collection):
944 """Converts collection type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000945
Marc Slemkod8b10512006-08-14 23:30:37 +0000946 suffix = typeToIOMethodSuffix(collection)
Marc Slemkodb14e172006-08-09 23:36:18 +0000947
Marc Slemkod8b10512006-08-14 23:30:37 +0000948 if isinstance(collection, MapType):
949 keyWriterCall = toWriterCall("ix->first", collection.keyType)
950 valueWriterCall = toWriterCall("ix->second", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000951
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000952 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000953 valueWriterCall= toWriterCall("*ix", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000954
Marc Slemkod8b10512006-08-14 23:30:37 +0000955 if isinstance(collection, MapType):
Marc Slemko17859852006-08-15 00:21:31 +0000956 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
957 keyType=toCTypeDeclaration(collection.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000958 keyWriterCall=keyWriterCall,
Marc Slemko17859852006-08-15 00:21:31 +0000959 valueType=toCTypeDeclaration(collection.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000960 valueWriterCall=valueWriterCall)
961
962 else:
Marc Slemko17859852006-08-15 00:21:31 +0000963 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
Marc Slemkodb14e172006-08-09 23:36:18 +0000964 valueWriterCall=valueWriterCall,
Marc Slemko17859852006-08-15 00:21:31 +0000965 valueType=toCTypeDeclaration(collection.valueType))
Marc Slemkob2039e72006-08-09 01:00:17 +0000966
967
968CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000969uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000970
971 std::string name;
972 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000973 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000974 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000975
Marc Slemko5b126d62006-08-11 23:03:42 +0000976 xfer+= iprot->readStructBegin(itrans, name);
977
Marc Slemkob2039e72006-08-09 01:00:17 +0000978 while(true) {
979
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000980 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000981
982 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
983
984 switch(id) {
985${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +0000986 default: xfer += iprot->skip(itrans, type); break;
987 }
Marc Slemkob2039e72006-08-09 01:00:17 +0000988
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000989 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000990 }
Marc Slemko5b126d62006-08-11 23:03:42 +0000991
992 xfer+= iprot->readStructEnd(itrans);
993
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000994 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000995}
996""")
997
Marc Slemkod8b10512006-08-14 23:30:37 +0000998CPP_WRITE_FIELD_DEFINITION = Template("""oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id}); ${fieldWriterCall}; oprot->writeFieldEnd(otrans)""")
999
Marc Slemkodb14e172006-08-09 23:36:18 +00001000CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001001uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +00001002
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001003 uint32_t xfer = 0;
1004
1005 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +00001006${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001007 xfer+= oprot->writeFieldStop(otrans);
1008 xfer += oprot->writeStructEnd(otrans);
1009 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +00001010}
1011""")
1012
Marc Slemkod8b10512006-08-14 23:30:37 +00001013def toStructReaderDefinition(struct):
1014 """Converts struct type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +00001015
Marc Slemkod8b10512006-08-14 23:30:37 +00001016 suffix = typeToIOMethodSuffix(struct)
Marc Slemkob2039e72006-08-09 01:00:17 +00001017
1018 # Sort field list in order of increasing ids
1019
1020 fieldList = []
Marc Slemkod8b10512006-08-14 23:30:37 +00001021 fieldList+= struct.fieldList
Marc Slemkob2039e72006-08-09 01:00:17 +00001022
1023 fieldList.sort(lambda a,b: a.id - b.id)
1024
1025 fieldSwitch=""
1026
1027 for field in fieldList:
1028 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +00001029 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +00001030
Marc Slemko17859852006-08-15 00:21:31 +00001031 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +00001032
Marc Slemkodb14e172006-08-09 23:36:18 +00001033
Marc Slemkod8b10512006-08-14 23:30:37 +00001034def toStructWriterDefinition(struct):
1035 """Converts struct type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001036
Marc Slemkod8b10512006-08-14 23:30:37 +00001037 suffix = typeToIOMethodSuffix(struct)
Marc Slemkodb14e172006-08-09 23:36:18 +00001038
Marc Slemkod8b10512006-08-14 23:30:37 +00001039 fieldWriterCalls = []
Marc Slemkodb14e172006-08-09 23:36:18 +00001040
Marc Slemkod8b10512006-08-14 23:30:37 +00001041 fieldWriterCalls = [CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
1042 type=toWireType(toCanonicalType(field.type)),
1043 id=field.id,
1044 fieldWriterCall=toWriterCall("value."+field.name, field.type))+";"
1045 for field in struct.fieldList]
1046
1047 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n ")
1048
Marc Slemko17859852006-08-15 00:21:31 +00001049 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +00001050
Marc Slemkod8b10512006-08-14 23:30:37 +00001051CPP_WRITE_RESULT_STRUCT_DEFINITION = Template("""
1052uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
1053
1054 uint32_t xfer = 0;
1055
1056 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
1057 if(${value}.__isset.x)
1058${fieldWriterCalls}
1059 xfer+= oprot->writeFieldStop(otrans);
1060 xfer += oprot->writeStructEnd(otrans);
1061 return xfer;
1062}
1063""")
1064
1065def toResultStructReaderDefinition(struct):
1066 """Converts internal results struct to a reader function definition"""
1067 return toStructReaderDefinition(struct)
1068
1069def toResultStructWriterDefinition(struct):
1070 """Converts internal results struct to a reader function definition. The difference between this function and toStructWriterDefinition is that this only sends one field, either success or an exception field, depending on which field is set"""
1071
1072 suffix = typeToIOMethodSuffix(struct)
1073
1074 fieldWriterCalls = ["if(value.__isset."+field.name+") { "+toWriterCall("value."+field.name, field.type)+";}" for field in struct.fieldList]
1075
1076 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n else ")
1077
Marc Slemko17859852006-08-15 00:21:31 +00001078 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
Marc Slemkod8b10512006-08-14 23:30:37 +00001079
Marc Slemkodb14e172006-08-09 23:36:18 +00001080def toReaderDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001081 """Converts thrift type to a reader function definition"""
1082
Marc Slemkob2039e72006-08-09 01:00:17 +00001083 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001084 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +00001085
Marc Slemko5b126d62006-08-11 23:03:42 +00001086 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001087 return toStructReaderDefinition(ttype)
1088
Marc Slemko5b126d62006-08-11 23:03:42 +00001089 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001090 return ""
1091
Marc Slemko5b126d62006-08-11 23:03:42 +00001092 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001093 return ""
1094
1095 else:
1096 raise Exception, "Unsupported type: "+str(ttype)
1097
Marc Slemkodb14e172006-08-09 23:36:18 +00001098def toWriterDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001099 """Converts thrift type to a writer function definition"""
1100
Marc Slemkodb14e172006-08-09 23:36:18 +00001101 if isinstance(ttype, CollectionType):
1102 return toCollectionWriterDefinition(ttype)
1103
Marc Slemko5b126d62006-08-11 23:03:42 +00001104 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001105 return toStructWriterDefinition(ttype)
1106
Marc Slemko5b126d62006-08-11 23:03:42 +00001107 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001108 return ""
1109
Marc Slemko5b126d62006-08-11 23:03:42 +00001110 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001111 return ""
1112
1113 else:
1114 raise Exception, "Unsupported type: "+str(ttype)
1115
Marc Slemkodb14e172006-08-09 23:36:18 +00001116def toOrderedIOList(ttype, result=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001117 """Builds a list of types ordered by doing a depth first traverse of all thrift type definitions. This gives us a list from which we can
1118generate read/write methods without making forward references."""
1119
Marc Slemkodb14e172006-08-09 23:36:18 +00001120 if not result:
1121 result = []
1122
1123 if ttype in result:
1124 return result
1125
1126 elif isinstance(ttype, PrimitiveType):
1127 return result
1128
1129 elif isinstance(ttype, CollectionType):
1130
Marc Slemko5b126d62006-08-11 23:03:42 +00001131 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001132 result = toOrderedIOList(ttype.keyType, result)
1133
1134 result = toOrderedIOList(ttype.valueType, result)
1135
1136 result.append(ttype)
1137
Marc Slemko5b126d62006-08-11 23:03:42 +00001138 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001139 for field in ttype.fieldList:
1140 result = toOrderedIOList(field.type, result)
1141 result.append(ttype)
1142
Marc Slemko5b126d62006-08-11 23:03:42 +00001143 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001144 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001145 return result
1146
Marc Slemko5b126d62006-08-11 23:03:42 +00001147 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001148 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001149 return result
1150
1151 elif isinstance(ttype, Program):
1152
1153 for struct in ttype.structMap.values():
1154 result = toOrderedIOList(struct, result)
1155
1156 for service in ttype.serviceMap.values():
1157 result = toOrderedIOList(service, result)
1158
1159 elif isinstance(ttype, Service):
1160 for function in ttype.functionList:
1161 result = toOrderedIOList(function, result)
1162
1163 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001164 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001165
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001166 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001167 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001168 # inline those struct definitions with the implementation, not in the types header
1169
Marc Slemko5b126d62006-08-11 23:03:42 +00001170 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001171 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001172
1173 else:
1174 raise Exception, "Unsupported thrift type: "+str(ttype)
1175
1176 return result
1177
1178def toIOMethodImplementations(program):
Marc Slemkod8b10512006-08-14 23:30:37 +00001179 """Generates read and write methods for all non-primitive types in a thrift program as well as for the internal argStruct and resultStruct types for
1180all service functions"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001181
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001182 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001183
1184 iolist = toOrderedIOList(program)
1185
1186 result = ""
1187
1188 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001189 result+= toReaderDefinition(ttype)
1190 result+= toWriterDefinition(ttype)
1191
Marc Slemko5b126d62006-08-11 23:03:42 +00001192 # For all function argument lists, we need to create both struct definitions
1193 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1194 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001195 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1196 # we've already seen
1197
1198 for service in program.serviceMap.values():
1199 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001200 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001201 result+= toReaderDefinition(function.argsStruct)
1202 result+= toWriterDefinition(function.argsStruct)
1203 result+= toStructDefinition(function.resultStruct)
Marc Slemkod8b10512006-08-14 23:30:37 +00001204 result+= toResultStructReaderDefinition(function.resultStruct)
1205 result+= toResultStructWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001206
Marc Slemkodb14e172006-08-09 23:36:18 +00001207 return result;
1208
1209def toImplementationSourceName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001210 """Creates a file name for the implementation of client stubs, server skeletons, and non-primitive read/write methods."""
Marc Slemkodb14e172006-08-09 23:36:18 +00001211
1212 if not genDir:
1213 genDir = toGenDir(filename)
1214
1215 basename = toBasename(filename)
1216
1217 result = os.path.join(genDir, basename+".cc")
1218
1219 if debugp:
1220 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1221
1222 return result
1223
1224def writeImplementationSource(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001225 """Writes client stub, server skeleton, and non-primitive type I/O functions for all servciesf defined in program into a C/C++ source file. Uses the name of the original
1226thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001227
1228 implementationSource = toImplementationSourceName(filename, genDir)
1229
1230 if debugp:
1231 debugp("implementationSource: "+str(implementationSource))
1232
1233 cfile = CFile(implementationSource, "w")
1234
1235 basename = toBasename(filename)
1236
Marc Slemko17859852006-08-15 00:21:31 +00001237 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkodb14e172006-08-09 23:36:18 +00001238
1239 cfile.write(toIOMethodImplementations(program))
1240
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001241 cfile.write(toServerDefinition(program))
1242
Marc Slemko5b126d62006-08-11 23:03:42 +00001243 cfile.write(toClientDefinition(program))
1244
Marc Slemko17859852006-08-15 00:21:31 +00001245 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkodb14e172006-08-09 23:36:18 +00001246
1247 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001248
1249class CPPGenerator(Generator):
1250
1251 def __call__(self, program, filename, genDir=None, debugp=None):
1252
Marc Slemkodb14e172006-08-09 23:36:18 +00001253 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001254
Marc Slemkodb14e172006-08-09 23:36:18 +00001255 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001256
Marc Slemkodb14e172006-08-09 23:36:18 +00001257 writeImplementationSource(program, filename, genDir, debugp)