From: Marc Slemko Date: Thu, 24 Aug 2006 23:37:36 +0000 (+0000) Subject: Fixed handling of signed 64bit integers to support 32bit and 64bit architectures X-Git-Tag: 0.2.0~1704 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=d97eb611202c25d2210c647f32d7e780cfe319a6;p=common%2Fthrift.git Fixed handling of signed 64bit integers to support 32bit and 64bit architectures Fixed a few bugs with php code generation Initial stab at setting absolute thrift php require_once paths at configure time in order to guarantee APC caching. Needswork. It's hard to get automake to allow post-processing of installed files. Lightly reviewed by mark slee git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664768 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/src/cpp_generator.py b/compiler/src/cpp_generator.py index 97a5f360..bdd251de 100644 --- a/compiler/src/cpp_generator.py +++ b/compiler/src/cpp_generator.py @@ -624,7 +624,7 @@ def toServiceDeclaration(service, debugp=None): return toServiceInterfaceDeclaration(service, debugp) + toServerDeclaration(service, debugp) + toClientDeclaration(service, debugp) -def toGenDir(filename, suffix="cpp-gen", debugp=None): +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) diff --git a/compiler/src/php_generator.py b/compiler/src/php_generator.py index 71b1fd38..4ad990ca 100644 --- a/compiler/src/php_generator.py +++ b/compiler/src/php_generator.py @@ -24,7 +24,7 @@ HEADER_COMMENT = """readMessageBegin("+self.itrans+", "+messageNameVar.name+", "+seqidVar.name+");\n" + 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" @@ -236,10 +237,10 @@ class Reader(CodeGenerator): return self.indent()+self.iprot+"->readFieldEnd("+self.itrans+");\n" def toSkipField(self, fieldTypeVar): - return self.indent()+self.iprot+"->skipField("+self.itrans+", "+fieldTypeVar.name+");\n" + return self.indent()+self.iprot+"->skip("+self.itrans+", "+fieldTypeVar.name+");\n" def toReadPrimitive(self, value, suffix): - return self.indent()+value+" = "+self.iprot+"->read"+suffix+"("+self.itrans+");\n" + return self.indent()+self.iprot+"->read"+suffix+"("+self.itrans+", "+value+");\n" def toRead(self, value, ttype): @@ -397,8 +398,8 @@ class Writer(CodeGenerator): self.oprot = oprot self.otrans = otrans - def toWriteMessageBegin(self, messageName, seqid): - return self.indent()+self.oprot+"->writeMessageBegin("+self.otrans+", "+messageName+", "+seqid+");\n" + 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" @@ -521,11 +522,11 @@ class Writer(CodeGenerator): if isMap: - result+= self.indent()+"forech("+value+" as "+keyVar.name+" => "+elemVar.name+") {\n" + result+= self.indent()+"foreach("+value+" as "+keyVar.name+" => "+elemVar.name+") {\n" else: - result+= self.indent()+"forech("+value+" as "+elemVar.name+") {\n" + result+= self.indent()+"foreach("+value+" as "+elemVar.name+") {\n" self.indent+= 1 @@ -569,7 +570,7 @@ class ClientFunctionGenerator(CodeGenerator): self.indent+= 1 - result+= self.writer.toWriteMessageBegin("\""+function.name+"\"", "$this->seqid") + result+= self.writer.toWriteMessageBegin("\""+function.name+"\"", PHP_PROTOCOL_CALL, "$this->seqid") result+= self.indent()+"$this->_seqid++;\n" # Send the args struct @@ -606,14 +607,16 @@ class ClientFunctionGenerator(CodeGenerator): result+= self.writer.toWriteFlush(); resultVar = self.declare(function.resultStruct, "result") - nameVar = self.declare(function.resultStruct, "name") - seqidVar = self.declare(function.resultStruct, "seqid") + 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, seqidVar) + result+= self.reader.toReadMessageBegin(nameVar, typeVar, seqidVar) result+= self.indent()+"{\n" @@ -846,8 +849,8 @@ PHP_SP = Template("boost::shared_ptr<${klass}> ") PHP_PROTOCOL_TSTOP = "TType::STOP" PHP_PROTOCOL_TTYPE = "TType::" -PHP_PROTOCOL_CALL = "TMessageType::T_CALL" -PHP_PROTOCOL_REPLY = "TMessageType::T_REPLY" +PHP_PROTOCOL_CALL = "TMessageType::CALL" +PHP_PROTOCOL_REPLY = "TMessageType::REPLY" PHP_TTYPE_MAP = { STOP_TYPE : PHP_PROTOCOL_TTYPE+"STOP", @@ -870,7 +873,7 @@ PHP_TTYPE_MAP = { DOUBLE_TYPE : PHP_PROTOCOL_TTYPE+"DOUBLE", StructType : PHP_PROTOCOL_TTYPE+"STRUCT", ExceptionType : PHP_PROTOCOL_TTYPE+"STRUCT", - ListType : PHP_PROTOCOL_TTYPE+"LIST", + ListType : PHP_PROTOCOL_TTYPE+"LST", MapType : PHP_PROTOCOL_TTYPE+"MAP", SetType : PHP_PROTOCOL_TTYPE+"SET" } @@ -895,7 +898,7 @@ to their canonical form and converts enums to signedf 32 bit integers""" else: raise Exception, "No wire type for thrift type: "+str(ttype) -def toGenDir(filename, suffix="php-gen", debugp=None): +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) @@ -948,7 +951,7 @@ thrift source, filename, and the optional generated C++ code directory, genDir, basename = toBasename(filename) - phpFile.write(PHP_TYPES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace))) + phpFile.write(PHP_TYPES_HEADER.substitute(prefix=PREFIX, source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace))) phpFile.write(toDefinitions(program.definitions)) @@ -984,7 +987,7 @@ thrift source, filename, and the optional generated C++ code directory, genDir, basename = toBasename(filename) - phpFile.write(PHP_SERVICES_HEADER.substitute(source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace))) + phpFile.write(PHP_SERVICES_HEADER.substitute(prefix=PREFIX, source=basename, date=time.ctime(), namespacePrefix=toPHPNamespacePrefix(program.namespace))) # Generate classes for function result "structs" diff --git a/lib/cpp/src/protocol/TProtocol.h b/lib/cpp/src/protocol/TProtocol.h index 38c53479..092dd8d5 100644 --- a/lib/cpp/src/protocol/TProtocol.h +++ b/lib/cpp/src/protocol/TProtocol.h @@ -33,7 +33,8 @@ enum TType { T_VOID = 1, T_BOOL = 2, T_BYTE = 3, - T_U08 = 4, + T_U08 = 3, + T_I08 = 4, T_U16 = 5, T_I16 = 6, T_U32 = 7, @@ -41,13 +42,13 @@ enum TType { T_U64 = 9, T_I64 = 10, T_STRING = 11, - T_UTF7 = 12, - T_STRUCT = 13, - T_MAP = 14, - T_SET = 15, - T_LIST = 16, - T_UTF8 = 17, - T_UTF16 = 18 + T_UTF7 = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_UTF8 = 16, + T_UTF16 = 17 }; /** diff --git a/lib/cpp/src/test/StressTest.thrift b/lib/cpp/src/test/StressTest.thrift index 3d2f9d82..a1f909c2 100644 --- a/lib/cpp/src/test/StressTest.thrift +++ b/lib/cpp/src/test/StressTest.thrift @@ -7,6 +7,9 @@ service Service { u16 echoU16(u16 arg), u32 echoU32(u32 arg), u64 echoU64(u64 arg), + i16 echoI16(i16 arg), + i32 echoI32(i32 arg), + i64 echoI64(i64 arg), string echoString(string arg), list echoList(list arg), set echoSet(set arg), diff --git a/lib/cpp/src/test/main.cc b/lib/cpp/src/test/main.cc index 69a6eb05..062f9037 100644 --- a/lib/cpp/src/test/main.cc +++ b/lib/cpp/src/test/main.cc @@ -31,6 +31,9 @@ class Server : public ServiceServerIf { void echoVoid() {return;} uint8_t echoByte(uint8_t arg) {return arg;} + int16_t echoI16(int16_t arg) {return arg;} + int32_t echoI32(int32_t arg) {return arg;} + int64_t echoI64(int64_t arg) {return arg;} uint16_t echoU16(uint16_t arg) {return arg;} uint32_t echoU32(uint32_t arg) {return arg;} uint64_t echoU64(uint64_t arg) {return arg;} @@ -43,12 +46,13 @@ class Server : public ServiceServerIf { class ClientThread: public Runnable { public: - ClientThread(shared_ptrtransport, shared_ptr client, Monitor& monitor, size_t& workerCount, size_t loopCount) : + ClientThread(shared_ptrtransport, shared_ptr client, Monitor& monitor, size_t& workerCount, size_t loopCount, TType loopType) : _transport(transport), _client(client), _monitor(monitor), _workerCount(workerCount), - _loopCount(loopCount) + _loopCount(loopCount), + _loopType(loopType) {} void run() { @@ -65,14 +69,17 @@ public: _transport->open(); - //uint64_t arg = 0; - //uint64_t result = 0; - - for(size_t ix = 0; ix < _loopCount; ix++) { - // result = _client->echoU64(arg); - // assert(result == arg); - _client->echoVoid(); - //arg++; + switch(_loopType) { + case T_VOID: loopEchoVoid(); break; + case T_BYTE: loopEchoByte(); break; + case T_I16: loopEchoI16(); break; + case T_I32: loopEchoI32(); break; + case T_I64: loopEchoI64(); break; + case T_U16: loopEchoU16(); break; + case T_U32: loopEchoU32(); break; + case T_U64: loopEchoU64(); break; + case T_STRING: loopEchoString(); break; + default: cerr << "Unexpected loop type" << _loopType << endl; break; } _endTime = Util::currentTime(); @@ -91,12 +98,91 @@ public: } } } + + void loopEchoVoid() { + for(size_t ix = 0; ix < _loopCount; ix++) { + _client->echoVoid(); + } + } + + void loopEchoByte() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint8_t arg = 1; + uint8_t result; + result =_client->echoByte(arg); + assert(result == arg); + } + } + + void loopEchoI16() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint16_t arg = 1; + uint16_t result; + result =_client->echoI16(arg); + assert(result == arg); + } + } + + void loopEchoI32() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint32_t arg = 1; + uint32_t result; + result =_client->echoI32(arg); + assert(result == arg); + } + } + + void loopEchoI64() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint64_t arg = 1; + uint64_t result; + result =_client->echoI64(arg); + assert(result == arg); + } + } + + void loopEchoU16() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint16_t arg = 1; + uint16_t result; + result =_client->echoU16(arg); + assert(result == arg); + } + } + + void loopEchoU32() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint32_t arg = 1; + uint32_t result; + result =_client->echoU32(arg); + assert(result == arg); + } + } + + void loopEchoU64() { + for(size_t ix = 0; ix < _loopCount; ix++) { + uint64_t arg = 1; + uint64_t result; + result =_client->echoU64(arg); + assert(result == arg); + } + } + + void loopEchoString() { + for(size_t ix = 0; ix < _loopCount; ix++) { + string arg = "hello"; + string result; + result =_client->echoString(arg); + assert(result == arg); + } + } shared_ptr _transport; shared_ptr _client; Monitor& _monitor; size_t& _workerCount; size_t _loopCount; + TType _loopType; long long _startTime; long long _endTime; bool _done; @@ -111,6 +197,8 @@ int main(int argc, char **argv) { size_t workerCount = 4; size_t clientCount = 10; size_t loopCount = 10000; + TType loopType = T_VOID; + string callName = "echoVoid"; bool runServer = true; ostringstream usage; @@ -119,6 +207,7 @@ int main(int argc, char **argv) { argv[0] << " [--port=] [--server] [--server-type=] [--protocol-type=] [--workers=] [--clients=] [--loop=]" << endl << "\tclients Number of client threads to create - 0 implies no clients, i.e. server only. Default is " << clientCount << endl << "\thelp Prints this help text." << endl << + "\tcall Service method to call. Default is " << callName << endl << "\tloop The number of remote thrift calls each client makes. Default is " << loopCount << endl << "\tport The port the server and clients should bind to for thrift network connections. Default is " << port << endl << "\tserver Run the Thrift server in this process. Default is " << runServer << endl << @@ -163,6 +252,10 @@ int main(int argc, char **argv) { loopCount = atoi(args["loop"].c_str()); } + if(!args["call"].empty()) { + callName = args["call"]; + } + if(!args["port"].empty()) { port = atoi(args["port"].c_str()); } @@ -249,6 +342,17 @@ int main(int argc, char **argv) { set > clientThreads; + if(callName == "echoVoid") { loopType = T_VOID;} + else if(callName == "echoByte") { loopType = T_BYTE;} + else if(callName == "echoI16") { loopType = T_I16;} + else if(callName == "echoI32") { loopType = T_I32;} + else if(callName == "echoI64") { loopType = T_I64;} + else if(callName == "echoU16") { loopType = T_U16;} + else if(callName == "echoU32") { loopType = T_U32;} + else if(callName == "echoU64") { loopType = T_U64;} + else if(callName == "echoString") { loopType = T_STRING;} + else {throw invalid_argument("Unknown service call "+callName);} + for(size_t ix = 0; ix < clientCount; ix++) { shared_ptr socket(new TSocket("127.0.01", port)); @@ -256,7 +360,7 @@ int main(int argc, char **argv) { shared_ptr binaryProtocol(new TBinaryProtocol()); shared_ptr serviceClient(new ServiceClient(bufferedSocket, binaryProtocol)); - clientThreads.insert(threadFactory->newThread(shared_ptr(new ClientThread(bufferedSocket, serviceClient, monitor, threadCount, loopCount)))); + clientThreads.insert(threadFactory->newThread(shared_ptr(new ClientThread(bufferedSocket, serviceClient, monitor, threadCount, loopCount, loopType)))); } for(std::set >::const_iterator thread = clientThreads.begin(); thread != clientThreads.end(); thread++) { diff --git a/lib/php/src/Thrift.php b/lib/php/src/Thrift.php index 8a256114..1e8f3fb6 100644 --- a/lib/php/src/Thrift.php +++ b/lib/php/src/Thrift.php @@ -1,9 +1,5 @@ diff --git a/lib/php/src/protocol/TBinaryProtocol.php b/lib/php/src/protocol/TBinaryProtocol.php index 867a8aa1..0d2349e7 100644 --- a/lib/php/src/protocol/TBinaryProtocol.php +++ b/lib/php/src/protocol/TBinaryProtocol.php @@ -1,7 +1,7 @@ writeString($out, $name) + + $this->writeByte($out, $type) + + $this->writeU32($out, $seqid); + } + + public function writeMessageEnd($out) { + return 0; + } + public function writeStructBegin($out, $name) { return 0; } @@ -22,7 +33,7 @@ class TBinaryProtocol extends TProtocol { public function writeFieldBegin($out, $fieldName, $fieldType, $fieldId) { return $this->writeByte($out, $fieldType) + - $this->writeI32($out, $fieldId); + $this->writeI16($out, $fieldId); } public function writeFieldEnd($out) { @@ -65,40 +76,130 @@ class TBinaryProtocol extends TProtocol { return 0; } - public function writeByte($out, $byte) { - $data = pack('c', $byte); + public function writeBool($out, $value) { + $data = pack('c', $value ? 1 : 0); + $out->write($data, 1); + return 1; + } + + public function writeByte($out, $value) { + $data = pack('c', $value); + $out->write($data, 1); + return 1; + } + + public function writeI08($out, $value) { + $data = pack('c', $value); + $out->write($data, 1); + return 1; + } + + public function writeI16($out, $value) { + $data = pack('n', $value); + $out->write($data, 2); + return 2; + } + + public function writeI32($out, $value) { + $data = pack('N', $value); + $out->write($data, 4); + return 4; + } + + public function writeI64($out, $value) { + + /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic + since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */ + + if(PHP_INT_SIZE == 4) { + + $neg = $value < 0; + + if($neg) { + $value*= -1; + } + + $hi = (int)($value / 4294967296); + $lo = (int)$value; + + if($neg) { + $hi = ~$hi; + $lo = ~$lo; + if(($lo & (int)0xffffffff) == (int)0xffffffff) { + $lo = 0; + $hi++; + } else { + $lo++; + } + } + $data = pack('N2', $hi, $lo); + + } else { + $hi = $value >> 32; + $lo = $value & 0xFFFFFFFF; + $data = pack('N2', $hi, $lo); + } + + $out->write($data, 8); + return 8; + } + + public function writeU08($out, $value) { + $data = pack('c', $value); $out->write($data, 1); return 1; } - public function writeI32($out, $i32) { - $data = pack('l', $i32); - //if (!defined('BIG_ENDIAN')) { - $data = strrev($data); - //} + public function writeU16($out, $value) { + $data = pack('n', $value); + $out->write($data, 2); + return 2; + } + + public function writeU32($out, $value) { + $data = pack('N', $value); $out->write($data, 4); return 4; } - public function writeI64($out, $i64) { - $hi = $i64 >> 32; - $lo = $i64 & 0xFFFFFFFF; - if (!defined('BIG_ENDIAN')) { + public function writeU64($out, $value) { + + /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic + since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */ + + if(PHP_INT_SIZE == 4) { + + $hi = (int)($value / 4294967296); + $lo = (int)$value; $data = pack('N2', $hi, $lo); + } else { - $data = pack('N2', $lo, $hi); + $hi = $value >> 32; + $lo = $value & 0xFFFFFFFF; + $data = pack('N2', $hi, $lo); } + $out->write($data, 8); return 8; } - public function writeString($out, $str) { - $len = strlen($str); - $result = $this->writeI32($out, $len); - $out->write($str, $len); + public function writeString($out, $value) { + $len = strlen($value); + $result = $this->writeU32($out, $len); + $out->write($value, $len); return $result + $len; } + public function readMessageBegin($in, &$name, &$type, &$seqid) { + $result = $this->readString($in, $name); + $result+= $this->readByte($in, $type); + $result+= $this->readU32($in, $seqid); + } + + public function readMessageEnd($out) { + return 0; + } + public function readStructBegin($in, &$name) { $name = ''; return 0; @@ -114,7 +215,7 @@ class TBinaryProtocol extends TProtocol { $fieldId = 0; return $result; } - $result += $this->readI32($in, $fieldId); + $result += $this->readI16($in, $fieldId); return $result; } @@ -153,43 +254,167 @@ class TBinaryProtocol extends TProtocol { return 0; } - public function readByte($in, &$byte) { + public function readBool($in, &$value) { + $data = $in->readAll(1); + $arr = unpack('c', $data); + $value = $arr[1] == 1; + return 1; + } + + public function readByte($in, &$value) { + $data = $in->readAll(1); + $arr = unpack('c', $data); + $value = $arr[1]; + return 1; + } + + public function readI08($in, &$value) { $data = $in->readAll(1); $arr = unpack('c', $data); - $byte = $arr[1]; + $value = $arr[1]; return 1; } - public function readI32($in, &$i32) { + public function readI16($in, &$value) { + $data = $in->readAll(2); + $arr = unpack('n', $data); + $value = $arr[1]; + if($value > 0x7fff) { + $value = 0 - (($value - 1) ^ 0xffff); + } + return 2; + } + + public function readI32($in, &$value) { $data = $in->readAll(4); - if (!defined('BIG_ENDIAN')) { - $data = strrev($data); + $arr = unpack('N', $data); + $value = $arr[1]; + if($value > 0x7fffffff) { + $value = 0 - (($value - 1) ^ 0xffffffff); } - $arr = unpack('l', $data); - $i32 = $arr[1]; return 4; } - public function readI64($in, &$i64) { + public function readI64($in, &$value) { + $data = $in->readAll(8); + $arr = unpack('N2', $data); + + /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic + since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */ + + if(PHP_INT_SIZE == 4) { + + $hi = $arr[1]; + $lo = $arr[2]; + $isNeg = $hi < 0; + + // Check for a negative + if($isNeg) { + $hi = ~$hi & (int)0xffffffff; + $lo = ~$lo & (int)0xffffffff; + + if($lo == (int)0xffffffff) { + $hi++; + $lo = 0; + } else { + $lo++; + } + } + + /* Force 32bit words in excess of 2G to pe positive - we deal wigh sign + explicitly below */ + + if($hi & (int)0x80000000) { + $hi&= (int)0x7fffffff; + $hi += 0x80000000; + } + + if($lo & (int)0x80000000) { + $lo&= (int)0x7fffffff; + $lo += 0x80000000; + } + + $value = $hi * 4294967296 + $lo; + + if($isNeg) { + $value = 0 - $value; + } + } else { + + // Check for a negative + if ($arr[1] & 0x80000000) { + $arr[1] = $arr[1] ^ 0xFFFFFFFF; + $arr[2] = $arr[2] ^ 0xFFFFFFFF; + $value = 0 - $arr[1]*4294967296 - $arr[2] - 1; + } else { + $value = $arr[1]*4294967296 + $arr[2]; + } + } + + return 8; + } + + public function readU08($in, &$value) { + $data = $in->readAll(1); + $arr = unpack('c', $data); + $value = $arr[1]; + return 1; + } + + public function readU16($in, &$value) { + $data = $in->readAll(2); + $arr = unpack('n', $data); + $value = $arr[1]; + return 2; + } + + public function readU32($in, &$value) { + $data = $in->readAll(4); + $arr = unpack('N', $data); + $value = $arr[1]; + return 4; + } + + public function readU64($in, &$value) { + $data = $in->readAll(8); + $arr = unpack('N2', $data); + + /* If we are on a 32bit architecture we have to explicitly deal with 64-bit twos-complement arithmetic + since PHP wants to treat all ints as signed and any int over 2^31 - 1 as a float */ + + if(PHP_INT_SIZE == 4) { + + $hi = $arr[1]; + $lo = $arr[2]; + + /* Prevent implicit integer sign extension */ + + if($hi & (int)0x80000000) { + $hi&= (int)0x7fffffff; + $hi += 0x80000000; + } + + if($lo & (int)0x80000000) { + $lo&= (int)0x7fffffff; + $lo += 0x80000000; + } + + $value = $hi * 4294967296 + $lo; - // Check for a negative - if ($arr[1] & 0x80000000) { - $arr[1] = $arr[1] ^ 0xFFFFFFFF; - $arr[2] = $arr[2] ^ 0xFFFFFFFF; - $i64 = 0 - $arr[1]*4294967296 - $arr[2] - 1; } else { - $i64 = $arr[1]*4294967296 + $arr[2]; + + $value = $arr[1]*4294967296 + $arr[2]; } return 8; } - public function readString($in, &$str) { - $result = $this->readI32($in, $len); - $str = $in->readAll($len); + public function readString($in, &$value) { + $result = $this->readU32($in, $len); + $value = $in->readAll($len); return $result + $len; } } -?> \ No newline at end of file +?> diff --git a/lib/php/src/protocol/TProtocol.php b/lib/php/src/protocol/TProtocol.php index 5a69bbdd..a3596ab8 100644 --- a/lib/php/src/protocol/TProtocol.php +++ b/lib/php/src/protocol/TProtocol.php @@ -1,7 +1,7 @@ */ class TType { - const STOP = 1; - const BYTE = 2; - const I32 = 6; - const I64 = 8; - const STRING = 9; - const STRUCT = 10; - const MAP = 11; - const SET = 12; - const LST = 13; // cannot use LIST keyword in PHP! + const STOP = 0; + const VOID = 1; + const BOOL = 2; + const BYTE = 3; + const U08 = 3; + const I08 = 4; + const U16 = 5; + const I16 = 6; + const U32 = 7; + const I32 = 8; + const U64 = 9; + const I64 = 10; + const STRING = 11; + const UTF7 = 11; + const STRUCT = 12; + const MAP = 13; + const SET = 14; + const LST = 15; // cannot use LIST keyword in PHP! + const UTF8 = 16; + const UTF16 = 17; +} + +class TMessageType { + const CALL = 1; + const REPLY = 2; }