blob: 2c8efc51d26460a7ab09058751d96a2baf516d31 [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:
233 ~${service}If() {}
234${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 Slemko0b4ffa92006-08-11 02:49:29 +0000259CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
260""")
261
262CPP_SERVER_FUNCTION_DEFINITION = Template("""
263void ${service}ServerIf::process_${function}("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
264
265 uint32_t xfer = 0;
266
Marc Slemko5b126d62006-08-11 23:03:42 +0000267 ${argsStructDeclaration};
268
269 ${argsStructReader};
270
271 ${returnValueDeclaration};
272
273 ${functionCall};
274
275 ${resultStructDeclaration};
276
277 ${returnToResult};
278
279 ${resultStructWriter};
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000280
281 otrans->flush();
282}
Marc Slemkob2039e72006-08-09 01:00:17 +0000283""")
284
285CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
286CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000287CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
288CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
289CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000290
Marc Slemkodb14e172006-08-09 23:36:18 +0000291CPP_TTYPE_MAP = {
292 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
293 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
294 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
295 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
296 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
297 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
298 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
299 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
300 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
301 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
302 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
303 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
304 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
305 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
306 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
307 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
308 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000309 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
310 ListType : CPP_PROTOCOL_NS+"::T_LIST",
311 MapType : CPP_PROTOCOL_NS+"::T_MAP",
312 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000313}
314
315def toWireType(ttype):
316
317 if isinstance(ttype, PrimitiveType):
318 return CPP_TTYPE_MAP[ttype]
319
Marc Slemko5b126d62006-08-11 23:03:42 +0000320 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000321 return CPP_TTYPE_MAP[I32_TYPE]
322
Marc Slemko5b126d62006-08-11 23:03:42 +0000323 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000324 return toWireType(toCanonicalType(ttype))
325
Marc Slemko5b126d62006-08-11 23:03:42 +0000326 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000327 return CPP_TTYPE_MAP[type(ttype)]
328
329 else:
330 raise Exception, "No wire type for thrift type: "+str(ttype)
331
Marc Slemkob2039e72006-08-09 01:00:17 +0000332CPP_SERVER_DECLARATION = Template("""
333class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
334 public:
335 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
336 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
337 virtual ~${service}ServerIf() {}
338 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
339 protected:
340 """+CPP_PROTOCOLP+""" _iprot;
341 """+CPP_PROTOCOLP+""" _oprot;
342 private:
343${functionDeclarations}};
344""")
345
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000346def toServerDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000347
348 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
349
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000350 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000351
352CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
353""")
354
Marc Slemko5b126d62006-08-11 23:03:42 +0000355
356CPP_CLIENT_FUNCTION_DEFINITION = Template("""
357${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) {
358
359 uint32_t xfer = 0;
360 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
361 uint32_t cseqid = 0;
362 uint32_t rseqid = 0;
363
364 _oprot->writeMessageBegin(_otrans, """+CPP_PROTOCOL_CALL+""", cseqid);
365
366 ${argsStructDeclaration};
367
368${argsToStruct};
369
370 ${argsStructWriter};
371
372 _otrans->flush();
373
374 _iprot->readMessageBegin(_itrans, messageType, rseqid);
375
376 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
377 rseqid != cseqid) {
378 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
379 }
380
381 ${resultStructDeclaration};
382
383 ${resultStructReader};
384
385 _iprot->readMessageEnd(_itrans);
386
387 if(__result.__isset.success) {
388 ${success};
389 } else {
390 throw """+CPP_EXCEPTION+"""(\"${function} failed\");
391 }
392}
393""")
394
Marc Slemkob2039e72006-08-09 01:00:17 +0000395CPP_CLIENT_DECLARATION = Template("""
396class ${service}Client : public ${service}If {
397
398 public:
399
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000400 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000401
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000402 ${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 +0000403
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000404${functionDeclarations}
405 private:
406 """+CPP_TRANSPORTP+""" _itrans;
407 """+CPP_TRANSPORTP+""" _otrans;
408 """+CPP_PROTOCOLP+""" _iprot;
409 """+CPP_PROTOCOLP+""" _oprot;
410};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000411
Marc Slemko5b126d62006-08-11 23:03:42 +0000412def toServerFunctionDefinition(servicePrefix, function, debugp=None):
413 result = ""
414
415 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
416
417 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
418
419 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
420
421 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
422
423 if function.returnType() != VOID_TYPE:
424 returnValueDeclaration = typeToCTypeDeclaration(toCanonicalType(function.returnType()))+" __returnValue"
425 functionCall = "__returnValue = "
426 returnToResult = "__result.success = __returnValue"
427 else:
428 returnValueDeclaration = ""
429 functionCall = ""
430 returnToResult = ""
431
432 functionCall+= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+")"
433
434 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
435 argsStructDeclaration=argsStructDeclaration,
436 argsStructReader=argsStructReader,
437 functionCall=functionCall,
438 returnToResult=returnToResult,
439 resultStructDeclaration=resultStructDeclaration,
440 resultStructWriter=resultStructWriter,
441 returnValueDeclaration=returnValueDeclaration)
442
443
444
445 return result
446
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000447def toServerServiceDefinition(service, debugp=None):
448
449 result = ""
450
451 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000452
453 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000454
455 return result
456
457def toServerDefinition(program, debugp=None):
458
459 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
460
461def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000462
463 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
464
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000465 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000466
Marc Slemko5b126d62006-08-11 23:03:42 +0000467def toClientFunctionDefinition(servicePrefix, function, debugp=None):
468
469 returnDeclaration = typeToCTypeDeclaration(function.returnType())
470
471 argsDeclaration = string.join([typeToCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
472
473 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
474
475 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
476
477 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
478
479 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
480
481 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
482
483 if(toCanonicalType(function.returnType()) != VOID_TYPE):
484
485 success = "return __result.success;"
486 else:
487 success = ""
488
489 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
490 function=function.name,
491 returnDeclaration=returnDeclaration,
492 argsDeclaration=argsDeclaration,
493 argsStructDeclaration=argsStructDeclaration,
494 argsStructWriter=argsStructWriter,
495 argsToStruct=argsToStruct,
496 resultStructDeclaration=resultStructDeclaration,
497 resultStructReader=resultStructReader,
498 success=success)
499
500def toClientServiceDefinition(service, debugp=None):
501
502 result = ""
503
504 for function in service.functionList:
505
506 result+= toClientFunctionDefinition(service.name, function)
507
508 return result
509
510def toClientDefinition(program, debugp=None):
511
512 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
513
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000514def toServiceDeclaration(service, debugp=None):
515 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000516
517def toGenDir(filename, suffix="cpp-gen", debugp=None):
518
519 result = os.path.join(os.path.split(filename)[0], suffix)
520
521 if not os.path.exists(result):
522 os.mkdir(result)
523
524 return result
525
526def toBasename(filename, debugp=None):
527 """ Take the filename minus the path and\".thrift\" extension if present """
528
529 basename = os.path.split(filename)[1]
530
531 tokens = os.path.splitext(basename)
532
533 if tokens[1].lower() == ".thrift":
534 basename = tokens[0]
535
536 if debugp:
537 debugp("toBasename("+str(filename)+") => "+str(basename))
538
539 return basename
540
541def toDefinitionHeaderName(filename, genDir=None, debugp=None):
542
543 if not genDir:
544 genDir = toGenDir(filename)
545
546 basename = toBasename(filename)
547
548 result = os.path.join(genDir, basename+"_types.h")
549
550 if debugp:
551 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
552
553 return result
554
555def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
556
557 definitionHeader = toDefinitionHeaderName(filename, genDir)
558
559 if debugp:
560 debugp("definitionHeader: "+str(definitionHeader))
561
562 cfile = CFile(definitionHeader, "w")
563
564 basename = toBasename(filename)
565
566 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
567
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000568 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000569
570 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
571
572 cfile.close()
573
574def toServicesHeaderName(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+".h")
582
583 if debugp:
584 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
585
586 return result
587
588
589def writeServicesHeader(program, filename, genDir=None, debugp=None):
590
591 servicesHeader = toServicesHeaderName(filename, genDir)
592
593 if debugp:
594 debugp("servicesHeader: "+str(servicesHeader))
595
596 cfile = CFile(servicesHeader, "w")
597
598 basename = toBasename(filename)
599
600 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
601
602 services = []
603
604 # Build orderered list of service definitions by scanning definitions list for services
605
606 for definition in program.definitions:
607 if isinstance(definition, Service) and definition.name in program.serviceMap:
608 services.append(definition)
609
610 for service in services:
611
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000612 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000613
614 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
615
616 cfile.close()
617
618
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000619CPP_STRUCT_READ = Template("""
620uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
621
Marc Slemkob2039e72006-08-09 01:00:17 +0000622 std::string name;
623 uint32_t id;
624 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000625 uint32_t xfer = 0;
626
Marc Slemkob2039e72006-08-09 01:00:17 +0000627 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000628 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000629 if(type == """+CPP_PROTOCOL_TSTOP+""") {
630 break;
631 }
632 switch(id) {
633${readFieldListSwitch}
634 }
635 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000636
637 xfer+= _iprot->readStructEnd(_itrans);
638
639 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000640}
641""")
642
643CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000644 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000645 "bool" : "Bool",
646 "string": "String",
647 "utf7": "String",
648 "utf8": "String",
649 "utf16": "String",
650 "i08": "Byte",
651 "i16": "I16",
652 "i32": "I32",
653 "i64": "I64",
654 "u08": "Byte",
655 "u16": "U16",
656 "u32": "U32",
657 "u64": "U64",
658 "float": "Double"
659}
660
661CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000662 MapType : "map",
663 ListType : "list",
664 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000665}
666
667def typeToIOMethodSuffix(ttype):
668
669 if isinstance(ttype, PrimitiveType):
670 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
671
672 elif isinstance(ttype, CollectionType):
673
674 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
675
Marc Slemko5b126d62006-08-11 23:03:42 +0000676 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000677 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
678
679 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
680
681 return result
682
Marc Slemko5b126d62006-08-11 23:03:42 +0000683 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000684 return "struct_"+ttype.name
685
Marc Slemko5b126d62006-08-11 23:03:42 +0000686 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000687 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000688
Marc Slemko5b126d62006-08-11 23:03:42 +0000689 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000690 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000691
692 else:
693 raise Exception, "Unknown type "+str(ttype)
694
Marc Slemko5b126d62006-08-11 23:03:42 +0000695def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkob2039e72006-08-09 01:00:17 +0000696
697 suffix = typeToIOMethodSuffix(ttype)
698
699 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000700 if ttype != VOID_TYPE:
701 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
702 else:
703 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000704
705 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000706 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000707
Marc Slemko5b126d62006-08-11 23:03:42 +0000708 elif isinstance(ttype, StructType):
709 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000710
Marc Slemko5b126d62006-08-11 23:03:42 +0000711 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000712 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000713
Marc Slemko5b126d62006-08-11 23:03:42 +0000714 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000715 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000716
717 else:
718 raise Exception, "Unknown type "+str(ttype)
719
Marc Slemko5b126d62006-08-11 23:03:42 +0000720def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkodb14e172006-08-09 23:36:18 +0000721
722 suffix = typeToIOMethodSuffix(ttype)
723
724 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000725 if ttype != VOID_TYPE:
726 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
727 else:
728 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000729
730 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000731 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000732
Marc Slemko5b126d62006-08-11 23:03:42 +0000733 elif isinstance(ttype, StructType):
734 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000735
Marc Slemko5b126d62006-08-11 23:03:42 +0000736 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000737 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000738
Marc Slemko5b126d62006-08-11 23:03:42 +0000739 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000740 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000741
742 else:
743 raise Exception, "Unknown type "+str(ttype)
744
745CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000746uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000747
748 uint32_t count;
749 ${keyType} key;
750 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000751 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000752
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000753 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000754
755 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000756 ${keyReaderCall};
757 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000758 value.insert(std::make_pair(key, elem));
759 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000760
761 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000762}
763""")
764
765CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000766uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000767
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000768 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000769
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000770 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000771
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000772 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000773 ${keyWriterCall};
774 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000775 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000776 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000777}
778""")
779
Marc Slemkob2039e72006-08-09 01:00:17 +0000780CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000781uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000782
783 uint32_t count;
784 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000785 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000786
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000787 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000788
789 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000790 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000791 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000792 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000793 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000794}
795""")
796
Marc Slemkodb14e172006-08-09 23:36:18 +0000797CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000798uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000799
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000800 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000801
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000802 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000803
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000804 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000805 ${valueWriterCall};
806 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000807 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000808}
809""")
810
811def toCollectionReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000812
813 suffix = typeToIOMethodSuffix(ttype)
814
Marc Slemko5b126d62006-08-11 23:03:42 +0000815 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000816 keyReaderCall = toReaderCall("key", ttype.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000817
Marc Slemkodb14e172006-08-09 23:36:18 +0000818 valueReaderCall= toReaderCall("elem", ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000819
Marc Slemko5b126d62006-08-11 23:03:42 +0000820 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000821 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
822 keyType=typeToCTypeDeclaration(ttype.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000823 keyReaderCall=keyReaderCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000824 valueType=typeToCTypeDeclaration(ttype.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000825 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000826
827 else:
Marc Slemko5b126d62006-08-11 23:03:42 +0000828 if isinstance(ttype, ListType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000829 insert="push_back"
830 else:
831 insert="insert"
832
Marc Slemkob2039e72006-08-09 01:00:17 +0000833 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
Marc Slemkodb14e172006-08-09 23:36:18 +0000834 valueReaderCall=valueReaderCall,
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000835 valueType=typeToCTypeDeclaration(ttype.valueType),
836 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000837
838
839def toCollectionWriterDefinition(ttype):
840
841 suffix = typeToIOMethodSuffix(ttype)
842
Marc Slemko5b126d62006-08-11 23:03:42 +0000843 if isinstance(ttype, MapType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000844 keyWriterCall = toWriterCall("ix->first", ttype.keyType)
845 valueWriterCall = toWriterCall("ix->second", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000846
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000847 else:
848 valueWriterCall= toWriterCall("*ix", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000849
Marc Slemko5b126d62006-08-11 23:03:42 +0000850 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000851 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
852 keyType=typeToCTypeDeclaration(ttype.keyType),
853 keyWriterCall=keyWriterCall,
854 valueType=typeToCTypeDeclaration(ttype.valueType),
855 valueWriterCall=valueWriterCall)
856
857 else:
858 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
859 valueWriterCall=valueWriterCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000860 valueType=typeToCTypeDeclaration(ttype.valueType))
861
862
863CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000864uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000865
866 std::string name;
867 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000868 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000869 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000870
Marc Slemko5b126d62006-08-11 23:03:42 +0000871 xfer+= iprot->readStructBegin(itrans, name);
872
Marc Slemkob2039e72006-08-09 01:00:17 +0000873 while(true) {
874
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000875 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000876
877 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
878
879 switch(id) {
880${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +0000881 default: xfer += iprot->skip(itrans, type); break;
882 }
Marc Slemkob2039e72006-08-09 01:00:17 +0000883
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000884 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000885 }
Marc Slemko5b126d62006-08-11 23:03:42 +0000886
887 xfer+= iprot->readStructEnd(itrans);
888
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000889 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000890}
891""")
892
Marc Slemkodb14e172006-08-09 23:36:18 +0000893CPP_WRITE_FIELD_DEFINITION = Template("""
894 oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id});
895 ${fieldWriterCall};
896 oprot->writeFieldEnd(otrans);
897""")
898
899CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000900uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000901
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000902 uint32_t xfer = 0;
903
904 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +0000905${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000906 xfer+= oprot->writeFieldStop(otrans);
907 xfer += oprot->writeStructEnd(otrans);
908 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000909}
910""")
911
912def toStructReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000913
914 suffix = typeToIOMethodSuffix(ttype)
915
916 # Sort field list in order of increasing ids
917
918 fieldList = []
919 fieldList+= ttype.fieldList
920
921 fieldList.sort(lambda a,b: a.id - b.id)
922
923 fieldSwitch=""
924
925 for field in fieldList:
926 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +0000927 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000928
929 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +0000930
931def toStructWriterDefinition(ttype):
932
933 suffix = typeToIOMethodSuffix(ttype)
934
935 writeCalls = ""
936
937 for field in ttype.fieldList:
938
939 writeCalls+= CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name, type=toWireType(field.type), id=field.id,
940 fieldWriterCall=toWriterCall("value."+field.name, field.type))
941
942 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=ttype.name, suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldWriterCalls=writeCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +0000943
Marc Slemkodb14e172006-08-09 23:36:18 +0000944def toReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000945 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000946 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +0000947
Marc Slemko5b126d62006-08-11 23:03:42 +0000948 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000949 return toStructReaderDefinition(ttype)
950
Marc Slemko5b126d62006-08-11 23:03:42 +0000951 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000952 return ""
953
Marc Slemko5b126d62006-08-11 23:03:42 +0000954 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000955 return ""
956
957 else:
958 raise Exception, "Unsupported type: "+str(ttype)
959
Marc Slemkodb14e172006-08-09 23:36:18 +0000960def toWriterDefinition(ttype):
961 if isinstance(ttype, CollectionType):
962 return toCollectionWriterDefinition(ttype)
963
Marc Slemko5b126d62006-08-11 23:03:42 +0000964 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000965 return toStructWriterDefinition(ttype)
966
Marc Slemko5b126d62006-08-11 23:03:42 +0000967 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000968 return ""
969
Marc Slemko5b126d62006-08-11 23:03:42 +0000970 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000971 return ""
972
973 else:
974 raise Exception, "Unsupported type: "+str(ttype)
975
Marc Slemkodb14e172006-08-09 23:36:18 +0000976def toOrderedIOList(ttype, result=None):
977 if not result:
978 result = []
979
980 if ttype in result:
981 return result
982
983 elif isinstance(ttype, PrimitiveType):
984 return result
985
986 elif isinstance(ttype, CollectionType):
987
Marc Slemko5b126d62006-08-11 23:03:42 +0000988 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000989 result = toOrderedIOList(ttype.keyType, result)
990
991 result = toOrderedIOList(ttype.valueType, result)
992
993 result.append(ttype)
994
Marc Slemko5b126d62006-08-11 23:03:42 +0000995 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000996 for field in ttype.fieldList:
997 result = toOrderedIOList(field.type, result)
998 result.append(ttype)
999
Marc Slemko5b126d62006-08-11 23:03:42 +00001000 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001001 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001002 return result
1003
Marc Slemko5b126d62006-08-11 23:03:42 +00001004 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001005 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001006 return result
1007
1008 elif isinstance(ttype, Program):
1009
1010 for struct in ttype.structMap.values():
1011 result = toOrderedIOList(struct, result)
1012
1013 for service in ttype.serviceMap.values():
1014 result = toOrderedIOList(service, result)
1015
1016 elif isinstance(ttype, Service):
1017 for function in ttype.functionList:
1018 result = toOrderedIOList(function, result)
1019
1020 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001021 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001022
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001023 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001024 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001025 # inline those struct definitions with the implementation, not in the types header
1026
Marc Slemko5b126d62006-08-11 23:03:42 +00001027 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001028 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001029
1030 else:
1031 raise Exception, "Unsupported thrift type: "+str(ttype)
1032
1033 return result
1034
1035def toIOMethodImplementations(program):
1036
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001037 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001038
1039 iolist = toOrderedIOList(program)
1040
1041 result = ""
1042
1043 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001044 result+= toReaderDefinition(ttype)
1045 result+= toWriterDefinition(ttype)
1046
Marc Slemko5b126d62006-08-11 23:03:42 +00001047 # For all function argument lists, we need to create both struct definitions
1048 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1049 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001050 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1051 # we've already seen
1052
1053 for service in program.serviceMap.values():
1054 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001055 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001056 result+= toReaderDefinition(function.argsStruct)
1057 result+= toWriterDefinition(function.argsStruct)
1058 result+= toStructDefinition(function.resultStruct)
1059 result+= toReaderDefinition(function.resultStruct)
1060 result+= toWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001061
Marc Slemkodb14e172006-08-09 23:36:18 +00001062 return result;
1063
1064def toImplementationSourceName(filename, genDir=None, debugp=None):
1065
1066 if not genDir:
1067 genDir = toGenDir(filename)
1068
1069 basename = toBasename(filename)
1070
1071 result = os.path.join(genDir, basename+".cc")
1072
1073 if debugp:
1074 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1075
1076 return result
1077
1078def writeImplementationSource(program, filename, genDir=None, debugp=None):
1079
1080 implementationSource = toImplementationSourceName(filename, genDir)
1081
1082 if debugp:
1083 debugp("implementationSource: "+str(implementationSource))
1084
1085 cfile = CFile(implementationSource, "w")
1086
1087 basename = toBasename(filename)
1088
1089 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
1090
1091 cfile.write(toIOMethodImplementations(program))
1092
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001093 cfile.write(toServerDefinition(program))
1094
Marc Slemko5b126d62006-08-11 23:03:42 +00001095 cfile.write(toClientDefinition(program))
1096
Marc Slemkodb14e172006-08-09 23:36:18 +00001097 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
1098
1099 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001100
1101class CPPGenerator(Generator):
1102
1103 def __call__(self, program, filename, genDir=None, debugp=None):
1104
Marc Slemkodb14e172006-08-09 23:36:18 +00001105 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001106
Marc Slemkodb14e172006-08-09 23:36:18 +00001107 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001108
Marc Slemkodb14e172006-08-09 23:36:18 +00001109 writeImplementationSource(program, filename, genDir, debugp)