blob: b03ca5d82c2cb4f4d32bc7fe9473c93ec1b5e131 [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 Slemkob2039e72006-08-09 01:00:17 +000021""")
22
23CPP_TYPES_FOOTER = Template("""
24#endif // !defined(${source}_types_h_)
25""")
26
27CPP_SERVICES_HEADER = Template(HEADER_COMMENT+"""
28#if !defined(${source}_h_)
29#define ${source}_h_ 1
30
Marc Slemkoc4eb9e82006-08-10 03:29:29 +000031#include <Thrift.h>
32#include <TProcessor.h>
33#include <protocol/TProtocol.h>
34#include <transport/TTransport.h>
Marc Slemkodb14e172006-08-09 23:36:18 +000035#include \"${source}_types.h\"
Marc Slemkob2039e72006-08-09 01:00:17 +000036""")
37
38CPP_SERVICES_FOOTER = Template("""
39#endif // !defined(${source}_h_)""")
40
Marc Slemkodb14e172006-08-09 23:36:18 +000041CPP_IMPL_HEADER = Template(HEADER_COMMENT+"""
42#include \"${source}.h\"
43""")
44
45CPP_IMPL_FOOTER = Template("")
46
Marc Slemkob2039e72006-08-09 01:00:17 +000047def cpp_debug(arg):
48 print(arg)
49
50class Indenter(object):
51 def __init__(self, level=0, step=4):
52 self.level = level
53 self.step = step
54 self.chunk = ""
55 for i in range(step):
56 self.chunk+= " "
57 self.prefix=""
58
59 def inc(self):
60 self.level+= self.step
61 self.prefix += self.chunk
62
63 def dec(self):
64 self.level-= self.step
65 if(self.level < 0):
66 raise Exception, "Illegal indent level"
67 self.prefix = self.prefix[:self.level]
68
69 def __call__(self):
70 return self.prefix
71
72class CFile(file):
73
74 def __init__(self, name, flags):
75 file.__init__(self, name, flags)
76 self.indent = Indenter()
77 self.newline = True
78
79 def rwrite(self, value):
80 file.write(self, value)
81
82 def write(self, value=""):
83 if self.newline:
84 self.rwrite(self.indent())
85 self.newline = False
86 self.rwrite(value)
87
88 def writeln(self, value=""):
89 self.write(value+"\n")
90 self.newline = True
91
92 def beginBlock(self):
93 self.writeln("{")
94 self.indent.inc();
95
96 def endBlock(self, suffix=""):
97 self.indent.dec();
98 self.writeln("}"+suffix)
99
100CPP_PRIMITIVE_MAP = {
101 "void" : "void",
102 "bool" : "bool",
103 "string": "std::string",
104 "utf7": "std::string",
105 "utf8": "std::wstring",
106 "utf16": "std::utf16",
107 "byte" : "uint8_t",
108 "i08": "int8_t",
109 "i16": "int16_t",
110 "i32": "int32_t",
111 "i64": "int64_t",
112 "u08": "uint8_t",
113 "u16": "uint16_t",
114 "u32": "uint32_t",
115 "u64": "uint64_t",
116 "float": "double"
117}
118
119CPP_CONTAINER_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000120 MapType : "std::map",
121 ListType: "std::list",
122 SetType : "std::set",
Marc Slemkob2039e72006-08-09 01:00:17 +0000123}
124
125def typeToCTypeDeclaration(ttype):
126
127 if isinstance(ttype, PrimitiveType):
128 return CPP_PRIMITIVE_MAP[ttype.name]
129
130 elif isinstance(ttype, CollectionType):
131
132 result = CPP_CONTAINER_MAP[type(ttype)]+"<"
133
Marc Slemko5b126d62006-08-11 23:03:42 +0000134 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000135 result+= typeToCTypeDeclaration(ttype.keyType)+", "+ typeToCTypeDeclaration(ttype.valueType)
136
Marc Slemko5b126d62006-08-11 23:03:42 +0000137 elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000138 result+= typeToCTypeDeclaration(ttype.valueType)
139
140 else:
141 raise Exception, "Unknown Collection Type "+str(ttype)
142
143 result+= "> "
144
145 return result
146
Marc Slemko5b126d62006-08-11 23:03:42 +0000147 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000148 return "struct "+ttype.name
149
Marc Slemko5b126d62006-08-11 23:03:42 +0000150 elif isinstance(ttype, TypedefType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000151 return ttype.name;
152
Marc Slemko5b126d62006-08-11 23:03:42 +0000153 elif isinstance(ttype, EnumType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000154 return ttype.name;
155
156 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +0000157 return typeToCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([typeToCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000158
159 elif isinstance(ttype, Field):
160 return typeToCTypeDeclaration(ttype.type)+ " "+ttype.name
161
162 else:
163 raise Exception, "Unknown type "+str(ttype)
164
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000165def toTypeDefDefinition(typedef):
Marc Slemkob2039e72006-08-09 01:00:17 +0000166
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000167 return "typedef "+typeToCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
Marc Slemkob2039e72006-08-09 01:00:17 +0000168
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000169def toEnumDefinition(enum):
Marc Slemkob2039e72006-08-09 01:00:17 +0000170
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000171 result = "enum "+enum.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000172
173 first = True
174
175 for ed in enum.enumDefs:
176 if first:
177 first = False
178 else:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000179 result+= ",\n"
180 result+= " "+ed.name+" = "+str(ed.id)
Marc Slemkob2039e72006-08-09 01:00:17 +0000181
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000182 result+= "\n};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000183
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000184 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000185
Marc Slemkob2039e72006-08-09 01:00:17 +0000186
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000187def toStructDefinition(struct):
188
189 result = "struct "+struct.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000190
191 for field in struct.fieldList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000192 if toCanonicalType(field.type) != VOID_TYPE:
193 result += " "+typeToCTypeDeclaration(field)+";\n"
194
195 result+= " struct {\n"
196
197 for field in struct.fieldList:
198 result+= " bool "+field.name+";\n"
199 result+= " } __isset;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000200
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000201 result+= "};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000202
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000203 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000204
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000205CPP_DEFINITION_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000206 TypedefType : toTypeDefDefinition,
207 EnumType : toEnumDefinition,
208 StructType : toStructDefinition,
Marc Slemkob2039e72006-08-09 01:00:17 +0000209 Service : None
210 }
211
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000212def toDefinitions(definitions):
213
214 result = ""
215
Marc Slemkob2039e72006-08-09 01:00:17 +0000216 for definition in definitions:
217
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000218 writer = CPP_DEFINITION_MAP[type(definition)]
Marc Slemkob2039e72006-08-09 01:00:17 +0000219
220 if writer:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000221 result+= writer(definition)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000222
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000223 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000224
225CPP_THRIFT_NS = "facebook::thrift"
226
227CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
228""")
229
230CPP_INTERFACE_DECLARATION = Template("""
231class ${service}If {
232 public:
Marc Slemkoe6889de2006-08-12 00:32:53 +0000233 virtual ~${service}If() {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000234${functionDeclarations}};
235""")
236
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000237def toServiceInterfaceDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000238
239 functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
240
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000241 return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000242
Marc Slemko5b126d62006-08-11 23:03:42 +0000243CPP_EXCEPTION = CPP_THRIFT_NS+"::Exception"
244
Marc Slemkob2039e72006-08-09 01:00:17 +0000245CPP_SP = Template("boost::shared_ptr<${klass}> ")
246
247CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
248CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
249
250CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000251CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
252CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
Marc Slemkob2039e72006-08-09 01:00:17 +0000253
254
255CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
256CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
257CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
258
Marc Slemkob2039e72006-08-09 01:00:17 +0000259CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
260CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000261CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
262CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
263CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000264
Marc Slemkodb14e172006-08-09 23:36:18 +0000265CPP_TTYPE_MAP = {
266 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
267 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
268 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
269 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
270 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
271 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
272 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
273 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
274 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
275 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
276 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
277 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
278 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
279 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
280 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
281 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
282 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000283 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
284 ListType : CPP_PROTOCOL_NS+"::T_LIST",
285 MapType : CPP_PROTOCOL_NS+"::T_MAP",
286 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000287}
288
Marc Slemko91f67482006-08-11 23:58:57 +0000289
290CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
291""")
292
293CPP_SERVER_FUNCTION_DEFINITION = Template("""
294void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
295
296 uint32_t xfer = 0;
297
298 ${argsStructDeclaration};
299
300 ${argsStructReader};
301
302 _iprot->readMessageEnd(itrans);
303
304 ${returnValueDeclaration};
305
306 ${functionCall};
307
308 ${resultStructDeclaration};
309
310 ${returnToResult};
311
312 _oprot->writeMessageBegin(otrans, \"${function}\", """+CPP_PROTOCOL_REPLY+""", seqid);
313
314 ${resultStructWriter};
315
316 _oprot->writeMessageEnd(otrans);
317
318 otrans->flush();
319}
320""")
321
322CPP_SERVER_PROCESS_DEFINITION = Template("""
323bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
324
Marc Slemko91f67482006-08-11 23:58:57 +0000325 std::string name;
326
327 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
328
329 uint32_t seqid;
330
331 _iprot->readMessageBegin(itrans, name, messageType, seqid);
332
333 if(messageType == """+CPP_PROTOCOL_CALL+""") {
334${callProcessSwitch}
335 } else {
336 throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
337 }
Marc Slemkoe6889de2006-08-12 00:32:53 +0000338
339 return true;
Marc Slemko91f67482006-08-11 23:58:57 +0000340}
341""")
342
Marc Slemkodb14e172006-08-09 23:36:18 +0000343def toWireType(ttype):
344
345 if isinstance(ttype, PrimitiveType):
346 return CPP_TTYPE_MAP[ttype]
347
Marc Slemko5b126d62006-08-11 23:03:42 +0000348 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000349 return CPP_TTYPE_MAP[I32_TYPE]
350
Marc Slemko5b126d62006-08-11 23:03:42 +0000351 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000352 return toWireType(toCanonicalType(ttype))
353
Marc Slemko5b126d62006-08-11 23:03:42 +0000354 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000355 return CPP_TTYPE_MAP[type(ttype)]
356
357 else:
358 raise Exception, "No wire type for thrift type: "+str(ttype)
359
Marc Slemkob2039e72006-08-09 01:00:17 +0000360CPP_SERVER_DECLARATION = Template("""
361class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
362 public:
363 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
364 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
365 virtual ~${service}ServerIf() {}
366 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
367 protected:
368 """+CPP_PROTOCOLP+""" _iprot;
369 """+CPP_PROTOCOLP+""" _oprot;
370 private:
371${functionDeclarations}};
372""")
373
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000374def toServerDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000375
376 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
377
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000378 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000379
380CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
381""")
382
Marc Slemko5b126d62006-08-11 23:03:42 +0000383
384CPP_CLIENT_FUNCTION_DEFINITION = Template("""
385${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) {
386
387 uint32_t xfer = 0;
Marc Slemko91f67482006-08-11 23:58:57 +0000388 std::string name;
Marc Slemko5b126d62006-08-11 23:03:42 +0000389 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
390 uint32_t cseqid = 0;
391 uint32_t rseqid = 0;
392
Marc Slemko91f67482006-08-11 23:58:57 +0000393 _oprot->writeMessageBegin(_otrans, \"${function}\", """+CPP_PROTOCOL_CALL+""", cseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000394
395 ${argsStructDeclaration};
396
397${argsToStruct};
398
399 ${argsStructWriter};
400
401 _otrans->flush();
402
Marc Slemko91f67482006-08-11 23:58:57 +0000403 _iprot->readMessageBegin(_itrans, name, messageType, rseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000404
405 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
406 rseqid != cseqid) {
407 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
408 }
409
410 ${resultStructDeclaration};
411
412 ${resultStructReader};
413
414 _iprot->readMessageEnd(_itrans);
415
416 if(__result.__isset.success) {
417 ${success};
418 } else {
419 throw """+CPP_EXCEPTION+"""(\"${function} failed\");
420 }
421}
422""")
423
Marc Slemkob2039e72006-08-09 01:00:17 +0000424CPP_CLIENT_DECLARATION = Template("""
425class ${service}Client : public ${service}If {
426
427 public:
428
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000429 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000430
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000431 ${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 +0000432
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000433${functionDeclarations}
434 private:
435 """+CPP_TRANSPORTP+""" _itrans;
436 """+CPP_TRANSPORTP+""" _otrans;
437 """+CPP_PROTOCOLP+""" _iprot;
438 """+CPP_PROTOCOLP+""" _oprot;
439};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000440
Marc Slemko5b126d62006-08-11 23:03:42 +0000441def toServerFunctionDefinition(servicePrefix, function, debugp=None):
442 result = ""
443
444 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
445
446 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
447
448 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
449
450 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
451
452 if function.returnType() != VOID_TYPE:
453 returnValueDeclaration = typeToCTypeDeclaration(toCanonicalType(function.returnType()))+" __returnValue"
454 functionCall = "__returnValue = "
455 returnToResult = "__result.success = __returnValue"
456 else:
457 returnValueDeclaration = ""
458 functionCall = ""
459 returnToResult = ""
460
461 functionCall+= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+")"
462
463 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
464 argsStructDeclaration=argsStructDeclaration,
465 argsStructReader=argsStructReader,
466 functionCall=functionCall,
467 returnToResult=returnToResult,
468 resultStructDeclaration=resultStructDeclaration,
469 resultStructWriter=resultStructWriter,
470 returnValueDeclaration=returnValueDeclaration)
471
472
473
474 return result
475
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000476def toServerServiceDefinition(service, debugp=None):
477
478 result = ""
479
480 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000481
482 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko66d67d82006-08-11 23:33:08 +0000483
Marc Slemko91f67482006-08-11 23:58:57 +0000484 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 +0000485
Marc Slemko91f67482006-08-11 23:58:57 +0000486 result+= CPP_SERVER_PROCESS_DEFINITION.substitute(service=service.name, callProcessSwitch=callProcessSwitch)
Marc Slemko66d67d82006-08-11 23:33:08 +0000487
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000488 return result
489
490def toServerDefinition(program, debugp=None):
491
492 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
493
494def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000495
496 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
497
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000498 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000499
Marc Slemko5b126d62006-08-11 23:03:42 +0000500def toClientFunctionDefinition(servicePrefix, function, debugp=None):
501
502 returnDeclaration = typeToCTypeDeclaration(function.returnType())
503
504 argsDeclaration = string.join([typeToCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
505
506 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
507
508 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
509
510 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
511
512 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
513
514 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
515
516 if(toCanonicalType(function.returnType()) != VOID_TYPE):
517
518 success = "return __result.success;"
519 else:
520 success = ""
521
522 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
523 function=function.name,
524 returnDeclaration=returnDeclaration,
525 argsDeclaration=argsDeclaration,
526 argsStructDeclaration=argsStructDeclaration,
527 argsStructWriter=argsStructWriter,
528 argsToStruct=argsToStruct,
529 resultStructDeclaration=resultStructDeclaration,
530 resultStructReader=resultStructReader,
531 success=success)
532
533def toClientServiceDefinition(service, debugp=None):
534
535 result = ""
536
537 for function in service.functionList:
538
539 result+= toClientFunctionDefinition(service.name, function)
540
541 return result
542
543def toClientDefinition(program, debugp=None):
544
545 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
546
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000547def toServiceDeclaration(service, debugp=None):
548 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000549
550def toGenDir(filename, suffix="cpp-gen", debugp=None):
551
552 result = os.path.join(os.path.split(filename)[0], suffix)
553
554 if not os.path.exists(result):
555 os.mkdir(result)
556
557 return result
558
559def toBasename(filename, debugp=None):
560 """ Take the filename minus the path and\".thrift\" extension if present """
561
562 basename = os.path.split(filename)[1]
563
564 tokens = os.path.splitext(basename)
565
566 if tokens[1].lower() == ".thrift":
567 basename = tokens[0]
568
569 if debugp:
570 debugp("toBasename("+str(filename)+") => "+str(basename))
571
572 return basename
573
574def toDefinitionHeaderName(filename, genDir=None, debugp=None):
575
576 if not genDir:
577 genDir = toGenDir(filename)
578
579 basename = toBasename(filename)
580
581 result = os.path.join(genDir, basename+"_types.h")
582
583 if debugp:
584 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
585
586 return result
587
588def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
589
590 definitionHeader = toDefinitionHeaderName(filename, genDir)
591
592 if debugp:
593 debugp("definitionHeader: "+str(definitionHeader))
594
595 cfile = CFile(definitionHeader, "w")
596
597 basename = toBasename(filename)
598
599 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
600
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000601 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000602
603 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
604
605 cfile.close()
606
607def toServicesHeaderName(filename, genDir=None, debugp=None):
608
609 if not genDir:
610 genDir = toGenDir(filename)
611
612 basename = toBasename(filename)
613
614 result = os.path.join(genDir, basename+".h")
615
616 if debugp:
617 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
618
619 return result
620
621
622def writeServicesHeader(program, filename, genDir=None, debugp=None):
623
624 servicesHeader = toServicesHeaderName(filename, genDir)
625
626 if debugp:
627 debugp("servicesHeader: "+str(servicesHeader))
628
629 cfile = CFile(servicesHeader, "w")
630
631 basename = toBasename(filename)
632
633 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
634
635 services = []
636
637 # Build orderered list of service definitions by scanning definitions list for services
638
639 for definition in program.definitions:
640 if isinstance(definition, Service) and definition.name in program.serviceMap:
641 services.append(definition)
642
643 for service in services:
644
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000645 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000646
647 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
648
649 cfile.close()
650
651
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000652CPP_STRUCT_READ = Template("""
653uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
654
Marc Slemkob2039e72006-08-09 01:00:17 +0000655 std::string name;
656 uint32_t id;
657 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000658 uint32_t xfer = 0;
659
Marc Slemkob2039e72006-08-09 01:00:17 +0000660 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000661 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000662 if(type == """+CPP_PROTOCOL_TSTOP+""") {
663 break;
664 }
665 switch(id) {
666${readFieldListSwitch}
667 }
668 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000669
670 xfer+= _iprot->readStructEnd(_itrans);
671
672 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000673}
674""")
675
676CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000677 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000678 "bool" : "Bool",
679 "string": "String",
680 "utf7": "String",
681 "utf8": "String",
682 "utf16": "String",
683 "i08": "Byte",
684 "i16": "I16",
685 "i32": "I32",
686 "i64": "I64",
687 "u08": "Byte",
688 "u16": "U16",
689 "u32": "U32",
690 "u64": "U64",
691 "float": "Double"
692}
693
694CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000695 MapType : "map",
696 ListType : "list",
697 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000698}
699
700def typeToIOMethodSuffix(ttype):
701
702 if isinstance(ttype, PrimitiveType):
703 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
704
705 elif isinstance(ttype, CollectionType):
706
707 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
708
Marc Slemko5b126d62006-08-11 23:03:42 +0000709 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000710 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
711
712 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
713
714 return result
715
Marc Slemko5b126d62006-08-11 23:03:42 +0000716 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000717 return "struct_"+ttype.name
718
Marc Slemko5b126d62006-08-11 23:03:42 +0000719 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000720 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000721
Marc Slemko5b126d62006-08-11 23:03:42 +0000722 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000723 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000724
725 else:
726 raise Exception, "Unknown type "+str(ttype)
727
Marc Slemko5b126d62006-08-11 23:03:42 +0000728def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkob2039e72006-08-09 01:00:17 +0000729
730 suffix = typeToIOMethodSuffix(ttype)
731
732 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000733 if ttype != VOID_TYPE:
734 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
735 else:
736 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000737
738 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000739 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000740
Marc Slemko5b126d62006-08-11 23:03:42 +0000741 elif isinstance(ttype, StructType):
742 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000743
Marc Slemko5b126d62006-08-11 23:03:42 +0000744 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000745 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000746
Marc Slemko5b126d62006-08-11 23:03:42 +0000747 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000748 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000749
750 else:
751 raise Exception, "Unknown type "+str(ttype)
752
Marc Slemko5b126d62006-08-11 23:03:42 +0000753def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkodb14e172006-08-09 23:36:18 +0000754
755 suffix = typeToIOMethodSuffix(ttype)
756
757 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000758 if ttype != VOID_TYPE:
759 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
760 else:
761 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000762
763 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000764 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000765
Marc Slemko5b126d62006-08-11 23:03:42 +0000766 elif isinstance(ttype, StructType):
767 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000768
Marc Slemko5b126d62006-08-11 23:03:42 +0000769 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000770 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000771
Marc Slemko5b126d62006-08-11 23:03:42 +0000772 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000773 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000774
775 else:
776 raise Exception, "Unknown type "+str(ttype)
777
778CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000779uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000780
781 uint32_t count;
782 ${keyType} key;
783 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000784 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000785
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000786 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000787
Marc Slemkoe6889de2006-08-12 00:32:53 +0000788 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000789 ${keyReaderCall};
790 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000791 value.insert(std::make_pair(key, elem));
792 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000793
794 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000795}
796""")
797
798CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000799uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000800
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000801 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000802
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000803 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000804
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000805 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000806 ${keyWriterCall};
807 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000808 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000809 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000810}
811""")
812
Marc Slemkob2039e72006-08-09 01:00:17 +0000813CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000814uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000815
816 uint32_t count;
817 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000818 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000819
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000820 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000821
Marc Slemkoe6889de2006-08-12 00:32:53 +0000822 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000823 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000824 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000825 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000826 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000827}
828""")
829
Marc Slemkodb14e172006-08-09 23:36:18 +0000830CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000831uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000832
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000833 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000834
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000835 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000836
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000837 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000838 ${valueWriterCall};
839 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000840 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000841}
842""")
843
844def toCollectionReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000845
846 suffix = typeToIOMethodSuffix(ttype)
847
Marc Slemko5b126d62006-08-11 23:03:42 +0000848 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000849 keyReaderCall = toReaderCall("key", ttype.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000850
Marc Slemkodb14e172006-08-09 23:36:18 +0000851 valueReaderCall= toReaderCall("elem", ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000852
Marc Slemko5b126d62006-08-11 23:03:42 +0000853 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000854 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
855 keyType=typeToCTypeDeclaration(ttype.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000856 keyReaderCall=keyReaderCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000857 valueType=typeToCTypeDeclaration(ttype.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000858 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000859
860 else:
Marc Slemko5b126d62006-08-11 23:03:42 +0000861 if isinstance(ttype, ListType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000862 insert="push_back"
863 else:
864 insert="insert"
865
Marc Slemkob2039e72006-08-09 01:00:17 +0000866 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
Marc Slemkodb14e172006-08-09 23:36:18 +0000867 valueReaderCall=valueReaderCall,
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000868 valueType=typeToCTypeDeclaration(ttype.valueType),
869 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000870
871
872def toCollectionWriterDefinition(ttype):
873
874 suffix = typeToIOMethodSuffix(ttype)
875
Marc Slemko5b126d62006-08-11 23:03:42 +0000876 if isinstance(ttype, MapType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000877 keyWriterCall = toWriterCall("ix->first", ttype.keyType)
878 valueWriterCall = toWriterCall("ix->second", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000879
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000880 else:
881 valueWriterCall= toWriterCall("*ix", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000882
Marc Slemko5b126d62006-08-11 23:03:42 +0000883 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000884 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
885 keyType=typeToCTypeDeclaration(ttype.keyType),
886 keyWriterCall=keyWriterCall,
887 valueType=typeToCTypeDeclaration(ttype.valueType),
888 valueWriterCall=valueWriterCall)
889
890 else:
891 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
892 valueWriterCall=valueWriterCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000893 valueType=typeToCTypeDeclaration(ttype.valueType))
894
895
896CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000897uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000898
899 std::string name;
900 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000901 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000902 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000903
Marc Slemko5b126d62006-08-11 23:03:42 +0000904 xfer+= iprot->readStructBegin(itrans, name);
905
Marc Slemkob2039e72006-08-09 01:00:17 +0000906 while(true) {
907
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000908 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000909
910 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
911
912 switch(id) {
913${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +0000914 default: xfer += iprot->skip(itrans, type); break;
915 }
Marc Slemkob2039e72006-08-09 01:00:17 +0000916
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000917 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000918 }
Marc Slemko5b126d62006-08-11 23:03:42 +0000919
920 xfer+= iprot->readStructEnd(itrans);
921
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000922 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000923}
924""")
925
Marc Slemkodb14e172006-08-09 23:36:18 +0000926CPP_WRITE_FIELD_DEFINITION = Template("""
927 oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id});
928 ${fieldWriterCall};
929 oprot->writeFieldEnd(otrans);
930""")
931
932CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000933uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000934
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000935 uint32_t xfer = 0;
936
937 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +0000938${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000939 xfer+= oprot->writeFieldStop(otrans);
940 xfer += oprot->writeStructEnd(otrans);
941 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000942}
943""")
944
945def toStructReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000946
947 suffix = typeToIOMethodSuffix(ttype)
948
949 # Sort field list in order of increasing ids
950
951 fieldList = []
952 fieldList+= ttype.fieldList
953
954 fieldList.sort(lambda a,b: a.id - b.id)
955
956 fieldSwitch=""
957
958 for field in fieldList:
959 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +0000960 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000961
962 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +0000963
964def toStructWriterDefinition(ttype):
965
966 suffix = typeToIOMethodSuffix(ttype)
967
968 writeCalls = ""
969
970 for field in ttype.fieldList:
971
972 writeCalls+= CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name, type=toWireType(field.type), id=field.id,
973 fieldWriterCall=toWriterCall("value."+field.name, field.type))
974
975 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=ttype.name, suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldWriterCalls=writeCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +0000976
Marc Slemkodb14e172006-08-09 23:36:18 +0000977def toReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000978 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000979 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +0000980
Marc Slemko5b126d62006-08-11 23:03:42 +0000981 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000982 return toStructReaderDefinition(ttype)
983
Marc Slemko5b126d62006-08-11 23:03:42 +0000984 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000985 return ""
986
Marc Slemko5b126d62006-08-11 23:03:42 +0000987 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000988 return ""
989
990 else:
991 raise Exception, "Unsupported type: "+str(ttype)
992
Marc Slemkodb14e172006-08-09 23:36:18 +0000993def toWriterDefinition(ttype):
994 if isinstance(ttype, CollectionType):
995 return toCollectionWriterDefinition(ttype)
996
Marc Slemko5b126d62006-08-11 23:03:42 +0000997 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000998 return toStructWriterDefinition(ttype)
999
Marc Slemko5b126d62006-08-11 23:03:42 +00001000 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001001 return ""
1002
Marc Slemko5b126d62006-08-11 23:03:42 +00001003 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001004 return ""
1005
1006 else:
1007 raise Exception, "Unsupported type: "+str(ttype)
1008
Marc Slemkodb14e172006-08-09 23:36:18 +00001009def toOrderedIOList(ttype, result=None):
1010 if not result:
1011 result = []
1012
1013 if ttype in result:
1014 return result
1015
1016 elif isinstance(ttype, PrimitiveType):
1017 return result
1018
1019 elif isinstance(ttype, CollectionType):
1020
Marc Slemko5b126d62006-08-11 23:03:42 +00001021 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001022 result = toOrderedIOList(ttype.keyType, result)
1023
1024 result = toOrderedIOList(ttype.valueType, result)
1025
1026 result.append(ttype)
1027
Marc Slemko5b126d62006-08-11 23:03:42 +00001028 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001029 for field in ttype.fieldList:
1030 result = toOrderedIOList(field.type, result)
1031 result.append(ttype)
1032
Marc Slemko5b126d62006-08-11 23:03:42 +00001033 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001034 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001035 return result
1036
Marc Slemko5b126d62006-08-11 23:03:42 +00001037 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001038 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001039 return result
1040
1041 elif isinstance(ttype, Program):
1042
1043 for struct in ttype.structMap.values():
1044 result = toOrderedIOList(struct, result)
1045
1046 for service in ttype.serviceMap.values():
1047 result = toOrderedIOList(service, result)
1048
1049 elif isinstance(ttype, Service):
1050 for function in ttype.functionList:
1051 result = toOrderedIOList(function, result)
1052
1053 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001054 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001055
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001056 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001057 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001058 # inline those struct definitions with the implementation, not in the types header
1059
Marc Slemko5b126d62006-08-11 23:03:42 +00001060 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001061 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001062
1063 else:
1064 raise Exception, "Unsupported thrift type: "+str(ttype)
1065
1066 return result
1067
1068def toIOMethodImplementations(program):
1069
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001070 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001071
1072 iolist = toOrderedIOList(program)
1073
1074 result = ""
1075
1076 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001077 result+= toReaderDefinition(ttype)
1078 result+= toWriterDefinition(ttype)
1079
Marc Slemko5b126d62006-08-11 23:03:42 +00001080 # For all function argument lists, we need to create both struct definitions
1081 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1082 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001083 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1084 # we've already seen
1085
1086 for service in program.serviceMap.values():
1087 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001088 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001089 result+= toReaderDefinition(function.argsStruct)
1090 result+= toWriterDefinition(function.argsStruct)
1091 result+= toStructDefinition(function.resultStruct)
1092 result+= toReaderDefinition(function.resultStruct)
1093 result+= toWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001094
Marc Slemkodb14e172006-08-09 23:36:18 +00001095 return result;
1096
1097def toImplementationSourceName(filename, genDir=None, debugp=None):
1098
1099 if not genDir:
1100 genDir = toGenDir(filename)
1101
1102 basename = toBasename(filename)
1103
1104 result = os.path.join(genDir, basename+".cc")
1105
1106 if debugp:
1107 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1108
1109 return result
1110
1111def writeImplementationSource(program, filename, genDir=None, debugp=None):
1112
1113 implementationSource = toImplementationSourceName(filename, genDir)
1114
1115 if debugp:
1116 debugp("implementationSource: "+str(implementationSource))
1117
1118 cfile = CFile(implementationSource, "w")
1119
1120 basename = toBasename(filename)
1121
1122 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
1123
1124 cfile.write(toIOMethodImplementations(program))
1125
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001126 cfile.write(toServerDefinition(program))
1127
Marc Slemko5b126d62006-08-11 23:03:42 +00001128 cfile.write(toClientDefinition(program))
1129
Marc Slemkodb14e172006-08-09 23:36:18 +00001130 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
1131
1132 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001133
1134class CPPGenerator(Generator):
1135
1136 def __call__(self, program, filename, genDir=None, debugp=None):
1137
Marc Slemkodb14e172006-08-09 23:36:18 +00001138 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001139
Marc Slemkodb14e172006-08-09 23:36:18 +00001140 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001141
Marc Slemkodb14e172006-08-09 23:36:18 +00001142 writeImplementationSource(program, filename, genDir, debugp)