blob: 834877ef8c19c97fb74b529c30712f27ae3aa793 [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 = {
120 Map : "std::map",
121 List: "std::list",
122 Set : "std::set",
123}
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
134 if isinstance(ttype, Map):
135 result+= typeToCTypeDeclaration(ttype.keyType)+", "+ typeToCTypeDeclaration(ttype.valueType)
136
137 elif isinstance(ttype, Set) or isinstance(ttype, List):
138 result+= typeToCTypeDeclaration(ttype.valueType)
139
140 else:
141 raise Exception, "Unknown Collection Type "+str(ttype)
142
143 result+= "> "
144
145 return result
146
147 elif isinstance(ttype, Struct):
148 return "struct "+ttype.name
149
150 elif isinstance(ttype, TypeDef):
151 return ttype.name;
152
153 elif isinstance(ttype, Enum):
154 return ttype.name;
155
156 elif isinstance(ttype, Function):
157 return typeToCTypeDeclaration(ttype.resultType)+ " "+ttype.name+"("+string.join([typeToCTypeDeclaration(arg) for arg in ttype.argFieldList], ", ")+")"
158
159 elif isinstance(ttype, Field):
160 return typeToCTypeDeclaration(ttype.type)+ " "+ttype.name
161
162 else:
163 raise Exception, "Unknown type "+str(ttype)
164
165def writeTypeDefDefinition(cfile, typedef):
166
167 cfile.writeln("typedef "+typeToCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";")
168
169def writeEnumDefinition(cfile, enum):
170
171 cfile.write("enum "+enum.name+" ");
172
173 cfile.beginBlock();
174
175 first = True
176
177 for ed in enum.enumDefs:
178 if first:
179 first = False
180 else:
181 cfile.writeln(",")
182 cfile.write(ed.name+" = "+str(ed.id))
183
184 cfile.writeln()
185 cfile.endBlock(";");
186
187def writeStructDefinition(cfile, struct):
188
189 cfile.write("struct "+struct.name+" ");
190
191 cfile.beginBlock()
192
193 for field in struct.fieldList:
194 cfile.writeln(typeToCTypeDeclaration(field)+";")
195
196 cfile.endBlock(";")
197
198
199CPP_DEFINITION_WRITER_MAP = {
200 TypeDef : writeTypeDefDefinition,
201 Enum : writeEnumDefinition,
202 Struct : writeStructDefinition,
203 Service : None
204 }
205
206def writeDefinitions(cfile, definitions):
207 for definition in definitions:
208
209 writer = CPP_DEFINITION_WRITER_MAP[type(definition)]
210
211 if writer:
212 writer(cfile, definition)
213
214 cfile.writeln()
215
216CPP_THRIFT_NS = "facebook::thrift"
217
218CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
219""")
220
221CPP_INTERFACE_DECLARATION = Template("""
222class ${service}If {
223 public:
224 ~${service}If() {}
225${functionDeclarations}};
226""")
227
228def writeServiceInterfaceDeclaration(cfile, service, debugp=None):
229
230 functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
231
232 cfile.write(CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations))
233
234CPP_SP = Template("boost::shared_ptr<${klass}> ")
235
236CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
237CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
238
239CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000240CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
241CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
Marc Slemkob2039e72006-08-09 01:00:17 +0000242
243
244CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
245CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
246CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
247
248CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}("""+CPP_TRANSPORTP+""" _itrans, """+CPP_TRANSPORTP+""" _otrans);
249""")
250
251CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
252CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
253
Marc Slemkodb14e172006-08-09 23:36:18 +0000254CPP_TTYPE_MAP = {
255 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
256 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
257 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
258 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
259 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
260 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
261 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
262 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
263 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
264 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
265 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
266 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
267 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
268 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
269 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
270 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
271 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
272 Struct : CPP_PROTOCOL_NS+"::T_STRUCT",
273 List : CPP_PROTOCOL_NS+"::T_LIST",
274 Map : CPP_PROTOCOL_NS+"::T_MAP",
275 Set : CPP_PROTOCOL_NS+"::T_SET"
276}
277
278def toWireType(ttype):
279
280 if isinstance(ttype, PrimitiveType):
281 return CPP_TTYPE_MAP[ttype]
282
283 elif isinstance(ttype, Struct) or isinstance(ttype, CollectionType):
284 return CPP_TTYPE_MAP[type(ttype)]
285
286 else:
287 raise Exception, "No wire type for thrift type: "+str(ttype)
288
Marc Slemkob2039e72006-08-09 01:00:17 +0000289CPP_SERVER_DECLARATION = Template("""
290class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
291 public:
292 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
293 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
294 virtual ~${service}ServerIf() {}
295 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
296 protected:
297 """+CPP_PROTOCOLP+""" _iprot;
298 """+CPP_PROTOCOLP+""" _oprot;
299 private:
300${functionDeclarations}};
301""")
302
303def writeServerDeclaration(cfile, service, debugp=None):
304
305 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
306
307 cfile.write(CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations))
308
309CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
310""")
311
312CPP_CLIENT_DECLARATION = Template("""
313class ${service}Client : public ${service}If {
314
315 public:
316
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000317 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000318
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000319 ${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 +0000320
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000321${functionDeclarations}
322 private:
323 """+CPP_TRANSPORTP+""" _itrans;
324 """+CPP_TRANSPORTP+""" _otrans;
325 """+CPP_PROTOCOLP+""" _iprot;
326 """+CPP_PROTOCOLP+""" _oprot;
327};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000328
329def writeClientDeclaration(cfile, service, debugp=None):
330
331 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
332
333 cfile.writeln(CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations))
334
335def writeServiceDeclaration(cfile, service, debugp=None):
336 writeServiceInterfaceDeclaration(cfile, service, debugp)
337 writeServerDeclaration(cfile, service, debugp)
338 writeClientDeclaration(cfile, service, debugp)
339
340def toGenDir(filename, suffix="cpp-gen", debugp=None):
341
342 result = os.path.join(os.path.split(filename)[0], suffix)
343
344 if not os.path.exists(result):
345 os.mkdir(result)
346
347 return result
348
349def toBasename(filename, debugp=None):
350 """ Take the filename minus the path and\".thrift\" extension if present """
351
352 basename = os.path.split(filename)[1]
353
354 tokens = os.path.splitext(basename)
355
356 if tokens[1].lower() == ".thrift":
357 basename = tokens[0]
358
359 if debugp:
360 debugp("toBasename("+str(filename)+") => "+str(basename))
361
362 return basename
363
364def toDefinitionHeaderName(filename, genDir=None, debugp=None):
365
366 if not genDir:
367 genDir = toGenDir(filename)
368
369 basename = toBasename(filename)
370
371 result = os.path.join(genDir, basename+"_types.h")
372
373 if debugp:
374 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
375
376 return result
377
378def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
379
380 definitionHeader = toDefinitionHeaderName(filename, genDir)
381
382 if debugp:
383 debugp("definitionHeader: "+str(definitionHeader))
384
385 cfile = CFile(definitionHeader, "w")
386
387 basename = toBasename(filename)
388
389 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
390
391 writeDefinitions(cfile, program.definitions)
392
393 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
394
395 cfile.close()
396
397def toServicesHeaderName(filename, genDir=None, debugp=None):
398
399 if not genDir:
400 genDir = toGenDir(filename)
401
402 basename = toBasename(filename)
403
404 result = os.path.join(genDir, basename+".h")
405
406 if debugp:
407 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
408
409 return result
410
411
412def writeServicesHeader(program, filename, genDir=None, debugp=None):
413
414 servicesHeader = toServicesHeaderName(filename, genDir)
415
416 if debugp:
417 debugp("servicesHeader: "+str(servicesHeader))
418
419 cfile = CFile(servicesHeader, "w")
420
421 basename = toBasename(filename)
422
423 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
424
425 services = []
426
427 # Build orderered list of service definitions by scanning definitions list for services
428
429 for definition in program.definitions:
430 if isinstance(definition, Service) and definition.name in program.serviceMap:
431 services.append(definition)
432
433 for service in services:
434
435 writeServiceDeclaration(cfile, service)
436
437 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
438
439 cfile.close()
440
441
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000442CPP_STRUCT_READ = Template("""
443uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
444
Marc Slemkob2039e72006-08-09 01:00:17 +0000445 std::string name;
446 uint32_t id;
447 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000448 uint32_t xfer = 0;
449
Marc Slemkob2039e72006-08-09 01:00:17 +0000450 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000451 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000452 if(type == """+CPP_PROTOCOL_TSTOP+""") {
453 break;
454 }
455 switch(id) {
456${readFieldListSwitch}
457 }
458 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000459
460 xfer+= _iprot->readStructEnd(_itrans);
461
462 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000463}
464""")
465
466CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
467 "bool" : "Bool",
468 "string": "String",
469 "utf7": "String",
470 "utf8": "String",
471 "utf16": "String",
472 "i08": "Byte",
473 "i16": "I16",
474 "i32": "I32",
475 "i64": "I64",
476 "u08": "Byte",
477 "u16": "U16",
478 "u32": "U32",
479 "u64": "U64",
480 "float": "Double"
481}
482
483CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemkodb14e172006-08-09 23:36:18 +0000484 Map : "map",
485 List : "list",
486 Set : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000487}
488
489def typeToIOMethodSuffix(ttype):
490
491 if isinstance(ttype, PrimitiveType):
492 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
493
494 elif isinstance(ttype, CollectionType):
495
496 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
497
498 if isinstance(ttype, Map):
499 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
500
501 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
502
503 return result
504
505 elif isinstance(ttype, Struct):
506 return "struct_"+ttype.name
507
508 elif isinstance(ttype, TypeDef):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000509 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000510
511 elif isinstance(ttype, Enum):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000512 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000513
514 else:
515 raise Exception, "Unknown type "+str(ttype)
516
Marc Slemkodb14e172006-08-09 23:36:18 +0000517def toReaderCall(value, ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000518
519 suffix = typeToIOMethodSuffix(ttype)
520
521 if isinstance(ttype, PrimitiveType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000522 return "xfer += iprot->read"+suffix+"(itrans, "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000523
524 elif isinstance(ttype, CollectionType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000525 return "xfer+= read_"+suffix+"(iprot, itrans, "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000526
527 elif isinstance(ttype, Struct):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000528 return "xfer+= read_"+suffix+"(iprot, itrans, "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000529
530 elif isinstance(ttype, TypeDef):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000531 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000532
533 elif isinstance(ttype, Enum):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000534 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE)
Marc Slemkodb14e172006-08-09 23:36:18 +0000535
536 else:
537 raise Exception, "Unknown type "+str(ttype)
538
539def toWriterCall(value, ttype):
540
541 suffix = typeToIOMethodSuffix(ttype)
542
543 if isinstance(ttype, PrimitiveType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000544 return "xfer+= oprot->write"+suffix+"(otrans, "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000545
546 elif isinstance(ttype, CollectionType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000547 return "xfer+= write_"+suffix+"(oprot, otrans, "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000548
549 elif isinstance(ttype, Struct):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000550 return "xfer+= write_"+suffix+"(oprot, otrans, "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000551
552 elif isinstance(ttype, TypeDef):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000553 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000554
555 elif isinstance(ttype, Enum):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000556 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE)
Marc Slemkob2039e72006-08-09 01:00:17 +0000557
558 else:
559 raise Exception, "Unknown type "+str(ttype)
560
561CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000562uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000563
564 uint32_t count;
565 ${keyType} key;
566 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000567 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000568
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000569 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000570
571 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000572 ${keyReaderCall};
573 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000574 value.insert(std::make_pair(key, elem));
575 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000576
577 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000578}
579""")
580
581CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000582uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000583
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000584 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000585
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000586 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000587
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000588 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000589 ${keyWriterCall};
590 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000591 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000592 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000593}
594""")
595
Marc Slemkob2039e72006-08-09 01:00:17 +0000596CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000597uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000598
599 uint32_t count;
600 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000601 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000602
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000603 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000604
605 for(int ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000606 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000607 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000608 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000609 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000610}
611""")
612
Marc Slemkodb14e172006-08-09 23:36:18 +0000613CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000614uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000615
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000616 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000617
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000618 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000619
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000620 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000621 ${valueWriterCall};
622 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000623 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000624}
625""")
626
627def toCollectionReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000628
629 suffix = typeToIOMethodSuffix(ttype)
630
631 if isinstance(ttype, Map):
Marc Slemkodb14e172006-08-09 23:36:18 +0000632 keyReaderCall = toReaderCall("key", ttype.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000633
Marc Slemkodb14e172006-08-09 23:36:18 +0000634 valueReaderCall= toReaderCall("elem", ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000635
636 if isinstance(ttype, Map):
637 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
638 keyType=typeToCTypeDeclaration(ttype.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000639 keyReaderCall=keyReaderCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000640 valueType=typeToCTypeDeclaration(ttype.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000641 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000642
643 else:
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000644 if isinstance(ttype, List):
645 insert="push_back"
646 else:
647 insert="insert"
648
Marc Slemkob2039e72006-08-09 01:00:17 +0000649 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
Marc Slemkodb14e172006-08-09 23:36:18 +0000650 valueReaderCall=valueReaderCall,
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000651 valueType=typeToCTypeDeclaration(ttype.valueType),
652 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000653
654
655def toCollectionWriterDefinition(ttype):
656
657 suffix = typeToIOMethodSuffix(ttype)
658
659 if isinstance(ttype, Map):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000660 keyWriterCall = toWriterCall("ix->first", ttype.keyType)
661 valueWriterCall = toWriterCall("ix->second", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000662
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000663 else:
664 valueWriterCall= toWriterCall("*ix", ttype.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000665
666 if isinstance(ttype, Map):
667 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
668 keyType=typeToCTypeDeclaration(ttype.keyType),
669 keyWriterCall=keyWriterCall,
670 valueType=typeToCTypeDeclaration(ttype.valueType),
671 valueWriterCall=valueWriterCall)
672
673 else:
674 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype),
675 valueWriterCall=valueWriterCall,
Marc Slemkob2039e72006-08-09 01:00:17 +0000676 valueType=typeToCTypeDeclaration(ttype.valueType))
677
678
679CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000680uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000681
682 std::string name;
683 """+CPP_PROTOCOL_TTYPE+""" type;
684 uint16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000685 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000686
687 while(true) {
688
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000689 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000690
691 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
692
693 switch(id) {
694${fieldSwitch}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000695 default: xfer += iprot->skip(itrans, type); break;}
Marc Slemkob2039e72006-08-09 01:00:17 +0000696
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000697 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000698 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000699 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000700}
701""")
702
Marc Slemkodb14e172006-08-09 23:36:18 +0000703CPP_WRITE_FIELD_DEFINITION = Template("""
704 oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id});
705 ${fieldWriterCall};
706 oprot->writeFieldEnd(otrans);
707""")
708
709CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000710uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000711
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000712 uint32_t xfer = 0;
713
714 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +0000715${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000716 xfer+= oprot->writeFieldStop(otrans);
717 xfer += oprot->writeStructEnd(otrans);
718 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000719}
720""")
721
722def toStructReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000723
724 suffix = typeToIOMethodSuffix(ttype)
725
726 # Sort field list in order of increasing ids
727
728 fieldList = []
729 fieldList+= ttype.fieldList
730
731 fieldList.sort(lambda a,b: a.id - b.id)
732
733 fieldSwitch=""
734
735 for field in fieldList:
736 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemkodb14e172006-08-09 23:36:18 +0000737 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000738
739 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +0000740
741def toStructWriterDefinition(ttype):
742
743 suffix = typeToIOMethodSuffix(ttype)
744
745 writeCalls = ""
746
747 for field in ttype.fieldList:
748
749 writeCalls+= CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name, type=toWireType(field.type), id=field.id,
750 fieldWriterCall=toWriterCall("value."+field.name, field.type))
751
752 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=ttype.name, suffix=suffix, declaration=typeToCTypeDeclaration(ttype), fieldWriterCalls=writeCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +0000753
Marc Slemkodb14e172006-08-09 23:36:18 +0000754def toReaderDefinition(ttype):
Marc Slemkob2039e72006-08-09 01:00:17 +0000755 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000756 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +0000757
758 elif isinstance(ttype, Struct):
Marc Slemkodb14e172006-08-09 23:36:18 +0000759 return toStructReaderDefinition(ttype)
760
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000761 elif isinstance(ttype, TypeDef):
762 return ""
763
764 elif isinstance(ttype, Enum):
765 return ""
766
767 else:
768 raise Exception, "Unsupported type: "+str(ttype)
769
Marc Slemkodb14e172006-08-09 23:36:18 +0000770def toWriterDefinition(ttype):
771 if isinstance(ttype, CollectionType):
772 return toCollectionWriterDefinition(ttype)
773
774 elif isinstance(ttype, Struct):
775 return toStructWriterDefinition(ttype)
776
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000777 elif isinstance(ttype, TypeDef):
778 return ""
779
780 elif isinstance(ttype, Enum):
781 return ""
782
783 else:
784 raise Exception, "Unsupported type: "+str(ttype)
785
Marc Slemkodb14e172006-08-09 23:36:18 +0000786def toOrderedIOList(ttype, result=None):
787 if not result:
788 result = []
789
790 if ttype in result:
791 return result
792
793 elif isinstance(ttype, PrimitiveType):
794 return result
795
796 elif isinstance(ttype, CollectionType):
797
798 if isinstance(ttype, Map):
799 result = toOrderedIOList(ttype.keyType, result)
800
801 result = toOrderedIOList(ttype.valueType, result)
802
803 result.append(ttype)
804
805 elif isinstance(ttype, Struct):
806 for field in ttype.fieldList:
807 result = toOrderedIOList(field.type, result)
808 result.append(ttype)
809
810 elif isinstance(ttype, TypeDef):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000811 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +0000812 return result
813
814 elif isinstance(ttype, Enum):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000815 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +0000816 return result
817
818 elif isinstance(ttype, Program):
819
820 for struct in ttype.structMap.values():
821 result = toOrderedIOList(struct, result)
822
823 for service in ttype.serviceMap.values():
824 result = toOrderedIOList(service, result)
825
826 elif isinstance(ttype, Service):
827 for function in ttype.functionList:
828 result = toOrderedIOList(function, result)
829
830 elif isinstance(ttype, Function):
831 result = toOrderedIOList(ttype.resultType, result)
832
833 for arg in ttype.argFieldList:
834 result = toOrderedIOList(arg.type, result)
835
836 else:
837 raise Exception, "Unsupported thrift type: "+str(ttype)
838
839 return result
840
841def toIOMethodImplementations(program):
842
843 # get orderede list of all types that need marshallers:
844
845 iolist = toOrderedIOList(program)
846
847 result = ""
848
849 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +0000850 result+= toReaderDefinition(ttype)
851 result+= toWriterDefinition(ttype)
852
853 return result;
854
855def toImplementationSourceName(filename, genDir=None, debugp=None):
856
857 if not genDir:
858 genDir = toGenDir(filename)
859
860 basename = toBasename(filename)
861
862 result = os.path.join(genDir, basename+".cc")
863
864 if debugp:
865 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
866
867 return result
868
869def writeImplementationSource(program, filename, genDir=None, debugp=None):
870
871 implementationSource = toImplementationSourceName(filename, genDir)
872
873 if debugp:
874 debugp("implementationSource: "+str(implementationSource))
875
876 cfile = CFile(implementationSource, "w")
877
878 basename = toBasename(filename)
879
880 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
881
882 cfile.write(toIOMethodImplementations(program))
883
884 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
885
886 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +0000887
888class CPPGenerator(Generator):
889
890 def __call__(self, program, filename, genDir=None, debugp=None):
891
Marc Slemkodb14e172006-08-09 23:36:18 +0000892 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000893
Marc Slemkodb14e172006-08-09 23:36:18 +0000894 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000895
Marc Slemkodb14e172006-08-09 23:36:18 +0000896 writeImplementationSource(program, filename, genDir, debugp)