blob: 92636c5a96607e9a40b55a6eb0b0b5d3dbda68df [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 Slemko66d67d82006-08-11 23:33:08 +0000259CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000260""")
261
262CPP_SERVER_FUNCTION_DEFINITION = Template("""
Marc Slemko66d67d82006-08-11 23:33:08 +0000263void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000264
265 uint32_t xfer = 0;
266
Marc Slemko5b126d62006-08-11 23:03:42 +0000267 ${argsStructDeclaration};
268
269 ${argsStructReader};
270
Marc Slemko66d67d82006-08-11 23:33:08 +0000271 iprot->readMessageEnd(itrans);
272
Marc Slemko5b126d62006-08-11 23:03:42 +0000273 ${returnValueDeclaration};
274
275 ${functionCall};
276
277 ${resultStructDeclaration};
278
279 ${returnToResult};
280
Marc Slemko66d67d82006-08-11 23:33:08 +0000281 oprot->writeMessageBegin(otrans, """+CPP_PROTOCOL_REPLY+""", seqid);
282
Marc Slemko5b126d62006-08-11 23:03:42 +0000283 ${resultStructWriter};
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000284
Marc Slemko66d67d82006-08-11 23:33:08 +0000285 oprot->writeMessaeEnd(otrans);
286
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000287 otrans->flush();
288}
Marc Slemkob2039e72006-08-09 01:00:17 +0000289""")
290
Marc Slemko66d67d82006-08-11 23:33:08 +0000291CPP_SERVER_PROCESS_DEFINITION = Template("""
292bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
293
294 uint32_t xfer = 0;
295
296 std::string name;
297
298 """+CPP_MESSAGE_TYPE+""" messageType;
299
300 uint32_t seqid;
301
302 _iprot->readMessageBegin(_itrans, name, messageType, cseqid);
303
304 if(messageType == """+CPP_PROTOCOL_CALL+""") {
305${callProcessSwitch}
306 } else {
307 throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
308 }
309}
310""")
311
Marc Slemkob2039e72006-08-09 01:00:17 +0000312CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
313CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000314CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
315CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
316CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000317
Marc Slemkodb14e172006-08-09 23:36:18 +0000318CPP_TTYPE_MAP = {
319 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
320 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
321 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
322 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
323 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
324 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
325 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
326 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
327 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
328 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
329 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
330 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
331 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
332 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
333 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
334 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
335 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000336 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
337 ListType : CPP_PROTOCOL_NS+"::T_LIST",
338 MapType : CPP_PROTOCOL_NS+"::T_MAP",
339 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000340}
341
342def toWireType(ttype):
343
344 if isinstance(ttype, PrimitiveType):
345 return CPP_TTYPE_MAP[ttype]
346
Marc Slemko5b126d62006-08-11 23:03:42 +0000347 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000348 return CPP_TTYPE_MAP[I32_TYPE]
349
Marc Slemko5b126d62006-08-11 23:03:42 +0000350 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000351 return toWireType(toCanonicalType(ttype))
352
Marc Slemko5b126d62006-08-11 23:03:42 +0000353 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000354 return CPP_TTYPE_MAP[type(ttype)]
355
356 else:
357 raise Exception, "No wire type for thrift type: "+str(ttype)
358
Marc Slemkob2039e72006-08-09 01:00:17 +0000359CPP_SERVER_DECLARATION = Template("""
360class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
361 public:
362 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
363 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
364 virtual ~${service}ServerIf() {}
365 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
366 protected:
367 """+CPP_PROTOCOLP+""" _iprot;
368 """+CPP_PROTOCOLP+""" _oprot;
369 private:
370${functionDeclarations}};
371""")
372
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000373def toServerDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000374
375 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
376
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000377 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000378
379CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
380""")
381
Marc Slemko5b126d62006-08-11 23:03:42 +0000382
383CPP_CLIENT_FUNCTION_DEFINITION = Template("""
384${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) {
385
386 uint32_t xfer = 0;
387 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
388 uint32_t cseqid = 0;
389 uint32_t rseqid = 0;
390
391 _oprot->writeMessageBegin(_otrans, """+CPP_PROTOCOL_CALL+""", cseqid);
392
393 ${argsStructDeclaration};
394
395${argsToStruct};
396
397 ${argsStructWriter};
398
399 _otrans->flush();
400
401 _iprot->readMessageBegin(_itrans, messageType, rseqid);
402
403 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
404 rseqid != cseqid) {
405 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
406 }
407
408 ${resultStructDeclaration};
409
410 ${resultStructReader};
411
412 _iprot->readMessageEnd(_itrans);
413
414 if(__result.__isset.success) {
415 ${success};
416 } else {
417 throw """+CPP_EXCEPTION+"""(\"${function} failed\");
418 }
419}
420""")
421
Marc Slemkob2039e72006-08-09 01:00:17 +0000422CPP_CLIENT_DECLARATION = Template("""
423class ${service}Client : public ${service}If {
424
425 public:
426
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000427 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000428
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000429 ${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 +0000430
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000431${functionDeclarations}
432 private:
433 """+CPP_TRANSPORTP+""" _itrans;
434 """+CPP_TRANSPORTP+""" _otrans;
435 """+CPP_PROTOCOLP+""" _iprot;
436 """+CPP_PROTOCOLP+""" _oprot;
437};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000438
Marc Slemko5b126d62006-08-11 23:03:42 +0000439def toServerFunctionDefinition(servicePrefix, function, debugp=None):
440 result = ""
441
442 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
443
444 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
445
446 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
447
448 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
449
450 if function.returnType() != VOID_TYPE:
451 returnValueDeclaration = typeToCTypeDeclaration(toCanonicalType(function.returnType()))+" __returnValue"
452 functionCall = "__returnValue = "
453 returnToResult = "__result.success = __returnValue"
454 else:
455 returnValueDeclaration = ""
456 functionCall = ""
457 returnToResult = ""
458
459 functionCall+= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+")"
460
461 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
462 argsStructDeclaration=argsStructDeclaration,
463 argsStructReader=argsStructReader,
464 functionCall=functionCall,
465 returnToResult=returnToResult,
466 resultStructDeclaration=resultStructDeclaration,
467 resultStructWriter=resultStructWriter,
468 returnValueDeclaration=returnValueDeclaration)
469
470
471
472 return result
473
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000474def toServerServiceDefinition(service, debugp=None):
475
476 result = ""
477
478 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000479
480 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000481
Marc Slemko66d67d82006-08-11 23:33:08 +0000482
483 callProcessSwitch = "if"+string.join(["(name.compare(\""+function.name+"\") == 0) {"+toServerProcessFunctionCall(function)+";}" for function in service.functionList], "\n else if")
484
485 result+= CPP_SERVER_PROCESS_DEFINITION(service=service.name, callProcessSwitch=callProcessSwitch)
486
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000487 return result
488
489def toServerDefinition(program, debugp=None):
490
491 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
492
493def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000494
495 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
496
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000497 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000498
Marc Slemko5b126d62006-08-11 23:03:42 +0000499def toClientFunctionDefinition(servicePrefix, function, debugp=None):
500
501 returnDeclaration = typeToCTypeDeclaration(function.returnType())
502
503 argsDeclaration = string.join([typeToCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
504
505 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
506
507 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
508
509 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
510
511 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
512
513 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
514
515 if(toCanonicalType(function.returnType()) != VOID_TYPE):
516
517 success = "return __result.success;"
518 else:
519 success = ""
520
521 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
522 function=function.name,
523 returnDeclaration=returnDeclaration,
524 argsDeclaration=argsDeclaration,
525 argsStructDeclaration=argsStructDeclaration,
526 argsStructWriter=argsStructWriter,
527 argsToStruct=argsToStruct,
528 resultStructDeclaration=resultStructDeclaration,
529 resultStructReader=resultStructReader,
530 success=success)
531
532def toClientServiceDefinition(service, debugp=None):
533
534 result = ""
535
536 for function in service.functionList:
537
538 result+= toClientFunctionDefinition(service.name, function)
539
540 return result
541
542def toClientDefinition(program, debugp=None):
543
544 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
545
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000546def toServiceDeclaration(service, debugp=None):
547 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000548
549def toGenDir(filename, suffix="cpp-gen", debugp=None):
550
551 result = os.path.join(os.path.split(filename)[0], suffix)
552
553 if not os.path.exists(result):
554 os.mkdir(result)
555
556 return result
557
558def toBasename(filename, debugp=None):
559 """ Take the filename minus the path and\".thrift\" extension if present """
560
561 basename = os.path.split(filename)[1]
562
563 tokens = os.path.splitext(basename)
564
565 if tokens[1].lower() == ".thrift":
566 basename = tokens[0]
567
568 if debugp:
569 debugp("toBasename("+str(filename)+") => "+str(basename))
570
571 return basename
572
573def toDefinitionHeaderName(filename, genDir=None, debugp=None):
574
575 if not genDir:
576 genDir = toGenDir(filename)
577
578 basename = toBasename(filename)
579
580 result = os.path.join(genDir, basename+"_types.h")
581
582 if debugp:
583 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
584
585 return result
586
587def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
588
589 definitionHeader = toDefinitionHeaderName(filename, genDir)
590
591 if debugp:
592 debugp("definitionHeader: "+str(definitionHeader))
593
594 cfile = CFile(definitionHeader, "w")
595
596 basename = toBasename(filename)
597
598 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
599
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000600 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000601
602 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
603
604 cfile.close()
605
606def toServicesHeaderName(filename, genDir=None, debugp=None):
607
608 if not genDir:
609 genDir = toGenDir(filename)
610
611 basename = toBasename(filename)
612
613 result = os.path.join(genDir, basename+".h")
614
615 if debugp:
616 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
617
618 return result
619
620
621def writeServicesHeader(program, filename, genDir=None, debugp=None):
622
623 servicesHeader = toServicesHeaderName(filename, genDir)
624
625 if debugp:
626 debugp("servicesHeader: "+str(servicesHeader))
627
628 cfile = CFile(servicesHeader, "w")
629
630 basename = toBasename(filename)
631
632 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
633
634 services = []
635
636 # Build orderered list of service definitions by scanning definitions list for services
637
638 for definition in program.definitions:
639 if isinstance(definition, Service) and definition.name in program.serviceMap:
640 services.append(definition)
641
642 for service in services:
643
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000644 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000645
646 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
647
648 cfile.close()
649
650
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000651CPP_STRUCT_READ = Template("""
652uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
653
Marc Slemkob2039e72006-08-09 01:00:17 +0000654 std::string name;
655 uint32_t id;
656 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000657 uint32_t xfer = 0;
658
Marc Slemkob2039e72006-08-09 01:00:17 +0000659 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000660 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000661 if(type == """+CPP_PROTOCOL_TSTOP+""") {
662 break;
663 }
664 switch(id) {
665${readFieldListSwitch}
666 }
667 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000668
669 xfer+= _iprot->readStructEnd(_itrans);
670
671 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000672}
673""")
674
675CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000676 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000677 "bool" : "Bool",
678 "string": "String",
679 "utf7": "String",
680 "utf8": "String",
681 "utf16": "String",
682 "i08": "Byte",
683 "i16": "I16",
684 "i32": "I32",
685 "i64": "I64",
686 "u08": "Byte",
687 "u16": "U16",
688 "u32": "U32",
689 "u64": "U64",
690 "float": "Double"
691}
692
693CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000694 MapType : "map",
695 ListType : "list",
696 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000697}
698
699def typeToIOMethodSuffix(ttype):
700
701 if isinstance(ttype, PrimitiveType):
702 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
703
704 elif isinstance(ttype, CollectionType):
705
706 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
707
Marc Slemko5b126d62006-08-11 23:03:42 +0000708 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000709 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
710
711 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
712
713 return result
714
Marc Slemko5b126d62006-08-11 23:03:42 +0000715 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000716 return "struct_"+ttype.name
717
Marc Slemko5b126d62006-08-11 23:03:42 +0000718 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000719 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000720
Marc Slemko5b126d62006-08-11 23:03:42 +0000721 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000722 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000723
724 else:
725 raise Exception, "Unknown type "+str(ttype)
726
Marc Slemko5b126d62006-08-11 23:03:42 +0000727def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkob2039e72006-08-09 01:00:17 +0000728
729 suffix = typeToIOMethodSuffix(ttype)
730
731 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000732 if ttype != VOID_TYPE:
733 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
734 else:
735 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000736
737 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000738 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000739
Marc Slemko5b126d62006-08-11 23:03:42 +0000740 elif isinstance(ttype, StructType):
741 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000742
Marc Slemko5b126d62006-08-11 23:03:42 +0000743 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000744 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000745
Marc Slemko5b126d62006-08-11 23:03:42 +0000746 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000747 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000748
749 else:
750 raise Exception, "Unknown type "+str(ttype)
751
Marc Slemko5b126d62006-08-11 23:03:42 +0000752def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkodb14e172006-08-09 23:36:18 +0000753
754 suffix = typeToIOMethodSuffix(ttype)
755
756 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000757 if ttype != VOID_TYPE:
758 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
759 else:
760 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000761
762 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000763 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000764
Marc Slemko5b126d62006-08-11 23:03:42 +0000765 elif isinstance(ttype, StructType):
766 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000767
Marc Slemko5b126d62006-08-11 23:03:42 +0000768 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000769 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000770
Marc Slemko5b126d62006-08-11 23:03:42 +0000771 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000772 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000773
774 else:
775 raise Exception, "Unknown type "+str(ttype)
776
777CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000778uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000779
780 uint32_t count;
781 ${keyType} key;
782 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000783 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000784
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000785 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000786
787 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000788 ${keyReaderCall};
789 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000790 value.insert(std::make_pair(key, elem));
791 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000792
793 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000794}
795""")
796
797CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000798uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000799
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000800 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000801
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000802 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +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 ${keyWriterCall};
806 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000807 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000808 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000809}
810""")
811
Marc Slemkob2039e72006-08-09 01:00:17 +0000812CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000813uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000814
815 uint32_t count;
816 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000817 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000818
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000819 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000820
821 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000822 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000823 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000824 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000825 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000826}
827""")
828
Marc Slemkodb14e172006-08-09 23:36:18 +0000829CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000830uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000831
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000832 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000833
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000834 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000835
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000836 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000837 ${valueWriterCall};
838 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000839 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000840}
841""")
842
843def toCollectionReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000844
845 suffix = typeToIOMethodSuffix(ttype)
846
Marc Slemko5b126d62006-08-11 23:03:42 +0000847 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000848 keyReaderCall = toReaderCall("key", ttype.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000849
Marc Slemkodb14e172006-08-09 23:36:18 +0000850 valueReaderCall= toReaderCall("elem", ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000851
Marc Slemko5b126d62006-08-11 23:03:42 +0000852 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000853 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
854 keyType=typeToCTypeDeclaration(ttype.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000855 keyReaderCall=keyReaderCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000856 valueType=typeToCTypeDeclaration(ttype.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000857 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000858
859 else:
Marc Slemko5b126d62006-08-11 23:03:42 +0000860 if isinstance(ttype, ListType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000861 insert="push_back"
862 else:
863 insert="insert"
864
Marc Slemkob2039e72006-08-09 01:00:17 +0000865 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
Marc Slemkodb14e172006-08-09 23:36:18 +0000866 valueReaderCall=valueReaderCall,
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000867 valueType=typeToCTypeDeclaration(ttype.valueType),
868 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000869
870
871def toCollectionWriterDefinition(ttype):
872
873 suffix = typeToIOMethodSuffix(ttype)
874
Marc Slemko5b126d62006-08-11 23:03:42 +0000875 if isinstance(ttype, MapType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000876 keyWriterCall = toWriterCall("ix->first", ttype.keyType)
877 valueWriterCall = toWriterCall("ix->second", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000878
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000879 else:
880 valueWriterCall= toWriterCall("*ix", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000881
Marc Slemko5b126d62006-08-11 23:03:42 +0000882 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000883 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
884 keyType=typeToCTypeDeclaration(ttype.keyType),
885 keyWriterCall=keyWriterCall,
886 valueType=typeToCTypeDeclaration(ttype.valueType),
887 valueWriterCall=valueWriterCall)
888
889 else:
890 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
891 valueWriterCall=valueWriterCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000892 valueType=typeToCTypeDeclaration(ttype.valueType))
893
894
895CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000896uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000897
898 std::string name;
899 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000900 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000901 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000902
Marc Slemko5b126d62006-08-11 23:03:42 +0000903 xfer+= iprot->readStructBegin(itrans, name);
904
Marc Slemkob2039e72006-08-09 01:00:17 +0000905 while(true) {
906
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000907 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000908
909 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
910
911 switch(id) {
912${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +0000913 default: xfer += iprot->skip(itrans, type); break;
914 }
Marc Slemkob2039e72006-08-09 01:00:17 +0000915
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000916 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000917 }
Marc Slemko5b126d62006-08-11 23:03:42 +0000918
919 xfer+= iprot->readStructEnd(itrans);
920
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000921 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000922}
923""")
924
Marc Slemkodb14e172006-08-09 23:36:18 +0000925CPP_WRITE_FIELD_DEFINITION = Template("""
926 oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id});
927 ${fieldWriterCall};
928 oprot->writeFieldEnd(otrans);
929""")
930
931CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000932uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000933
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000934 uint32_t xfer = 0;
935
936 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +0000937${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000938 xfer+= oprot->writeFieldStop(otrans);
939 xfer += oprot->writeStructEnd(otrans);
940 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000941}
942""")
943
944def toStructReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000945
946 suffix = typeToIOMethodSuffix(ttype)
947
948 # Sort field list in order of increasing ids
949
950 fieldList = []
951 fieldList+= ttype.fieldList
952
953 fieldList.sort(lambda a,b: a.id - b.id)
954
955 fieldSwitch=""
956
957 for field in fieldList:
958 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +0000959 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000960
961 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +0000962
963def toStructWriterDefinition(ttype):
964
965 suffix = typeToIOMethodSuffix(ttype)
966
967 writeCalls = ""
968
969 for field in ttype.fieldList:
970
971 writeCalls+= CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name, type=toWireType(field.type), id=field.id,
972 fieldWriterCall=toWriterCall("value."+field.name, field.type))
973
974 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=ttype.name, suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldWriterCalls=writeCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +0000975
Marc Slemkodb14e172006-08-09 23:36:18 +0000976def toReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000977 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000978 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +0000979
Marc Slemko5b126d62006-08-11 23:03:42 +0000980 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000981 return toStructReaderDefinition(ttype)
982
Marc Slemko5b126d62006-08-11 23:03:42 +0000983 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000984 return ""
985
Marc Slemko5b126d62006-08-11 23:03:42 +0000986 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000987 return ""
988
989 else:
990 raise Exception, "Unsupported type: "+str(ttype)
991
Marc Slemkodb14e172006-08-09 23:36:18 +0000992def toWriterDefinition(ttype):
993 if isinstance(ttype, CollectionType):
994 return toCollectionWriterDefinition(ttype)
995
Marc Slemko5b126d62006-08-11 23:03:42 +0000996 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000997 return toStructWriterDefinition(ttype)
998
Marc Slemko5b126d62006-08-11 23:03:42 +0000999 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001000 return ""
1001
Marc Slemko5b126d62006-08-11 23:03:42 +00001002 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001003 return ""
1004
1005 else:
1006 raise Exception, "Unsupported type: "+str(ttype)
1007
Marc Slemkodb14e172006-08-09 23:36:18 +00001008def toOrderedIOList(ttype, result=None):
1009 if not result:
1010 result = []
1011
1012 if ttype in result:
1013 return result
1014
1015 elif isinstance(ttype, PrimitiveType):
1016 return result
1017
1018 elif isinstance(ttype, CollectionType):
1019
Marc Slemko5b126d62006-08-11 23:03:42 +00001020 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001021 result = toOrderedIOList(ttype.keyType, result)
1022
1023 result = toOrderedIOList(ttype.valueType, result)
1024
1025 result.append(ttype)
1026
Marc Slemko5b126d62006-08-11 23:03:42 +00001027 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001028 for field in ttype.fieldList:
1029 result = toOrderedIOList(field.type, result)
1030 result.append(ttype)
1031
Marc Slemko5b126d62006-08-11 23:03:42 +00001032 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001033 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001034 return result
1035
Marc Slemko5b126d62006-08-11 23:03:42 +00001036 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001037 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001038 return result
1039
1040 elif isinstance(ttype, Program):
1041
1042 for struct in ttype.structMap.values():
1043 result = toOrderedIOList(struct, result)
1044
1045 for service in ttype.serviceMap.values():
1046 result = toOrderedIOList(service, result)
1047
1048 elif isinstance(ttype, Service):
1049 for function in ttype.functionList:
1050 result = toOrderedIOList(function, result)
1051
1052 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001053 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001054
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001055 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001056 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001057 # inline those struct definitions with the implementation, not in the types header
1058
Marc Slemko5b126d62006-08-11 23:03:42 +00001059 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001060 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001061
1062 else:
1063 raise Exception, "Unsupported thrift type: "+str(ttype)
1064
1065 return result
1066
1067def toIOMethodImplementations(program):
1068
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001069 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001070
1071 iolist = toOrderedIOList(program)
1072
1073 result = ""
1074
1075 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001076 result+= toReaderDefinition(ttype)
1077 result+= toWriterDefinition(ttype)
1078
Marc Slemko5b126d62006-08-11 23:03:42 +00001079 # For all function argument lists, we need to create both struct definitions
1080 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1081 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001082 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1083 # we've already seen
1084
1085 for service in program.serviceMap.values():
1086 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001087 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001088 result+= toReaderDefinition(function.argsStruct)
1089 result+= toWriterDefinition(function.argsStruct)
1090 result+= toStructDefinition(function.resultStruct)
1091 result+= toReaderDefinition(function.resultStruct)
1092 result+= toWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001093
Marc Slemkodb14e172006-08-09 23:36:18 +00001094 return result;
1095
1096def toImplementationSourceName(filename, genDir=None, debugp=None):
1097
1098 if not genDir:
1099 genDir = toGenDir(filename)
1100
1101 basename = toBasename(filename)
1102
1103 result = os.path.join(genDir, basename+".cc")
1104
1105 if debugp:
1106 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1107
1108 return result
1109
1110def writeImplementationSource(program, filename, genDir=None, debugp=None):
1111
1112 implementationSource = toImplementationSourceName(filename, genDir)
1113
1114 if debugp:
1115 debugp("implementationSource: "+str(implementationSource))
1116
1117 cfile = CFile(implementationSource, "w")
1118
1119 basename = toBasename(filename)
1120
1121 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
1122
1123 cfile.write(toIOMethodImplementations(program))
1124
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001125 cfile.write(toServerDefinition(program))
1126
Marc Slemko5b126d62006-08-11 23:03:42 +00001127 cfile.write(toClientDefinition(program))
1128
Marc Slemkodb14e172006-08-09 23:36:18 +00001129 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
1130
1131 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001132
1133class CPPGenerator(Generator):
1134
1135 def __call__(self, program, filename, genDir=None, debugp=None):
1136
Marc Slemkodb14e172006-08-09 23:36:18 +00001137 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001138
Marc Slemkodb14e172006-08-09 23:36:18 +00001139 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001140
Marc Slemkodb14e172006-08-09 23:36:18 +00001141 writeImplementationSource(program, filename, genDir, debugp)