+++ /dev/null
-install-exec-hook:
- $(PYTHON) setup.py install install_scripts --install-dir=$(bindir)
+++ /dev/null
-#!/bin/sh
-
-rm -rf \
-AUTHORS \
-COPYING \
-ChangeLog \
-INSTALL \
-Makefile \
-Makefile.in \
-Makefile.orig \
-NEWS \
-README \
-aclocal.m4 \
-autom4te.cache \
-autoscan.log \
-config.guess \
-config.h \
-config.hin \
-config.log \
-config.status \
-config.sub \
-configure \
-configure.scan \
-depcomp \
-.deps \
-install-sh \
-.libs \
-libtool \
-ltmain.sh \
-Makefile.in \
-missing
-
-aclocal
-touch NEWS README AUTHORS ChangeLog
-autoconf
-automake -ac
+++ /dev/null
-AC_PREREQ(2.59)
-
-AC_INIT([compiler], [1.0])
-
-AC_CONFIG_AUX_DIR([.])
-
-AM_INIT_AUTOMAKE
-
-AM_PATH_PYTHON(2.4,, :)
-
-AC_CONFIG_FILES([Makefile])
-
-AC_OUTPUT
+++ /dev/null
-from distutils.core import setup
-
-setup(name = 'Thrift',
- version = '1.0',
- description = 'Thrift IDL compiler',
- author = ['Mark Slee', 'Marc Kwiatkowski'],
- author_email = ['mcslee@facebook.com', 'marc@facebook.com'],
- url = 'http://code.facebook.com/thrift',
- package_dir = {'thrift' : 'src'},
- py_modules = ['thrift.parser', 'thrift.cpp_generator', 'thrift.generator', 'thrift.php_generator'],
- scripts = ['src/thrift']
- )
-
+++ /dev/null
-__all__ = ['parser', 'generator', 'cpp_generator', 'php_generator']
+++ /dev/null
-import time
-import os
-import os.path
-from string import Template
-from thrift.parser import *
-from thrift.generator import *
-
-HEADER_COMMENT = """/**
- * Autogenerated by Thrift
- * ${date}
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
- """
-
-CPP_TYPES_HEADER = Template(HEADER_COMMENT+"""
-#if !defined(${source}_types_h_)
-#define ${source}_types_h_ 1
-
-#include <Thrift.h>
-${namespacePrefix}
-""")
-
-CPP_TYPES_FOOTER = Template("""
-${namespaceSuffix}
-#endif // !defined(${source}_types_h_)
-""")
-
-CPP_SERVICES_HEADER = Template(HEADER_COMMENT+"""
-#if !defined(${source}_h_)
-#define ${source}_h_ 1
-
-#include <Thrift.h>
-#include <TProcessor.h>
-#include <protocol/TProtocol.h>
-#include <transport/TTransport.h>
-#include \"${source}_types.h\"
-
-${namespacePrefix}
-""")
-
-CPP_SERVICES_FOOTER = Template("""
-${namespaceSuffix}
-#endif // !defined(${source}_h_)""")
-
-CPP_IMPL_HEADER = Template(HEADER_COMMENT+"""
-#include \"${source}.h\"
-
-${namespacePrefix}
-""")
-
-CPP_IMPL_FOOTER = Template("""
-${namespaceSuffix}
-""")
-
-def cpp_debug(arg):
- print(arg)
-
-class Indenter(object):
- def __init__(self, level=0, step=4):
- self.level = level
- self.step = step
- self.chunk = ""
- for i in range(step):
- self.chunk+= " "
- self.prefix=""
-
- def inc(self):
- self.level+= self.step
- self.prefix += self.chunk
-
- def dec(self):
- self.level-= self.step
- if(self.level < 0):
- raise Exception, "Illegal indent level"
- self.prefix = self.prefix[:self.level]
-
- def __call__(self):
- return self.prefix
-
-class CFile(file):
-
- def __init__(self, name, flags):
- file.__init__(self, name, flags)
- self.indent = Indenter()
- self.newline = True
-
- def rwrite(self, value):
- file.write(self, value)
-
- def write(self, value=""):
- if self.newline:
- self.rwrite(self.indent())
- self.newline = False
- self.rwrite(value)
-
- def writeln(self, value=""):
- self.write(value+"\n")
- self.newline = True
-
- def beginBlock(self):
- self.writeln("{")
- self.indent.inc();
-
- def endBlock(self, suffix=""):
- self.indent.dec();
- self.writeln("}"+suffix)
-
-CPP_PRIMITIVE_MAP = {
- "void" : "void",
- "bool" : "bool",
- "string": "std::string",
- "utf7": "std::string",
- "utf8": "std::wstring",
- "utf16": "std::utf16",
- "byte" : "uint8_t",
- "i08": "int8_t",
- "i16": "int16_t",
- "i32": "int32_t",
- "i64": "int64_t",
- "u08": "uint8_t",
- "u16": "uint16_t",
- "u32": "uint32_t",
- "u64": "uint64_t",
- "float": "float",
- "double": "double"
-}
-
-CPP_CONTAINER_MAP = {
- MapType : "std::map",
- ListType: "std::list",
- SetType : "std::set",
-}
-
-def toCNamespacePrefix(namespace):
- if not namespace:
- return ""
- else:
- return string.join(["namespace "+token + " {" for token in string.split(namespace, ".")], " ")
-
-def toCNamespaceSuffix(namespace):
- if not namespace:
- return ""
- else:
- return string.join(["}" for token in string.split(namespace, ".")], "")
-
-def toCTypeDeclaration(ttype):
- """ Converts the thrift IDL type to the corresponding C/C++ type. Note that if ttype is FieldType, this function c
-converts to type declaration followed by field name, i.e. \"string string_thing\""""
-
- if isinstance(ttype, PrimitiveType):
- return CPP_PRIMITIVE_MAP[ttype.name]
-
- elif isinstance(ttype, CollectionType):
-
- result = CPP_CONTAINER_MAP[type(ttype)]+"<"
-
- if isinstance(ttype, MapType):
- result+= toCTypeDeclaration(ttype.keyType)+", "+ toCTypeDeclaration(ttype.valueType)
-
- elif isinstance(ttype, SetType) or isinstance(ttype, ListType):
- result+= toCTypeDeclaration(ttype.valueType)
-
- else:
- raise Exception, "Unknown Collection Type "+str(ttype)
-
- result+= "> "
-
- return result
-
- elif isinstance(ttype, StructType):
- return "struct "+ttype.name
-
- elif isinstance(ttype, TypedefType):
- return ttype.name;
-
- elif isinstance(ttype, EnumType):
- return ttype.name;
-
- elif isinstance(ttype, Function):
- result = toCTypeDeclaration(ttype.returnType())+ " "+ttype.name+"("+string.join([toCTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
- if len(ttype.exceptions()):
- result+= " throw("+string.join([toCTypeDeclaration(exceptions.type) for exceptions in ttype.exceptions()], ", ")+")"
- return result
-
- elif isinstance(ttype, Field):
- return toCTypeDeclaration(ttype.type)+ " "+ttype.name
-
- else:
- raise Exception, "Unknown type "+str(ttype)
-
-def toTypeDefDefinition(typedef):
- """ Converts a thrift typedef to a C/C++ typedef """
-
- return "typedef "+toCTypeDeclaration(typedef.definitionType)+" "+typedef.name+";"
-
-def toEnumDefinition(enum):
- """ Converts a thrift enum to a C/C++ enum """
-
- result = "enum "+enum.name+" {\n"
-
- first = True
-
- for ed in enum.enumDefs:
- if first:
- first = False
- else:
- result+= ",\n"
- result+= " "+ed.name+" = "+str(ed.id)
-
- result+= "\n};\n"
-
- return result
-
-def toStructDefinition(struct):
- """Converts a thrift struct to a C/C++ struct"""
-
- result = "struct "+struct.name+" {\n"
-
- # Create constructor defaults for primitive types
-
- 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]], ", ")
-
- if len(ctorValues) > 0:
- result+= " "+struct.name+"() : "+ctorValues+ " {}\n"
-
- # Field declarations
-
- result+= string.join([" "+toCTypeDeclaration(field)+";\n" for field in struct.fieldList if not isVoidType(field.type)], "")
-
- # is-field-set struct and ctor
-
- ctorValues = string.join([field.name+"(false)" for field in struct.fieldList if not isVoidType(field.type)], ", ")
-
- if len(ctorValues) > 0:
- result+= " struct __isset {\n"
- result+= " __isset() : "+ctorValues+" {}\n"
- result+= string.join([" bool "+field.name+";\n" for field in struct.fieldList if not isVoidType(field.type)], "")
- result+= " } __isset;\n"
-
- # bring it on home
-
- result+= "};\n"
-
- return result
-
-CPP_DEFINITION_MAP = {
- TypedefType : toTypeDefDefinition,
- EnumType : toEnumDefinition,
- StructType : toStructDefinition,
- ExceptionType : toStructDefinition,
- Service : None
- }
-
-def toDefinitions(definitions):
- """Converts an arbitrafy thrift grammatical unit definition to the corresponding C/C++ definition"""
-
- result = ""
-
- for definition in definitions:
-
- writer = CPP_DEFINITION_MAP[type(definition)]
-
- if writer:
- result+= writer(definition)+"\n"
-
- return result
-
-CPP_THRIFT_NS = "facebook::thrift"
-
-CPP_INTERFACE_FUNCTION_DECLARATION = Template(""" virtual ${functionDeclaration} = 0;
-""")
-
-CPP_INTERFACE_DECLARATION = Template("""
-class ${service}If {
- public:
- virtual ~${service}If() {}
-${functionDeclarations}};
-""")
-
-def toServiceInterfaceDeclaration(service, debugp=None):
- """Converts a thrift service definition into a C++ abstract base class"""
-
- functionDeclarations = string.join([CPP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
-
- return CPP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
-
-CPP_EXCEPTION = CPP_THRIFT_NS+"::Exception"
-
-CPP_SP = Template("boost::shared_ptr<${klass}> ")
-
-CPP_PROCESSOR = CPP_THRIFT_NS+"::TProcessor"
-CPP_PROCESSORP = CPP_SP.substitute(klass=CPP_PROCESSOR)
-
-CPP_PROTOCOL_NS = CPP_THRIFT_NS+"::protocol"
-CPP_PROTOCOL = CPP_PROTOCOL_NS+"::TProtocol"
-CPP_PROTOCOLP = CPP_SP.substitute(klass="const "+CPP_PROTOCOL)
-
-
-CPP_TRANSPORT_NS = CPP_THRIFT_NS+"::transport"
-CPP_TRANSPORT = CPP_TRANSPORT_NS+"::TTransport"
-CPP_TRANSPORTP = CPP_SP.substitute(klass=CPP_TRANSPORT)
-
-CPP_PROTOCOL_TSTOP = CPP_PROTOCOL_NS+"::T_STOP"
-CPP_PROTOCOL_TTYPE = CPP_PROTOCOL_NS+"::TType"
-CPP_PROTOCOL_MESSAGE_TYPE = CPP_PROTOCOL_NS+"::TMessageType"
-CPP_PROTOCOL_CALL = CPP_PROTOCOL_NS+"::T_CALL"
-CPP_PROTOCOL_REPLY = CPP_PROTOCOL_NS+"::T_REPLY"
-
-CPP_TTYPE_MAP = {
- STOP_TYPE : CPP_PROTOCOL_NS+"::T_STOP",
- VOID_TYPE : CPP_PROTOCOL_NS+"::T_VOID",
- BOOL_TYPE : CPP_PROTOCOL_NS+"::T_BOOL",
- UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
- UTF7_TYPE : CPP_PROTOCOL_NS+"::T_UTF7",
- UTF8_TYPE : CPP_PROTOCOL_NS+"::T_UTF8",
- UTF16_TYPE : CPP_PROTOCOL_NS+"::T_UTF16",
- U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
- I08_TYPE : CPP_PROTOCOL_NS+"::T_I08",
- I16_TYPE : CPP_PROTOCOL_NS+"::T_I16",
- I32_TYPE : CPP_PROTOCOL_NS+"::T_I32",
- I64_TYPE : CPP_PROTOCOL_NS+"::T_I64",
- U08_TYPE : CPP_PROTOCOL_NS+"::T_U08",
- U16_TYPE : CPP_PROTOCOL_NS+"::T_U16",
- U32_TYPE : CPP_PROTOCOL_NS+"::T_U32",
- U64_TYPE : CPP_PROTOCOL_NS+"::T_U64",
- FLOAT_TYPE : CPP_PROTOCOL_NS+"::T_FLOAT",
- DOUBLE_TYPE : CPP_PROTOCOL_NS+"::T_DOUBLE",
- StructType : CPP_PROTOCOL_NS+"::T_STRUCT",
- ExceptionType : CPP_PROTOCOL_NS+"::T_STRUCT",
- ListType : CPP_PROTOCOL_NS+"::T_LIST",
- MapType : CPP_PROTOCOL_NS+"::T_MAP",
- SetType : CPP_PROTOCOL_NS+"::T_SET"
-}
-
-
-CPP_SERVER_FUNCTION_DECLARATION = Template(""" void process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans);
-""")
-
-CPP_SERVER_FUNCTION_DEFINITION = Template("""
-void ${service}ServerIf::process_${function}(uint32_t seqid, """+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
-
- uint32_t xfer = 0;
-
- ${argsStructDeclaration};
-
- ${argsStructReader};
-
- _iprot->readMessageEnd(itrans);
-
- ${resultStructDeclaration};
-
- ${functionCall}
-
- _oprot->writeMessageBegin(otrans, \"${function}\", """+CPP_PROTOCOL_REPLY+""", seqid);
-
- ${resultStructWriter};
-
- _oprot->writeMessageEnd(otrans);
-
- otrans->flush();
-}
-""")
-
-CPP_SERVER_PROCESS_DEFINITION = Template("""
-bool ${service}ServerIf::process("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans) {
-
- std::string name;
-
- """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
-
- uint32_t seqid;
-
- _iprot->readMessageBegin(itrans, name, messageType, seqid);
-
- if(messageType == """+CPP_PROTOCOL_CALL+""") {
-${callProcessSwitch}
- } else {
- throw """+CPP_EXCEPTION+"""(\"Unexpected message type\");
- }
-
- return true;
-}
-""")
-
-def toWireType(ttype):
- """Converts a thrift type to the corresponding wire type. This differs from toCTypeDeclaration in that it reduces typedefs
-to their canonical form and converts enums to signedf 32 bit integers"""
-
- if isinstance(ttype, PrimitiveType):
- return CPP_TTYPE_MAP[ttype]
-
- elif isinstance(ttype, EnumType):
- return CPP_TTYPE_MAP[I32_TYPE]
-
- elif isinstance(ttype, TypedefType):
- return toWireType(toCanonicalType(ttype))
-
- elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
- return CPP_TTYPE_MAP[type(ttype)]
-
- else:
- raise Exception, "No wire type for thrift type: "+str(ttype)
-
-CPP_SERVER_DECLARATION = Template("""
-class ${service}ServerIf : public ${service}If, public """+CPP_PROCESSOR+""" {
- public:
- ${service}ServerIf("""+CPP_PROTOCOLP+""" protocol): _iprot(protocol), _oprot(protocol) {}
- ${service}ServerIf("""+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _iprot(iprot), _oprot(oprot) {}
- virtual ~${service}ServerIf() {}
- bool process("""+CPP_TRANSPORTP+""" _itrans,"""+CPP_TRANSPORTP+""" _otrans);
- protected:
- """+CPP_PROTOCOLP+""" _iprot;
- """+CPP_PROTOCOLP+""" _oprot;
- private:
-${functionDeclarations}};
-""")
-
-def toServerDeclaration(service, debugp=None):
- """Converts a thrift service definition to the Server skeleton class declaration."""
-
- functionDeclarations = string.join([CPP_SERVER_FUNCTION_DECLARATION.substitute(function=function.name) for function in service.functionList], "")
-
- return CPP_SERVER_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
-
-CPP_CLIENT_FUNCTION_DECLARATION = Template(""" ${functionDeclaration};
-""")
-
-
-CPP_CLIENT_FUNCTION_DEFINITION = Template("""
-${returnDeclaration} ${service}Client::${function}(${argsDeclaration}) ${exceptionDeclaration} {
-
- uint32_t xfer = 0;
- std::string name;
- """+CPP_PROTOCOL_MESSAGE_TYPE+""" messageType;
- uint32_t cseqid = 0;
- uint32_t rseqid = 0;
-
- _oprot->writeMessageBegin(_otrans, \"${function}\", """+CPP_PROTOCOL_CALL+""", cseqid);
-
- ${argsStructDeclaration};
-
-${argsToStruct};
-
- ${argsStructWriter};
-
- _otrans->flush();
-
- _iprot->readMessageBegin(_itrans, name, messageType, rseqid);
-
- if(messageType != """+CPP_PROTOCOL_REPLY+""" ||
- rseqid != cseqid) {
- throw """+CPP_EXCEPTION+"""(\"unexpected message type or id\");
- }
-
- ${resultStructDeclaration};
-
- ${resultStructReader};
-
- _iprot->readMessageEnd(_itrans);
-
-${returnResult}
- throw """+CPP_EXCEPTION+"""(\"${function} failed: unknown result\");
-}
-""")
-
-CPP_CLIENT_DECLARATION = Template("""
-class ${service}Client : public ${service}If {
-
- public:
-
- ${service}Client("""+CPP_TRANSPORTP+""" transport, """+CPP_PROTOCOLP+""" protocol): _itrans(transport), _otrans(transport), _iprot(protocol), _oprot(protocol) {}
-
- ${service}Client("""+CPP_TRANSPORTP+""" itrans, """+CPP_TRANSPORTP+""" otrans, """+CPP_PROTOCOLP+""" iprot, """+CPP_PROTOCOLP+""" oprot) : _itrans(itrans), _otrans(otrans), _iprot(iprot), _oprot(oprot) {}
-
-${functionDeclarations}
- private:
- """+CPP_TRANSPORTP+""" _itrans;
- """+CPP_TRANSPORTP+""" _otrans;
- """+CPP_PROTOCOLP+""" _iprot;
- """+CPP_PROTOCOLP+""" _oprot;
-};""")
-
-def toServerFunctionDefinition(servicePrefix, function, debugp=None):
- """Converts a thrift service method declaration into a server method-call processoror function"""
- result = ""
-
- argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
-
- argsStructReader = toReaderCall("__args", function.argsStruct, "_iprot")
-
- resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
-
- resultStructWriter = toWriterCall("__result", function.resultStruct, "_oprot")
-
- if not isVoidType(function.returnType()):
- functionCallPrefix= "__result.success = "
- functionCallSuffix = "\n __result.__isset.success = true;"
- else:
- functionCallPrefix = ""
- functionCallSuffix = ""
-
- functionCall= function.name+"("+string.join(["__args."+arg.name for arg in function.args()], ", ")+");"
-
- exceptions = function.exceptions()
-
- if len(exceptions) > 0:
- functionCallPrefix= "try {\n "+functionCallPrefix
-
- 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 }"
- for ix in range(len(exceptions))], "")
-
- functionCall = functionCallPrefix+functionCall+functionCallSuffix
-
- result+= CPP_SERVER_FUNCTION_DEFINITION.substitute(service=servicePrefix, function=function.name,
- argsStructDeclaration=argsStructDeclaration,
- argsStructReader=argsStructReader,
- functionCall=functionCall,
- resultStructDeclaration=resultStructDeclaration,
- resultStructWriter=resultStructWriter)
- return result
-
-def toServerServiceDefinition(service, debugp=None):
- """Converts a thrift service definiton to a server skeleton implementation"""
-
- result = ""
-
- for function in service.functionList:
-
- result+= toServerFunctionDefinition(service.name, function, debugp)
-
- 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 }"
-
- result+= CPP_SERVER_PROCESS_DEFINITION.substitute(service=service.name, callProcessSwitch=callProcessSwitch)
-
- return result
-
-def toServerDefinition(program, debugp=None):
-
- return string.join([toServerServiceDefinition(service) for service in program.serviceMap.values()], "\n")
-
-def toClientDeclaration(service, debugp=None):
-
- functionDeclarations = string.join([CPP_CLIENT_FUNCTION_DECLARATION.substitute(functionDeclaration=toCTypeDeclaration(function)) for function in service.functionList], "")
-
- return CPP_CLIENT_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)+"\n"
-
-def toClientFunctionDefinition(servicePrefix, function, debugp=None):
- """Converts a thrift service method declaration to a client stub implementation"""
-
- isVoid = isVoidType(function.returnType())
-
- returnDeclaration = toCTypeDeclaration(function.returnType())
-
- argsDeclaration = string.join([toCTypeDeclaration(function.args()[ix].type)+" __arg"+str(ix) for ix in range(len(function.args()))], ", ")
-
- exceptionDeclaration = string.join([toCTypeDeclaration(exception.type) for exception in function.exceptions()], ", ")
-
- if len(exceptionDeclaration)> 0:
- exceptionDeclaration = "throw("+exceptionDeclaration+")"
-
- argsStructDeclaration = toCTypeDeclaration(function.argsStruct)+" __args"
-
- argsStructWriter = toWriterCall("__args", function.argsStruct, "_oprot", "_otrans")
-
- argsToStruct= string.join([" __args."+function.args()[ix].name+" = __arg"+str(ix) for ix in range(len(function.args()))], ";\n")
-
- resultStructDeclaration = toCTypeDeclaration(function.resultStruct)+" __result"
-
- resultStructReader = toReaderCall("__result", function.resultStruct, "_iprot", "_itrans")
-
- exceptions = function.exceptions()
-
- """ void return and non-void returns require very different arrangments. For void returns, we don't actually expect
- anything to have been sent from the remote side, therefore we need to check for explicit exception returns first,
- then, if none were encountered, return. For void we test for success first - since this is the most likey result -
- and then check for exceptions. In both cases, we need to handle the case where there are no specified exceptions. """
-
- if len(exceptions) > 0:
- errors= ["if(__result.__isset."+exception.name+") {\n throw __result."+exception.name+";\n }" for exception in exceptions]
- else:
- errors = []
-
- if not isVoid:
- returnResult = " if(__result.__isset.success) {\n return __result.success;\n}"
- if len(errors) > 0:
- returnResult+= " else "+string.join(errors, " else ")
- else:
- if len(errors) > 0:
- returnResult= " "+string.join(errors, " else ")+" else {\n return;\n }\n"
- else:
- returnResult=" return;\n"
-
- return CPP_CLIENT_FUNCTION_DEFINITION.substitute(service=servicePrefix,
- function=function.name,
- returnDeclaration=returnDeclaration,
- argsDeclaration=argsDeclaration,
- exceptionDeclaration=exceptionDeclaration,
- argsStructDeclaration=argsStructDeclaration,
- argsStructWriter=argsStructWriter,
- argsToStruct=argsToStruct,
- resultStructDeclaration=resultStructDeclaration,
- resultStructReader=resultStructReader,
- returnResult=returnResult)
-
-def toClientServiceDefinition(service, debugp=None):
- """Converts a thrift service definition to a client stub implementation"""
-
- result = ""
-
- for function in service.functionList:
-
- result+= toClientFunctionDefinition(service.name, function)
-
- return result
-
-def toClientDefinition(program, debugp=None):
- """Converts all services in a thrift program to client stub implementations"""
-
- return string.join([toClientServiceDefinition(service) for service in program.serviceMap.values()], "\n")
-
-def toServiceDeclaration(service, debugp=None):
- """Converts all services in a thrift program to service interface or abstract base class declarations"""
-
- return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp)
-
-def toGenDir(filename, suffix="gen-cpp", debugp=None):
- """creates a generated-code subdirectory for C++ code based on filename of thrift source file and optional suffix"""
-
- result = os.path.join(os.path.split(filename)[0], suffix)
-
- if not os.path.exists(result):
- os.mkdir(result)
-
- return result
-
-def toBasename(filename, debugp=None):
- """ Take the filename minus the path and\".thrift\" extension if present """
-
- basename = os.path.split(filename)[1]
-
- tokens = os.path.splitext(basename)
-
- if tokens[1].lower() == ".thrift":
- basename = tokens[0]
-
- if debugp:
- debugp("toBasename("+str(filename)+") => "+str(basename))
-
- return basename
-
-def toDefinitionHeaderName(filename, genDir=None, debugp=None):
- """Creates a file name for the public thrift data types based on filename of thrift source file and optional suffix"""
-
- if not genDir:
- genDir = toGenDir(filename)
-
- basename = toBasename(filename)
-
- result = os.path.join(genDir, basename+"_types.h")
-
- if debugp:
- debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
-
- return result
-
-def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
- """Writes public thrift data types defined in program into a public data types 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"""
-
- definitionHeader = toDefinitionHeaderName(filename, genDir)
-
- if debugp:
- debugp("definitionHeader: "+str(definitionHeader))
-
- cfile = CFile(definitionHeader, "w")
-
- basename = toBasename(filename)
-
- cfile.writeln(CPP_TYPES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
-
- cfile.write(toDefinitions(program.definitions))
-
- cfile.writeln(CPP_TYPES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
-
- cfile.close()
-
-def toServicesHeaderName(filename, genDir=None, debugp=None):
- """Creates a file name for the public thrift services based on filename of thrift source file and optional suffix"""
-
- if not genDir:
- genDir = toGenDir(filename)
-
- basename = toBasename(filename)
-
- result = os.path.join(genDir, basename+".h")
-
- if debugp:
- debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
-
- return result
-
-def writeServicesHeader(program, filename, genDir=None, debugp=None):
- """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"""
-
- servicesHeader = toServicesHeaderName(filename, genDir)
-
- if debugp:
- debugp("servicesHeader: "+str(servicesHeader))
-
- cfile = CFile(servicesHeader, "w")
-
- basename = toBasename(filename)
-
- cfile.writeln(CPP_SERVICES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
-
- services = []
-
- # Build orderered list of service definitions by scanning definitions list for services
-
- for definition in program.definitions:
- if isinstance(definition, Service) and definition.name in program.serviceMap:
- services.append(definition)
-
- for service in services:
-
- cfile.write(toServiceDeclaration(service))
-
- cfile.writeln(CPP_SERVICES_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
-
- cfile.close()
-
-
-CPP_STRUCT_READ = Template("""
-uint32_t read${name}Struct("""+CPP_PROTOCOLP+""" _iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
-
- std::string name;
- uint32_t id;
- uint32_t type;
- uint32_t xfer = 0;
-
- while(true) {
- xfer+= _iprot->readFieldBegin(_itrans, name, type, id);
- if(type == """+CPP_PROTOCOL_TSTOP+""") {
- break;
- }
- switch(id) {
-${readFieldListSwitch}
- }
- }
-
- xfer+= _iprot->readStructEnd(_itrans);
-
- return xfer;
-}
-""")
-
-CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
- "void" :"Void",
- "bool" : "Bool",
- "string": "String",
- "utf7": "String",
- "utf8": "String",
- "utf16": "String",
- "i08": "Byte",
- "i16": "I16",
- "i32": "I32",
- "i64": "I64",
- "u08": "Byte",
- "u16": "U16",
- "u32": "U32",
- "u64": "U64",
- "float": "Float",
- "double": "Double"
-}
-
-CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP = {
- MapType : "map",
- ListType : "list",
- SetType : "set"
-}
-
-def typeToIOMethodSuffix(ttype):
- """Converts type to a name suitable as a suffix with TProtocol primitive read and write methods or with a generated read or write
-method for a complex type"""
-
- if isinstance(ttype, PrimitiveType):
- return CPP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP[ttype.name]
-
- elif isinstance(ttype, CollectionType):
-
- result = CPP_COLLECTION_TYPE_IO_METHOD_SUFFIX_MAP[type(ttype)]+"_"
-
- if isinstance(ttype, MapType):
- result+= "k_"+typeToIOMethodSuffix(ttype.keyType)+"_"
-
- result += "v_"+typeToIOMethodSuffix(ttype.valueType)
-
- return result
-
- elif isinstance(ttype, StructType):
- return "struct_"+ttype.name
-
- elif isinstance(ttype, TypedefType):
- return ttype.name
-
- elif isinstance(ttype, EnumType):
- return ttype.name
-
- else:
- raise Exception, "Unknown type "+str(ttype)
-
-def toReaderCall(value, ttype, reader="iprot", transport="itrans"):
- """Converts type to a name suitable as a suffix with TProtocol primitive read methods or with a generated read
-method for a complex type"""
-
- suffix = typeToIOMethodSuffix(ttype)
-
- if isinstance(ttype, PrimitiveType):
- if ttype != VOID_TYPE:
- return "xfer += "+reader+"->read"+suffix+"("+transport+", "+value+")"
- else:
- return ""
-
- elif isinstance(ttype, CollectionType):
- return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
-
- elif isinstance(ttype, StructType):
- return "xfer+= read_"+suffix+"("+reader+", "+transport+", "+value+")"
-
- elif isinstance(ttype, TypedefType):
- return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, reader)
-
- elif isinstance(ttype, EnumType):
- return toReaderCall("reinterpret_cast<"+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, reader)
-
- else:
- raise Exception, "Unknown type "+str(ttype)
-
-def toWriterCall(value, ttype, writer="oprot", transport="otrans"):
- """Converts type to a name suitable as a suffix with TProtocol primitive write methods or with a generated write
-method for a complex type"""
-
- suffix = typeToIOMethodSuffix(ttype)
-
- if isinstance(ttype, PrimitiveType):
- if ttype != VOID_TYPE:
- return "xfer+= "+writer+"->write"+suffix+"("+transport+", "+value+")"
- else:
- return ""
-
- elif isinstance(ttype, CollectionType):
- return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
-
- elif isinstance(ttype, StructType):
- return "xfer+= write_"+suffix+"("+writer+", "+transport+", "+value+")"
-
- elif isinstance(ttype, TypedefType):
- return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(ttype.definitionType)+"&>("+value+")", ttype.definitionType, writer)
-
- elif isinstance(ttype, EnumType):
- return toWriterCall("reinterpret_cast<const "+toCTypeDeclaration(I32_TYPE)+"&>("+value+")", I32_TYPE, writer)
-
- else:
- raise Exception, "Unknown type "+str(ttype)
-
-CPP_READ_MAP_DEFINITION = Template("""
-uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
-
- uint32_t count;
- ${keyType} key;
- ${valueType} elem;
- uint32_t xfer = 0;
- """+CPP_PROTOCOL_TTYPE+""" keyType;
- """+CPP_PROTOCOL_TTYPE+""" valueType;
-
- xfer += iprot->readMapBegin(itrans, keyType, valueType, count);
-
- /* XXX
- Should we assert that read key and value type are correct? */
-
- for(uint32_t ix = 0; ix < count; ix++) {
- ${keyReaderCall};
- ${valueReaderCall};
- value.insert(std::make_pair(key, elem));
- }
-
- xfer += iprot->readMapEnd(itrans);
-
- return xfer;
-}
-""")
-
-CPP_WRITE_MAP_DEFINITION = Template("""
-uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
-
- uint32_t xfer = 0;
-
- xfer += oprot->writeMapBegin(otrans, ${keyWireType}, ${valueWireType}, value.size());
-
- for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
- ${keyWriterCall};
- ${valueWriterCall};
- }
-
- xfer += oprot->writeMapEnd(otrans);
- return xfer;
-}
-""")
-
-CPP_READ_LIST_DEFINITION = Template("""
-uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
-
- uint32_t count;
- ${valueType} elem;
- uint32_t xfer = 0;
- """+CPP_PROTOCOL_TTYPE+""" valueType;
-
- xfer += iprot->read${protocolSuffix}Begin(itrans, valueType, count);
-
- /* XXX
- Should we assert that read value type is correct? */
-
- xfer+= iprot->readU32(itrans, count);
-
- for(uint32_t ix = 0; ix < count; ix++) {
- ${valueReaderCall};
- value.${insert}(elem);
- }
-
- xfer += iprot->read${protocolSuffix}End(itrans);
- return xfer;
-}
-""")
-
-CPP_WRITE_LIST_DEFINITION = Template("""
-uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
-
- uint32_t xfer = 0;
-
- xfer+= oprot->write${protocolSuffix}Begin(otrans, ${valueWireType}, value.size());
-
- for(${declaration}::const_iterator ix = value.begin(); ix != value.end(); ++ix) {
- ${valueWriterCall};
- }
-
- xfer+= oprot->write${protocolSuffix}End(otrans);
-
- return xfer;
-}
-""")
-
-def toCollectionReaderDefinition(collection):
- """Converts collection type to reader function definition"""
-
- suffix = typeToIOMethodSuffix(collection)
-
- if isinstance(collection, MapType):
- keyReaderCall = toReaderCall("key", collection.keyType)
-
- valueReaderCall= toReaderCall("elem", collection.valueType)
-
- if isinstance(collection, MapType):
- return CPP_READ_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
- keyType=toCTypeDeclaration(collection.keyType),
- keyReaderCall=keyReaderCall,
- valueType=toCTypeDeclaration(collection.valueType),
- valueReaderCall=valueReaderCall)
-
- else:
- if isinstance(collection, ListType):
- protocolSuffix="List"
- insert="push_back"
- else:
- protocolSuffix="Set"
- insert="insert"
-
- return CPP_READ_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
- protocolSuffix=protocolSuffix,
- valueReaderCall=valueReaderCall,
- valueType=toCTypeDeclaration(collection.valueType),
- insert=insert)
-
-
-def toCollectionWriterDefinition(collection):
- """Converts collection type to writer function definition"""
-
- suffix = typeToIOMethodSuffix(collection)
-
- if isinstance(collection, MapType):
- keyWriterCall = toWriterCall("ix->first", collection.keyType)
- keyWireType = toWireType(collection.keyType)
- valueWriterCall = toWriterCall("ix->second", collection.valueType)
-
- else:
- valueWriterCall= toWriterCall("*ix", collection.valueType)
-
- valueWireType = toWireType(collection.valueType)
-
- if isinstance(collection, MapType):
- return CPP_WRITE_MAP_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
- keyType=toCTypeDeclaration(collection.keyType),
- keyWireType=keyWireType,
- keyWriterCall=keyWriterCall,
- valueType=toCTypeDeclaration(collection.valueType),
- valueWireType=valueWireType,
- valueWriterCall=valueWriterCall)
-
- else:
- if isinstance(collection, ListType):
- protocolSuffix = "List"
- elif isinstance(collection, SetType):
- protocolSuffix = "Set"
- else:
- raise Exception, "Unknown collection type "+str(type(collection))+":"+str(collection)
-
- return CPP_WRITE_LIST_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(collection),
- protocolSuffix=protocolSuffix,
- valueWireType=valueWireType,
- valueWriterCall=valueWriterCall,
- valueType=toCTypeDeclaration(collection.valueType))
-
-
-CPP_READ_STRUCT_DEFINITION = Template("""
-uint32_t read_${suffix}("""+CPP_PROTOCOLP+""" iprot, """+CPP_TRANSPORTP+""" itrans, ${declaration}& value) {
-
- std::string name;
- """+CPP_PROTOCOL_TTYPE+""" type;
- int16_t id;
- uint32_t xfer = 0;
-
- xfer+= iprot->readStructBegin(itrans, name);
-
- while(true) {
-
- xfer+= iprot->readFieldBegin(itrans, name, type, id);
-
- if(type == """+CPP_PROTOCOL_TSTOP+""") {break;}
-
- switch(id) {
-${fieldSwitch}
- default: xfer += iprot->skip(itrans, type); break;
- }
-
- xfer+= iprot->readFieldEnd(itrans);
- }
-
- xfer+= iprot->readStructEnd(itrans);
-
- return xfer;
-}
-""")
-
-CPP_WRITE_FIELD_DEFINITION = Template("""oprot->writeFieldBegin(otrans, \"${name}\", ${type}, ${id}); ${fieldWriterCall}; oprot->writeFieldEnd(otrans)""")
-
-CPP_WRITE_STRUCT_DEFINITION = Template("""
-uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
-
- uint32_t xfer = 0;
-
- xfer+= oprot->writeStructBegin(otrans, \"${name}\");
-${fieldWriterCalls}
- xfer+= oprot->writeFieldStop(otrans);
- xfer += oprot->writeStructEnd(otrans);
- return xfer;
-}
-""")
-
-def toStructReaderDefinition(struct):
- """Converts struct type to reader function definition"""
-
- suffix = typeToIOMethodSuffix(struct)
-
- # Sort field list in order of increasing ids
-
- fieldList = []
- fieldList+= struct.fieldList
-
- fieldList.sort(lambda a,b: a.id - b.id)
-
- fieldSwitch=""
-
- for field in fieldList:
- if isVoidType(field.type):
- continue;
- fieldSwitch+= " case "+str(field.id)+": "
- fieldSwitch+= toReaderCall("value."+field.name, field.type)+"; value.__isset."+field.name+" = true; break;\n"
-
- return CPP_READ_STRUCT_DEFINITION.substitute(suffix=suffix, declaration=toCTypeDeclaration(struct), fieldSwitch=fieldSwitch)
-
-
-def toStructWriterDefinition(struct):
- """Converts struct type to writer function definition"""
-
- suffix = typeToIOMethodSuffix(struct)
-
- fieldWriterCalls = []
-
- fieldWriterCalls = [CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
- type=toWireType(toCanonicalType(field.type)),
- id=field.id,
- fieldWriterCall=toWriterCall("value."+field.name, field.type))+";"
- for field in struct.fieldList if not isVoidType(field.type)
- ]
-
- fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n ")
-
- return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
-
-CPP_WRITE_RESULT_STRUCT_DEFINITION = Template("""
-uint32_t write_${suffix}("""+CPP_PROTOCOLP+""" oprot, """+CPP_TRANSPORTP+""" otrans, const ${declaration}& value) {
-
- uint32_t xfer = 0;
-
- xfer+= oprot->writeStructBegin(otrans, \"${name}\");
- if(${value}.__isset.x)
-${fieldWriterCalls}
- xfer+= oprot->writeFieldStop(otrans);
- xfer += oprot->writeStructEnd(otrans);
- return xfer;
-}
-""")
-
-def toResultStructReaderDefinition(struct):
- """Converts internal results struct to a reader function definition"""
-
- return toStructReaderDefinition(struct)
-
-def toResultStructWriterDefinition(struct):
- """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"""
-
- suffix = typeToIOMethodSuffix(struct)
-
- fieldWriterCalls = ["if(value.__isset."+field.name+") { "+
- CPP_WRITE_FIELD_DEFINITION.substitute(name=field.name,
- type=toWireType(toCanonicalType(field.type)),
- id=field.id,
- fieldWriterCall=toWriterCall("value."+field.name, field.type))+";}"
- for field in struct.fieldList if not isVoidType(field.type)]
-
- fieldWriterCalls = " "+string.join(fieldWriterCalls, "\n else ")
-
- return CPP_WRITE_STRUCT_DEFINITION.substitute(name=struct.name, suffix=suffix, declaration=toCTypeDeclaration(struct), fieldWriterCalls=fieldWriterCalls)
-
-def toReaderDefinition(ttype):
- """Converts thrift type to a reader function definition"""
-
- if isinstance(ttype, CollectionType):
- return toCollectionReaderDefinition(ttype)
-
- elif isinstance(ttype, StructType):
- return toStructReaderDefinition(ttype)
-
- elif isinstance(ttype, TypedefType):
- return ""
-
- elif isinstance(ttype, EnumType):
- return ""
-
- else:
- raise Exception, "Unsupported type: "+str(ttype)
-
-def toWriterDefinition(ttype):
- """Converts thrift type to a writer function definition"""
-
- if isinstance(ttype, CollectionType):
- return toCollectionWriterDefinition(ttype)
-
- elif isinstance(ttype, StructType):
- return toStructWriterDefinition(ttype)
-
- elif isinstance(ttype, TypedefType):
- return ""
-
- elif isinstance(ttype, EnumType):
- return ""
-
- else:
- raise Exception, "Unsupported type: "+str(ttype)
-
-def toOrderedIOList(ttype, result=None):
- """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
-generate read/write methods without making forward references."""
-
- if not result:
- result = []
-
- if ttype in result:
- return result
-
- elif isinstance(ttype, PrimitiveType):
- return result
-
- elif isinstance(ttype, CollectionType):
-
- if isinstance(ttype, MapType):
- result = toOrderedIOList(ttype.keyType, result)
-
- result = toOrderedIOList(ttype.valueType, result)
-
- result.append(ttype)
-
- elif isinstance(ttype, StructType):
- for field in ttype.fieldList:
- result = toOrderedIOList(field.type, result)
- result.append(ttype)
-
- elif isinstance(ttype, TypedefType):
- result.append(ttype)
- return result
-
- elif isinstance(ttype, EnumType):
- result.append(ttype)
- return result
-
- elif isinstance(ttype, Program):
-
- for struct in ttype.structMap.values():
- result = toOrderedIOList(struct, result)
-
- for service in ttype.serviceMap.values():
- result = toOrderedIOList(service, result)
-
- elif isinstance(ttype, Service):
- for function in ttype.functionList:
- result = toOrderedIOList(function, result)
-
- elif isinstance(ttype, Function):
- result = toOrderedIOList(ttype.returnType(), result)
-
- # skip the args struct itself and just order the arguments themselves
- # we don't want the arg struct to be referred to until later, since we need to
- # inline those struct definitions with the implementation, not in the types header
-
- for field in ttype.args():
- result = toOrderedIOList(field.type, result)
-
- else:
- raise Exception, "Unsupported thrift type: "+str(ttype)
-
- return result
-
-def toIOMethodImplementations(program):
- """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
-all service functions"""
-
- # get ordered list of all types that need marshallers:
-
- iolist = toOrderedIOList(program)
-
- result = ""
-
- for ttype in iolist:
- result+= toReaderDefinition(ttype)
- result+= toWriterDefinition(ttype)
-
- # For all function argument lists, we need to create both struct definitions
- # and io methods. We keep the struct definitions local, since they aren't part of the service API
- #
- # Note that we don't need to do a depth-first traverse of arg structs since they can only include fields
- # we've already seen
-
- for service in program.serviceMap.values():
- for function in service.functionList:
- result+= toStructDefinition(function.argsStruct)
- result+= toReaderDefinition(function.argsStruct)
- result+= toWriterDefinition(function.argsStruct)
- result+= toStructDefinition(function.resultStruct)
- result+= toResultStructReaderDefinition(function.resultStruct)
- result+= toResultStructWriterDefinition(function.resultStruct)
-
- return result;
-
-def toImplementationSourceName(filename, genDir=None, debugp=None):
- """Creates a file name for the implementation of client stubs, server skeletons, and non-primitive read/write methods."""
-
- if not genDir:
- genDir = toGenDir(filename)
-
- basename = toBasename(filename)
-
- result = os.path.join(genDir, basename+".cc")
-
- if debugp:
- debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
-
- return result
-
-def writeImplementationSource(program, filename, genDir=None, debugp=None):
- """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
-thrift source, filename, and the optional generated C++ code directory, genDir, to determine the name and location of header file"""
-
- implementationSource = toImplementationSourceName(filename, genDir)
-
- if debugp:
- debugp("implementationSource: "+str(implementationSource))
-
- cfile = CFile(implementationSource, "w")
-
- basename = toBasename(filename)
-
- cfile.writeln(CPP_IMPL_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toCNamespacePrefix(program.namespace)))
-
- cfile.write(toIOMethodImplementations(program))
-
- cfile.write(toServerDefinition(program))
-
- cfile.write(toClientDefinition(program))
-
- cfile.writeln(CPP_IMPL_FOOTER.substitute(source=basename, namespaceSuffix=toCNamespaceSuffix(program.namespace)))
-
- cfile.close()
-
-class CPPGenerator(Generator):
-
- def __call__(self, program, filename, genDir=None, debugp=None):
-
- writeDefinitionHeader(program, filename, genDir, debugp)
-
- writeServicesHeader(program, filename, genDir, debugp)
-
- writeImplementationSource(program, filename, genDir, debugp)
+++ /dev/null
-class Generator(object):
- def __call__(self, program, filename, gendir, debugp=None):
- raise Exception, "Not implemented"
+++ /dev/null
-#!python
-""" Thrift IDL parser/compiler
-
- This parser uses the Python PLY LALR parser generator to build a parser for the Thrift IDL grammar.
-
- If a compiles \"thyc\" file exists for a given source \"thrift\" file it computes a hash of the file and determines
- if if it is the source of the \"thyc\" file. If so, it simply returns the parse tree previously computed, otherwise it
- parses the source and generates a new \"thyc\" file (assuming of course the source file contains no errors.)
-
- When the parser encounters import statements it searches for corresponding \"thrift\" or \"thyc\" files in paths corresponding to
- the specified namespace.
-
- Author(s): Mark Slee(mclee@facebook.com), Marc Kwiatkowski (marc@facebook.com)
-
- $Id:
-"""
-
-import lex
-import os
-import pickle
-import string
-import yacc
-
-class Error(object):
-
- def __init__(self, start=0, end=0, message=""):
- if len(message) == 0:
- raise Exception, "NO MESSAGE"
- self.message = message
- self.start = start
- self.end = end
-
- def __str__(self):
- return str(self.start)+": error: "+self.message
-
-class SyntaxError(Error):
- def __init__(self, yaccSymbol):
- if isinstance(yaccSymbol, yacc.YaccSymbol):
- Error.__init__(self, yaccSymbol.lineno, yaccSymbol.lineno, "syntax error "+str(yaccSymbol.value))
- else:
- Error.__init__(self, 1, 1, "syntax error "+str(yaccSymbol))
-
-class SymanticsError(Error):
-
- def __init__(self, definition, message):
- Error.__init__(self, definition.start, definition.end, message)
- self.definition = definition
-
- def __str__(self):
- return str(self.start)+": error: "+self.message
-
-class ErrorException(Exception):
- def __init__(self, errors=None):
- Exception.__init__(self)
- self.errors = errors
-
-class Definition(object):
- """ Abstract thrift IDL definition unit """
-
- def __init__(self, symbols=None, name="", id=None):
- if symbols:
- self.lines(symbols)
- self.name = name
- self.id = id
-
- def validate(self):
- pass
-
- def lines(self, symbols):
- self.start = symbols.lineno(1)
- self.end = symbols.lineno(len(symbols) - 1)
-
-class Identifier(Definition):
- """ An Identifier - name and optional integer id """
-
- def __init__(self, symbols, name, id=None):
- Definition.__init__(self, symbols, name, id)
-
- def __str__(self):
- result = self.name
- if self.id != 0:
- result+="="+str(self.id)
- return result
-
-def toCanonicalType(ttype):
- if isinstance(ttype, TypedefType):
- return toCanonicalType(ttype.definitionType)
- else:
- return ttype
-
-def isVoidType(ttype):
- """Is canonnical type of the specified type void?"""
- return toCanonicalType(ttype) == VOID_TYPE
-
-def isComparableType(ttype):
- """Is the type one that is implicitly comparable and thus is suitable for use in C++ maps and sets and java Sets and Maps?"""
- ttype = toCanonicalType(ttype)
- return isinstance(ttype, PrimitiveType) or isinstance(ttype, EnumType)
-
-class Type(Definition):
- """ Abstract Type definition """
-
- def __init__(self, symbols, name):
- Definition.__init__(self, symbols, name)
- self.name = name
-
- def __str__(self):
- return self.name
-
-class TypedefType(Type):
-
- def __init__(self, symbols, name, definitionType):
- Type.__init__(self, symbols, name)
- self.definitionType = definitionType
-
- def __str__(self):
- return self.name+"<"+str(self.name)+", "+str(self.definitionType)+">"
-
-""" Primitive Types """
-
-class PrimitiveType(Type):
-
- def __init__(self, name):
- Type.__init__(self, None, name)
-
-STOP_TYPE = PrimitiveType("stop")
-VOID_TYPE = PrimitiveType("void")
-BOOL_TYPE = PrimitiveType("bool")
-STRING_TYPE = PrimitiveType("utf7")
-UTF7_TYPE = STRING_TYPE
-UTF8_TYPE = PrimitiveType("utf8")
-UTF16_TYPE = PrimitiveType("utf16")
-BYTE_TYPE = PrimitiveType("u08")
-I08_TYPE = PrimitiveType("i08")
-I16_TYPE = PrimitiveType("i16")
-I32_TYPE = PrimitiveType("i32")
-I64_TYPE = PrimitiveType("i64")
-U08_TYPE = PrimitiveType("u08")
-U16_TYPE = PrimitiveType("u16")
-U32_TYPE = PrimitiveType("u32")
-U64_TYPE = PrimitiveType("u64")
-FLOAT_TYPE = PrimitiveType("float")
-DOUBLE_TYPE = PrimitiveType("double")
-
-PRIMITIVE_MAP = {
- "stop" : STOP_TYPE,
- "void" : VOID_TYPE,
- "bool" : BOOL_TYPE,
- "string": UTF7_TYPE,
- "utf7": UTF7_TYPE,
- "utf8": UTF8_TYPE,
- "utf16": UTF16_TYPE,
- "byte" : U08_TYPE,
- "i08": I08_TYPE,
- "i16": I16_TYPE,
- "i32": I32_TYPE,
- "i64": I64_TYPE,
- "u08": U08_TYPE,
- "u16": U16_TYPE,
- "u32": U32_TYPE,
- "u64": U64_TYPE,
- "float": FLOAT_TYPE,
- "double": DOUBLE_TYPE
-}
-
-""" Collection Types """
-
-class CollectionType(Type):
-
- def __init__(self, symbols, name):
- Type.__init__(self, symbols, name)
-
- def validate(self):
- return True
-
-class MapType(CollectionType):
-
- def __init__(self, symbols, keyType, valueType):
- CollectionType.__init__(self, symbols, "map<"+keyType.name+","+valueType.name +">")
- self.keyType = keyType
- self.valueType = valueType
-
- def validate(self):
- if not isComparableType(self.keyType):
- raise ErrorException([SymanticsError(self, "key type \""+str(self.keyType)+"\" is not a comparable type.")])
-
-class SetType(CollectionType):
-
- def __init__(self, symbols, valueType):
- CollectionType.__init__(self, symbols, "set<"+valueType.name+">")
- self.valueType = valueType
-
- def validate(self):
- if not isComparableType(self.valueType):
- raise ErrorException([SymanticsError(self, "value type \""+str(self.valueType)+"\" is not a comparable type.")])
-
-class ListType(CollectionType):
-
- def __init__(self, symbols, valueType):
- CollectionType.__init__(self, symbols, "list<"+valueType.name+">")
- self.valueType = valueType
-
-class EnumType(Definition):
-
- def __init__(self, symbols, name, enumDefs):
- Definition.__init__(self, symbols, name)
- self.enumDefs = enumDefs
-
- def validate(self):
- ids = {}
- names = {}
- errors = []
-
- for enumDef in self.enumDefs:
-
- if enumDef.name in names:
- errors.append(SymanticsError(enumDef, self.name+"."+str(enumDef.name)+" already defined at line "+str(names[enumDef.name].start)))
- else:
- names[enumDef.name] = enumDef
-
- if enumDef.id != None:
- oldEnumDef = ids.get(enumDef.id)
- if oldEnumDef:
- errors.append(SymanticsError(enumDef, "enum "+self.name+" \""+str(enumDef.name)+"\" uses constant already assigned to \""+oldEnumDef.name+"\""))
- else:
- ids[enumDef.id] = enumDef
-
- if len(errors):
- raise ErrorException(errors)
-
- def assignId(enumDef, currentId, ids):
- 'Finds the next available id number for an enum definition'
-
- eid= currentId + 1
-
- while eid in ids:
- eid += 1
-
- enumDef.id = eid
-
- ids[enumDef.id] = enumDef
-
- return eid
-
- # assign ids for all enum defs with unspecified ids
-
- currentId = 0
-
- for enumDef in self.enumDefs:
- if not enumDef.id:
- assignId(enumDef, currentId, ids)
- currentId = enumDef.id
-
- def __repr__(self):
- return str(self)
-
- def __str__(self):
- return self.name+"<"+string.join(map(lambda enumDef: str(enumDef), self.enumDefs), ", ")
-
-class EnumDef(Definition):
-
- def __init__(self, symbols, name, id=None):
- Definition.__init__(self, symbols, name, id)
-
- def __repr__(self):
- return str(self)
-
- def __str__(self):
- result = self.name
- if self.id:
- result+= ":"+str(self.id)
- return result
-
-
-class Field(Definition):
-
- def __init__(self, symbols, type, identifier):
- Definition.__init__(self, symbols, identifier.name, identifier.id)
- self.type = type
- self.identifier = identifier
-
- def __str__(self):
- return "<"+str(self.type)+", "+str(self.identifier)+">"
-
-def validateFieldList(fieldList):
-
- errors = []
- names = {}
- ids = {}
-
- for field in fieldList:
-
- if field.name in names:
- oldField = names[field.name]
- errors.append(SymanticsError(field, "field \""+field.name+"\" already defined at "+str(oldField.start)))
- else:
- names[field.name] = field
-
- if field.id != None:
- oldField = ids.get(field.id)
- if oldField:
- errors.append(SymanticsError(field, "field \""+field.name+"\" uses constant already assigned to \""+oldField.name+"\""))
- else:
- ids[field.id] = field
-
- if len(errors):
- raise ErrorException(errors)
-
- def assignId(field, currentId, ids):
- 'Finds the next available id number for a field'
- fid = currentId - 1
-
- while fid in ids:
- fid-= 1
-
- field.id = fid
-
- ids[field.id] = field
-
- return fid
-
- # assign ids for all fields with unspecified ids
-
- currentId = 0
-
- for field in fieldList:
- if not field.id:
- currentId = assignId(field, currentId, ids)
-
-class StructType(Type):
-
- def __init__(self, symbols, name, fieldList):
- Type.__init__(self, symbols, name)
- self.fieldList = fieldList
-
- def validate(self):
- validateFieldList(self.fieldList)
-
- def __str__(self):
- return self.name+"<"+string.join(map(lambda a: str(a), self.fieldList), ", ")+">"
-
-class ExceptionType(StructType):
-
- def __init__(self, symbols, name, fieldList):
- StructType.__init__(self, symbols, name, fieldList)
-
-class Function(Definition):
-
- def __init__(self, symbols, name, resultStruct, argsStruct):
- Definition.__init__(self, symbols, name)
- self.resultStruct = resultStruct
- self.argsStruct = argsStruct
-
- def validate(self):
- validateFieldList(self.argsStruct.fieldList)
- validateFieldList(self.resultStruct.fieldList)
-
- def args(self):
- return self.argsStruct.fieldList
-
- def returnType(self):
- return self.resultStruct.fieldList[0].type
-
- def exceptions(self):
- return self.resultStruct.fieldList[1:]
-
- def __str__(self):
- return self.name+"("+str(self.argsStruct)+") => "+str(self.resultStruct)
-
-class Service(Definition):
-
- def __init__(self, symbols, name, functionList):
- Definition.__init__(self, symbols, name)
- self.functionList = functionList
-
- def validate(self):
-
- errors = []
- functionNames = {}
- for function in self.functionList:
- if function.name in functionNames:
- oldFunction = functionNames[function.name]
- errors.append(SymanticsError(function, "function "+function.name+" already defined at "+str(oldFunction.start)))
-
- if len(errors):
- raise ErrorException(errors)
-
- def __str__(self):
- return self.name+"("+string.join(map(lambda a: str(a), self.functionList), ", ")+")"
-
-class Program(object):
-
- def __init__(self, symbols=None, name="",
- namespace="",
- definitions=None,
- serviceMap=None,
- typedefMap=None,
- enumMap=None, structMap=None,
- collectionMap=None,
- primitiveMap=None):
-
- self.name = name
-
- self.namespace = namespace
-
- if not definitions:
- definitions = []
- self.definitions = definitions
-
- if not serviceMap:
- serviceMap = {}
- self.serviceMap = serviceMap
-
- if not typedefMap:
- typedefMap = {}
- self.typedefMap = typedefMap
-
- if not enumMap:
- enumMap = {}
- self.enumMap = enumMap
-
- if not structMap:
- structMap = {}
- self.structMap = structMap
-
- if not collectionMap:
- collectionMap = {}
- self.collectionMap = collectionMap
-
- if not primitiveMap:
- primitiveMap = PRIMITIVE_MAP
- self.primitiveMap = primitiveMap
-
- def addDefinition(self, definition, definitionMap, definitionTypeName):
-
- oldDefinition = definitionMap.get(definition.name)
- if oldDefinition:
- raise ErrorException([SymanticsError(definition, definitionTypeName+" "+definition.name+" is already defined at "+str(oldDefinition.start))])
- else:
- definitionMap[definition.name] = definition
-
- # keep an ordered list of definitions so that stub/skel generators can determine the original order
-
- self.definitions.append(definition)
-
- def addStruct(self, struct):
- self.addDefinition(struct, self.structMap, "struct")
-
- def addTypedef(self, typedef):
- self.addDefinition(typedef, self.typedefMap, "typedef")
-
- def addEnum(self, enum):
- self.addDefinition(enum, self.enumMap, "enum")
-
- def addService(self, service):
- self.addDefinition(service, self.serviceMap, "service")
-
- def addCollection(self, collection):
- if collection.name in self.collectionMap:
- return self.collectionMap[collection.name]
- else:
- self.collectionMap[collection.name] = collection
- return collection
-
- def getType(self, parent, symbol):
- """ Get the type definition for a symbol"""
-
- typeName = None
-
- if isinstance(symbol, Type):
- return symbol
- elif isinstance(symbol, Field):
- typeName = symbol.type.name
- elif isinstance(symbol, Identifier):
- typeName = symbol.name
- else:
- raise ErrorException([SymanticsError(parent, "unknown symbol \""+str(symbol)+"\"")])
-
- for tmap in (self.primitiveMap, self.collectionMap, self.typedefMap, self.enumMap, self.structMap):
- if typeName in tmap:
- return tmap[typeName]
-
- raise ErrorException([SymanticsError(parent, "\""+typeName+"\" is not defined.")])
-
- def hasType(self, parent, symbol):
- """ Determine if a type definition exists for the symbol"""
-
- return self.getType(parent, symbol) != None
-
- def validate(self):
-
- errors = []
-
- # Verify that struct fields types, collection key and element types, and typedef defined types exists and replaces
- # type names with references to the type objects
-
- for struct in self.structMap.values():
- for field in struct.fieldList:
- try:
- field.type = self.getType(struct, field)
- except ErrorException, e:
- errors+= e.errors
-
- for collection in self.collectionMap.values():
- try:
- if isinstance(collection, MapType):
- collection.keyType = self.getType(collection, collection.keyType)
-
- collection.valueType = self.getType(collection, collection.valueType)
-
- collection.validate()
-
- except ErrorException, e:
- errors+= e.errors
-
- for typedef in self.typedefMap.values():
- try:
- typedef.definitionType = self.getType(self, typedef.definitionType)
-
- except ErrorException, e:
- errors+= e.errors
-
- # Verify that service function result and arg list types exist and replace type name with reference to definition
-
- for service in self.serviceMap.values():
-
- for function in service.functionList:
-
- for field in function.resultStruct.fieldList:
- try:
- field.type = self.getType(function, field)
- except ErrorException, e:
- errors+= e.errors
-
- for field in function.argsStruct.fieldList:
- try:
- field.type = self.getType(function, field)
- except ErrorException, e:
- errors+= e.errors
-
- if len(errors):
- raise ErrorException(errors)
-
- def validateNamespace(self, namespace):
-
- if self.namespace != "":
- raise ErrorException([SymanticsError, self, "namespace already defined as \""+self.namespace+"\""])
- self.namespace = namespace
-
-class Parser(object):
-
- reserved = ("BYTE",
- # "CONST",
- "DOUBLE",
- "ENUM",
- "EXCEPTION",
- # "EXTENDS",
- "I08",
- "I16",
- "I32",
- "I64",
- "LIST",
- "MAP",
- "NAMESPACE",
- "SERVICE",
- "SET",
- # "STATIC",
- "STRING",
- "STRUCT",
- # "SYNCHRONIZED",
- "THROWS",
- "TYPEDEF",
- "U08",
- "U16",
- "U32",
- "U64",
- "UTF16",
- "UTF8",
- "VOID"
- )
-
- tokens = reserved + (
- # Literals (identifier, integer constant, float constant, string constant, char const)
- 'ID', 'ICONST', # 'SCONST', 'FCONST',
- # Operators default=, optional*, variable...
- 'ASSIGN', #'OPTIONAL', 'ELLIPSIS',
- # Delimeters ( ) { } < > , . ; :
- 'LPAREN', 'RPAREN',
- 'LBRACE', 'RBRACE',
- 'LANGLE', 'RANGLE',
- 'COMMA', 'PERIOD' #, 'SEMI' , 'COLON'
- )
-
- precendence = ()
-
- reserved_map = {}
-
- for r in reserved:
- reserved_map[r.lower()] = r
-
- def t_ID(self, t):
- r'[A-Za-z_][\w_]*'
- t.type = self.reserved_map.get(t.value,"ID")
- return t
-
- # Completely ignored characters
- t_ignore = ' \t\x0c'
-
-# t_OPTIONAL = r'\*'
- t_ASSIGN = r'='
-
- # Delimeters
- t_LPAREN = r'\('
- t_RPAREN = r'\)'
- t_LANGLE = r'\<'
- t_RANGLE = r'\>'
- t_LBRACE = r'\{'
- t_RBRACE = r'\}'
- t_COMMA = r','
- t_PERIOD = r'\.'
-# t_SEMI = r';'
-# t_COLON = r':'
-# t_ELLIPSIS = r'\.\.\.'
-
- # Integer literal
- t_ICONST = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
-
- # Floating literal
-# t_FCONST = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
-
- # String literal
-# t_SCONST = r'\"([^\\\n]|(\\.))*?\"'
-
- # Comments
- def t_comment(self, t):
- r'(?:/\*(.|\n)*?\*/)|(?://[^\n]*\n)'
- t.lineno += t.value.count('\n')
-
- def t_error(self, t):
- print "Illegal character %s" % repr(t.value[0])
- t.skip(1)
-
- # Newlines
- def t_newline(self, t):
- r'\n+'
- t.lineno += t.value.count("\n")
-
- def p_program(self, p):
- 'program : definitionlist'
- pass
-
- def p_definitionlist_1(self, p):
- 'definitionlist : definitionlist definition'
- pass
-
- def p_definitionlist_2(self, p):
- 'definitionlist :'
- pass
-
- def p_definition_1(self, p):
- 'definition : typedef'
- self.pdebug("p_definition_1", p)
- p[0] = p[1]
- try:
- self.program.addTypedef(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_definition_2(self, p):
- 'definition : enum'
- self.pdebug("p_definition_2", p)
- p[0] = p[1]
- try:
- self.program.addEnum(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_definition_3(self, p):
- 'definition : struct'
- self.pdebug("p_definition_3", p)
- p[0] = p[1]
- try:
- self.program.addStruct(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_definition_4(self, p):
- 'definition : service'
- self.pdebug("p_definition_4", p)
- p[0] = p[1]
- try:
- self.program.addService(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_definition_5(self, p):
- 'definition : exception'
- self.pdebug("p_definition_5", p)
- p[0] = p[1]
- try:
- self.program.addStruct(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_definition_6(self, p):
- 'definition : namespace'
- self.pdebug("p_definition_6", p)
- p[0] = p[1]
-
- def p_typedef(self, p):
- 'typedef : TYPEDEF definitiontype ID'
- self.pdebug("p_typedef", p)
- p[0] = TypedefType(p, p[3], p[2])
- try:
- p[0].validate()
-
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_enum(self, p):
- 'enum : ENUM ID LBRACE enumdeflist RBRACE'
- self.pdebug("p_enum", p)
- p[0] = EnumType(p, p[2], p[4])
-
- try:
- p[0].validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_enumdeflist_1(self, p):
- 'enumdeflist : enumdeflist COMMA enumdef'
- self.pdebug("p_enumdeflist_1", p)
- p[0] = p[1] + (p[3],)
-
- def p_enumdeflist_2(self, p):
- 'enumdeflist : enumdef'
- self.pdebug("p_enumdeflist_2", p)
- p[0] = (p[1],)
-
- def p_enumdef_0(self, p):
- 'enumdef : ID ASSIGN ICONST'
- self.pdebug("p_enumdef_0", p)
- p[0] = EnumDef(p, p[1], int(p[3]))
-
- def p_enumdef_1(self, p):
- 'enumdef : ID'
- self.pdebug("p_enumdef_1", p)
- p[0] = EnumDef(p, p[1])
-
- def p_struct(self, p):
- 'struct : STRUCT ID LBRACE fieldlist RBRACE'
- self.pdebug("p_struct", p)
- p[0] = StructType(p, p[2], p[4])
-
- try:
- p[0].validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_exception(self, p):
- 'exception : EXCEPTION ID LBRACE fieldlist RBRACE'
- self.pdebug("p_struct", p)
- p[0] = ExceptionType(p, p[2], p[4])
-
- try:
- p[0].validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_namespace(self, p):
- 'namespace : NAMESPACE namespacespecifier'
- self.pdebug("p_struct", p)
- p[0] = p[2]
-
- try:
- self.program.validateNamespace(p[0])
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_namespacespecifier_1(self, p):
- 'namespacespecifier : ID'
- self.pdebug("p_namespacespecifier", p)
- p[0] = p[1]
-
- def p_namespacespecifier_2(self, p):
- 'namespacespecifier : ID PERIOD namespacespecifier'
- self.pdebug("p_namespacespecifier", p)
- p[0] = p[1]+"."+p[3]
-
- def p_service(self, p):
- 'service : SERVICE ID LBRACE functionlist RBRACE'
- self.pdebug("p_service", p)
- p[0] = Service(p, p[2], p[4])
- try:
- p[0].validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_functionlist_1(self, p):
- 'functionlist : function COMMA functionlist'
- self.pdebug("p_functionlist_1", p)
- p[0] = (p[1],) + p[3]
-
- def p_functionlist_2(self, p):
- 'functionlist : function'
- self.pdebug("p_functionlist_2", p)
- p[0] = (p[1],)
-
- def p_functionlist_3(self, p):
- 'functionlist : '
- self.pdebug("p_functionlist_3", p)
- p[0] = ()
-
- def p_function(self, p):
- 'function : functiontype functionmodifiers ID LPAREN fieldlist RPAREN exceptionspecifier'
- self.pdebug("p_function", p)
-
- resultStruct = StructType(p, p[3]+"_result", (Field(p, p[1], Identifier(None, "success", 0)),)+p[7])
-
- p[0] = Function(p, p[3], resultStruct, StructType(p, p[3]+"_args", p[5]))
- try:
- p[0].validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- def p_functionmodifiers(self, p):
- 'functionmodifiers :'
- self.pdebug("p_functionmodifiers", p)
- p[0] = ()
-
- def p_fieldlist_1(self, p):
- 'fieldlist : field COMMA fieldlist'
- self.pdebug("p_fieldlist_1", p)
- p[0] = (p[1],) + p[3]
-
- def p_fieldlist_2(self, p):
- 'fieldlist : field'
- self.pdebug("p_fieldlist_2", p)
- p[0] = (p[1],)
-
- def p_fieldlist_3(self, p):
- 'fieldlist :'
- self.pdebug("p_fieldlist_3", p)
- p[0] = ()
-
- def p_field_1(self, p):
- 'field : fieldtype ID ASSIGN ICONST'
- self.pdebug("p_field_1", p)
- p[0] = Field(p, p[1], Identifier(None, p[2], int(p[4])))
-
- def p_field_2(self, p):
- 'field : fieldtype ID'
- self.pdebug("p_field_2", p)
- p[0] = Field(p, p[1], Identifier(None, p[2]))
-
- def p_exceptionSpecifier_1(self, p):
- 'exceptionspecifier : THROWS LPAREN fieldlist RPAREN'
- self.pdebug("p_exceptionspecifier", p)
- p[0] = p[3]
-
- def p_exceptionSpecifier_2(self, p):
- 'exceptionspecifier : empty'
- self.pdebug("p_exceptionspecifier", p)
- p[0] = ()
-
- def p_definitiontype_1(self, p):
- 'definitiontype : basetype'
- self.pdebug("p_definitiontype_1", p)
- p[0] = p[1]
-
- def p_definitiontype_2(self, p):
- 'definitiontype : collectiontype'
- self.pdebug("p_definitiontype_2", p)
- p[0] = p[1]
-
- def p_functiontype_1(self, p):
- 'functiontype : fieldtype'
- self.pdebug("p_functiontype_1", p)
- p[0] = p[1]
-
- def p_functiontype_2(self, p):
- 'functiontype : VOID'
- self.pdebug("p_functiontype_2", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_fieldtype_1(self, p):
- 'fieldtype : ID'
- self.pdebug("p_fieldtype_1", p)
- p[0] = Identifier(p, p[1])
-
- def p_fieldtype_2(self, p):
- 'fieldtype : basetype'
- self.pdebug("p_fieldtype_2", p)
- p[0] = p[1]
-
- def p_fieldtype_3(self, p):
- 'fieldtype : collectiontype'
- self.pdebug("p_fieldtype_3", p)
- p[0] = p[1]
-
- def p_basetype_1(self, p):
- 'basetype : STRING'
- self.pdebug("p_basetype_1", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_2(self, p):
- 'basetype : BYTE'
- self.pdebug("p_basetype_2", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_3(self, p):
- 'basetype : I08'
- self.pdebug("p_basetype_3", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_4(self, p):
- 'basetype : U08'
- self.pdebug("p_basetype_4", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_5(self, p):
- 'basetype : I16'
- self.pdebug("p_basetype_5", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_6(self, p):
- 'basetype : U16'
- self.pdebug("p_basetype_6", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_7(self, p):
- 'basetype : I32'
- self.pdebug("p_basetype_7", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_8(self, p):
- 'basetype : U32'
- self.pdebug("p_basetype_8", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_9(self, p):
- 'basetype : I64'
- self.pdebug("p_basetype_9", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_10(self, p):
- 'basetype : U64'
- self.pdebug("p_basetype_10", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_11(self, p):
- 'basetype : UTF8'
- self.pdebug("p_basetype_11", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_12(self, p):
- 'basetype : UTF16'
- self.pdebug("p_basetype_12", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_basetype_13(self, p):
- 'basetype : DOUBLE'
- self.pdebug("p_basetype_13", p)
- p[0] = self.program.primitiveMap[p[1].lower()]
-
- def p_collectiontype_1(self, p):
- 'collectiontype : maptype'
- self.pdebug("p_collectiontype_1", p)
- p[0] = self.program.addCollection(p[1])
-
- def p_collectiontype_2(self, p):
- 'collectiontype : settype'
- self.pdebug("p_collectiontype_2", p)
- p[0] = self.program.addCollection(p[1])
-
- def p_collectiontype_3(self, p):
- 'collectiontype : listtype'
- self.pdebug("p_collectiontype_3", p)
- p[0] = self.program.addCollection(p[1])
-
- def p_maptype(self, p):
- 'maptype : MAP LANGLE fieldtype COMMA fieldtype RANGLE'
- self.pdebug("p_maptype", p)
- p[0] = MapType(p, p[3], p[5])
-
- def p_settype(self, p):
- 'settype : SET LANGLE fieldtype RANGLE'
- self.pdebug("p_settype", p)
- p[0] = SetType(p, p[3])
-
- def p_listtype(self, p):
- 'listtype : LIST LANGLE fieldtype RANGLE'
- self.pdebug("p_listtype", p)
- p[0] = ListType(p, p[3])
-
- def p_empty(self, p):
- "empty : "
- pass
-
- def p_error(self, p):
- # p_error is called with an empty token if eof was encountered unexpectedly.
- if not p:
- self.errors.append(SyntaxError("Unexpected end of file"))
- else:
- self.errors.append(SyntaxError(p))
-
- def pdebug(self, name, p):
- if self.debug:
- print(name+"("+string.join(["P["+str(ix)+"]<<"+str(p[ix])+">>" for ix in range(len(p))], ", ")+")")
-
- def __init__(self, **kw):
- self.debug = kw.get('debug', 0)
- self.names = { }
- self.program = Program()
- self.errors = []
-
- try:
- modname = os.path.split(os.path.splitext(__file__)[0])[1] + "_" + self.__class__.__name__
- except:
- modname = "parser"+"_"+self.__class__.__name__
- self.debugfile = modname + ".dbg"
- self.tabmodule = modname + "_" + "parsetab"
- #print self.debugfile, self.tabmodule
-
- # Build the lexer and parser
- lex.lex(module=self, debug=self.debug)
- yacc.yacc(module=self,
- debug=self.debug,
- debugfile=self.debugfile,
- tabmodule=self.tabmodule)
-
- def parsestring(self, s, filename=""):
- yacc.parse(s)
-
- if len(self.errors) == 0:
- try:
- self.program.validate()
- except ErrorException, e:
- self.errors+= e.errors
-
- if len(self.errors):
- for error in self.errors:
- print(filename+":"+str(error))
-
- def parse(self, filename, doPickle=True):
-
- f = file(filename, "r")
-
- self.parsestring(f.read(), filename)
-
- if len(self.errors) == 0 and doPickle:
-
- outf = file(os.path.splitext(filename)[0]+".thyc", "w")
-
- pickle.dump(self.program, outf)
+++ /dev/null
-""" Thrift IDL PHP client stub generator
-
- This generated PHP class definitions and client stubs for a valid thrift IDL definition
-
- Author(s): Mark Slee(mclee@facebook.com), Marc Kwiatkowski (marc@facebook.com)
-
- $Id:
-"""
-import time
-
-import os
-import os.path
-from string import Template
-from thrift.parser import *
-from thrift.generator import *
-
-HEADER_COMMENT = """<?php
-/**
- * Autogenerated by Thrift
- * ${date}
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
- """
-
-PHP_TYPES_HEADER = Template(HEADER_COMMENT+"""
-require_once ${prefix}.'thrift/Thrift.php\';
-""")
-
-PHP_TYPES_FOOTER = Template("""
-?>
-""")
-
-PHP_SERVICES_HEADER = Template(HEADER_COMMENT+"""
-
-require_once dirname(__FILE__).\'/${source}_types.php\';
-require_once ${prefix}.'thrift/protocol/TType.php';
-require_once ${prefix}.'thrift/protocol/TProtocol.php';
-require_once ${prefix}.'thrift/transport/TTransport.php';
-""")
-
-PHP_SERVICES_FOOTER = Template("""
-?>
-""")
-
-PHP_IMPL_HEADER = Template(HEADER_COMMENT+"""
-
-require_once ${prefix}.'thrift/Thrift.php';
-require_once ${prefix}.dirname(__FILE__).\'/${source}_types.php\';
-
-""")
-
-PHP_IMPL_FOOTER = Template("""
-?>
-""")
-
-def php_debug(arg):
- print(arg)
-
-class Indenter(object):
- def __init__(self, margin=4):
- self.margin = ''.join([' ' for ix in range(margin)])
- self.level = 0
-
- def __getitem__(self, level):
- return ''.join([self.margin for ix in range(level)])
-
- def __iadd__(self, value):
- self.level = self.level + value
- return self
-
- def __isub__(self, value):
- self.level = self.level - value
- return self
-
- def __call__(self):
- return self.__getitem__(self.level)
-
-class Variable(object):
- def __init__(self, ttype, name):
- self.ttype = ttype
- self.name = name
-
- def toDeclaration(self, new=False):
- if not new:
- defaultValue = defaultValueForType(self.ttype)
- else:
- defaultValue = newInstanceForType(self.ttype)
- return self.name+" = "+defaultValue
-
-class Scope(object):
- def __init__(self, parent=None):
- self.index = 0
- self.vars = {}
- self.parent = parent
- self.childIndex = 0
- if self.parent:
- self.level = self.parent.level + 1
- self.index = self.parent.childIndex
- self.parent.childIndex+= 1
- self.suffix = self.parent.suffix+str(self.index)
- else:
- self.level = 0
- self.index = 0
- self.suffix = ""
-
- def declare(self, ttype, name):
- if name in self.vars:
- raise Exception, "Variable \""+name+"\" already declared in this scope."
- result = Variable(ttype, "$_"+name+self.suffix)
- self.vars[name] = result
- return result
-
- def get(self, var):
- if var.name in self.vars:
- return self.vars[var.name]
- elif self.parent:
- return self.parent.get(var)
- else:
- raise Exception, "Variable \""+var.name+"\" does not exist in any enclosing scope"
-
-PHP_TYPE_PROTOCOL_MAP = {
- BOOL_TYPE : "Bool",
- STRING_TYPE: "String",
- UTF7_TYPE: "String",
- UTF8_TYPE: "Wstring",
- BYTE_TYPE : "Byte",
- I08_TYPE: "Byte",
- I16_TYPE: "I16",
- I32_TYPE: "I32",
- I64_TYPE: "I64",
- I16_TYPE: "I16",
- I32_TYPE: "I32",
- I64_TYPE: "I64",
- U08_TYPE: "Byte",
- U16_TYPE: "U16",
- U32_TYPE: "U32",
- U64_TYPE: "U64",
- U16_TYPE: "U16",
- U32_TYPE: "U32",
- U64_TYPE: "U64",
- FLOAT_TYPE: "Float",
- DOUBLE_TYPE: "Double"
- }
-
-PHP_PRIMITIVE_TYPE_IO_METHOD_SUFFIX_MAP = {
- "void" :"Void",
- "bool" : "Bool",
- "string": "String",
- "utf7": "String",
- "utf8": "String",
- "utf16": "String",
- "i08": "Byte",
- "i16": "I16",
- "i32": "I32",
- "i64": "I64",
- "u08": "Byte",
- "u16": "U16",
- "u32": "U32",
- "u64": "U64",
- "float": "Float",
- "double": "Double"
-}
-
-class CodeGenerator(object):
- def __init__(self,
- scope=Scope(),
- indent = Indenter()):
- self.scope = scope
- self.indent = indent
-
- def newScope(self):
- self.scope = Scope(self.scope)
-
- def oldScope(self):
- if not self.scope.parent:
- raise Exception, "Unbalanced scope entry/exit"
-
- self.scope = self.scope.parent
-
- def declare(self, type, name, defaultValue=None):
- tvar = self.scope.declare(type, name)
- return tvar
-
- def toDeclaration(self, tvar, new=False):
- if not new:
- defaultValue = defaultValueForType(tvar.ttype)
- else:
- defaultValue = newInstanceForType(tvar.ttype)
-
- return self.indent()+tvar.name+" = "+defaultValue+";\n"
-
-class Reader(CodeGenerator):
- def __init__(self,
- iprot="$this->_iprot",
- itrans="$this->_itrans",
- scope=Scope(),
- indent = Indenter()):
- CodeGenerator.__init__(self, scope, indent)
- self.iprot = iprot
- self.itrans = itrans
-
- def toReadMessageBegin(self, messageNameVar, messageTypeVar, seqidVar):
- return self.indent()+self.iprot+"->readMessageBegin("+self.itrans+", "+messageNameVar.name+", "+messageTypeVar.name+", "+seqidVar.name+");\n"
-
- def toReadMessageEnd(self):
- return self.indent()+self.iprot+"->readMessageEnd("+self.itrans+");\n"
-
- def toReadStructBegin(self, structNameVar):
- return self.indent()+self.iprot+"->readStructBegin("+self.itrans+", "+structNameVar.name+");\n"
-
- def toReadStructEnd(self):
- return self.indent()+self.iprot+"->readStructEnd("+self.itrans+");\n"
-
- def toReadMapBegin(self, keyTypeVar, valueTypeVar, sizeVar):
- return self.indent()+self.iprot+"->readMapBegin("+self.itrans+", "+keyTypeVar.name+", "+valueTypeVar.name+", "+sizeVar.name+");\n"
-
- def toReadMapEnd(self):
- return self.indent()+self.iprot+"->readMapEnd("+self.itrans+");\n"
-
- def toReadSetBegin(self, valueTypeVar, sizeVar):
- return self.indent()+self.iprot+"->readSetBegin("+self.itrans+", "+valueTypeVar.name+", "+sizeVar.name+");\n"
-
- def toReadSetEnd(self):
- return self.indent()+self.iprot+"->readSetEnd("+self.itrans+");\n"
-
- def toReadListBegin(self, valueTypeVar, sizeVar):
- return self.indent()+self.iprot+"->readListBegin("+self.itrans+", "+valueTypeVar.name+", "+sizeVar.name+");\n"
-
- def toReadListEnd(self):
- return self.indent()+self.iprot+"->readListEnd("+self.itrans+");\n"
-
- def toReadFieldBegin(self, fieldNameVar, fieldTypeVar, fieldIdVar):
- return self.indent()+self.iprot+"->readFieldBegin("+self.itrans+", "+fieldNameVar.name+", "+fieldTypeVar.name+", "+fieldIdVar.name+");\n"
-
- def toReadFieldEnd(self):
- return self.indent()+self.iprot+"->readFieldEnd("+self.itrans+");\n"
-
- def toSkipField(self, fieldTypeVar):
- return self.indent()+self.iprot+"->skip("+self.itrans+", "+fieldTypeVar.name+");\n"
-
- def toReadPrimitive(self, value, suffix):
- return self.indent()+self.iprot+"->read"+suffix+"("+self.itrans+", "+value+");\n"
-
- def toRead(self, value, ttype):
-
- if isinstance(ttype, PrimitiveType):
- return self.toReadPrimitive(value, PHP_TYPE_PROTOCOL_MAP[ttype])
-
- elif isinstance(ttype, StructType):
- self.newScope()
- result = self.toReadStruct(value, ttype)
- self.oldScope()
- return result
-
- elif isinstance(ttype, CollectionType):
- self.newScope()
- result = self.toReadCollection(value, ttype)
- self.oldScope()
- return result
-
- elif isinstance(ttype, EnumType):
- return self.toReadPrimitive(value, PHP_TYPE_PROTOCOL_MAP[I32_TYPE])
-
- elif isinstance(ttype, TypedefType):
- return self.toRead(value, ttype.definitionType)
-
- else:
- raise Exception, "Unsupported type "+str(type(ttype))+":"+str(ttype)
-
- def toReadStruct(self, value, struct):
-
- nameVar = self.declare(STRING_TYPE, "name")
- fieldIdVar = self.declare(I16_TYPE, "fieldId")
- fieldTypeVar = self.declare(U32_TYPE, "fieldType")
- localVars = [nameVar, fieldTypeVar, fieldIdVar]
-
- result= string.join([self.toDeclaration(localVar) for localVar in localVars], "")
-
- result+= self.toReadStructBegin(nameVar)
-
- result+= self.indent()+"while(true) {\n"
-
- self.indent += 1
-
- result+= self.toReadFieldBegin(nameVar, fieldTypeVar, fieldIdVar)
-
- result += self.indent()+"if("+fieldTypeVar.name+" == "+PHP_PROTOCOL_TSTOP+") {\n"
-
- self.indent+= 1
-
- result+= self.indent()+"break;\n"
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- result+= self.indent()+"switch("+fieldIdVar.name+") {\n"
-
- self.indent+= 1
-
- # Sort field list in order of increasing ids
-
- fieldList = []
-
- fieldList+= struct.fieldList
-
- fieldList.sort(lambda a,b: a.id - b.id)
-
- for field in fieldList:
- if isVoidType(field.type):
- continue
-
- result+= self.indent()+"case "+str(field.id)+":\n"
-
- result+= self.toRead(value+"->"+field.name, field.type)
- result+= self.indent()+"break;\n"
-
- result+= self.indent()+"default:\n"
- result+= self.toSkipField(fieldTypeVar)
- result+= self.indent()+"break;\n"
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- result+= self.toReadStructEnd()
-
- return result
-
- def toReadCollection(self, value, collection):
-
- isMap = isinstance(collection, MapType)
-
- sizeVar = self.declare(U32_TYPE, "size")
- valueTypeVar = self.declare(U32_TYPE, "valueType")
- elemVar = self.declare(collection.valueType, "elem")
- localVars = [sizeVar, valueTypeVar, elemVar]
-
- if isMap:
- keyTypeVar = self.declare(U32_TYPE, "keyType")
- key = self.declare(collection.keyType, "key")
- localVars+= [keyTypeVar, key]
-
- ix = self.declare(U32_TYPE, "ix")
-
- result= string.join([self.toDeclaration(localVar) for localVar in localVars], "")
-
- if isMap:
- result+= self.toReadMapBegin(keyTypeVar, valueTypeVar, sizeVar)
- elif isinstance(collection, ListType):
- result+= self.toReadListBegin(valueTypeVar, sizeVar)
- elif isinstance(collection, SetType):
- result+= self.toReadSetBegin(valueTypeVar, sizeVar)
- else:
- raise Exception, "Unknown collection type "+str(collection)
-
- result+= self.indent()+"for("+ix.name+" = 0; "+ix.name+" < "+sizeVar.name+"; ++"+ix.name+") {\n"
-
- self.indent+= 1
-
- if isMap:
- result+= self.toRead(key.name, collection.keyType)
-
- result+= self.toRead(elemVar.name, collection.valueType)
-
- if isMap:
- result+= self.indent()+value+"["+key.name+"] = "+elemVar.name+";\n"
- else:
- result+= self.indent()+value+"[] = "+elemVar.name+";\n"
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- if isMap:
- result+= self.toReadMapEnd()
- elif isinstance(collection, ListType):
- result+= self.toReadListEnd()
- elif isinstance(collection, SetType):
- result+= self.toReadSetEnd()
- else:
- raise Exception, "Unknown collection type "+str(collection)
-
- return result
-
-class Writer(CodeGenerator):
- def __init__(self,
- oprot="$this->_oprot",
- otrans="$this->_otrans",
- scope=Scope(),
- indent=Indenter()):
- CodeGenerator.__init__(self, scope, indent)
- self.oprot = oprot
- self.otrans = otrans
-
- def toWriteMessageBegin(self, messageName, type, seqid):
- return self.indent()+self.oprot+"->writeMessageBegin("+self.otrans+", "+messageName+", "+type+", "+seqid+");\n"
-
- def toWriteMessageEnd(self):
- return self.indent()+self.oprot+"->writeMessageEnd("+self.otrans+");\n"
-
- def toWriteStructBegin(self, structName):
- return self.indent()+self.oprot+"->writeStructBegin("+self.otrans+", "+structName+");\n"
-
- def toWriteStructEnd(self):
- return self.indent()+self.oprot+"->writeStructEnd("+self.otrans+");\n"
-
- def toWriteMapBegin(self, keyType, valueType, size):
- return self.indent()+self.oprot+"->writeMapBegin("+self.otrans+", "+keyType+", "+valueType+", "+size+");\n"
-
- def toWriteMapEnd(self):
- return self.indent()+self.oprot+"->writeMapEnd("+self.otrans+");\n"
-
- def toWriteSetBegin(self, valueType, size):
- return self.indent()+self.oprot+"->writeSetBegin("+self.otrans+", "+valueType+", "+size+");\n"
-
- def toWriteSetEnd(self):
- return self.indent()+self.oprot+"->writeSetEnd("+self.otrans+");\n"
-
- def toWriteListBegin(self, valueType, size):
- return self.indent()+self.oprot+"->writeListBegin("+self.otrans+", "+valueType+", "+size+");\n"
-
- def toWriteListEnd(self):
- return self.indent()+self.oprot+"->writeListEnd("+self.otrans+");\n"
-
- def toWriteFieldBegin(self, fieldName, fieldType, fieldId):
- return self.indent()+self.oprot+"->writeFieldBegin("+self.otrans+", "+fieldName+", "+fieldType+", "+str(fieldId)+");\n"
-
- def toWriteFieldEnd(self):
- return self.indent()+self.oprot+"->writeFieldEnd("+self.otrans+");\n"
-
- def toWriteFieldStop(self):
- return self.indent()+self.oprot+"->writeFieldStop("+self.otrans+");\n"
-
- def toSkipField(self, fieldType):
- return self.indent()+self.oprot+"->skipField("+self.otrans+", "+fieldType+");\n"
-
- def toWriteFlush(self):
- return self.indent()+self.otrans+"->flush();\n"
-
- def toWritePrimitive(self, value, suffix):
- return self.indent()+self.oprot+"->write"+suffix+"("+self.otrans+", "+value+");\n"
-
- def toWrite(self, value, ttype):
-
- if isinstance(ttype, PrimitiveType):
- return self.toWritePrimitive(value, PHP_TYPE_PROTOCOL_MAP[ttype])
-
- elif isinstance(ttype, StructType):
- self.newScope()
- result = self.toWriteStruct(value, ttype)
- self.oldScope()
- return result
-
- elif isinstance(ttype, CollectionType):
- self.newScope()
- result = self.toWriteCollection(value, ttype)
- self.oldScope()
- return result
-
- elif isinstance(ttype, EnumType):
- return self.toWritePrimitive(value, PHP_TYPE_PROTOCOL_MAP[I32_TYPE])
-
- elif isinstance(ttype, TypedefType):
- return self.toWrite(value, ttype.definitionType)
-
- else:
- raise Exception, "Unsupported type "+str(type(ttype))+":"+str(ttype)
-
- def toWriteStruct(self, value, struct):
-
- result=self.indent()+"{\n"
-
- self.indent+= 1
-
- result+= self.toWriteStructBegin("\""+struct.name+"\"")
-
- for field in struct.fieldList:
- if isVoidType(field.type):
- continue
-
- result+= self.toWriteFieldBegin("\""+field.name+"\"", toWireType(field.type), field.id)
- result+= self.toWrite(value+"->"+field.name, field.type)
- result+= self.toWriteFieldEnd()
-
- result+= self.toWriteFieldStop()
-
- result+= self.toWriteStructEnd()
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- return result
-
- def toWriteCollection(self, value, collection):
-
- result=self.indent()+"{\n"
-
- self.indent+= 1
-
- size = "count("+value+")"
-
- isMap = isinstance(collection, MapType)
-
- elemVar = self.declare(VOID_TYPE, "elem")
-
- if isMap:
- keyVar = self.declare(VOID_TYPE, "key")
- result+= self.toWriteMapBegin(toWireType(collection.keyType), toWireType(collection.valueType), size)
- elif isinstance(collection, ListType):
- result+= self.toWriteListBegin(toWireType(collection.valueType), size)
- elif isinstance(collection, SetType):
- result+= self.toWriteSetBegin(toWireType(collection.valueType), size)
- else:
- raise Exception, "Unknown collection type "+str(collection)
-
- if isMap:
-
- result+= self.indent()+"foreach("+value+" as "+keyVar.name+" => "+elemVar.name+") {\n"
-
- else:
-
- result+= self.indent()+"foreach("+value+" as "+elemVar.name+") {\n"
-
- self.indent+= 1
-
- if isMap:
- result+= self.toWrite(keyVar.name, collection.keyType)
-
- result+= self.toWrite(elemVar.name, collection.valueType)
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- if isMap:
- result+= self.toWriteMapEnd()
- elif isinstance(collection, ListType):
- result+= self.toWriteListEnd()
- elif isinstance(collection, SetType):
- result+= self.toWriteSetEnd()
- else:
- raise Exception, "Unknown collection type "+str(collection)
-
- self.indent-= 1
-
- result+= self.indent()+"}\n"
-
- return result
-
-class ClientFunctionGenerator(CodeGenerator):
- def __init__(self,
- scope=Scope(),
- indent=Indenter()):
- CodeGenerator.__init__(self, scope, indent)
- self.reader = Reader(scope=scope, indent=indent)
- self.writer = Writer(scope=scope, indent=indent)
-
- def __call__(self, function):
-
- result= self.indent()+"public function "+function.name+"("+string.join(["$arg"+str(ix) for ix in range(len(function.args()))], ", ")+") {\n"
-
- self.newScope()
-
- self.indent+= 1
-
- result+= self.writer.toWriteMessageBegin("\""+function.name+"\"", PHP_PROTOCOL_CALL, "$this->seqid")
- result+= self.indent()+"$this->_seqid++;\n"
-
- # Send the args struct
-
- result+= self.indent()+"{\n"
-
- self.newScope()
-
- self.indent+= 1
-
- result+= self.writer.toWriteStructBegin("\""+function.argsStruct.name+"\"")
-
- for ix in range(len(function.argsStruct.fieldList)):
- field = function.argsStruct.fieldList[ix]
- if isVoidType(field.type):
- continue
-
- result+= self.writer.toWriteFieldBegin("\""+field.name+"\"", toWireType(field.type), field.id)
- result+= self.writer.toWrite("$arg"+str(ix), field.type)
- result+= self.writer.toWriteFieldEnd()
-
- result+= self.writer.toWriteFieldStop()
-
- result+= self.writer.toWriteStructEnd()
-
- self.indent-= 1
-
- self.oldScope()
-
- result+= self.indent()+"}\n"
-
- result+= self.writer.toWriteMessageEnd()
-
- result+= self.writer.toWriteFlush();
-
- resultVar = self.declare(function.resultStruct, "result")
- nameVar = self.declare(STRING_TYPE, "name")
- typeVar = self.declare(U32_TYPE, "type")
- seqidVar = self.declare(U32_TYPE, "seqid")
-
- result+= self.toDeclaration(resultVar, True)
- result+= self.toDeclaration(nameVar)
- result+= self.toDeclaration(typeVar)
- result+= self.toDeclaration(seqidVar)
-
- result+= self.reader.toReadMessageBegin(nameVar, typeVar, seqidVar)
-
- result+= self.indent()+"{\n"
-
- self.newScope()
-
- self.indent+= 1
-
- result+= self.reader.toRead(resultVar.name, function.resultStruct)
-
- self.indent-= 1
-
- self.oldScope()
-
- result+= self.indent()+"}\n"
-
- result+= self.reader.toReadMessageEnd()
-
- if not isVoidType(function.returnType()):
- result+= self.indent()+"return "+resultVar.name+"->success;\n"
- else:
- result+= self.indent()+"return;\n"
-
- self.indent-= 1
-
- self.oldScope()
-
- result+= self.indent()+"}\n"
-
- return result
-
-class ClientServiceGenerator(CodeGenerator):
- def __init__(self,
- scope=Scope(),
- indent=Indenter()):
- CodeGenerator.__init__(self, scope, indent)
- self.functionGenerator = ClientFunctionGenerator(scope, indent)
-
- def __call__(self, service):
-
- result= self.indent()+"class "+service.name+"Client extends "+service.name+"If {\n"
-
- self.indent+= 1
-
- result+= self.indent()+"private $_itrans = null;\n"
- result+= self.indent()+"private $_otrans = null;\n\n"
-
- result+= self.indent()+"private $_iprot = null;\n"
- result+= self.indent()+"private $_oprot = null;\n\n"
- result+= self.indent()+"private $_seqid = 0;\n\n"
-
- result+= self.indent()+"public function __construct() {\n"
- self.indent+= 1
-
- result+= self.indent()+"$argv = func_get_args();\n"
- result+= self.indent()+"$argc = count($argv);\n"
- result+= self.indent()+"if ($argc == 2) {;\n"
- self.indent+= 1
- result+= self.indent()+"$this->_itrans = $this->_otrans = $argv[0];\n"
- result+= self.indent()+"$this->_iprot = $this->_oprot = $argv[1];\n"
- self.indent-= 1
- result+= self.indent()+"} else if($argc == 4) {\n"
- self.indent+= 1
- result+= self.indent()+"$this->_itrans = $argv[0];\n"
- result+= self.indent()+"$this->_otrans = $argv[1];\n"
- result+= self.indent()+"$this->_iprot = $argv[2];\n"
- result+= self.indent()+"$this->_oprot = $argv[3];\n"
- self.indent-= 1
- result+= self.indent()+"}\n"
- self.indent-= 1
- result+= self.indent()+"}\n\n"
-
- for function in service.functionList:
-
- result+= self.functionGenerator(function)
-
- self.indent-= 1
- result+= self.indent()+"}\n"
-
- return result
-
-PHP_PRIMITIVE_DEFAULT_MAP = {
- VOID_TYPE : "",
- BOOL_TYPE : "False",
- STRING_TYPE: "\'\'",
- UTF7_TYPE: "\'\'",
- UTF8_TYPE: "\'\'",
- UTF16_TYPE: "\'\'",
- BYTE_TYPE : "0",
- I08_TYPE: "0",
- I16_TYPE: "0",
- I32_TYPE: "0",
- I64_TYPE: "0",
- U08_TYPE: "0",
- U16_TYPE: "0",
- U32_TYPE: "0",
- U64_TYPE: "0",
- FLOAT_TYPE: "0.0",
- DOUBLE_TYPE: "0.0"
-}
-
-def toPHPNamespacePrefix(namespace):
- """No namespaces in PHP"""
- return ""
-
-def toPHPNamespaceSuffix(namespace):
- """No namespaces in PHP"""
- return ""
-
-def defaultValueForType(ttype, value=None):
- """Returns the default literal value for a given type"""
-
- if value:
- return value
- elif isinstance(ttype, PrimitiveType):
- return PHP_PRIMITIVE_DEFAULT_MAP[ttype]
- elif isinstance(ttype, CollectionType):
- return "array()"
- elif isinstance(ttype, StructType):
- return "null"
- elif isinstance(ttype, EnumType):
- return "0"
- elif isinstance(ttype, TypedefType):
- return defaultValueForType(toCanonicalType(ttype))
- else:
- raise Exception, "Unknown type "+str(ttype)
-
-def newInstanceForType(ttype, value=None):
- """Returns the default new instance for a given type"""
-
- if value:
- return value
- elif isinstance(ttype, StructType):
- return "new "+ttype.name+"()"
- else:
- return defaultValueForType(ttype, value)
-
-def toPHPTypeDeclaration(ttype):
- """ Converts the thrift IDL type to the corresponding PHP type. Note that if ttype is FieldType, this function
-converts to type declaration followed by field name, i.e. \"string string_thing\""""
-
- if isinstance(ttype, Field):
- return "$"+ttype.name
- if isinstance(ttype, Function):
- return ttype.name+"("+string.join([toPHPTypeDeclaration(arg) for arg in ttype.args()], ", ")+")"
- else:
- return ""
-
-def toTypedefDefinition(typedef):
- """Converts a thrift typedef to a PHP typdef definition."""
-
- return ""
-
-def toEnumDefinition(enum):
- """ Converts a thrift enum to a PHP enum """
-
- result = "$GLOBALS[\'E_"+enum.name+"\'] = array(\n"
-
- result += string.join([" \'"+ed.name+"\' => "+str(ed.id)+",\n" for ed in enum.enumDefs], "")
-
- result+= ");\n\n"
-
- result += "final class "+enum.name+" {\n"
-
- result += string.join([" const "+ed.name+" = "+str(ed.id)+";\n" for ed in enum.enumDefs], "")
-
- result += "}\n"
-
- return result
-
-def toStructDefinition(struct):
- """Converts a thrift struct to a PHP class"""
-
- result = "class "+struct.name+" {\n"
-
- # Create constructor defaults for primitive types
-
- # Field declarations
-
- result+= string.join([" public $"+field.name+" = "+defaultValueForType(field.type)+";\n" for field in struct.fieldList if not isVoidType(field.type)], "")
-
- # bring it on home
-
- result+= "}\n"
-
- return result
-
-PHP_DEFINITION_MAP = {
- TypedefType : toTypedefDefinition,
- EnumType : toEnumDefinition,
- StructType : toStructDefinition,
- ExceptionType : toStructDefinition,
- Service : None
- }
-
-def toDefinitions(definitions):
- """Converts an arbitrary thrift grammatical unit definition to the corresponding PHP definition"""
-
- result = ""
-
- for definition in definitions:
-
- writer = PHP_DEFINITION_MAP[type(definition)]
-
- if writer:
- result+= writer(definition)+"\n"
-
- return result
-
-PHP_THRIFT_NS = "facebook::thrift"
-
-PHP_INTERFACE_FUNCTION_DECLARATION = Template(""" public abstract function ${functionDeclaration};
-""")
-
-PHP_INTERFACE_DECLARATION = Template("""
-abstract class ${service}If {
-${functionDeclarations}};
-""")
-
-def toServiceInterfaceDeclaration(service, debugp=None):
- """Converts a thrift service definition into a C++ abstract base class"""
-
- functionDeclarations = string.join([PHP_INTERFACE_FUNCTION_DECLARATION.substitute(service=service.name, functionDeclaration=toPHPTypeDeclaration(function)) for function in service.functionList], "")
-
- return PHP_INTERFACE_DECLARATION.substitute(service=service.name, functionDeclarations=functionDeclarations)
-
-PHP_EXCEPTION = PHP_THRIFT_NS+"::Exception"
-
-PHP_SP = Template("boost::shared_ptr<${klass}> ")
-
-
-PHP_PROTOCOL_TSTOP = "TType::STOP"
-PHP_PROTOCOL_TTYPE = "TType::"
-PHP_PROTOCOL_CALL = "TMessageType::CALL"
-PHP_PROTOCOL_REPLY = "TMessageType::REPLY"
-
-PHP_TTYPE_MAP = {
- STOP_TYPE : PHP_PROTOCOL_TTYPE+"STOP",
- VOID_TYPE : PHP_PROTOCOL_TTYPE+"VOID",
- BOOL_TYPE : PHP_PROTOCOL_TTYPE+"BOOL",
- UTF7_TYPE : PHP_PROTOCOL_TTYPE+"UTF7",
- UTF7_TYPE : PHP_PROTOCOL_TTYPE+"UTF7",
- UTF8_TYPE : PHP_PROTOCOL_TTYPE+"UTF8",
- UTF16_TYPE : PHP_PROTOCOL_TTYPE+"UTF16",
- U08_TYPE : PHP_PROTOCOL_TTYPE+"U08",
- I08_TYPE : PHP_PROTOCOL_TTYPE+"I08",
- I16_TYPE : PHP_PROTOCOL_TTYPE+"I16",
- I32_TYPE : PHP_PROTOCOL_TTYPE+"I32",
- I64_TYPE : PHP_PROTOCOL_TTYPE+"I64",
- U08_TYPE : PHP_PROTOCOL_TTYPE+"U08",
- U16_TYPE : PHP_PROTOCOL_TTYPE+"U16",
- U32_TYPE : PHP_PROTOCOL_TTYPE+"U32",
- U64_TYPE : PHP_PROTOCOL_TTYPE+"U64",
- FLOAT_TYPE : PHP_PROTOCOL_TTYPE+"FLOAT",
- DOUBLE_TYPE : PHP_PROTOCOL_TTYPE+"DOUBLE",
- StructType : PHP_PROTOCOL_TTYPE+"STRUCT",
- ExceptionType : PHP_PROTOCOL_TTYPE+"STRUCT",
- ListType : PHP_PROTOCOL_TTYPE+"LST",
- MapType : PHP_PROTOCOL_TTYPE+"MAP",
- SetType : PHP_PROTOCOL_TTYPE+"SET"
-}
-
-
-def toWireType(ttype):
- """Converts a thrift type to the corresponding wire type. This differs from toPHPTypeDeclaration in that it reduces typedefs
-to their canonical form and converts enums to signedf 32 bit integers"""
-
- if isinstance(ttype, PrimitiveType):
- return PHP_TTYPE_MAP[ttype]
-
- elif isinstance(ttype, EnumType):
- return PHP_TTYPE_MAP[I32_TYPE]
-
- elif isinstance(ttype, TypedefType):
- return toWireType(toCanonicalType(ttype))
-
- elif isinstance(ttype, StructType) or isinstance(ttype, CollectionType):
- return PHP_TTYPE_MAP[type(ttype)]
-
- else:
- raise Exception, "No wire type for thrift type: "+str(ttype)
-
-def toGenDir(filename, suffix="gen-php", debugp=None):
- """creates a generated-code subdirectory for C++ code based on filename of thrift source file and optional suffix"""
-
- result = os.path.join(os.path.split(filename)[0], suffix)
-
- if not os.path.exists(result):
- os.mkdir(result)
-
- return result
-
-def toBasename(filename, debugp=None):
- """ Take the filename minus the path and\".thrift\" extension if present """
-
- basename = os.path.split(filename)[1]
-
- tokens = os.path.splitext(basename)
-
- if tokens[1].lower() == ".thrift":
- basename = tokens[0]
-
- if debugp:
- debugp("toBasename("+str(filename)+") => "+str(basename))
-
- return basename
-
-def toDefinitionHeaderName(filename, genDir=None, debugp=None):
- """Creates a file name for the public thrift data types based on filename of thrift source file and optional suffix"""
-
- if not genDir:
- genDir = toGenDir(filename)
-
- basename = toBasename(filename)
-
- result = os.path.join(genDir, basename+"_types.php")
-
- if debugp:
- debugp("toDefinitionHeaderName("+str(filename)+", "+str(genDir)+") => "+str(basename))
-
- return result
-
-def writeDefinitionHeader(program, filename, genDir=None, debugp=None):
- """Writes public thrift data types defined in program into a public data types 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"""
-
- definitionHeader = toDefinitionHeaderName(filename, genDir)
-
- if debugp:
- debugp("definitionHeader: "+str(definitionHeader))
-
- phpFile = file(definitionHeader, "w")
-
- basename = toBasename(filename)
-
- phpFile.write(PHP_TYPES_HEADER.substitute(prefix=PREFIX, source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace)))
-
- phpFile.write(toDefinitions(program.definitions))
-
- phpFile.write(PHP_TYPES_FOOTER.substitute(source=basename, namespaceSuffix=toPHPNamespaceSuffix(program.namespace)))
-
- phpFile.close()
-
-def toToImplementationSourceName(filename, genDir=None, debugp=None):
- """Creates a file name for the public thrift data types based on filename of thrift source file and optional suffix"""
-
- if not genDir:
- genDir = toGenDir(filename)
-
- basename = toBasename(filename)
-
- result = os.path.join(genDir, basename+".php")
-
- if debugp:
- debugp("toToImplementationSourceName("+str(filename)+", "+str(genDir)+") => "+str(basename))
-
- return result
-
-def writeImplementationSource(program, filename, genDir=None, debugp=None):
- """Writes public thrift service interface, client stubs, and private types defined in a thrift program into a php library 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"""
-
- toImplementationSource = toToImplementationSourceName(filename, genDir)
-
- if debugp:
- debugp("toImplementationSource: "+str(toImplementationSource))
-
- phpFile = file(toImplementationSource, "w")
-
- basename = toBasename(filename)
-
- phpFile.write(PHP_SERVICES_HEADER.substitute(prefix=PREFIX, source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace)))
-
- # Generate classes for function result "structs"
-
- privateStructs = []
-
- for service in program.serviceMap.values():
-
- phpFile.write(toServiceInterfaceDeclaration(service))
-
- for function in service.functionList:
- privateStructs.append(function.resultStruct)
-
- phpFile.write(toDefinitions(privateStructs))
-
- serviceGenerator = ClientServiceGenerator()
-
- for service in program.serviceMap.values():
-
- phpFile.write(serviceGenerator(service))
-
- phpFile.write(PHP_SERVICES_FOOTER.substitute(source=basename, namespaceSuffix=toPHPNamespaceSuffix(program.namespace)))
-
- phpFile.close()
-
-class PHPGenerator(Generator):
-
- def __call__(self, program, filename, genDir=None, debugp=None):
-
- writeDefinitionHeader(program, filename, genDir, debugp)
-
- writeImplementationSource(program, filename, genDir, debugp)
+++ /dev/null
-#!python
-import sys
-from thrift import generator
-from thrift import cpp_generator
-from thrift import php_generator
-from thrift import parser
-
-def thrift(source, cpp=False, java=False, perl=False, php=False, python=False, ruby=False, debug=False):
-
- generators = []
-
- if cpp:
- generators.append(cpp_generator.CPPGenerator())
-
- if php:
- generators.append(php_generator.PHPGenerator())
-
- p = parser.Parser(debug=debug)
-
- p.parse(source, False)
-
- for generator in generators:
- generator(p.program, source)
-
- if len(p.errors):
- return -1
- else:
- return 0
-
-def main(args):
-
- cpp = False
- perl = False
- php = False
- python = False
- java = False
- ruby = False
-
- debug = False
-
- if "--cpp" in args:
- cpp = True
- args.remove("--cpp")
- if "--php" in args:
- php = True
- args.remove("--php")
- if "--debug" in args:
- debug = True
- args.remove("--debug")
-
- filename = args[-1]
-
- result = thrift(filename, cpp, java, perl, php, python, ruby, debug)
-
- sys.exit(result)
-
-if __name__ == '__main__':
- main(sys.argv)
-
AC_CONFIG_FILES([Makefile])
-AC_CONFIG_SUBDIRS([compiler/py lib/cpp lib/php lib/py])
+AC_CONFIG_SUBDIRS([lib/cpp lib/php lib/py])
AC_OUTPUT