PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/release-0.0.0-rc0/hive/external/service/lib/php/protocol/TBinaryProtocol.php

#
PHP | 431 lines | 319 code | 67 blank | 45 comment | 38 complexity | 5c5c93548ffcfd792c85b11f599afcde MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, JSON, CPL-1.0
  1. <?php
  2. /*
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. * @package thrift.protocol
  21. */
  22. include_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
  23. /**
  24. * Binary implementation of the Thrift protocol.
  25. *
  26. */
  27. class TBinaryProtocol extends TProtocol {
  28. const VERSION_MASK = 0xffff0000;
  29. const VERSION_1 = 0x80010000;
  30. protected $strictRead_ = false;
  31. protected $strictWrite_ = true;
  32. public function __construct($trans, $strictRead=false, $strictWrite=true) {
  33. parent::__construct($trans);
  34. $this->strictRead_ = $strictRead;
  35. $this->strictWrite_ = $strictWrite;
  36. }
  37. public function writeMessageBegin($name, $type, $seqid) {
  38. if ($this->strictWrite_) {
  39. $version = self::VERSION_1 | $type;
  40. return
  41. $this->writeI32($version) +
  42. $this->writeString($name) +
  43. $this->writeI32($seqid);
  44. } else {
  45. return
  46. $this->writeString($name) +
  47. $this->writeByte($type) +
  48. $this->writeI32($seqid);
  49. }
  50. }
  51. public function writeMessageEnd() {
  52. return 0;
  53. }
  54. public function writeStructBegin($name) {
  55. return 0;
  56. }
  57. public function writeStructEnd() {
  58. return 0;
  59. }
  60. public function writeFieldBegin($fieldName, $fieldType, $fieldId) {
  61. return
  62. $this->writeByte($fieldType) +
  63. $this->writeI16($fieldId);
  64. }
  65. public function writeFieldEnd() {
  66. return 0;
  67. }
  68. public function writeFieldStop() {
  69. return
  70. $this->writeByte(TType::STOP);
  71. }
  72. public function writeMapBegin($keyType, $valType, $size) {
  73. return
  74. $this->writeByte($keyType) +
  75. $this->writeByte($valType) +
  76. $this->writeI32($size);
  77. }
  78. public function writeMapEnd() {
  79. return 0;
  80. }
  81. public function writeListBegin($elemType, $size) {
  82. return
  83. $this->writeByte($elemType) +
  84. $this->writeI32($size);
  85. }
  86. public function writeListEnd() {
  87. return 0;
  88. }
  89. public function writeSetBegin($elemType, $size) {
  90. return
  91. $this->writeByte($elemType) +
  92. $this->writeI32($size);
  93. }
  94. public function writeSetEnd() {
  95. return 0;
  96. }
  97. public function writeBool($value) {
  98. $data = pack('c', $value ? 1 : 0);
  99. $this->trans_->write($data, 1);
  100. return 1;
  101. }
  102. public function writeByte($value) {
  103. $data = pack('c', $value);
  104. $this->trans_->write($data, 1);
  105. return 1;
  106. }
  107. public function writeI16($value) {
  108. $data = pack('n', $value);
  109. $this->trans_->write($data, 2);
  110. return 2;
  111. }
  112. public function writeI32($value) {
  113. $data = pack('N', $value);
  114. $this->trans_->write($data, 4);
  115. return 4;
  116. }
  117. public function writeI64($value) {
  118. // If we are on a 32bit architecture we have to explicitly deal with
  119. // 64-bit twos-complement arithmetic since PHP wants to treat all ints
  120. // as signed and any int over 2^31 - 1 as a float
  121. if (PHP_INT_SIZE == 4) {
  122. $neg = $value < 0;
  123. if ($neg) {
  124. $value *= -1;
  125. }
  126. $hi = (int)($value / 4294967296);
  127. $lo = (int)$value;
  128. if ($neg) {
  129. $hi = ~$hi;
  130. $lo = ~$lo;
  131. if (($lo & (int)0xffffffff) == (int)0xffffffff) {
  132. $lo = 0;
  133. $hi++;
  134. } else {
  135. $lo++;
  136. }
  137. }
  138. $data = pack('N2', $hi, $lo);
  139. } else {
  140. $hi = $value >> 32;
  141. $lo = $value & 0xFFFFFFFF;
  142. $data = pack('N2', $hi, $lo);
  143. }
  144. $this->trans_->write($data, 8);
  145. return 8;
  146. }
  147. public function writeDouble($value) {
  148. $data = pack('d', $value);
  149. $this->trans_->write(strrev($data), 8);
  150. return 8;
  151. }
  152. public function writeString($value) {
  153. $len = strlen($value);
  154. $result = $this->writeI32($len);
  155. if ($len) {
  156. $this->trans_->write($value, $len);
  157. }
  158. return $result + $len;
  159. }
  160. public function readMessageBegin(&$name, &$type, &$seqid) {
  161. $result = $this->readI32($sz);
  162. if ($sz < 0) {
  163. $version = (int) ($sz & self::VERSION_MASK);
  164. if ($version != (int) self::VERSION_1) {
  165. throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
  166. }
  167. $type = $sz & 0x000000ff;
  168. $result +=
  169. $this->readString($name) +
  170. $this->readI32($seqid);
  171. } else {
  172. if ($this->strictRead_) {
  173. throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
  174. } else {
  175. // Handle pre-versioned input
  176. $name = $this->trans_->readAll($sz);
  177. $result +=
  178. $sz +
  179. $this->readByte($type) +
  180. $this->readI32($seqid);
  181. }
  182. }
  183. return $result;
  184. }
  185. public function readMessageEnd() {
  186. return 0;
  187. }
  188. public function readStructBegin(&$name) {
  189. $name = '';
  190. return 0;
  191. }
  192. public function readStructEnd() {
  193. return 0;
  194. }
  195. public function readFieldBegin(&$name, &$fieldType, &$fieldId) {
  196. $result = $this->readByte($fieldType);
  197. if ($fieldType == TType::STOP) {
  198. $fieldId = 0;
  199. return $result;
  200. }
  201. $result += $this->readI16($fieldId);
  202. return $result;
  203. }
  204. public function readFieldEnd() {
  205. return 0;
  206. }
  207. public function readMapBegin(&$keyType, &$valType, &$size) {
  208. return
  209. $this->readByte($keyType) +
  210. $this->readByte($valType) +
  211. $this->readI32($size);
  212. }
  213. public function readMapEnd() {
  214. return 0;
  215. }
  216. public function readListBegin(&$elemType, &$size) {
  217. return
  218. $this->readByte($elemType) +
  219. $this->readI32($size);
  220. }
  221. public function readListEnd() {
  222. return 0;
  223. }
  224. public function readSetBegin(&$elemType, &$size) {
  225. return
  226. $this->readByte($elemType) +
  227. $this->readI32($size);
  228. }
  229. public function readSetEnd() {
  230. return 0;
  231. }
  232. public function readBool(&$value) {
  233. $data = $this->trans_->readAll(1);
  234. $arr = unpack('c', $data);
  235. $value = $arr[1] == 1;
  236. return 1;
  237. }
  238. public function readByte(&$value) {
  239. $data = $this->trans_->readAll(1);
  240. $arr = unpack('c', $data);
  241. $value = $arr[1];
  242. return 1;
  243. }
  244. public function readI16(&$value) {
  245. $data = $this->trans_->readAll(2);
  246. $arr = unpack('n', $data);
  247. $value = $arr[1];
  248. if ($value > 0x7fff) {
  249. $value = 0 - (($value - 1) ^ 0xffff);
  250. }
  251. return 2;
  252. }
  253. public function readI32(&$value) {
  254. $data = $this->trans_->readAll(4);
  255. $arr = unpack('N', $data);
  256. $value = $arr[1];
  257. if ($value > 0x7fffffff) {
  258. $value = 0 - (($value - 1) ^ 0xffffffff);
  259. }
  260. return 4;
  261. }
  262. public function readI64(&$value) {
  263. $data = $this->trans_->readAll(8);
  264. $arr = unpack('N2', $data);
  265. // If we are on a 32bit architecture we have to explicitly deal with
  266. // 64-bit twos-complement arithmetic since PHP wants to treat all ints
  267. // as signed and any int over 2^31 - 1 as a float
  268. if (PHP_INT_SIZE == 4) {
  269. $hi = $arr[1];
  270. $lo = $arr[2];
  271. $isNeg = $hi < 0;
  272. // Check for a negative
  273. if ($isNeg) {
  274. $hi = ~$hi & (int)0xffffffff;
  275. $lo = ~$lo & (int)0xffffffff;
  276. if ($lo == (int)0xffffffff) {
  277. $hi++;
  278. $lo = 0;
  279. } else {
  280. $lo++;
  281. }
  282. }
  283. // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
  284. // explicitly below
  285. if ($hi & (int)0x80000000) {
  286. $hi &= (int)0x7fffffff;
  287. $hi += 0x80000000;
  288. }
  289. if ($lo & (int)0x80000000) {
  290. $lo &= (int)0x7fffffff;
  291. $lo += 0x80000000;
  292. }
  293. $value = $hi * 4294967296 + $lo;
  294. if ($isNeg) {
  295. $value = 0 - $value;
  296. }
  297. } else {
  298. // Upcast negatives in LSB bit
  299. if ($arr[2] & 0x80000000) {
  300. $arr[2] = $arr[2] & 0xffffffff;
  301. }
  302. // Check for a negative
  303. if ($arr[1] & 0x80000000) {
  304. $arr[1] = $arr[1] & 0xffffffff;
  305. $arr[1] = $arr[1] ^ 0xffffffff;
  306. $arr[2] = $arr[2] ^ 0xffffffff;
  307. $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
  308. } else {
  309. $value = $arr[1]*4294967296 + $arr[2];
  310. }
  311. }
  312. return 8;
  313. }
  314. public function readDouble(&$value) {
  315. $data = strrev($this->trans_->readAll(8));
  316. $arr = unpack('d', $data);
  317. $value = $arr[1];
  318. return 8;
  319. }
  320. public function readString(&$value) {
  321. $result = $this->readI32($len);
  322. if ($len) {
  323. $value = $this->trans_->readAll($len);
  324. } else {
  325. $value = '';
  326. }
  327. return $result + $len;
  328. }
  329. }
  330. /**
  331. * Binary Protocol Factory
  332. */
  333. class TBinaryProtocolFactory implements TProtocolFactory {
  334. private $strictRead_ = false;
  335. private $strictWrite_ = false;
  336. public function __construct($strictRead=false, $strictWrite=false) {
  337. $this->strictRead_ = $strictRead;
  338. $this->strictWrite_ = $strictWrite;
  339. }
  340. public function getProtocol($trans) {
  341. return new TBinaryProtocol($trans, $this->strictRead, $this->strictWrite);
  342. }
  343. }
  344. /**
  345. * Accelerated binary protocol: used in conjunction with the thrift_protocol
  346. * extension for faster deserialization
  347. */
  348. class TBinaryProtocolAccelerated extends TBinaryProtocol {
  349. public function __construct($trans, $strictRead=false, $strictWrite=true) {
  350. // If the transport doesn't implement putBack, wrap it in a
  351. // TBufferedTransport (which does)
  352. if (!method_exists($trans, 'putBack')) {
  353. $trans = new TBufferedTransport($trans);
  354. }
  355. parent::__construct($trans, $strictRead, $strictWrite);
  356. }
  357. public function isStrictRead() {
  358. return $this->strictRead_;
  359. }
  360. public function isStrictWrite() {
  361. return $this->strictWrite_;
  362. }
  363. }
  364. ?>