blob: d518230803b064317c56d4c1384b7adc33019f09 [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",
Marc Slemkod8b10512006-08-14 23:30:37 +0000116 "float": "float",
117 "double": "double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000118}
119
120CPP_CONTAINER_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000121 MapType : "std::map",
122 ListType: "std::list",
123 SetType : "std::set",
Marc Slemkob2039e72006-08-09 01:00:17 +0000124}
125
126def typeToCTypeDeclaration(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000127 """ Converts the thrift IDL type to the corresponding C/C++ type. Note that if ttype is FieldType, this function c
128converts to type declaration followed by field name, i.e. \"string string_thing\""""
Marc Slemkob2039e72006-08-09 01:00:17 +0000129
130 if isinstance(ttype, PrimitiveType):
131 return CPP_PRIMITIVE_MAP[ttype.name]
132
133 elif isinstance(ttype, CollectionType):
134
135 result = CPP_CONTAINER_MAP[type(ttype)]+"<"
136
Marc Slemko5b126d62006-08-11 23:03:42 +0000137 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000138 result+= typeToCTypeDeclaration(ttype.keyType)+", "+ typeToCTypeDeclaration(ttype.valueType)
139
Marc Slemko5b126d62006-08-11 23:03:42 +0000140 elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000141 result+= typeToCTypeDeclaration(ttype.valueType)
142
143 else:
144 raise Exception, "Unknown Collection Type "+str(ttype)
145
146 result+= "> "
147
148 return result
149
Marc Slemko5b126d62006-08-11 23:03:42 +0000150 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000151 return "struct "+ttype.name
152
Marc Slemko5b126d62006-08-11 23:03:42 +0000153 elif isinstance(ttype, TypedefType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000154 return ttype.name;
155
Marc Slemko5b126d62006-08-11 23:03:42 +0000156 elif isinstance(ttype, EnumType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000157 return ttype.name;
158
159 elif isinstance(ttype, Function):
Marc Slemkod8b10512006-08-14 23:30:37 +0000160 result = typeToCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([typeToCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
161 if len(ttype.exceptions()):
162 result+= " throw("+string.join([typeToCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
163 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000164
165 elif isinstance(ttype, Field):
166 return typeToCTypeDeclaration(ttype.type)+ " "+ttype.name
167
168 else:
169 raise Exception, "Unknown type "+str(ttype)
170
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000171def toTypeDefDefinition(typedef):
Marc Slemkod8b10512006-08-14 23:30:37 +0000172 """ Converts a thrift typedef to a C/C++ typedef """
Marc Slemkob2039e72006-08-09 01:00:17 +0000173
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000174 return "typedef "+typeToCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
Marc Slemkob2039e72006-08-09 01:00:17 +0000175
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000176def toEnumDefinition(enum):
Marc Slemkod8b10512006-08-14 23:30:37 +0000177 """ Converts a thrift enum to a C/C++ enum """
Marc Slemkob2039e72006-08-09 01:00:17 +0000178
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000179 result = "enum "+enum.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000180
181 first = True
182
183 for ed in enum.enumDefs:
184 if first:
185 first = False
186 else:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000187 result+= ",\n"
188 result+= " "+ed.name+" = "+str(ed.id)
Marc Slemkob2039e72006-08-09 01:00:17 +0000189
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000190 result+= "\n};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000191
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000192 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000193
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000194def toStructDefinition(struct):
Marc Slemkod8b10512006-08-14 23:30:37 +0000195 """Converts a thrift struct to a C/C++ struct"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000196
197 result = "struct "+struct.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000198
199 for field in struct.fieldList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000200 if toCanonicalType(field.type) != VOID_TYPE:
201 result += " "+typeToCTypeDeclaration(field)+";\n"
202
203 result+= " struct {\n"
204
205 for field in struct.fieldList:
206 result+= " bool "+field.name+";\n"
207 result+= " } __isset;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000208
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000209 result+= "};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000210
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000211 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000212
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000213CPP_DEFINITION_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000214 TypedefType : toTypeDefDefinition,
215 EnumType : toEnumDefinition,
216 StructType : toStructDefinition,
Marc Slemkod8b10512006-08-14 23:30:37 +0000217 ExceptionType : toStructDefinition,
Marc Slemkob2039e72006-08-09 01:00:17 +0000218 Service : None
219 }
220
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000221def toDefinitions(definitions):
Marc Slemkod8b10512006-08-14 23:30:37 +0000222 """Converts an arbitrafy thrift grammatical unit definition to the corresponding C/C++ definition"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000223
224 result = ""
225
Marc Slemkob2039e72006-08-09 01:00:17 +0000226 for definition in definitions:
227
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000228 writer = CPP_DEFINITION_MAP[type(definition)]
Marc Slemkob2039e72006-08-09 01:00:17 +0000229
230 if writer:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000231 result+= writer(definition)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000232
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000233 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000234
235CPP_THRIFT_NS = "facebook::thrift"
236
237CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
238""")
239
240CPP_INTERFACE_DECLARATION = Template("""
241class ${service}If {
242 public:
Marc Slemkoe6889de2006-08-12 00:32:53 +0000243 virtual ~${service}If() {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000244${functionDeclarations}};
245""")
246
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000247def toServiceInterfaceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000248 """Converts a thrift service definition into a C++ abstract base class"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000249
250 functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
251
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000252 return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000253
Marc Slemko5b126d62006-08-11 23:03:42 +0000254CPP_EXCEPTION = CPP_THRIFT_NS+"::Exception"
255
Marc Slemkob2039e72006-08-09 01:00:17 +0000256CPP_SP = Template("boost::shared_ptr<${klass}> ")
257
258CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
259CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
260
261CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000262CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
263CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
Marc Slemkob2039e72006-08-09 01:00:17 +0000264
265
266CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
267CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
268CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
269
Marc Slemkob2039e72006-08-09 01:00:17 +0000270CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
271CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000272CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
273CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
274CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000275
Marc Slemkodb14e172006-08-09 23:36:18 +0000276CPP_TTYPE_MAP = {
277 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
278 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
279 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
280 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
281 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
282 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
283 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
284 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
285 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
286 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
287 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
288 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
289 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
290 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
291 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
292 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
293 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000294 DOUBLE_TYPE : CPP_PROTOCOL_NS+"::T_DOUBLE",
Marc Slemko5b126d62006-08-11 23:03:42 +0000295 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000296 ExceptionType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000297 ListType : CPP_PROTOCOL_NS+"::T_LIST",
298 MapType : CPP_PROTOCOL_NS+"::T_MAP",
299 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000300}
301
Marc Slemko91f67482006-08-11 23:58:57 +0000302
303CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
304""")
305
306CPP_SERVER_FUNCTION_DEFINITION = Template("""
307void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
308
309 uint32_t xfer = 0;
310
311 ${argsStructDeclaration};
312
313 ${argsStructReader};
314
315 _iprot->readMessageEnd(itrans);
316
Marc Slemko91f67482006-08-11 23:58:57 +0000317 ${resultStructDeclaration};
318
Marc Slemkod8b10512006-08-14 23:30:37 +0000319 ${functionCall};
Marc Slemko91f67482006-08-11 23:58:57 +0000320
321 _oprot->writeMessageBegin(otrans, \"${function}\", """+CPP_PROTOCOL_REPLY+""", seqid);
322
323 ${resultStructWriter};
324
325 _oprot->writeMessageEnd(otrans);
326
327 otrans->flush();
328}
329""")
330
331CPP_SERVER_PROCESS_DEFINITION = Template("""
332bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
333
Marc Slemko91f67482006-08-11 23:58:57 +0000334 std::string name;
335
336 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
337
338 uint32_t seqid;
339
340 _iprot->readMessageBegin(itrans, name, messageType, seqid);
341
342 if(messageType == """+CPP_PROTOCOL_CALL+""") {
343${callProcessSwitch}
344 } else {
345 throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
346 }
Marc Slemkoe6889de2006-08-12 00:32:53 +0000347
348 return true;
Marc Slemko91f67482006-08-11 23:58:57 +0000349}
350""")
351
Marc Slemkodb14e172006-08-09 23:36:18 +0000352def toWireType(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000353 """Converts a thrift type to the corresponding wire type. This differs from typeToCTypeDeclaration in that it reduces typedefs
354to their canonical form and converts enums to signedf 32 bit integers"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000355
356 if isinstance(ttype, PrimitiveType):
357 return CPP_TTYPE_MAP[ttype]
358
Marc Slemko5b126d62006-08-11 23:03:42 +0000359 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000360 return CPP_TTYPE_MAP[I32_TYPE]
361
Marc Slemko5b126d62006-08-11 23:03:42 +0000362 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000363 return toWireType(toCanonicalType(ttype))
364
Marc Slemko5b126d62006-08-11 23:03:42 +0000365 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000366 return CPP_TTYPE_MAP[type(ttype)]
367
368 else:
369 raise Exception, "No wire type for thrift type: "+str(ttype)
370
Marc Slemkob2039e72006-08-09 01:00:17 +0000371CPP_SERVER_DECLARATION = Template("""
372class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
373 public:
374 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
375 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
376 virtual ~${service}ServerIf() {}
377 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
378 protected:
379 """+CPP_PROTOCOLP+""" _iprot;
380 """+CPP_PROTOCOLP+""" _oprot;
381 private:
382${functionDeclarations}};
383""")
384
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000385def toServerDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000386 """Converts a thrift service definition to the Server skeleton class declaration."""
Marc Slemkob2039e72006-08-09 01:00:17 +0000387
388 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
389
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000390 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000391
392CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
393""")
394
Marc Slemko5b126d62006-08-11 23:03:42 +0000395
396CPP_CLIENT_FUNCTION_DEFINITION = Template("""
Marc Slemkod8b10512006-08-14 23:30:37 +0000397${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) ${exceptionDeclaration} {
Marc Slemko5b126d62006-08-11 23:03:42 +0000398
399 uint32_t xfer = 0;
Marc Slemko91f67482006-08-11 23:58:57 +0000400 std::string name;
Marc Slemko5b126d62006-08-11 23:03:42 +0000401 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
402 uint32_t cseqid = 0;
403 uint32_t rseqid = 0;
404
Marc Slemko91f67482006-08-11 23:58:57 +0000405 _oprot->writeMessageBegin(_otrans, \"${function}\", """+CPP_PROTOCOL_CALL+""", cseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000406
407 ${argsStructDeclaration};
408
409${argsToStruct};
410
411 ${argsStructWriter};
412
413 _otrans->flush();
414
Marc Slemko91f67482006-08-11 23:58:57 +0000415 _iprot->readMessageBegin(_itrans, name, messageType, rseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000416
417 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
418 rseqid != cseqid) {
419 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
420 }
421
422 ${resultStructDeclaration};
423
424 ${resultStructReader};
425
426 _iprot->readMessageEnd(_itrans);
427
428 if(__result.__isset.success) {
Marc Slemkod8b10512006-08-14 23:30:37 +0000429 ${success}
430 } ${error} else {
431 throw """+CPP_EXCEPTION+"""(\"${function} failed: unknown result");
Marc Slemko5b126d62006-08-11 23:03:42 +0000432 }
433}
434""")
435
Marc Slemkob2039e72006-08-09 01:00:17 +0000436CPP_CLIENT_DECLARATION = Template("""
437class ${service}Client : public ${service}If {
438
439 public:
440
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000441 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000442
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000443 ${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 +0000444
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000445${functionDeclarations}
446 private:
447 """+CPP_TRANSPORTP+""" _itrans;
448 """+CPP_TRANSPORTP+""" _otrans;
449 """+CPP_PROTOCOLP+""" _iprot;
450 """+CPP_PROTOCOLP+""" _oprot;
451};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000452
Marc Slemko5b126d62006-08-11 23:03:42 +0000453def toServerFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000454 """Converts a thrift service method declaration into a server method-call processoror function"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000455 result = ""
456
457 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
458
459 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
460
461 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
462
463 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
464
Marc Slemkod8b10512006-08-14 23:30:37 +0000465
Marc Slemko5b126d62006-08-11 23:03:42 +0000466
Marc Slemkod8b10512006-08-14 23:30:37 +0000467 if function.returnType() != VOID_TYPE:
468 functionCallPrefix= "__result.success = "
469 functionCallSuffix = "__result.__isset.success = true;"
470 else:
471 functionCallPrefix = ""
472 functionCallSuffix = ""
473
474 functionCall= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+");"
475
476 exceptions = function.exceptions()
477
478 if len(exceptions) > 0:
479 functionCallPrefix= "try {"+functionCallPrefix
480
481 functionCallSuffix = functionCallSuffix+"} "+string.join(["catch("+typeToCTypeDeclaration(exceptions[ix].type)+"& e"+str(ix)+") {__result."+exceptions[ix].name+" = e"+str(ix)+"; __result.__isset."+exceptions[ix].name+" = true;}" for ix in range(len(exceptions))], "")
482
483 functionCall = functionCallPrefix+functionCall+functionCallSuffix
Marc Slemko5b126d62006-08-11 23:03:42 +0000484
485 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
486 argsStructDeclaration=argsStructDeclaration,
487 argsStructReader=argsStructReader,
488 functionCall=functionCall,
Marc Slemko5b126d62006-08-11 23:03:42 +0000489 resultStructDeclaration=resultStructDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000490 resultStructWriter=resultStructWriter)
Marc Slemko5b126d62006-08-11 23:03:42 +0000491 return result
492
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000493def toServerServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000494 """Converts a thrift service definiton to a server skeleton implementation"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000495
496 result = ""
497
498 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000499
500 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko66d67d82006-08-11 23:33:08 +0000501
Marc Slemko91f67482006-08-11 23:58:57 +0000502 callProcessSwitch = " if"+string.join(["(name.compare(\""+function.name+"\") == 0) { process_"+function.name+"(seqid, itrans, otrans);}" for function in service.functionList], "\n else if")+"\n else {throw "+CPP_EXCEPTION+"(\"Unknown function name \\\"\"+name+\"\\\"\");}"
Marc Slemko66d67d82006-08-11 23:33:08 +0000503
Marc Slemko91f67482006-08-11 23:58:57 +0000504 result+= CPP_SERVER_PROCESS_DEFINITION.substitute(service=service.name, callProcessSwitch=callProcessSwitch)
Marc Slemko66d67d82006-08-11 23:33:08 +0000505
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000506 return result
507
508def toServerDefinition(program, debugp=None):
509
510 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
511
512def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000513
514 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=typeToCTypeDeclaration(function)) for function in service.functionList], "")
515
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000516 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000517
Marc Slemko5b126d62006-08-11 23:03:42 +0000518def toClientFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000519 """Converts a thrift service method declaration to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000520
521 returnDeclaration = typeToCTypeDeclaration(function.returnType())
522
523 argsDeclaration = string.join([typeToCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
524
Marc Slemkod8b10512006-08-14 23:30:37 +0000525 exceptionDeclaration = string.join([typeToCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
526
527 if len(exceptionDeclaration)> 0:
528 exceptionDeclaration = "throw("+exceptionDeclaration+")"
529
Marc Slemko5b126d62006-08-11 23:03:42 +0000530 argsStructDeclaration = typeToCTypeDeclaration(function.argsStruct)+" __args"
531
532 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
533
534 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
535
536 resultStructDeclaration = typeToCTypeDeclaration(function.resultStruct)+" __result"
537
538 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
539
540 if(toCanonicalType(function.returnType()) != VOID_TYPE):
541
542 success = "return __result.success;"
543 else:
544 success = ""
Marc Slemkod8b10512006-08-14 23:30:37 +0000545
546 exceptions = function.exceptions()
547
548 if len(exceptions) > 0:
549 error = "else if "+string.join(["(__result.__isset."+exception.name+") { throw __result."+exception.name+";}" for exception in exceptions], "else if")
550 else:
551 error = ""
Marc Slemko5b126d62006-08-11 23:03:42 +0000552
553 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
554 function=function.name,
555 returnDeclaration=returnDeclaration,
556 argsDeclaration=argsDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000557 exceptionDeclaration=exceptionDeclaration,
Marc Slemko5b126d62006-08-11 23:03:42 +0000558 argsStructDeclaration=argsStructDeclaration,
559 argsStructWriter=argsStructWriter,
560 argsToStruct=argsToStruct,
561 resultStructDeclaration=resultStructDeclaration,
562 resultStructReader=resultStructReader,
Marc Slemkod8b10512006-08-14 23:30:37 +0000563 success=success,
564 error=error)
Marc Slemko5b126d62006-08-11 23:03:42 +0000565
566def toClientServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000567 """Converts a thrift service definition to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000568
569 result = ""
570
571 for function in service.functionList:
572
573 result+= toClientFunctionDefinition(service.name, function)
574
575 return result
576
577def toClientDefinition(program, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000578 """Converts all services in a thrift program to client stub implementations"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000579
580 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
581
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000582def toServiceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000583 """Converts all services in a thrift program to service interface or abstract base class declarations"""
584
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000585 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000586
587def toGenDir(filename, suffix="cpp-gen", debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000588 """creates a generated-code subdirectory for C++ code based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000589
590 result = os.path.join(os.path.split(filename)[0], suffix)
591
592 if not os.path.exists(result):
593 os.mkdir(result)
594
595 return result
596
597def toBasename(filename, debugp=None):
598 """ Take the filename minus the path and\".thrift\" extension if present """
599
600 basename = os.path.split(filename)[1]
601
602 tokens = os.path.splitext(basename)
603
604 if tokens[1].lower() == ".thrift":
605 basename = tokens[0]
606
607 if debugp:
608 debugp("toBasename("+str(filename)+") => "+str(basename))
609
610 return basename
611
612def toDefinitionHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000613 """Creates a file name for the public thrift data types based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000614
615 if not genDir:
616 genDir = toGenDir(filename)
617
618 basename = toBasename(filename)
619
620 result = os.path.join(genDir, basename+"_types.h")
621
622 if debugp:
623 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
624
625 return result
626
627def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000628 """Writes public thrift data types defined in program into a public data types header file. Uses the name of the original
629thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000630
631 definitionHeader = toDefinitionHeaderName(filename, genDir)
632
633 if debugp:
634 debugp("definitionHeader: "+str(definitionHeader))
635
636 cfile = CFile(definitionHeader, "w")
637
638 basename = toBasename(filename)
639
640 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime()))
641
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000642 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000643
644 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename))
645
646 cfile.close()
647
648def toServicesHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000649 """Creates a file name for the public thrift services based on filename of thrift source file and optional suffix"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000650
651 if not genDir:
652 genDir = toGenDir(filename)
653
654 basename = toBasename(filename)
655
656 result = os.path.join(genDir, basename+".h")
657
658 if debugp:
659 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
660
661 return result
662
Marc Slemkob2039e72006-08-09 01:00:17 +0000663def writeServicesHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000664 """Writes public thrift service abstract base class, client class, and server class for all services defined in program into a public services header file. Uses the name of the original thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000665
666 servicesHeader = toServicesHeaderName(filename, genDir)
667
668 if debugp:
669 debugp("servicesHeader: "+str(servicesHeader))
670
671 cfile = CFile(servicesHeader, "w")
672
673 basename = toBasename(filename)
674
675 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime()))
676
677 services = []
678
679 # Build orderered list of service definitions by scanning definitions list for services
680
681 for definition in program.definitions:
682 if isinstance(definition, Service) and definition.name in program.serviceMap:
683 services.append(definition)
684
685 for service in services:
686
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000687 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000688
689 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename))
690
691 cfile.close()
692
693
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000694CPP_STRUCT_READ = Template("""
695uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
696
Marc Slemkob2039e72006-08-09 01:00:17 +0000697 std::string name;
698 uint32_t id;
699 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000700 uint32_t xfer = 0;
701
Marc Slemkob2039e72006-08-09 01:00:17 +0000702 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000703 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000704 if(type == """+CPP_PROTOCOL_TSTOP+""") {
705 break;
706 }
707 switch(id) {
708${readFieldListSwitch}
709 }
710 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000711
712 xfer+= _iprot->readStructEnd(_itrans);
713
714 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000715}
716""")
717
718CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000719 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000720 "bool" : "Bool",
721 "string": "String",
722 "utf7": "String",
723 "utf8": "String",
724 "utf16": "String",
725 "i08": "Byte",
726 "i16": "I16",
727 "i32": "I32",
728 "i64": "I64",
729 "u08": "Byte",
730 "u16": "U16",
731 "u32": "U32",
732 "u64": "U64",
Marc Slemkod8b10512006-08-14 23:30:37 +0000733 "float": "Float",
734 "double": "Double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000735}
736
737CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000738 MapType : "map",
739 ListType : "list",
740 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000741}
742
743def typeToIOMethodSuffix(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000744 """Converts type to a name suitable as a suffix with TProtocol primitive read and write methods or with a generated read or write
745method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000746
747 if isinstance(ttype, PrimitiveType):
748 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
749
750 elif isinstance(ttype, CollectionType):
751
752 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
753
Marc Slemko5b126d62006-08-11 23:03:42 +0000754 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000755 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
756
757 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
758
759 return result
760
Marc Slemko5b126d62006-08-11 23:03:42 +0000761 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000762 return "struct_"+ttype.name
763
Marc Slemko5b126d62006-08-11 23:03:42 +0000764 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000765 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000766
Marc Slemko5b126d62006-08-11 23:03:42 +0000767 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000768 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000769
770 else:
771 raise Exception, "Unknown type "+str(ttype)
772
Marc Slemko5b126d62006-08-11 23:03:42 +0000773def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000774 """Converts type to a name suitable as a suffix with TProtocol primitive read methods or with a generated read
775method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000776
777 suffix = typeToIOMethodSuffix(ttype)
778
779 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000780 if ttype != VOID_TYPE:
781 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
782 else:
783 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000784
785 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000786 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000787
Marc Slemko5b126d62006-08-11 23:03:42 +0000788 elif isinstance(ttype, StructType):
789 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000790
Marc Slemko5b126d62006-08-11 23:03:42 +0000791 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000792 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000793
Marc Slemko5b126d62006-08-11 23:03:42 +0000794 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000795 return toReaderCall("reinterpret_cast<"+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000796
797 else:
798 raise Exception, "Unknown type "+str(ttype)
799
Marc Slemko5b126d62006-08-11 23:03:42 +0000800def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000801 """Converts type to a name suitable as a suffix with TProtocol primitive write methods or with a generated write
802method for a complex type"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000803
804 suffix = typeToIOMethodSuffix(ttype)
805
806 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000807 if ttype != VOID_TYPE:
808 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
809 else:
810 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000811
812 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000813 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000814
Marc Slemko5b126d62006-08-11 23:03:42 +0000815 elif isinstance(ttype, StructType):
816 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000817
Marc Slemko5b126d62006-08-11 23:03:42 +0000818 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000819 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000820
Marc Slemko5b126d62006-08-11 23:03:42 +0000821 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000822 return toWriterCall("reinterpret_cast<const "+typeToCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000823
824 else:
825 raise Exception, "Unknown type "+str(ttype)
826
827CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000828uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000829
830 uint32_t count;
831 ${keyType} key;
832 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000833 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000834
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000835 xfer += iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000836
Marc Slemkoe6889de2006-08-12 00:32:53 +0000837 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000838 ${keyReaderCall};
839 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000840 value.insert(std::make_pair(key, elem));
841 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000842
843 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000844}
845""")
846
847CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000848uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000849
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000850 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000851
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000852 xfer += oprot->writeU32(otrans, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000853
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000854 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000855 ${keyWriterCall};
856 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000857 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000858 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000859}
860""")
861
Marc Slemkob2039e72006-08-09 01:00:17 +0000862CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000863uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000864
865 uint32_t count;
866 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000867 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000868
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000869 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000870
Marc Slemkoe6889de2006-08-12 00:32:53 +0000871 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000872 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000873 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000874 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000875 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000876}
877""")
878
Marc Slemkodb14e172006-08-09 23:36:18 +0000879CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000880uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000881
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000882 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000883
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000884 xfer+= oprot->writeU32(otrans, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000885
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000886 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000887 ${valueWriterCall};
888 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000889 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000890}
891""")
892
Marc Slemkod8b10512006-08-14 23:30:37 +0000893def toCollectionReaderDefinition(collection):
894 """Converts collection type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000895
Marc Slemkod8b10512006-08-14 23:30:37 +0000896 suffix = typeToIOMethodSuffix(collection)
Marc Slemkob2039e72006-08-09 01:00:17 +0000897
Marc Slemkod8b10512006-08-14 23:30:37 +0000898 if isinstance(collection, MapType):
899 keyReaderCall = toReaderCall("key", collection.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000900
Marc Slemkod8b10512006-08-14 23:30:37 +0000901 valueReaderCall= toReaderCall("elem", collection.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000902
Marc Slemkod8b10512006-08-14 23:30:37 +0000903 if isinstance(collection, MapType):
904 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
905 keyType=typeToCTypeDeclaration(collection.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000906 keyReaderCall=keyReaderCall,
Marc Slemkod8b10512006-08-14 23:30:37 +0000907 valueType=typeToCTypeDeclaration(collection.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000908 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000909
910 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000911 if isinstance(collection, ListType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000912 insert="push_back"
913 else:
914 insert="insert"
915
Marc Slemkod8b10512006-08-14 23:30:37 +0000916 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
Marc Slemkodb14e172006-08-09 23:36:18 +0000917 valueReaderCall=valueReaderCall,
Marc Slemkod8b10512006-08-14 23:30:37 +0000918 valueType=typeToCTypeDeclaration(collection.valueType),
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000919 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000920
921
Marc Slemkod8b10512006-08-14 23:30:37 +0000922def toCollectionWriterDefinition(collection):
923 """Converts collection type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000924
Marc Slemkod8b10512006-08-14 23:30:37 +0000925 suffix = typeToIOMethodSuffix(collection)
Marc Slemkodb14e172006-08-09 23:36:18 +0000926
Marc Slemkod8b10512006-08-14 23:30:37 +0000927 if isinstance(collection, MapType):
928 keyWriterCall = toWriterCall("ix->first", collection.keyType)
929 valueWriterCall = toWriterCall("ix->second", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000930
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000931 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000932 valueWriterCall= toWriterCall("*ix", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000933
Marc Slemkod8b10512006-08-14 23:30:37 +0000934 if isinstance(collection, MapType):
935 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
936 keyType=typeToCTypeDeclaration(collection.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000937 keyWriterCall=keyWriterCall,
Marc Slemkod8b10512006-08-14 23:30:37 +0000938 valueType=typeToCTypeDeclaration(collection.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000939 valueWriterCall=valueWriterCall)
940
941 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000942 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(collection),
Marc Slemkodb14e172006-08-09 23:36:18 +0000943 valueWriterCall=valueWriterCall,
Marc Slemkod8b10512006-08-14 23:30:37 +0000944 valueType=typeToCTypeDeclaration(collection.valueType))
Marc Slemkob2039e72006-08-09 01:00:17 +0000945
946
947CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000948uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000949
950 std::string name;
951 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000952 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000953 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000954
Marc Slemko5b126d62006-08-11 23:03:42 +0000955 xfer+= iprot->readStructBegin(itrans, name);
956
Marc Slemkob2039e72006-08-09 01:00:17 +0000957 while(true) {
958
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000959 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000960
961 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
962
963 switch(id) {
964${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +0000965 default: xfer += iprot->skip(itrans, type); break;
966 }
Marc Slemkob2039e72006-08-09 01:00:17 +0000967
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000968 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +0000969 }
Marc Slemko5b126d62006-08-11 23:03:42 +0000970
971 xfer+= iprot->readStructEnd(itrans);
972
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000973 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000974}
975""")
976
Marc Slemkod8b10512006-08-14 23:30:37 +0000977CPP_WRITE_FIELD_DEFINITION = Template("""oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id}); ${fieldWriterCall}; oprot->writeFieldEnd(otrans)""")
978
Marc Slemkodb14e172006-08-09 23:36:18 +0000979CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000980uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000981
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000982 uint32_t xfer = 0;
983
984 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +0000985${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000986 xfer+= oprot->writeFieldStop(otrans);
987 xfer += oprot->writeStructEnd(otrans);
988 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000989}
990""")
991
Marc Slemkod8b10512006-08-14 23:30:37 +0000992def toStructReaderDefinition(struct):
993 """Converts struct type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000994
Marc Slemkod8b10512006-08-14 23:30:37 +0000995 suffix = typeToIOMethodSuffix(struct)
Marc Slemkob2039e72006-08-09 01:00:17 +0000996
997 # Sort field list in order of increasing ids
998
999 fieldList = []
Marc Slemkod8b10512006-08-14 23:30:37 +00001000 fieldList+= struct.fieldList
Marc Slemkob2039e72006-08-09 01:00:17 +00001001
1002 fieldList.sort(lambda a,b: a.id - b.id)
1003
1004 fieldSwitch=""
1005
1006 for field in fieldList:
1007 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +00001008 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +00001009
Marc Slemkod8b10512006-08-14 23:30:37 +00001010 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +00001011
Marc Slemkodb14e172006-08-09 23:36:18 +00001012
Marc Slemkod8b10512006-08-14 23:30:37 +00001013def toStructWriterDefinition(struct):
1014 """Converts struct type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001015
Marc Slemkod8b10512006-08-14 23:30:37 +00001016 suffix = typeToIOMethodSuffix(struct)
Marc Slemkodb14e172006-08-09 23:36:18 +00001017
Marc Slemkod8b10512006-08-14 23:30:37 +00001018 fieldWriterCalls = []
Marc Slemkodb14e172006-08-09 23:36:18 +00001019
Marc Slemkod8b10512006-08-14 23:30:37 +00001020 fieldWriterCalls = [CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
1021 type=toWireType(toCanonicalType(field.type)),
1022 id=field.id,
1023 fieldWriterCall=toWriterCall("value."+field.name, field.type))+";"
1024 for field in struct.fieldList]
1025
1026 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n ")
1027
1028 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +00001029
Marc Slemkod8b10512006-08-14 23:30:37 +00001030CPP_WRITE_RESULT_STRUCT_DEFINITION = Template("""
1031uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
1032
1033 uint32_t xfer = 0;
1034
1035 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
1036 if(${value}.__isset.x)
1037${fieldWriterCalls}
1038 xfer+= oprot->writeFieldStop(otrans);
1039 xfer += oprot->writeStructEnd(otrans);
1040 return xfer;
1041}
1042""")
1043
1044def toResultStructReaderDefinition(struct):
1045 """Converts internal results struct to a reader function definition"""
1046 return toStructReaderDefinition(struct)
1047
1048def toResultStructWriterDefinition(struct):
1049 """Converts internal results struct to a reader function definition. The difference between this function and toStructWriterDefinition is that this only sends one field, either success or an exception field, depending on which field is set"""
1050
1051 suffix = typeToIOMethodSuffix(struct)
1052
1053 fieldWriterCalls = ["if(value.__isset."+field.name+") { "+toWriterCall("value."+field.name, field.type)+";}" for field in struct.fieldList]
1054
1055 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n else ")
1056
1057 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=typeToCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
1058
Marc Slemkodb14e172006-08-09 23:36:18 +00001059def toReaderDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001060 """Converts thrift type to a reader function definition"""
1061
Marc Slemkob2039e72006-08-09 01:00:17 +00001062 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001063 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +00001064
Marc Slemko5b126d62006-08-11 23:03:42 +00001065 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001066 return toStructReaderDefinition(ttype)
1067
Marc Slemko5b126d62006-08-11 23:03:42 +00001068 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001069 return ""
1070
Marc Slemko5b126d62006-08-11 23:03:42 +00001071 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001072 return ""
1073
1074 else:
1075 raise Exception, "Unsupported type: "+str(ttype)
1076
Marc Slemkodb14e172006-08-09 23:36:18 +00001077def toWriterDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001078 """Converts thrift type to a writer function definition"""
1079
Marc Slemkodb14e172006-08-09 23:36:18 +00001080 if isinstance(ttype, CollectionType):
1081 return toCollectionWriterDefinition(ttype)
1082
Marc Slemko5b126d62006-08-11 23:03:42 +00001083 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001084 return toStructWriterDefinition(ttype)
1085
Marc Slemko5b126d62006-08-11 23:03:42 +00001086 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001087 return ""
1088
Marc Slemko5b126d62006-08-11 23:03:42 +00001089 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001090 return ""
1091
1092 else:
1093 raise Exception, "Unsupported type: "+str(ttype)
1094
Marc Slemkodb14e172006-08-09 23:36:18 +00001095def toOrderedIOList(ttype, result=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001096 """Builds a list of types ordered by doing a depth first traverse of all thrift type definitions. This gives us a list from which we can
1097generate read/write methods without making forward references."""
1098
Marc Slemkodb14e172006-08-09 23:36:18 +00001099 if not result:
1100 result = []
1101
1102 if ttype in result:
1103 return result
1104
1105 elif isinstance(ttype, PrimitiveType):
1106 return result
1107
1108 elif isinstance(ttype, CollectionType):
1109
Marc Slemko5b126d62006-08-11 23:03:42 +00001110 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001111 result = toOrderedIOList(ttype.keyType, result)
1112
1113 result = toOrderedIOList(ttype.valueType, result)
1114
1115 result.append(ttype)
1116
Marc Slemko5b126d62006-08-11 23:03:42 +00001117 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001118 for field in ttype.fieldList:
1119 result = toOrderedIOList(field.type, result)
1120 result.append(ttype)
1121
Marc Slemko5b126d62006-08-11 23:03:42 +00001122 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001123 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001124 return result
1125
Marc Slemko5b126d62006-08-11 23:03:42 +00001126 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001127 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001128 return result
1129
1130 elif isinstance(ttype, Program):
1131
1132 for struct in ttype.structMap.values():
1133 result = toOrderedIOList(struct, result)
1134
1135 for service in ttype.serviceMap.values():
1136 result = toOrderedIOList(service, result)
1137
1138 elif isinstance(ttype, Service):
1139 for function in ttype.functionList:
1140 result = toOrderedIOList(function, result)
1141
1142 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001143 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001144
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001145 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001146 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001147 # inline those struct definitions with the implementation, not in the types header
1148
Marc Slemko5b126d62006-08-11 23:03:42 +00001149 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001150 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001151
1152 else:
1153 raise Exception, "Unsupported thrift type: "+str(ttype)
1154
1155 return result
1156
1157def toIOMethodImplementations(program):
Marc Slemkod8b10512006-08-14 23:30:37 +00001158 """Generates read and write methods for all non-primitive types in a thrift program as well as for the internal argStruct and resultStruct types for
1159all service functions"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001160
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001161 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001162
1163 iolist = toOrderedIOList(program)
1164
1165 result = ""
1166
1167 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001168 result+= toReaderDefinition(ttype)
1169 result+= toWriterDefinition(ttype)
1170
Marc Slemko5b126d62006-08-11 23:03:42 +00001171 # For all function argument lists, we need to create both struct definitions
1172 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1173 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001174 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1175 # we've already seen
1176
1177 for service in program.serviceMap.values():
1178 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001179 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001180 result+= toReaderDefinition(function.argsStruct)
1181 result+= toWriterDefinition(function.argsStruct)
1182 result+= toStructDefinition(function.resultStruct)
Marc Slemkod8b10512006-08-14 23:30:37 +00001183 result+= toResultStructReaderDefinition(function.resultStruct)
1184 result+= toResultStructWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001185
Marc Slemkodb14e172006-08-09 23:36:18 +00001186 return result;
1187
1188def toImplementationSourceName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001189 """Creates a file name for the implementation of client stubs, server skeletons, and non-primitive read/write methods."""
Marc Slemkodb14e172006-08-09 23:36:18 +00001190
1191 if not genDir:
1192 genDir = toGenDir(filename)
1193
1194 basename = toBasename(filename)
1195
1196 result = os.path.join(genDir, basename+".cc")
1197
1198 if debugp:
1199 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1200
1201 return result
1202
1203def writeImplementationSource(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001204 """Writes client stub, server skeleton, and non-primitive type I/O functions for all servciesf defined in program into a C/C++ source file. Uses the name of the original
1205thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001206
1207 implementationSource = toImplementationSourceName(filename, genDir)
1208
1209 if debugp:
1210 debugp("implementationSource: "+str(implementationSource))
1211
1212 cfile = CFile(implementationSource, "w")
1213
1214 basename = toBasename(filename)
1215
1216 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime()))
1217
1218 cfile.write(toIOMethodImplementations(program))
1219
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001220 cfile.write(toServerDefinition(program))
1221
Marc Slemko5b126d62006-08-11 23:03:42 +00001222 cfile.write(toClientDefinition(program))
1223
Marc Slemkodb14e172006-08-09 23:36:18 +00001224 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename))
1225
1226 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001227
1228class CPPGenerator(Generator):
1229
1230 def __call__(self, program, filename, genDir=None, debugp=None):
1231
Marc Slemkodb14e172006-08-09 23:36:18 +00001232 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001233
Marc Slemkodb14e172006-08-09 23:36:18 +00001234 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001235
Marc Slemkodb14e172006-08-09 23:36:18 +00001236 writeImplementationSource(program, filename, genDir, debugp)