HproseReader.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. <?php
  2. /**********************************************************\
  3. | |
  4. | hprose |
  5. | |
  6. | Official WebSite: http://www.hprose.com/ |
  7. | http://www.hprose.net/ |
  8. | http://www.hprose.org/ |
  9. | |
  10. \**********************************************************/
  11. /**********************************************************\
  12. * *
  13. * HproseReader.php *
  14. * *
  15. * hprose reader library for php5. *
  16. * *
  17. * LastModified: Nov 12, 2013 *
  18. * Author: Ma Bingyao <andot@hprfc.com> *
  19. * *
  20. \**********************************************************/
  21. require_once('HproseCommon.php');
  22. require_once('HproseTags.php');
  23. require_once('HproseClassManager.php');
  24. class HproseRawReader {
  25. public $stream;
  26. function __construct(&$stream) {
  27. $this->stream = &$stream;
  28. }
  29. public function readRaw($ostream = NULL, $tag = NULL) {
  30. if (is_null($ostream)) {
  31. $ostream = new HproseStringStream();
  32. }
  33. if (is_null($tag)) {
  34. $tag = $this->stream->getc();
  35. }
  36. switch ($tag) {
  37. case '0':
  38. case '1':
  39. case '2':
  40. case '3':
  41. case '4':
  42. case '5':
  43. case '6':
  44. case '7':
  45. case '8':
  46. case '9':
  47. case HproseTags::TagNull:
  48. case HproseTags::TagEmpty:
  49. case HproseTags::TagTrue:
  50. case HproseTags::TagFalse:
  51. case HproseTags::TagNaN:
  52. $ostream->write($tag);
  53. break;
  54. case HproseTags::TagInfinity:
  55. $ostream->write($tag);
  56. $ostream->write($this->stream->getc());
  57. break;
  58. case HproseTags::TagInteger:
  59. case HproseTags::TagLong:
  60. case HproseTags::TagDouble:
  61. case HproseTags::TagRef:
  62. $this->readNumberRaw($ostream, $tag);
  63. break;
  64. case HproseTags::TagDate:
  65. case HproseTags::TagTime:
  66. $this->readDateTimeRaw($ostream, $tag);
  67. break;
  68. case HproseTags::TagUTF8Char:
  69. $this->readUTF8CharRaw($ostream, $tag);
  70. break;
  71. case HproseTags::TagBytes:
  72. $this->readBytesRaw($ostream, $tag);
  73. break;
  74. case HproseTags::TagString:
  75. $this->readStringRaw($ostream, $tag);
  76. break;
  77. case HproseTags::TagGuid:
  78. $this->readGuidRaw($ostream, $tag);
  79. break;
  80. case HproseTags::TagList:
  81. case HproseTags::TagMap:
  82. case HproseTags::TagObject:
  83. $this->readComplexRaw($ostream, $tag);
  84. break;
  85. case HproseTags::TagClass:
  86. $this->readComplexRaw($ostream, $tag);
  87. $this->readRaw($ostream);
  88. break;
  89. case HproseTags::TagError:
  90. $ostream->write($tag);
  91. $this->readRaw($ostream);
  92. break;
  93. case false:
  94. throw new HproseException("No byte found in stream");
  95. default:
  96. throw new HproseException("Unexpected serialize tag '" + $tag + "' in stream");
  97. }
  98. return $ostream;
  99. }
  100. private function readNumberRaw($ostream, $tag) {
  101. $s = $tag .
  102. $this->stream->readuntil(HproseTags::TagSemicolon) .
  103. HproseTags::TagSemicolon;
  104. $ostream->write($s);
  105. }
  106. private function readDateTimeRaw($ostream, $tag) {
  107. $s = $tag;
  108. do {
  109. $tag = $this->stream->getc();
  110. $s .= $tag;
  111. } while ($tag != HproseTags::TagSemicolon &&
  112. $tag != HproseTags::TagUTC);
  113. $ostream->write($s);
  114. }
  115. private function readUTF8CharRaw($ostream, $tag) {
  116. $s = $tag;
  117. $tag = $this->stream->getc();
  118. $s .= $tag;
  119. $a = ord($tag);
  120. if (($a & 0xE0) == 0xC0) {
  121. $s .= $this->stream->getc();
  122. }
  123. elseif (($a & 0xF0) == 0xE0) {
  124. $s .= $this->stream->read(2);
  125. }
  126. elseif ($a > 0x7F) {
  127. throw new HproseException("bad utf-8 encoding");
  128. }
  129. $ostream->write($s);
  130. }
  131. private function readBytesRaw($ostream, $tag) {
  132. $len = $this->stream->readuntil(HproseTags::TagQuote);
  133. $s = $tag . $len . HproseTags::TagQuote . $this->stream->read((int)$len) . HproseTags::TagQuote;
  134. $this->stream->skip(1);
  135. $ostream->write($s);
  136. }
  137. private function readStringRaw($ostream, $tag) {
  138. $len = $this->stream->readuntil(HproseTags::TagQuote);
  139. $s = $tag . $len . HproseTags::TagQuote;
  140. $len = (int)$len;
  141. $this->stream->mark();
  142. $utf8len = 0;
  143. for ($i = 0; $i < $len; ++$i) {
  144. switch (ord($this->stream->getc()) >> 4) {
  145. case 0:
  146. case 1:
  147. case 2:
  148. case 3:
  149. case 4:
  150. case 5:
  151. case 6:
  152. case 7: {
  153. // 0xxx xxxx
  154. $utf8len++;
  155. break;
  156. }
  157. case 12:
  158. case 13: {
  159. // 110x xxxx 10xx xxxx
  160. $this->stream->skip(1);
  161. $utf8len += 2;
  162. break;
  163. }
  164. case 14: {
  165. // 1110 xxxx 10xx xxxx 10xx xxxx
  166. $this->stream->skip(2);
  167. $utf8len += 3;
  168. break;
  169. }
  170. case 15: {
  171. // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
  172. $this->stream->skip(3);
  173. $utf8len += 4;
  174. ++$i;
  175. break;
  176. }
  177. default: {
  178. throw new HproseException('bad utf-8 encoding');
  179. }
  180. }
  181. }
  182. $this->stream->reset();
  183. $this->stream->unmark();
  184. $s .= $this->stream->read($utf8len) . HproseTags::TagQuote;
  185. $this->stream->skip(1);
  186. $ostream->write($s);
  187. }
  188. private function readGuidRaw($ostream, $tag) {
  189. $s = $tag . $this->stream->read(38);
  190. $ostream->write($s);
  191. }
  192. private function readComplexRaw($ostream, $tag) {
  193. $s = $tag .
  194. $this->stream->readuntil(HproseTags::TagOpenbrace) .
  195. HproseTags::TagOpenbrace;
  196. $ostream->write($s);
  197. while (($tag = $this->stream->getc()) != HproseTags::TagClosebrace) {
  198. $this->readRaw($ostream, $tag);
  199. }
  200. $ostream->write($tag);
  201. }
  202. }
  203. class HproseSimpleReader extends HproseRawReader {
  204. private $classref;
  205. function __construct(&$stream) {
  206. parent::__construct($stream);
  207. $this->classref = array();
  208. }
  209. public function &unserialize($tag = NULL) {
  210. if (is_null($tag)) {
  211. $tag = $this->stream->getc();
  212. }
  213. $result = NULL;
  214. switch ($tag) {
  215. case '0':
  216. case '1':
  217. case '2':
  218. case '3':
  219. case '4':
  220. case '5':
  221. case '6':
  222. case '7':
  223. case '8':
  224. case '9':
  225. $result = (int)$tag; break;
  226. case HproseTags::TagInteger: $result = $this->readInteger(); break;
  227. case HproseTags::TagLong: $result = $this->readLong(); break;
  228. case HproseTags::TagDouble: $result = $this->readDouble(); break;
  229. case HproseTags::TagNull: break;
  230. case HproseTags::TagEmpty: $result = ''; break;
  231. case HproseTags::TagTrue: $result = true; break;
  232. case HproseTags::TagFalse: $result = false; break;
  233. case HproseTags::TagNaN: $result = log(-1); break;
  234. case HproseTags::TagInfinity: $result = $this->readInfinity(); break;
  235. case HproseTags::TagDate: $result = $this->readDate(); break;
  236. case HproseTags::TagTime: $result = $this->readTime(); break;
  237. case HproseTags::TagBytes: $result = $this->readBytes(); break;
  238. case HproseTags::TagUTF8Char: $result = $this->readUTF8Char(); break;
  239. case HproseTags::TagString: $result = $this->readString(); break;
  240. case HproseTags::TagGuid: $result = $this->readGuid(); break;
  241. case HproseTags::TagList: $result = &$this->readList(); break;
  242. case HproseTags::TagMap: $result = &$this->readMap(); break;
  243. case HproseTags::TagClass: $this->readClass(); $result = &$this->unserialize(); break;
  244. case HproseTags::TagObject: $result = $this->readObject(); break;
  245. case HproseTags::TagError: throw new HproseException($this->readString(true));
  246. case false: throw new HproseException('No byte found in stream');
  247. default: throw new HproseException("Unexpected serialize tag '$tag' in stream");
  248. }
  249. return $result;
  250. }
  251. public function checkTag($expectTag, $tag = NULL) {
  252. if (is_null($tag)) $tag = $this->stream->getc();
  253. if ($tag != $expectTag) {
  254. throw new HproseException("Tag '$expectTag' expected, but '$tag' found in stream");
  255. }
  256. }
  257. public function checkTags($expectTags, $tag = NULL) {
  258. if (is_null($tag)) $tag = $this->stream->getc();
  259. if (!in_array($tag, $expectTags)) {
  260. $expectTags = implode('', $expectTags);
  261. throw new HproseException("Tag '$expectTags' expected, but '$tag' found in stream");
  262. }
  263. return $tag;
  264. }
  265. public function readInteger($includeTag = false) {
  266. if ($includeTag) {
  267. $tag = $this->stream->getc();
  268. if (($tag >= '0') && ($tag <= '9')) {
  269. return (int)$tag;
  270. }
  271. $this->checkTag(HproseTags::TagInteger, $tag);
  272. }
  273. return (int)($this->stream->readuntil(HproseTags::TagSemicolon));
  274. }
  275. public function readLong($includeTag = false) {
  276. if ($includeTag) {
  277. $tag = $this->stream->getc();
  278. if (($tag >= '0') && ($tag <= '9')) {
  279. return $tag;
  280. }
  281. $this->checkTag(HproseTags::TagLong, $tag);
  282. }
  283. return $this->stream->readuntil(HproseTags::TagSemicolon);
  284. }
  285. public function readDouble($includeTag = false) {
  286. if ($includeTag) {
  287. $tag = $this->stream->getc();
  288. if (($tag >= '0') && ($tag <= '9')) {
  289. return (double)$tag;
  290. }
  291. $this->checkTag(HproseTags::TagDouble, $tag);
  292. }
  293. return (double)($this->stream->readuntil(HproseTags::TagSemicolon));
  294. }
  295. public function readNaN() {
  296. $this->checkTag(HproseTags::TagNaN);
  297. return log(-1);
  298. }
  299. public function readInfinity($includeTag = false) {
  300. if ($includeTag) $this->checkTag(HproseTags::TagInfinity);
  301. return (($this->stream->getc() == HproseTags::TagNeg) ? log(0) : -log(0));
  302. }
  303. public function readNull() {
  304. $this->checkTag(HproseTags::TagNull);
  305. return NULL;
  306. }
  307. public function readEmpty() {
  308. $this->checkTag(HproseTags::TagEmpty);
  309. return '';
  310. }
  311. public function readBoolean() {
  312. $tag = $this->checkTags(array(HproseTags::TagTrue, HproseTags::TagFalse));
  313. return ($tag == HproseTags::TagTrue);
  314. }
  315. public function readDate($includeTag = false) {
  316. if ($includeTag) $this->checkTag(HproseTags::TagDate);
  317. $year = (int)($this->stream->read(4));
  318. $month = (int)($this->stream->read(2));
  319. $day = (int)($this->stream->read(2));
  320. $tag = $this->stream->getc();
  321. if ($tag == HproseTags::TagTime) {
  322. $hour = (int)($this->stream->read(2));
  323. $minute = (int)($this->stream->read(2));
  324. $second = (int)($this->stream->read(2));
  325. $microsecond = 0;
  326. $tag = $this->stream->getc();
  327. if ($tag == HproseTags::TagPoint) {
  328. $microsecond = (int)($this->stream->read(3)) * 1000;
  329. $tag = $this->stream->getc();
  330. if (($tag >= '0') && ($tag <= '9')) {
  331. $microsecond += (int)($tag) * 100 + (int)($this->stream->read(2));
  332. $tag = $this->stream->getc();
  333. if (($tag >= '0') && ($tag <= '9')) {
  334. $this->stream->skip(2);
  335. $tag = $this->stream->getc();
  336. }
  337. }
  338. }
  339. if ($tag == HproseTags::TagUTC) {
  340. $date = new HproseDateTime($year, $month, $day,
  341. $hour, $minute, $second,
  342. $microsecond, true);
  343. }
  344. else {
  345. $date = new HproseDateTime($year, $month, $day,
  346. $hour, $minute, $second,
  347. $microsecond);
  348. }
  349. }
  350. elseif ($tag == HproseTags::TagUTC) {
  351. $date = new HproseDate($year, $month, $day, true);
  352. }
  353. else {
  354. $date = new HproseDate($year, $month, $day);
  355. }
  356. return $date;
  357. }
  358. public function readTime($includeTag = false) {
  359. if ($includeTag) $this->checkTag(HproseTags::TagTime);
  360. $hour = (int)($this->stream->read(2));
  361. $minute = (int)($this->stream->read(2));
  362. $second = (int)($this->stream->read(2));
  363. $microsecond = 0;
  364. $tag = $this->stream->getc();
  365. if ($tag == HproseTags::TagPoint) {
  366. $microsecond = (int)($this->stream->read(3)) * 1000;
  367. $tag = $this->stream->getc();
  368. if (($tag >= '0') && ($tag <= '9')) {
  369. $microsecond += (int)($tag) * 100 + (int)($this->stream->read(2));
  370. $tag = $this->stream->getc();
  371. if (($tag >= '0') && ($tag <= '9')) {
  372. $this->stream->skip(2);
  373. $tag = $this->stream->getc();
  374. }
  375. }
  376. }
  377. if ($tag == HproseTags::TagUTC) {
  378. $time = new HproseTime($hour, $minute, $second, $microsecond, true);
  379. }
  380. else {
  381. $time = new HproseTime($hour, $minute, $second, $microsecond);
  382. }
  383. return $time;
  384. }
  385. public function readBytes($includeTag = false) {
  386. if ($includeTag) $this->checkTag(HproseTags::TagBytes);
  387. $count = (int)($this->stream->readuntil(HproseTags::TagQuote));
  388. $bytes = $this->stream->read($count);
  389. $this->stream->skip(1);
  390. return $bytes;
  391. }
  392. public function readUTF8Char($includeTag = false) {
  393. if ($includeTag) $this->checkTag(HproseTags::TagUTF8Char);
  394. $c = $this->stream->getc();
  395. $s = $c;
  396. $a = ord($c);
  397. if (($a & 0xE0) == 0xC0) {
  398. $s .= $this->stream->getc();
  399. }
  400. elseif (($a & 0xF0) == 0xE0) {
  401. $s .= $this->stream->read(2);
  402. }
  403. elseif ($a > 0x7F) {
  404. throw new HproseException("bad utf-8 encoding");
  405. }
  406. return $s;
  407. }
  408. public function readString($includeTag = false) {
  409. if ($includeTag) $this->checkTag(HproseTags::TagString);
  410. $len = (int)$this->stream->readuntil(HproseTags::TagQuote);
  411. $this->stream->mark();
  412. $utf8len = 0;
  413. for ($i = 0; $i < $len; ++$i) {
  414. switch (ord($this->stream->getc()) >> 4) {
  415. case 0:
  416. case 1:
  417. case 2:
  418. case 3:
  419. case 4:
  420. case 5:
  421. case 6:
  422. case 7: {
  423. // 0xxx xxxx
  424. $utf8len++;
  425. break;
  426. }
  427. case 12:
  428. case 13: {
  429. // 110x xxxx 10xx xxxx
  430. $this->stream->skip(1);
  431. $utf8len += 2;
  432. break;
  433. }
  434. case 14: {
  435. // 1110 xxxx 10xx xxxx 10xx xxxx
  436. $this->stream->skip(2);
  437. $utf8len += 3;
  438. break;
  439. }
  440. case 15: {
  441. // 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
  442. $this->stream->skip(3);
  443. $utf8len += 4;
  444. ++$i;
  445. break;
  446. }
  447. default: {
  448. throw new HproseException('bad utf-8 encoding');
  449. }
  450. }
  451. }
  452. $this->stream->reset();
  453. $this->stream->unmark();
  454. $s = $this->stream->read($utf8len);
  455. $this->stream->skip(1);
  456. return $s;
  457. }
  458. public function readGuid($includeTag = false) {
  459. if ($includeTag) $this->checkTag(HproseTags::TagGuid);
  460. $this->stream->skip(1);
  461. $s = $this->stream->read(36);
  462. $this->stream->skip(1);
  463. return $s;
  464. }
  465. protected function &readListBegin() {
  466. $list = array();
  467. return $list;
  468. }
  469. protected function &readListEnd(&$list) {
  470. $count = (int)$this->stream->readuntil(HproseTags::TagOpenbrace);
  471. for ($i = 0; $i < $count; ++$i) {
  472. $list[] = &$this->unserialize();
  473. }
  474. $this->stream->skip(1);
  475. return $list;
  476. }
  477. public function &readList($includeTag = false) {
  478. if ($includeTag) $this->checkTag(HproseTags::TagList);
  479. $list = &$this->readListBegin();
  480. return $this->readListEnd($list);
  481. }
  482. protected function &readMapBegin() {
  483. $map = array();
  484. return $map;
  485. }
  486. protected function &readMapEnd(&$map) {
  487. $count = (int)$this->stream->readuntil(HproseTags::TagOpenbrace);
  488. for ($i = 0; $i < $count; ++$i) {
  489. $key = &$this->unserialize();
  490. $map[$key] = &$this->unserialize();
  491. }
  492. $this->stream->skip(1);
  493. return $map;
  494. }
  495. public function &readMap($includeTag = false) {
  496. if ($includeTag) $this->checkTag(HproseTags::TagMap);
  497. $map = &$this->readMapBegin();
  498. return $this->readMapEnd($map);
  499. }
  500. protected function readObjectBegin() {
  501. list($classname, $fields) = $this->classref[(int)$this->stream->readuntil(HproseTags::TagOpenbrace)];
  502. $object = new $classname;
  503. return array($object, $fields);
  504. }
  505. protected function readObjectEnd($object, $fields) {
  506. $count = count($fields);
  507. if (class_exists('ReflectionClass')) {
  508. $reflector = new ReflectionClass($object);
  509. for ($i = 0; $i < $count; ++$i) {
  510. $field = $fields[$i];
  511. if ($reflector->hasProperty($field)) {
  512. $property = $reflector->getProperty($field);
  513. $property->setAccessible(true);
  514. $property->setValue($object, $this->unserialize());
  515. }
  516. else {
  517. $object->$field = &$this->unserialize();
  518. }
  519. }
  520. }
  521. else {
  522. for ($i = 0; $i < $count; ++$i) {
  523. $object->$fields[$i] = &$this->unserialize();
  524. }
  525. }
  526. $this->stream->skip(1);
  527. return $object;
  528. }
  529. public function readObject($includeTag = false) {
  530. if ($includeTag) {
  531. $tag = $this->checkTags(array(HproseTags::TagClass, HproseTags::TagObject));
  532. if ($tag == HproseTags::TagClass) {
  533. $this->readClass();
  534. return $this->readObject(true);
  535. }
  536. }
  537. list($object, $fields) = $this->readObjectBegin();
  538. return $this->readObjectEnd($object, $fields);
  539. }
  540. protected function readClass() {
  541. $classname = HproseClassManager::getClass(self::readString());
  542. $count = (int)$this->stream->readuntil(HproseTags::TagOpenbrace);
  543. $fields = array();
  544. for ($i = 0; $i < $count; ++$i) {
  545. $fields[] = $this->readString(true);
  546. }
  547. $this->stream->skip(1);
  548. $this->classref[] = array($classname, $fields);
  549. }
  550. public function reset() {
  551. $this->classref = array();
  552. }
  553. }
  554. class HproseReader extends HproseSimpleReader {
  555. private $ref;
  556. function __construct(&$stream) {
  557. parent::__construct($stream);
  558. $this->ref = array();
  559. }
  560. public function &unserialize($tag = NULL) {
  561. if (is_null($tag)) {
  562. $tag = $this->stream->getc();
  563. }
  564. if ($tag == HproseTags::TagRef) {
  565. return $this->readRef();
  566. }
  567. return parent::unserialize($tag);
  568. }
  569. public function readDate($includeTag = false) {
  570. if ($includeTag) {
  571. $tag = $this->checkTags(array(HproseTags::TagDate, HproseTags::TagRef));
  572. if ($tag == HproseTags::TagRef) return $this->readRef();
  573. }
  574. $date = parent::readDate();
  575. $this->ref[] = $date;
  576. return $date;
  577. }
  578. public function readTime($includeTag = false) {
  579. if ($includeTag) {
  580. $tag = $this->checkTags(array(HproseTags::TagTime, HproseTags::TagRef));
  581. if ($tag == HproseTags::TagRef) return $this->readRef();
  582. }
  583. $time = parent::readTime();
  584. $this->ref[] = $time;
  585. return $time;
  586. }
  587. public function readBytes($includeTag = false) {
  588. if ($includeTag) {
  589. $tag = $this->checkTags(array(HproseTags::TagBytes, HproseTags::TagRef));
  590. if ($tag == HproseTags::TagRef) return $this->readRef();
  591. }
  592. $bytes = parent::readBytes();
  593. $this->ref[] = $bytes;
  594. return $bytes;
  595. }
  596. public function readString($includeTag = false) {
  597. if ($includeTag) {
  598. $tag = $this->checkTags(array(HproseTags::TagString, HproseTags::TagRef));
  599. if ($tag == HproseTags::TagRef) return $this->readRef();
  600. }
  601. $str = parent::readString();
  602. $this->ref[] = $str;
  603. return $str;
  604. }
  605. public function readGuid($includeTag = false) {
  606. if ($includeTag) {
  607. $tag = $this->checkTags(array(HproseTags::TagGuid, HproseTags::TagRef));
  608. if ($tag == HproseTags::TagRef) return $this->readRef();
  609. }
  610. $guid = parent::readGuid();
  611. $this->ref[] = $guid;
  612. return $guid;
  613. }
  614. public function &readList($includeTag = false) {
  615. if ($includeTag) {
  616. $tag = $this->checkTags(array(HproseTags::TagList, HproseTags::TagRef));
  617. if ($tag == HproseTags::TagRef) return $this->readRef();
  618. }
  619. $list = &$this->readListBegin();
  620. $this->ref[] = &$list;
  621. return $this->readListEnd($list);
  622. }
  623. public function &readMap($includeTag = false) {
  624. if ($includeTag) {
  625. $tag = $this->checkTags(array(HproseTags::TagMap, HproseTags::TagRef));
  626. if ($tag == HproseTags::TagRef) return $this->readRef();
  627. }
  628. $map = &$this->readMapBegin();
  629. $this->ref[] = &$map;
  630. return $this->readMapEnd($map);
  631. }
  632. public function readObject($includeTag = false) {
  633. if ($includeTag) {
  634. $tag = $this->checkTags(array(HproseTags::TagClass, HproseTags::TagObject, HproseTags::TagRef));
  635. if ($tag == HproseTags::TagRef) return $this->readRef();
  636. if ($tag == HproseTags::TagClass) {
  637. $this->readClass();
  638. return $this->readObject(true);
  639. }
  640. }
  641. list($object, $fields) = $this->readObjectBegin();
  642. $this->ref[] = $object;
  643. return $this->readObjectEnd($object, $fields);
  644. }
  645. private function &readRef() {
  646. $ref = &$this->ref[(int)$this->stream->readuntil(HproseTags::TagSemicolon)];
  647. if (gettype($ref) == 'array') {
  648. $result = &$ref;
  649. }
  650. else {
  651. $result = $ref;
  652. }
  653. return $result;
  654. }
  655. public function reset() {
  656. parent::reset();
  657. $this->ref = array();
  658. }
  659. }
  660. ?>