blob: 97a5f36011c55c3746ac3ae86f8d5283cf03b82d [file] [log] [blame]
Marc Slemkob2039e72006-08-09 01:00:17 +00001import time
2import os
3import os.path
4from string import Template
Marc Slemko53027fc2006-08-17 01:12:11 +00005from thrift.parser import *
6from thrift.generator import *
Marc Slemkob2039e72006-08-09 01:00:17 +00007
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 Slemko17859852006-08-15 00:21:31 +000021${namespacePrefix}
Marc Slemkob2039e72006-08-09 01:00:17 +000022""")
23
24CPP_TYPES_FOOTER = Template("""
Marc Slemko17859852006-08-15 00:21:31 +000025${namespaceSuffix}
Marc Slemkob2039e72006-08-09 01:00:17 +000026#endif // !defined(${source}_types_h_)
27""")
28
29CPP_SERVICES_HEADER = Template(HEADER_COMMENT+"""
30#if !defined(${source}_h_)
31#define ${source}_h_ 1
32
Marc Slemkoc4eb9e82006-08-10 03:29:29 +000033#include <Thrift.h>
34#include <TProcessor.h>
35#include <protocol/TProtocol.h>
36#include <transport/TTransport.h>
Marc Slemkodb14e172006-08-09 23:36:18 +000037#include \"${source}_types.h\"
Marc Slemko17859852006-08-15 00:21:31 +000038
39${namespacePrefix}
Marc Slemkob2039e72006-08-09 01:00:17 +000040""")
41
42CPP_SERVICES_FOOTER = Template("""
Marc Slemko17859852006-08-15 00:21:31 +000043${namespaceSuffix}
Marc Slemkob2039e72006-08-09 01:00:17 +000044#endif // !defined(${source}_h_)""")
45
Marc Slemkodb14e172006-08-09 23:36:18 +000046CPP_IMPL_HEADER = Template(HEADER_COMMENT+"""
47#include \"${source}.h\"
Marc Slemko17859852006-08-15 00:21:31 +000048
49${namespacePrefix}
Marc Slemkodb14e172006-08-09 23:36:18 +000050""")
51
Marc Slemko17859852006-08-15 00:21:31 +000052CPP_IMPL_FOOTER = Template("""
53${namespaceSuffix}
54""")
Marc Slemkodb14e172006-08-09 23:36:18 +000055
Marc Slemkob2039e72006-08-09 01:00:17 +000056def cpp_debug(arg):
57 print(arg)
58
59class Indenter(object):
60 def __init__(self, level=0, step=4):
61 self.level = level
62 self.step = step
63 self.chunk = ""
64 for i in range(step):
65 self.chunk+= " "
66 self.prefix=""
67
68 def inc(self):
69 self.level+= self.step
70 self.prefix += self.chunk
71
72 def dec(self):
73 self.level-= self.step
74 if(self.level < 0):
75 raise Exception, "Illegal indent level"
76 self.prefix = self.prefix[:self.level]
77
78 def __call__(self):
79 return self.prefix
80
81class CFile(file):
82
83 def __init__(self, name, flags):
84 file.__init__(self, name, flags)
85 self.indent = Indenter()
86 self.newline = True
87
88 def rwrite(self, value):
89 file.write(self, value)
90
91 def write(self, value=""):
92 if self.newline:
93 self.rwrite(self.indent())
94 self.newline = False
95 self.rwrite(value)
96
97 def writeln(self, value=""):
98 self.write(value+"\n")
99 self.newline = True
100
101 def beginBlock(self):
102 self.writeln("{")
103 self.indent.inc();
104
105 def endBlock(self, suffix=""):
106 self.indent.dec();
107 self.writeln("}"+suffix)
108
109CPP_PRIMITIVE_MAP = {
110 "void" : "void",
111 "bool" : "bool",
112 "string": "std::string",
113 "utf7": "std::string",
114 "utf8": "std::wstring",
115 "utf16": "std::utf16",
116 "byte" : "uint8_t",
117 "i08": "int8_t",
118 "i16": "int16_t",
119 "i32": "int32_t",
120 "i64": "int64_t",
121 "u08": "uint8_t",
122 "u16": "uint16_t",
123 "u32": "uint32_t",
124 "u64": "uint64_t",
Marc Slemkod8b10512006-08-14 23:30:37 +0000125 "float": "float",
126 "double": "double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000127}
128
129CPP_CONTAINER_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000130 MapType : "std::map",
131 ListType: "std::list",
132 SetType : "std::set",
Marc Slemkob2039e72006-08-09 01:00:17 +0000133}
134
Marc Slemko17859852006-08-15 00:21:31 +0000135def toCNamespacePrefix(namespace):
136 if not namespace:
137 return ""
138 else:
139 return string.join(["namespace "+token + " {" for token in string.split(namespace, ".")], " ")
140
141def toCNamespaceSuffix(namespace):
142 if not namespace:
143 return ""
144 else:
145 return string.join(["}" for token in string.split(namespace, ".")], "")
146
147def toCTypeDeclaration(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000148 """ Converts the thrift IDL type to the corresponding C/C++ type. Note that if ttype is FieldType, this function c
149converts to type declaration followed by field name, i.e. \"string string_thing\""""
Marc Slemkob2039e72006-08-09 01:00:17 +0000150
151 if isinstance(ttype, PrimitiveType):
152 return CPP_PRIMITIVE_MAP[ttype.name]
153
154 elif isinstance(ttype, CollectionType):
155
156 result = CPP_CONTAINER_MAP[type(ttype)]+"<"
157
Marc Slemko5b126d62006-08-11 23:03:42 +0000158 if isinstance(ttype, MapType):
Marc Slemko17859852006-08-15 00:21:31 +0000159 result+= toCTypeDeclaration(ttype.keyType)+", "+ toCTypeDeclaration(ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000160
Marc Slemko5b126d62006-08-11 23:03:42 +0000161 elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
Marc Slemko17859852006-08-15 00:21:31 +0000162 result+= toCTypeDeclaration(ttype.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000163
164 else:
165 raise Exception, "Unknown Collection Type "+str(ttype)
166
167 result+= "> "
168
169 return result
170
Marc Slemko5b126d62006-08-11 23:03:42 +0000171 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000172 return "struct "+ttype.name
173
Marc Slemko5b126d62006-08-11 23:03:42 +0000174 elif isinstance(ttype, TypedefType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000175 return ttype.name;
176
Marc Slemko5b126d62006-08-11 23:03:42 +0000177 elif isinstance(ttype, EnumType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000178 return ttype.name;
179
180 elif isinstance(ttype, Function):
Marc Slemko17859852006-08-15 00:21:31 +0000181 result = toCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([toCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
Marc Slemkod8b10512006-08-14 23:30:37 +0000182 if len(ttype.exceptions()):
Marc Slemko17859852006-08-15 00:21:31 +0000183 result+= " throw("+string.join([toCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
Marc Slemkod8b10512006-08-14 23:30:37 +0000184 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000185
186 elif isinstance(ttype, Field):
Marc Slemko17859852006-08-15 00:21:31 +0000187 return toCTypeDeclaration(ttype.type)+ " "+ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000188
189 else:
190 raise Exception, "Unknown type "+str(ttype)
191
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000192def toTypeDefDefinition(typedef):
Marc Slemkod8b10512006-08-14 23:30:37 +0000193 """ Converts a thrift typedef to a C/C++ typedef """
Marc Slemkob2039e72006-08-09 01:00:17 +0000194
Marc Slemko17859852006-08-15 00:21:31 +0000195 return "typedef "+toCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
Marc Slemkob2039e72006-08-09 01:00:17 +0000196
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000197def toEnumDefinition(enum):
Marc Slemkod8b10512006-08-14 23:30:37 +0000198 """ Converts a thrift enum to a C/C++ enum """
Marc Slemkob2039e72006-08-09 01:00:17 +0000199
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000200 result = "enum "+enum.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000201
202 first = True
203
204 for ed in enum.enumDefs:
205 if first:
206 first = False
207 else:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000208 result+= ",\n"
209 result+= " "+ed.name+" = "+str(ed.id)
Marc Slemkob2039e72006-08-09 01:00:17 +0000210
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000211 result+= "\n};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000212
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000213 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000214
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000215def toStructDefinition(struct):
Marc Slemkod8b10512006-08-14 23:30:37 +0000216 """Converts a thrift struct to a C/C++ struct"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000217
218 result = "struct "+struct.name+" {\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000219
Marc Slemkobf4fd192006-08-15 21:29:39 +0000220 # Create constructor defaults for primitive types
Marc Slemko5b126d62006-08-11 23:03:42 +0000221
Marc Slemkobf4fd192006-08-15 21:29:39 +0000222 ctorValues = string.join([field.name+"(0)" for field in struct.fieldList if isinstance(toCanonicalType(field.type), PrimitiveType) and toCanonicalType(field.type) not in [STRING_TYPE, UTF8_TYPE, UTF16_TYPE, VOID_TYPE]], ", ")
Marc Slemko5b126d62006-08-11 23:03:42 +0000223
Marc Slemkobf4fd192006-08-15 21:29:39 +0000224 if len(ctorValues) > 0:
225 result+= " "+struct.name+"() : "+ctorValues+ " {}\n"
226
227 # Field declarations
228
Marc Slemkoc6936402006-08-23 02:15:31 +0000229 result+= string.join([" "+toCTypeDeclaration(field)+";\n" for field in struct.fieldList if not isVoidType(field.type)], "")
Marc Slemkobf4fd192006-08-15 21:29:39 +0000230
231 # is-field-set struct and ctor
232
Marc Slemkoc6936402006-08-23 02:15:31 +0000233 ctorValues = string.join([field.name+"(false)" for field in struct.fieldList if not isVoidType(field.type)], ", ")
Marc Slemkobf4fd192006-08-15 21:29:39 +0000234
235 if len(ctorValues) > 0:
236 result+= " struct __isset {\n"
237 result+= " __isset() : "+ctorValues+" {}\n"
Marc Slemkoc6936402006-08-23 02:15:31 +0000238 result+= string.join([" bool "+field.name+";\n" for field in struct.fieldList if not isVoidType(field.type)], "")
Marc Slemkobf4fd192006-08-15 21:29:39 +0000239 result+= " } __isset;\n"
240
241 # bring it on home
Marc Slemkob2039e72006-08-09 01:00:17 +0000242
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000243 result+= "};\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000244
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000245 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000246
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000247CPP_DEFINITION_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000248 TypedefType : toTypeDefDefinition,
249 EnumType : toEnumDefinition,
250 StructType : toStructDefinition,
Marc Slemkod8b10512006-08-14 23:30:37 +0000251 ExceptionType : toStructDefinition,
Marc Slemkob2039e72006-08-09 01:00:17 +0000252 Service : None
253 }
254
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000255def toDefinitions(definitions):
Marc Slemkod8b10512006-08-14 23:30:37 +0000256 """Converts an arbitrafy thrift grammatical unit definition to the corresponding C/C++ definition"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000257
258 result = ""
259
Marc Slemkob2039e72006-08-09 01:00:17 +0000260 for definition in definitions:
261
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000262 writer = CPP_DEFINITION_MAP[type(definition)]
Marc Slemkob2039e72006-08-09 01:00:17 +0000263
264 if writer:
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000265 result+= writer(definition)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000266
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000267 return result
Marc Slemkob2039e72006-08-09 01:00:17 +0000268
269CPP_THRIFT_NS = "facebook::thrift"
270
271CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
272""")
273
274CPP_INTERFACE_DECLARATION = Template("""
275class ${service}If {
276 public:
Marc Slemkoe6889de2006-08-12 00:32:53 +0000277 virtual ~${service}If() {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000278${functionDeclarations}};
279""")
280
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000281def toServiceInterfaceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000282 """Converts a thrift service definition into a C++ abstract base class"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000283
Marc Slemko17859852006-08-15 00:21:31 +0000284 functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
Marc Slemkob2039e72006-08-09 01:00:17 +0000285
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000286 return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000287
Marc Slemko5b126d62006-08-11 23:03:42 +0000288CPP_EXCEPTION = CPP_THRIFT_NS+"::Exception"
289
Marc Slemkob2039e72006-08-09 01:00:17 +0000290CPP_SP = Template("boost::shared_ptr<${klass}> ")
291
292CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
293CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
294
295CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000296CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
297CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
Marc Slemkob2039e72006-08-09 01:00:17 +0000298
299
300CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
301CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
302CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
303
Marc Slemkob2039e72006-08-09 01:00:17 +0000304CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
305CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
Marc Slemko5b126d62006-08-11 23:03:42 +0000306CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
307CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
308CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
Marc Slemkob2039e72006-08-09 01:00:17 +0000309
Marc Slemkodb14e172006-08-09 23:36:18 +0000310CPP_TTYPE_MAP = {
311 STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
312 VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
313 BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
314 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
315 UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
316 UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
317 UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
318 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
319 I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
320 I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
321 I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
322 I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
323 U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
324 U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
325 U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
326 U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
327 FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000328 DOUBLE_TYPE : CPP_PROTOCOL_NS+"::T_DOUBLE",
Marc Slemko5b126d62006-08-11 23:03:42 +0000329 StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemkod8b10512006-08-14 23:30:37 +0000330 ExceptionType : CPP_PROTOCOL_NS+"::T_STRUCT",
Marc Slemko5b126d62006-08-11 23:03:42 +0000331 ListType : CPP_PROTOCOL_NS+"::T_LIST",
332 MapType : CPP_PROTOCOL_NS+"::T_MAP",
333 SetType : CPP_PROTOCOL_NS+"::T_SET"
Marc Slemkodb14e172006-08-09 23:36:18 +0000334}
335
Marc Slemko91f67482006-08-11 23:58:57 +0000336
337CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
338""")
339
340CPP_SERVER_FUNCTION_DEFINITION = Template("""
341void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
342
343 uint32_t xfer = 0;
344
345 ${argsStructDeclaration};
346
347 ${argsStructReader};
348
349 _iprot->readMessageEnd(itrans);
350
Marc Slemko91f67482006-08-11 23:58:57 +0000351 ${resultStructDeclaration};
352
Marc Slemkobf4fd192006-08-15 21:29:39 +0000353 ${functionCall}
Marc Slemko91f67482006-08-11 23:58:57 +0000354
355 _oprot->writeMessageBegin(otrans, \"${function}\", """+CPP_PROTOCOL_REPLY+""", seqid);
356
357 ${resultStructWriter};
358
359 _oprot->writeMessageEnd(otrans);
360
361 otrans->flush();
362}
363""")
364
365CPP_SERVER_PROCESS_DEFINITION = Template("""
366bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
367
Marc Slemko91f67482006-08-11 23:58:57 +0000368 std::string name;
369
370 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
371
372 uint32_t seqid;
373
374 _iprot->readMessageBegin(itrans, name, messageType, seqid);
375
376 if(messageType == """+CPP_PROTOCOL_CALL+""") {
377${callProcessSwitch}
378 } else {
379 throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
380 }
Marc Slemkoe6889de2006-08-12 00:32:53 +0000381
382 return true;
Marc Slemko91f67482006-08-11 23:58:57 +0000383}
384""")
385
Marc Slemkodb14e172006-08-09 23:36:18 +0000386def toWireType(ttype):
Marc Slemko17859852006-08-15 00:21:31 +0000387 """Converts a thrift type to the corresponding wire type. This differs from toCTypeDeclaration in that it reduces typedefs
Marc Slemkod8b10512006-08-14 23:30:37 +0000388to their canonical form and converts enums to signedf 32 bit integers"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000389
390 if isinstance(ttype, PrimitiveType):
391 return CPP_TTYPE_MAP[ttype]
392
Marc Slemko5b126d62006-08-11 23:03:42 +0000393 elif isinstance(ttype, EnumType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000394 return CPP_TTYPE_MAP[I32_TYPE]
395
Marc Slemko5b126d62006-08-11 23:03:42 +0000396 elif isinstance(ttype, TypedefType):
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000397 return toWireType(toCanonicalType(ttype))
398
Marc Slemko5b126d62006-08-11 23:03:42 +0000399 elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +0000400 return CPP_TTYPE_MAP[type(ttype)]
401
402 else:
403 raise Exception, "No wire type for thrift type: "+str(ttype)
404
Marc Slemkob2039e72006-08-09 01:00:17 +0000405CPP_SERVER_DECLARATION = Template("""
406class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
407 public:
408 ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
409 ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
410 virtual ~${service}ServerIf() {}
411 bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
412 protected:
413 """+CPP_PROTOCOLP+""" _iprot;
414 """+CPP_PROTOCOLP+""" _oprot;
415 private:
416${functionDeclarations}};
417""")
418
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000419def toServerDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000420 """Converts a thrift service definition to the Server skeleton class declaration."""
Marc Slemkob2039e72006-08-09 01:00:17 +0000421
422 functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
423
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000424 return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
Marc Slemkob2039e72006-08-09 01:00:17 +0000425
426CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
427""")
428
Marc Slemko5b126d62006-08-11 23:03:42 +0000429
430CPP_CLIENT_FUNCTION_DEFINITION = Template("""
Marc Slemkod8b10512006-08-14 23:30:37 +0000431${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) ${exceptionDeclaration} {
Marc Slemko5b126d62006-08-11 23:03:42 +0000432
433 uint32_t xfer = 0;
Marc Slemko91f67482006-08-11 23:58:57 +0000434 std::string name;
Marc Slemko5b126d62006-08-11 23:03:42 +0000435 """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
436 uint32_t cseqid = 0;
437 uint32_t rseqid = 0;
438
Marc Slemko91f67482006-08-11 23:58:57 +0000439 _oprot->writeMessageBegin(_otrans, \"${function}\", """+CPP_PROTOCOL_CALL+""", cseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000440
441 ${argsStructDeclaration};
442
443${argsToStruct};
444
445 ${argsStructWriter};
446
447 _otrans->flush();
448
Marc Slemko91f67482006-08-11 23:58:57 +0000449 _iprot->readMessageBegin(_itrans, name, messageType, rseqid);
Marc Slemko5b126d62006-08-11 23:03:42 +0000450
451 if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
452 rseqid != cseqid) {
453 throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
454 }
455
456 ${resultStructDeclaration};
457
458 ${resultStructReader};
459
460 _iprot->readMessageEnd(_itrans);
461
Marc Slemkobf4fd192006-08-15 21:29:39 +0000462${returnResult}
Marc Slemkoc6936402006-08-23 02:15:31 +0000463 throw """+CPP_EXCEPTION+"""(\"${function} failed: unknown result\");
Marc Slemko5b126d62006-08-11 23:03:42 +0000464}
465""")
466
Marc Slemkob2039e72006-08-09 01:00:17 +0000467CPP_CLIENT_DECLARATION = Template("""
468class ${service}Client : public ${service}If {
469
470 public:
471
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000472 ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
Marc Slemkob2039e72006-08-09 01:00:17 +0000473
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000474 ${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 +0000475
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000476${functionDeclarations}
477 private:
478 """+CPP_TRANSPORTP+""" _itrans;
479 """+CPP_TRANSPORTP+""" _otrans;
480 """+CPP_PROTOCOLP+""" _iprot;
481 """+CPP_PROTOCOLP+""" _oprot;
482};""")
Marc Slemkob2039e72006-08-09 01:00:17 +0000483
Marc Slemko5b126d62006-08-11 23:03:42 +0000484def toServerFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000485 """Converts a thrift service method declaration into a server method-call processoror function"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000486 result = ""
487
Marc Slemko17859852006-08-15 00:21:31 +0000488 argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
Marc Slemko5b126d62006-08-11 23:03:42 +0000489
490 argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
491
Marc Slemko17859852006-08-15 00:21:31 +0000492 resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
Marc Slemko5b126d62006-08-11 23:03:42 +0000493
494 resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
495
Marc Slemkoc6936402006-08-23 02:15:31 +0000496 if not isVoidType(function.returnType()):
Marc Slemkod8b10512006-08-14 23:30:37 +0000497 functionCallPrefix= "__result.success = "
Marc Slemkobf4fd192006-08-15 21:29:39 +0000498 functionCallSuffix = "\n __result.__isset.success = true;"
Marc Slemkod8b10512006-08-14 23:30:37 +0000499 else:
500 functionCallPrefix = ""
501 functionCallSuffix = ""
502
503 functionCall= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+");"
504
505 exceptions = function.exceptions()
506
507 if len(exceptions) > 0:
Marc Slemkobf4fd192006-08-15 21:29:39 +0000508 functionCallPrefix= "try {\n "+functionCallPrefix
Marc Slemkod8b10512006-08-14 23:30:37 +0000509
Marc Slemkobf4fd192006-08-15 21:29:39 +0000510 functionCallSuffix+= "\n }"+string.join([" catch("+toCTypeDeclaration(exceptions[ix].type)+"& e"+str(ix)+") {\n __result."+exceptions[ix].name+" = e"+str(ix)+";\n __result.__isset."+exceptions[ix].name+" = true;\n }"
511 for ix in range(len(exceptions))], "")
Marc Slemkod8b10512006-08-14 23:30:37 +0000512
513 functionCall = functionCallPrefix+functionCall+functionCallSuffix
Marc Slemko5b126d62006-08-11 23:03:42 +0000514
515 result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
516 argsStructDeclaration=argsStructDeclaration,
517 argsStructReader=argsStructReader,
518 functionCall=functionCall,
Marc Slemko5b126d62006-08-11 23:03:42 +0000519 resultStructDeclaration=resultStructDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000520 resultStructWriter=resultStructWriter)
Marc Slemko5b126d62006-08-11 23:03:42 +0000521 return result
522
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000523def toServerServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000524 """Converts a thrift service definiton to a server skeleton implementation"""
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000525
526 result = ""
527
528 for function in service.functionList:
Marc Slemko5b126d62006-08-11 23:03:42 +0000529
530 result+= toServerFunctionDefinition(service.name, function, debugp)
Marc Slemko66d67d82006-08-11 23:33:08 +0000531
Marc Slemko53027fc2006-08-17 01:12:11 +0000532 callProcessSwitch = " if"+string.join(["(name.compare(\""+function.name+"\") == 0) {\n process_"+function.name+"(seqid, itrans, otrans);\n }" for function in service.functionList], " else if")+" else {\n throw "+CPP_EXCEPTION+"(\"Unknown function name \\\"\"+name+\"\\\"\");\n }"
Marc Slemko66d67d82006-08-11 23:33:08 +0000533
Marc Slemko91f67482006-08-11 23:58:57 +0000534 result+= CPP_SERVER_PROCESS_DEFINITION.substitute(service=service.name, callProcessSwitch=callProcessSwitch)
Marc Slemko66d67d82006-08-11 23:33:08 +0000535
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000536 return result
537
538def toServerDefinition(program, debugp=None):
539
540 return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
541
542def toClientDeclaration(service, debugp=None):
Marc Slemkob2039e72006-08-09 01:00:17 +0000543
Marc Slemko17859852006-08-15 00:21:31 +0000544 functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
Marc Slemkob2039e72006-08-09 01:00:17 +0000545
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000546 return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
Marc Slemkob2039e72006-08-09 01:00:17 +0000547
Marc Slemko5b126d62006-08-11 23:03:42 +0000548def toClientFunctionDefinition(servicePrefix, function, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000549 """Converts a thrift service method declaration to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000550
Marc Slemkoc6936402006-08-23 02:15:31 +0000551 isVoid = isVoidType(function.returnType())
Marc Slemkobf4fd192006-08-15 21:29:39 +0000552
Marc Slemko17859852006-08-15 00:21:31 +0000553 returnDeclaration = toCTypeDeclaration(function.returnType())
Marc Slemko5b126d62006-08-11 23:03:42 +0000554
Marc Slemko17859852006-08-15 00:21:31 +0000555 argsDeclaration = string.join([toCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
Marc Slemko5b126d62006-08-11 23:03:42 +0000556
Marc Slemko17859852006-08-15 00:21:31 +0000557 exceptionDeclaration = string.join([toCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
Marc Slemkod8b10512006-08-14 23:30:37 +0000558
559 if len(exceptionDeclaration)> 0:
560 exceptionDeclaration = "throw("+exceptionDeclaration+")"
561
Marc Slemko17859852006-08-15 00:21:31 +0000562 argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
Marc Slemko5b126d62006-08-11 23:03:42 +0000563
564 argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
565
566 argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
567
Marc Slemko17859852006-08-15 00:21:31 +0000568 resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
Marc Slemko5b126d62006-08-11 23:03:42 +0000569
570 resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
571
Marc Slemkod8b10512006-08-14 23:30:37 +0000572 exceptions = function.exceptions()
573
Marc Slemkobf4fd192006-08-15 21:29:39 +0000574 """ void return and non-void returns require very different arrangments. For void returns, we don't actually expect
575 anything to have been sent from the remote side, therefore we need to check for explicit exception returns first,
576 then, if none were encountered, return. For void we test for success first - since this is the most likey result -
577 and then check for exceptions. In both cases, we need to handle the case where there are no specified exceptions. """
578
Marc Slemkod8b10512006-08-14 23:30:37 +0000579 if len(exceptions) > 0:
Marc Slemkobf4fd192006-08-15 21:29:39 +0000580 errors= ["if(__result.__isset."+exception.name+") {\n throw __result."+exception.name+";\n }" for exception in exceptions]
Marc Slemkod8b10512006-08-14 23:30:37 +0000581 else:
Marc Slemkobf4fd192006-08-15 21:29:39 +0000582 errors = []
583
584 if not isVoid:
585 returnResult = " if(__result.__isset.success) {\n return __result.success;\n}"
586 if len(errors) > 0:
587 returnResult+= " else "+string.join(errors, " else ")
588 else:
589 if len(errors) > 0:
590 returnResult= " "+string.join(errors, " else ")+" else {\n return;\n }\n"
591 else:
592 returnResult=" return;\n"
Marc Slemko5b126d62006-08-11 23:03:42 +0000593
594 return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
595 function=function.name,
596 returnDeclaration=returnDeclaration,
597 argsDeclaration=argsDeclaration,
Marc Slemkod8b10512006-08-14 23:30:37 +0000598 exceptionDeclaration=exceptionDeclaration,
Marc Slemko5b126d62006-08-11 23:03:42 +0000599 argsStructDeclaration=argsStructDeclaration,
600 argsStructWriter=argsStructWriter,
601 argsToStruct=argsToStruct,
602 resultStructDeclaration=resultStructDeclaration,
603 resultStructReader=resultStructReader,
Marc Slemkobf4fd192006-08-15 21:29:39 +0000604 returnResult=returnResult)
Marc Slemko5b126d62006-08-11 23:03:42 +0000605
606def toClientServiceDefinition(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000607 """Converts a thrift service definition to a client stub implementation"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000608
609 result = ""
610
611 for function in service.functionList:
612
613 result+= toClientFunctionDefinition(service.name, function)
614
615 return result
616
617def toClientDefinition(program, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000618 """Converts all services in a thrift program to client stub implementations"""
Marc Slemko5b126d62006-08-11 23:03:42 +0000619
620 return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
621
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000622def toServiceDeclaration(service, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000623 """Converts all services in a thrift program to service interface or abstract base class declarations"""
624
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000625 return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +0000626
627def toGenDir(filename, suffix="cpp-gen", debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000628 """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 +0000629
630 result = os.path.join(os.path.split(filename)[0], suffix)
631
632 if not os.path.exists(result):
633 os.mkdir(result)
634
635 return result
636
637def toBasename(filename, debugp=None):
638 """ Take the filename minus the path and\".thrift\" extension if present """
639
640 basename = os.path.split(filename)[1]
641
642 tokens = os.path.splitext(basename)
643
644 if tokens[1].lower() == ".thrift":
645 basename = tokens[0]
646
647 if debugp:
648 debugp("toBasename("+str(filename)+") => "+str(basename))
649
650 return basename
651
652def toDefinitionHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000653 """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 +0000654
655 if not genDir:
656 genDir = toGenDir(filename)
657
658 basename = toBasename(filename)
659
660 result = os.path.join(genDir, basename+"_types.h")
661
662 if debugp:
663 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
664
665 return result
666
667def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000668 """Writes public thrift data types defined in program into a public data types header file. Uses the name of the original
669thrift 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 +0000670
671 definitionHeader = toDefinitionHeaderName(filename, genDir)
672
673 if debugp:
674 debugp("definitionHeader: "+str(definitionHeader))
675
676 cfile = CFile(definitionHeader, "w")
677
678 basename = toBasename(filename)
679
Marc Slemko17859852006-08-15 00:21:31 +0000680 cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000681
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000682 cfile.write(toDefinitions(program.definitions))
Marc Slemkob2039e72006-08-09 01:00:17 +0000683
Marc Slemko17859852006-08-15 00:21:31 +0000684 cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000685
686 cfile.close()
687
688def toServicesHeaderName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000689 """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 +0000690
691 if not genDir:
692 genDir = toGenDir(filename)
693
694 basename = toBasename(filename)
695
696 result = os.path.join(genDir, basename+".h")
697
698 if debugp:
699 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
700
701 return result
702
Marc Slemkob2039e72006-08-09 01:00:17 +0000703def writeServicesHeader(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +0000704 """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 +0000705
706 servicesHeader = toServicesHeaderName(filename, genDir)
707
708 if debugp:
709 debugp("servicesHeader: "+str(servicesHeader))
710
711 cfile = CFile(servicesHeader, "w")
712
713 basename = toBasename(filename)
714
Marc Slemko17859852006-08-15 00:21:31 +0000715 cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000716
717 services = []
718
719 # Build orderered list of service definitions by scanning definitions list for services
720
721 for definition in program.definitions:
722 if isinstance(definition, Service) and definition.name in program.serviceMap:
723 services.append(definition)
724
725 for service in services:
726
Marc Slemko0b4ffa92006-08-11 02:49:29 +0000727 cfile.write(toServiceDeclaration(service))
Marc Slemkob2039e72006-08-09 01:00:17 +0000728
Marc Slemko17859852006-08-15 00:21:31 +0000729 cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkob2039e72006-08-09 01:00:17 +0000730
731 cfile.close()
732
733
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000734CPP_STRUCT_READ = Template("""
735uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
736
Marc Slemkob2039e72006-08-09 01:00:17 +0000737 std::string name;
738 uint32_t id;
739 uint32_t type;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000740 uint32_t xfer = 0;
741
Marc Slemkob2039e72006-08-09 01:00:17 +0000742 while(true) {
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000743 xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +0000744 if(type == """+CPP_PROTOCOL_TSTOP+""") {
745 break;
746 }
747 switch(id) {
748${readFieldListSwitch}
749 }
750 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000751
752 xfer+= _iprot->readStructEnd(_itrans);
753
754 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000755}
756""")
757
758CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000759 "void" :"Void",
Marc Slemkob2039e72006-08-09 01:00:17 +0000760 "bool" : "Bool",
761 "string": "String",
762 "utf7": "String",
763 "utf8": "String",
764 "utf16": "String",
765 "i08": "Byte",
766 "i16": "I16",
767 "i32": "I32",
768 "i64": "I64",
769 "u08": "Byte",
770 "u16": "U16",
771 "u32": "U32",
772 "u64": "U64",
Marc Slemkod8b10512006-08-14 23:30:37 +0000773 "float": "Float",
774 "double": "Double"
Marc Slemkob2039e72006-08-09 01:00:17 +0000775}
776
777CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
Marc Slemko5b126d62006-08-11 23:03:42 +0000778 MapType : "map",
779 ListType : "list",
780 SetType : "set"
Marc Slemkob2039e72006-08-09 01:00:17 +0000781}
782
783def typeToIOMethodSuffix(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +0000784 """Converts type to a name suitable as a suffix with TProtocol primitive read and write methods or with a generated read or write
785method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000786
787 if isinstance(ttype, PrimitiveType):
788 return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
789
790 elif isinstance(ttype, CollectionType):
791
792 result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
793
Marc Slemko5b126d62006-08-11 23:03:42 +0000794 if isinstance(ttype, MapType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000795 result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
796
797 result += "v_"+typeToIOMethodSuffix(ttype.valueType)
798
799 return result
800
Marc Slemko5b126d62006-08-11 23:03:42 +0000801 elif isinstance(ttype, StructType):
Marc Slemkob2039e72006-08-09 01:00:17 +0000802 return "struct_"+ttype.name
803
Marc Slemko5b126d62006-08-11 23:03:42 +0000804 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000805 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000806
Marc Slemko5b126d62006-08-11 23:03:42 +0000807 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000808 return ttype.name
Marc Slemkob2039e72006-08-09 01:00:17 +0000809
810 else:
811 raise Exception, "Unknown type "+str(ttype)
812
Marc Slemko5b126d62006-08-11 23:03:42 +0000813def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000814 """Converts type to a name suitable as a suffix with TProtocol primitive read methods or with a generated read
815method for a complex type"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000816
817 suffix = typeToIOMethodSuffix(ttype)
818
819 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000820 if ttype != VOID_TYPE:
821 return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
822 else:
823 return ""
Marc Slemkob2039e72006-08-09 01:00:17 +0000824
825 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000826 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000827
Marc Slemko5b126d62006-08-11 23:03:42 +0000828 elif isinstance(ttype, StructType):
829 return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
Marc Slemkob2039e72006-08-09 01:00:17 +0000830
Marc Slemko5b126d62006-08-11 23:03:42 +0000831 elif isinstance(ttype, TypedefType):
Marc Slemko17859852006-08-15 00:21:31 +0000832 return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
Marc Slemkob2039e72006-08-09 01:00:17 +0000833
Marc Slemko5b126d62006-08-11 23:03:42 +0000834 elif isinstance(ttype, EnumType):
Marc Slemko17859852006-08-15 00:21:31 +0000835 return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
Marc Slemkodb14e172006-08-09 23:36:18 +0000836
837 else:
838 raise Exception, "Unknown type "+str(ttype)
839
Marc Slemko5b126d62006-08-11 23:03:42 +0000840def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
Marc Slemkod8b10512006-08-14 23:30:37 +0000841 """Converts type to a name suitable as a suffix with TProtocol primitive write methods or with a generated write
842method for a complex type"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000843
844 suffix = typeToIOMethodSuffix(ttype)
845
846 if isinstance(ttype, PrimitiveType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000847 if ttype != VOID_TYPE:
848 return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
849 else:
850 return ""
Marc Slemkodb14e172006-08-09 23:36:18 +0000851
852 elif isinstance(ttype, CollectionType):
Marc Slemko5b126d62006-08-11 23:03:42 +0000853 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000854
Marc Slemko5b126d62006-08-11 23:03:42 +0000855 elif isinstance(ttype, StructType):
856 return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
Marc Slemkodb14e172006-08-09 23:36:18 +0000857
Marc Slemko5b126d62006-08-11 23:03:42 +0000858 elif isinstance(ttype, TypedefType):
Marc Slemko17859852006-08-15 00:21:31 +0000859 return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
Marc Slemkodb14e172006-08-09 23:36:18 +0000860
Marc Slemko5b126d62006-08-11 23:03:42 +0000861 elif isinstance(ttype, EnumType):
Marc Slemko17859852006-08-15 00:21:31 +0000862 return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
Marc Slemkob2039e72006-08-09 01:00:17 +0000863
864 else:
865 raise Exception, "Unknown type "+str(ttype)
866
867CPP_READ_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000868uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000869
870 uint32_t count;
871 ${keyType} key;
872 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000873 uint32_t xfer = 0;
Marc Slemkob09f5882006-08-23 22:03:34 +0000874 """+CPP_PROTOCOL_TTYPE+""" keyType;
875 """+CPP_PROTOCOL_TTYPE+""" valueType;
Marc Slemkob2039e72006-08-09 01:00:17 +0000876
Marc Slemkob09f5882006-08-23 22:03:34 +0000877 xfer += iprot->readMapBegin(itrans, keyType, valueType, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000878
Marc Slemkob09f5882006-08-23 22:03:34 +0000879 /* XXX
880 Should we assert that read key and value type are correct? */
881
Marc Slemkoe6889de2006-08-12 00:32:53 +0000882 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000883 ${keyReaderCall};
884 ${valueReaderCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000885 value.insert(std::make_pair(key, elem));
886 }
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000887
Marc Slemkob09f5882006-08-23 22:03:34 +0000888 xfer += iprot->readMapEnd(itrans);
889
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000890 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000891}
892""")
893
894CPP_WRITE_MAP_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000895uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000896
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000897 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +0000898
Marc Slemkob09f5882006-08-23 22:03:34 +0000899 xfer += oprot->writeMapBegin(otrans, ${keyWireType}, ${valueWireType}, value.size());
Marc Slemkob2039e72006-08-09 01:00:17 +0000900
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000901 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000902 ${keyWriterCall};
903 ${valueWriterCall};
Marc Slemkob2039e72006-08-09 01:00:17 +0000904 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000905
906 xfer += oprot->writeMapEnd(otrans);
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000907 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000908}
909""")
910
Marc Slemkob2039e72006-08-09 01:00:17 +0000911CPP_READ_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000912uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +0000913
914 uint32_t count;
915 ${valueType} elem;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000916 uint32_t xfer = 0;
Marc Slemkob09f5882006-08-23 22:03:34 +0000917 """+CPP_PROTOCOL_TTYPE+""" valueType;
918
919 xfer += iprot->read${protocolSuffix}Begin(itrans, valueType, count);
920
921 /* XXX
922 Should we assert that read value type is correct? */
Marc Slemkob2039e72006-08-09 01:00:17 +0000923
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000924 xfer+= iprot->readU32(itrans, count);
Marc Slemkob2039e72006-08-09 01:00:17 +0000925
Marc Slemkoe6889de2006-08-12 00:32:53 +0000926 for(uint32_t ix = 0; ix < count; ix++) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000927 ${valueReaderCall};
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000928 value.${insert}(elem);
Marc Slemkob2039e72006-08-09 01:00:17 +0000929 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000930
931 xfer += iprot->read${protocolSuffix}End(itrans);
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000932 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +0000933}
934""")
935
Marc Slemkodb14e172006-08-09 23:36:18 +0000936CPP_WRITE_LIST_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000937uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000938
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000939 uint32_t xfer = 0;
Marc Slemkodb14e172006-08-09 23:36:18 +0000940
Marc Slemkob09f5882006-08-23 22:03:34 +0000941 xfer+= oprot->write${protocolSuffix}Begin(otrans, ${valueWireType}, value.size());
Marc Slemkodb14e172006-08-09 23:36:18 +0000942
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000943 for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
Marc Slemkodb14e172006-08-09 23:36:18 +0000944 ${valueWriterCall};
945 }
Marc Slemkob09f5882006-08-23 22:03:34 +0000946
947 xfer+= oprot->write${protocolSuffix}End(otrans);
948
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000949 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +0000950}
951""")
952
Marc Slemkod8b10512006-08-14 23:30:37 +0000953def toCollectionReaderDefinition(collection):
954 """Converts collection type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +0000955
Marc Slemkod8b10512006-08-14 23:30:37 +0000956 suffix = typeToIOMethodSuffix(collection)
Marc Slemkob2039e72006-08-09 01:00:17 +0000957
Marc Slemkod8b10512006-08-14 23:30:37 +0000958 if isinstance(collection, MapType):
959 keyReaderCall = toReaderCall("key", collection.keyType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000960
Marc Slemkod8b10512006-08-14 23:30:37 +0000961 valueReaderCall= toReaderCall("elem", collection.valueType)
Marc Slemkob2039e72006-08-09 01:00:17 +0000962
Marc Slemkod8b10512006-08-14 23:30:37 +0000963 if isinstance(collection, MapType):
Marc Slemko17859852006-08-15 00:21:31 +0000964 return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
965 keyType=toCTypeDeclaration(collection.keyType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000966 keyReaderCall=keyReaderCall,
Marc Slemko17859852006-08-15 00:21:31 +0000967 valueType=toCTypeDeclaration(collection.valueType),
Marc Slemkodb14e172006-08-09 23:36:18 +0000968 valueReaderCall=valueReaderCall)
Marc Slemkob2039e72006-08-09 01:00:17 +0000969
970 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000971 if isinstance(collection, ListType):
Marc Slemkob09f5882006-08-23 22:03:34 +0000972 protocolSuffix="List"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000973 insert="push_back"
974 else:
Marc Slemkob09f5882006-08-23 22:03:34 +0000975 protocolSuffix="Set"
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000976 insert="insert"
977
Marc Slemko17859852006-08-15 00:21:31 +0000978 return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
Marc Slemkob09f5882006-08-23 22:03:34 +0000979 protocolSuffix=protocolSuffix,
Marc Slemkodb14e172006-08-09 23:36:18 +0000980 valueReaderCall=valueReaderCall,
Marc Slemko17859852006-08-15 00:21:31 +0000981 valueType=toCTypeDeclaration(collection.valueType),
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000982 insert=insert)
Marc Slemkodb14e172006-08-09 23:36:18 +0000983
984
Marc Slemkod8b10512006-08-14 23:30:37 +0000985def toCollectionWriterDefinition(collection):
986 """Converts collection type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +0000987
Marc Slemkod8b10512006-08-14 23:30:37 +0000988 suffix = typeToIOMethodSuffix(collection)
Marc Slemkodb14e172006-08-09 23:36:18 +0000989
Marc Slemkod8b10512006-08-14 23:30:37 +0000990 if isinstance(collection, MapType):
991 keyWriterCall = toWriterCall("ix->first", collection.keyType)
Marc Slemkob09f5882006-08-23 22:03:34 +0000992 keyWireType = toWireType(collection.keyType)
Marc Slemkod8b10512006-08-14 23:30:37 +0000993 valueWriterCall = toWriterCall("ix->second", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000994
Marc Slemkoc4eb9e82006-08-10 03:29:29 +0000995 else:
Marc Slemkod8b10512006-08-14 23:30:37 +0000996 valueWriterCall= toWriterCall("*ix", collection.valueType)
Marc Slemkodb14e172006-08-09 23:36:18 +0000997
Marc Slemkob09f5882006-08-23 22:03:34 +0000998 valueWireType = toWireType(collection.valueType)
999
Marc Slemkod8b10512006-08-14 23:30:37 +00001000 if isinstance(collection, MapType):
Marc Slemko17859852006-08-15 00:21:31 +00001001 return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
Marc Slemkob09f5882006-08-23 22:03:34 +00001002 keyType=toCTypeDeclaration(collection.keyType),
1003 keyWireType=keyWireType,
1004 keyWriterCall=keyWriterCall,
1005 valueType=toCTypeDeclaration(collection.valueType),
1006 valueWireType=valueWireType,
1007 valueWriterCall=valueWriterCall)
Marc Slemkodb14e172006-08-09 23:36:18 +00001008
1009 else:
Marc Slemkob09f5882006-08-23 22:03:34 +00001010 if isinstance(collection, ListType):
1011 protocolSuffix = "List"
1012 elif isinstance(collection, SetType):
1013 protocolSuffix = "Set"
1014 else:
1015 raise Exception, "Unknown collection type "+str(type(collection))+":"+str(collection)
1016
Marc Slemko17859852006-08-15 00:21:31 +00001017 return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
Marc Slemkob09f5882006-08-23 22:03:34 +00001018 protocolSuffix=protocolSuffix,
1019 valueWireType=valueWireType,
1020 valueWriterCall=valueWriterCall,
1021 valueType=toCTypeDeclaration(collection.valueType))
Marc Slemkob2039e72006-08-09 01:00:17 +00001022
1023
1024CPP_READ_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001025uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
Marc Slemkob2039e72006-08-09 01:00:17 +00001026
1027 std::string name;
1028 """+CPP_PROTOCOL_TTYPE+""" type;
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001029 int16_t id;
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001030 uint32_t xfer = 0;
Marc Slemkob2039e72006-08-09 01:00:17 +00001031
Marc Slemko5b126d62006-08-11 23:03:42 +00001032 xfer+= iprot->readStructBegin(itrans, name);
1033
Marc Slemkob2039e72006-08-09 01:00:17 +00001034 while(true) {
1035
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001036 xfer+= iprot->readFieldBegin(itrans, name, type, id);
Marc Slemkob2039e72006-08-09 01:00:17 +00001037
1038 if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
1039
1040 switch(id) {
1041${fieldSwitch}
Marc Slemko5b126d62006-08-11 23:03:42 +00001042 default: xfer += iprot->skip(itrans, type); break;
1043 }
Marc Slemkob2039e72006-08-09 01:00:17 +00001044
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001045 xfer+= iprot->readFieldEnd(itrans);
Marc Slemkob2039e72006-08-09 01:00:17 +00001046 }
Marc Slemko5b126d62006-08-11 23:03:42 +00001047
1048 xfer+= iprot->readStructEnd(itrans);
1049
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001050 return xfer;
Marc Slemkob2039e72006-08-09 01:00:17 +00001051}
1052""")
1053
Marc Slemkod8b10512006-08-14 23:30:37 +00001054CPP_WRITE_FIELD_DEFINITION = Template("""oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id}); ${fieldWriterCall}; oprot->writeFieldEnd(otrans)""")
1055
Marc Slemkodb14e172006-08-09 23:36:18 +00001056CPP_WRITE_STRUCT_DEFINITION = Template("""
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001057uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
Marc Slemkodb14e172006-08-09 23:36:18 +00001058
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001059 uint32_t xfer = 0;
1060
1061 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
Marc Slemkodb14e172006-08-09 23:36:18 +00001062${fieldWriterCalls}
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001063 xfer+= oprot->writeFieldStop(otrans);
1064 xfer += oprot->writeStructEnd(otrans);
1065 return xfer;
Marc Slemkodb14e172006-08-09 23:36:18 +00001066}
1067""")
1068
Marc Slemkod8b10512006-08-14 23:30:37 +00001069def toStructReaderDefinition(struct):
1070 """Converts struct type to reader function definition"""
Marc Slemkob2039e72006-08-09 01:00:17 +00001071
Marc Slemkod8b10512006-08-14 23:30:37 +00001072 suffix = typeToIOMethodSuffix(struct)
Marc Slemkob2039e72006-08-09 01:00:17 +00001073
1074 # Sort field list in order of increasing ids
1075
1076 fieldList = []
Marc Slemkod8b10512006-08-14 23:30:37 +00001077 fieldList+= struct.fieldList
Marc Slemkob2039e72006-08-09 01:00:17 +00001078
1079 fieldList.sort(lambda a,b: a.id - b.id)
1080
1081 fieldSwitch=""
1082
1083 for field in fieldList:
Marc Slemkoc6936402006-08-23 02:15:31 +00001084 if isVoidType(field.type):
Marc Slemkobf4fd192006-08-15 21:29:39 +00001085 continue;
Marc Slemkob2039e72006-08-09 01:00:17 +00001086 fieldSwitch+= " case "+str(field.id)+": "
Marc Slemko5b126d62006-08-11 23:03:42 +00001087 fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
Marc Slemkob2039e72006-08-09 01:00:17 +00001088
Marc Slemko17859852006-08-15 00:21:31 +00001089 return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
Marc Slemkodb14e172006-08-09 23:36:18 +00001090
Marc Slemkodb14e172006-08-09 23:36:18 +00001091
Marc Slemkod8b10512006-08-14 23:30:37 +00001092def toStructWriterDefinition(struct):
1093 """Converts struct type to writer function definition"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001094
Marc Slemkod8b10512006-08-14 23:30:37 +00001095 suffix = typeToIOMethodSuffix(struct)
Marc Slemkodb14e172006-08-09 23:36:18 +00001096
Marc Slemkod8b10512006-08-14 23:30:37 +00001097 fieldWriterCalls = []
Marc Slemkodb14e172006-08-09 23:36:18 +00001098
Marc Slemkod8b10512006-08-14 23:30:37 +00001099 fieldWriterCalls = [CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
1100 type=toWireType(toCanonicalType(field.type)),
1101 id=field.id,
1102 fieldWriterCall=toWriterCall("value."+field.name, field.type))+";"
Marc Slemkoc6936402006-08-23 02:15:31 +00001103 for field in struct.fieldList if not isVoidType(field.type)
Marc Slemkobf4fd192006-08-15 21:29:39 +00001104 ]
Marc Slemkod8b10512006-08-14 23:30:37 +00001105
1106 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n ")
1107
Marc Slemko17859852006-08-15 00:21:31 +00001108 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
Marc Slemkob2039e72006-08-09 01:00:17 +00001109
Marc Slemkod8b10512006-08-14 23:30:37 +00001110CPP_WRITE_RESULT_STRUCT_DEFINITION = Template("""
1111uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
1112
1113 uint32_t xfer = 0;
1114
1115 xfer+= oprot->writeStructBegin(otrans, \"${name}\");
1116 if(${value}.__isset.x)
1117${fieldWriterCalls}
1118 xfer+= oprot->writeFieldStop(otrans);
1119 xfer += oprot->writeStructEnd(otrans);
1120 return xfer;
1121}
1122""")
1123
1124def toResultStructReaderDefinition(struct):
1125 """Converts internal results struct to a reader function definition"""
Marc Slemkobf4fd192006-08-15 21:29:39 +00001126
Marc Slemkod8b10512006-08-14 23:30:37 +00001127 return toStructReaderDefinition(struct)
1128
1129def toResultStructWriterDefinition(struct):
1130 """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"""
1131
1132 suffix = typeToIOMethodSuffix(struct)
1133
Marc Slemkobf4fd192006-08-15 21:29:39 +00001134 fieldWriterCalls = ["if(value.__isset."+field.name+") { "+
1135 CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
1136 type=toWireType(toCanonicalType(field.type)),
1137 id=field.id,
1138 fieldWriterCall=toWriterCall("value."+field.name, field.type))+";}"
Marc Slemkoc6936402006-08-23 02:15:31 +00001139 for field in struct.fieldList if not isVoidType(field.type)]
Marc Slemkod8b10512006-08-14 23:30:37 +00001140
1141 fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n else ")
1142
Marc Slemko17859852006-08-15 00:21:31 +00001143 return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
Marc Slemkod8b10512006-08-14 23:30:37 +00001144
Marc Slemkodb14e172006-08-09 23:36:18 +00001145def toReaderDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001146 """Converts thrift type to a reader function definition"""
1147
Marc Slemkob2039e72006-08-09 01:00:17 +00001148 if isinstance(ttype, CollectionType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001149 return toCollectionReaderDefinition(ttype)
Marc Slemkob2039e72006-08-09 01:00:17 +00001150
Marc Slemko5b126d62006-08-11 23:03:42 +00001151 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001152 return toStructReaderDefinition(ttype)
1153
Marc Slemko5b126d62006-08-11 23:03:42 +00001154 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001155 return ""
1156
Marc Slemko5b126d62006-08-11 23:03:42 +00001157 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001158 return ""
1159
1160 else:
1161 raise Exception, "Unsupported type: "+str(ttype)
1162
Marc Slemkodb14e172006-08-09 23:36:18 +00001163def toWriterDefinition(ttype):
Marc Slemkod8b10512006-08-14 23:30:37 +00001164 """Converts thrift type to a writer function definition"""
1165
Marc Slemkodb14e172006-08-09 23:36:18 +00001166 if isinstance(ttype, CollectionType):
1167 return toCollectionWriterDefinition(ttype)
1168
Marc Slemko5b126d62006-08-11 23:03:42 +00001169 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001170 return toStructWriterDefinition(ttype)
1171
Marc Slemko5b126d62006-08-11 23:03:42 +00001172 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001173 return ""
1174
Marc Slemko5b126d62006-08-11 23:03:42 +00001175 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001176 return ""
1177
1178 else:
1179 raise Exception, "Unsupported type: "+str(ttype)
1180
Marc Slemkodb14e172006-08-09 23:36:18 +00001181def toOrderedIOList(ttype, result=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001182 """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
1183generate read/write methods without making forward references."""
1184
Marc Slemkodb14e172006-08-09 23:36:18 +00001185 if not result:
1186 result = []
1187
1188 if ttype in result:
1189 return result
1190
1191 elif isinstance(ttype, PrimitiveType):
1192 return result
1193
1194 elif isinstance(ttype, CollectionType):
1195
Marc Slemko5b126d62006-08-11 23:03:42 +00001196 if isinstance(ttype, MapType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001197 result = toOrderedIOList(ttype.keyType, result)
1198
1199 result = toOrderedIOList(ttype.valueType, result)
1200
1201 result.append(ttype)
1202
Marc Slemko5b126d62006-08-11 23:03:42 +00001203 elif isinstance(ttype, StructType):
Marc Slemkodb14e172006-08-09 23:36:18 +00001204 for field in ttype.fieldList:
1205 result = toOrderedIOList(field.type, result)
1206 result.append(ttype)
1207
Marc Slemko5b126d62006-08-11 23:03:42 +00001208 elif isinstance(ttype, TypedefType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001209 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001210 return result
1211
Marc Slemko5b126d62006-08-11 23:03:42 +00001212 elif isinstance(ttype, EnumType):
Marc Slemkoc4eb9e82006-08-10 03:29:29 +00001213 result.append(ttype)
Marc Slemkodb14e172006-08-09 23:36:18 +00001214 return result
1215
1216 elif isinstance(ttype, Program):
1217
1218 for struct in ttype.structMap.values():
1219 result = toOrderedIOList(struct, result)
1220
1221 for service in ttype.serviceMap.values():
1222 result = toOrderedIOList(service, result)
1223
1224 elif isinstance(ttype, Service):
1225 for function in ttype.functionList:
1226 result = toOrderedIOList(function, result)
1227
1228 elif isinstance(ttype, Function):
Marc Slemko5b126d62006-08-11 23:03:42 +00001229 result = toOrderedIOList(ttype.returnType(), result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001230
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001231 # skip the args struct itself and just order the arguments themselves
Marc Slemko5b126d62006-08-11 23:03:42 +00001232 # we don't want the arg struct to be referred to until later, since we need to
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001233 # inline those struct definitions with the implementation, not in the types header
1234
Marc Slemko5b126d62006-08-11 23:03:42 +00001235 for field in ttype.args():
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001236 result = toOrderedIOList(field.type, result)
Marc Slemkodb14e172006-08-09 23:36:18 +00001237
1238 else:
1239 raise Exception, "Unsupported thrift type: "+str(ttype)
1240
1241 return result
1242
1243def toIOMethodImplementations(program):
Marc Slemkod8b10512006-08-14 23:30:37 +00001244 """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
1245all service functions"""
Marc Slemkodb14e172006-08-09 23:36:18 +00001246
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001247 # get ordered list of all types that need marshallers:
Marc Slemkodb14e172006-08-09 23:36:18 +00001248
1249 iolist = toOrderedIOList(program)
1250
1251 result = ""
1252
1253 for ttype in iolist:
Marc Slemkodb14e172006-08-09 23:36:18 +00001254 result+= toReaderDefinition(ttype)
1255 result+= toWriterDefinition(ttype)
1256
Marc Slemko5b126d62006-08-11 23:03:42 +00001257 # For all function argument lists, we need to create both struct definitions
1258 # and io methods. We keep the struct definitions local, since they aren't part of the service API
1259 #
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001260 # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
1261 # we've already seen
1262
1263 for service in program.serviceMap.values():
1264 for function in service.functionList:
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001265 result+= toStructDefinition(function.argsStruct)
Marc Slemko5b126d62006-08-11 23:03:42 +00001266 result+= toReaderDefinition(function.argsStruct)
1267 result+= toWriterDefinition(function.argsStruct)
1268 result+= toStructDefinition(function.resultStruct)
Marc Slemkod8b10512006-08-14 23:30:37 +00001269 result+= toResultStructReaderDefinition(function.resultStruct)
1270 result+= toResultStructWriterDefinition(function.resultStruct)
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001271
Marc Slemkodb14e172006-08-09 23:36:18 +00001272 return result;
1273
1274def toImplementationSourceName(filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001275 """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 +00001276
1277 if not genDir:
1278 genDir = toGenDir(filename)
1279
1280 basename = toBasename(filename)
1281
1282 result = os.path.join(genDir, basename+".cc")
1283
1284 if debugp:
1285 debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
1286
1287 return result
1288
1289def writeImplementationSource(program, filename, genDir=None, debugp=None):
Marc Slemkod8b10512006-08-14 23:30:37 +00001290 """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
1291thrift 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 +00001292
1293 implementationSource = toImplementationSourceName(filename, genDir)
1294
1295 if debugp:
1296 debugp("implementationSource: "+str(implementationSource))
1297
1298 cfile = CFile(implementationSource, "w")
1299
1300 basename = toBasename(filename)
1301
Marc Slemko17859852006-08-15 00:21:31 +00001302 cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
Marc Slemkodb14e172006-08-09 23:36:18 +00001303
1304 cfile.write(toIOMethodImplementations(program))
1305
Marc Slemko0b4ffa92006-08-11 02:49:29 +00001306 cfile.write(toServerDefinition(program))
1307
Marc Slemko5b126d62006-08-11 23:03:42 +00001308 cfile.write(toClientDefinition(program))
1309
Marc Slemko17859852006-08-15 00:21:31 +00001310 cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
Marc Slemkodb14e172006-08-09 23:36:18 +00001311
1312 cfile.close()
Marc Slemkob2039e72006-08-09 01:00:17 +00001313
1314class CPPGenerator(Generator):
1315
1316 def __call__(self, program, filename, genDir=None, debugp=None):
1317
Marc Slemkodb14e172006-08-09 23:36:18 +00001318 writeDefinitionHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001319
Marc Slemkodb14e172006-08-09 23:36:18 +00001320 writeServicesHeader(program, filename, genDir, debugp)
Marc Slemkob2039e72006-08-09 01:00:17 +00001321
Marc Slemkodb14e172006-08-09 23:36:18 +00001322 writeImplementationSource(program, filename, genDir, debugp)