You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
11 KiB
PHTML
301 lines
11 KiB
PHTML
5 years ago
|
<?php
|
||
|
/**********************************************************\
|
||
|
| |
|
||
|
| hprose |
|
||
|
| |
|
||
|
| Official WebSite: http://www.hprose.com/ |
|
||
|
| http://www.hprose.net/ |
|
||
|
| http://www.hprose.org/ |
|
||
|
| |
|
||
|
\**********************************************************/
|
||
|
|
||
|
/**********************************************************\
|
||
|
* *
|
||
|
* HproseWriter.php *
|
||
|
* *
|
||
|
* hprose writer library for php5. *
|
||
|
* *
|
||
|
* LastModified: Nov 13, 2013 *
|
||
|
* Author: Ma Bingyao <andot@hprfc.com> *
|
||
|
* *
|
||
|
\**********************************************************/
|
||
|
|
||
|
require_once('HproseCommon.php');
|
||
|
require_once('HproseTags.php');
|
||
|
require_once('HproseClassManager.php');
|
||
|
|
||
|
class HproseSimpleWriter {
|
||
|
public $stream;
|
||
|
private $classref;
|
||
|
private $fieldsref;
|
||
|
function __construct(&$stream) {
|
||
|
$this->stream = &$stream;
|
||
|
$this->classref = array();
|
||
|
$this->fieldsref = array();
|
||
|
}
|
||
|
public function serialize(&$var) {
|
||
|
if ((!isset($var)) || ($var === NULL)) {
|
||
|
$this->writeNull();
|
||
|
}
|
||
|
elseif (is_scalar($var)) {
|
||
|
if (is_int($var)) {
|
||
|
$this->writeInteger($var);
|
||
|
}
|
||
|
elseif (is_bool($var)) {
|
||
|
$this->writeBoolean($var);
|
||
|
}
|
||
|
elseif (is_float($var)) {
|
||
|
$this->writeDouble($var);
|
||
|
}
|
||
|
elseif (is_string($var)) {
|
||
|
if ($var === '') {
|
||
|
$this->writeEmpty();
|
||
|
}
|
||
|
elseif ((strlen($var) < 4) && is_utf8($var) && (ustrlen($var) == 1)) {
|
||
|
$this->writeUTF8Char($var);
|
||
|
}
|
||
|
elseif (is_utf8($var)) {
|
||
|
$this->writeString($var, true);
|
||
|
}
|
||
|
else {
|
||
|
$this->writeBytes($var, true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
elseif (is_array($var)) {
|
||
|
if (is_list($var)) {
|
||
|
$this->writeList($var, true);
|
||
|
}
|
||
|
else {
|
||
|
$this->writeMap($var, true);
|
||
|
}
|
||
|
}
|
||
|
elseif (is_object($var)) {
|
||
|
if ($var instanceof stdClass) {
|
||
|
$this->writeStdObject($var, true);
|
||
|
}
|
||
|
elseif (($var instanceof HproseDate) || ($var instanceof HproseDateTime)) {
|
||
|
$this->writeDate($var, true);
|
||
|
}
|
||
|
elseif ($var instanceof HproseTime) {
|
||
|
$this->writeTime($var, true);
|
||
|
}
|
||
|
else {
|
||
|
$this->writeObject($var, true);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
throw new HproseException('Not support to serialize this data');
|
||
|
}
|
||
|
}
|
||
|
public function writeInteger($integer) {
|
||
|
if ($integer >= 0 && $integer <= 9) {
|
||
|
$this->stream->write((string)$integer);
|
||
|
}
|
||
|
else {
|
||
|
$this->stream->write(HproseTags::TagInteger . $integer . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
}
|
||
|
public function writeLong($long) {
|
||
|
if ($long >= '0' && $long <= '9') {
|
||
|
$this->stream->write($long);
|
||
|
}
|
||
|
else {
|
||
|
$this->stream->write(HproseTags::TagLong . $long . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
}
|
||
|
public function writeDouble($double) {
|
||
|
if (is_nan($double)) {
|
||
|
$this->writeNaN();
|
||
|
}
|
||
|
elseif (is_infinite($double)) {
|
||
|
$this->writeInfinity($double > 0);
|
||
|
}
|
||
|
else {
|
||
|
$this->stream->write(HproseTags::TagDouble . $double . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
}
|
||
|
public function writeNaN() {
|
||
|
$this->stream->write(HproseTags::TagNaN);
|
||
|
}
|
||
|
public function writeInfinity($positive = true) {
|
||
|
$this->stream->write(HproseTags::TagInfinity . ($positive ? HproseTags::TagPos : HproseTags::TagNeg));
|
||
|
}
|
||
|
public function writeNull() {
|
||
|
$this->stream->write(HproseTags::TagNull);
|
||
|
}
|
||
|
public function writeEmpty() {
|
||
|
$this->stream->write(HproseTags::TagEmpty);
|
||
|
}
|
||
|
public function writeBoolean($bool) {
|
||
|
$this->stream->write($bool ? HproseTags::TagTrue : HproseTags::TagFalse);
|
||
|
}
|
||
|
public function writeDate($date, $checkRef = false) {
|
||
|
if ($date->utc) {
|
||
|
$this->stream->write(HproseTags::TagDate . $date->toString(false));
|
||
|
}
|
||
|
else {
|
||
|
$this->stream->write(HproseTags::TagDate . $date->toString(false) . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
}
|
||
|
public function writeTime($time, $checkRef = false) {
|
||
|
if ($time->utc) {
|
||
|
$this->stream->write(HproseTags::TagTime . $time->toString(false));
|
||
|
}
|
||
|
else {
|
||
|
$this->stream->write(HproseTags::TagTime . $time->toString(false) . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
}
|
||
|
public function writeBytes($bytes, $checkRef = false) {
|
||
|
$len = strlen($bytes);
|
||
|
$this->stream->write(HproseTags::TagBytes);
|
||
|
if ($len > 0) $this->stream->write((string)$len);
|
||
|
$this->stream->write(HproseTags::TagQuote . $bytes . HproseTags::TagQuote);
|
||
|
}
|
||
|
public function writeUTF8Char($char) {
|
||
|
$this->stream->write(HproseTags::TagUTF8Char . $char);
|
||
|
}
|
||
|
public function writeString($str, $checkRef = false) {
|
||
|
$len = ustrlen($str);
|
||
|
$this->stream->write(HproseTags::TagString);
|
||
|
if ($len > 0) $this->stream->write((string)$len);
|
||
|
$this->stream->write(HproseTags::TagQuote . $str . HproseTags::TagQuote);
|
||
|
}
|
||
|
public function writeList(&$list, $checkRef = false) {
|
||
|
$count = count($list);
|
||
|
$this->stream->write(HproseTags::TagList);
|
||
|
if ($count > 0) $this->stream->write((string)$count);
|
||
|
$this->stream->write(HproseTags::TagOpenbrace);
|
||
|
for ($i = 0; $i < $count; ++$i) {
|
||
|
$this->serialize($list[$i]);
|
||
|
}
|
||
|
$this->stream->write(HproseTags::TagClosebrace);
|
||
|
}
|
||
|
public function writeMap(&$map, $checkRef = false) {
|
||
|
$count = count($map);
|
||
|
$this->stream->write(HproseTags::TagMap);
|
||
|
if ($count > 0) $this->stream->write((string)$count);
|
||
|
$this->stream->write(HproseTags::TagOpenbrace);
|
||
|
foreach ($map as $key => &$value) {
|
||
|
$this->serialize($key);
|
||
|
$this->serialize($value);
|
||
|
}
|
||
|
$this->stream->write(HproseTags::TagClosebrace);
|
||
|
}
|
||
|
public function writeStdObject($obj, $checkRef = false) {
|
||
|
$map = (array)$obj;
|
||
|
self::writeMap($map);
|
||
|
}
|
||
|
protected function writeObjectBegin($obj) {
|
||
|
$class = get_class($obj);
|
||
|
$alias = HproseClassManager::getClassAlias($class);
|
||
|
$fields = array_keys((array)$obj);
|
||
|
if (array_key_exists($alias, $this->classref)) {
|
||
|
$index = $this->classref[$alias];
|
||
|
}
|
||
|
else {
|
||
|
$index = $this->writeClass($alias, $fields);
|
||
|
}
|
||
|
return $index;
|
||
|
}
|
||
|
protected function writeObjectEnd($obj, $index) {
|
||
|
$fields = $this->fieldsref[$index];
|
||
|
$count = count($fields);
|
||
|
$this->stream->write(HproseTags::TagObject . $index . HproseTags::TagOpenbrace);
|
||
|
$array = (array)$obj;
|
||
|
for ($i = 0; $i < $count; ++$i) {
|
||
|
$this->serialize($array[$fields[$i]]);
|
||
|
}
|
||
|
$this->stream->write(HproseTags::TagClosebrace);
|
||
|
}
|
||
|
public function writeObject($obj, $checkRef = false) {
|
||
|
$this->writeObjectEnd($obj, $this->writeObjectBegin($obj));
|
||
|
}
|
||
|
protected function writeClass($alias, $fields) {
|
||
|
$len = ustrlen($alias);
|
||
|
$this->stream->write(HproseTags::TagClass . $len .
|
||
|
HproseTags::TagQuote . $alias . HproseTags::TagQuote);
|
||
|
$count = count($fields);
|
||
|
if ($count > 0) $this->stream->write((string)$count);
|
||
|
$this->stream->write(HproseTags::TagOpenbrace);
|
||
|
for ($i = 0; $i < $count; ++$i) {
|
||
|
$field = $fields[$i];
|
||
|
if ($field{0} === "\0") {
|
||
|
$field = substr($field, strpos($field, "\0", 1) + 1);
|
||
|
}
|
||
|
$this->writeString($field);
|
||
|
}
|
||
|
$this->stream->write(HproseTags::TagClosebrace);
|
||
|
$index = count($this->fieldsref);
|
||
|
$this->classref[$alias] = $index;
|
||
|
$this->fieldsref[$index] = $fields;
|
||
|
return $index;
|
||
|
}
|
||
|
public function reset() {
|
||
|
$this->classref = array();
|
||
|
$this->fieldsref = array();
|
||
|
}
|
||
|
}
|
||
|
class HproseWriter extends HproseSimpleWriter {
|
||
|
private $ref;
|
||
|
private $arrayref;
|
||
|
function __construct(&$stream) {
|
||
|
parent::__construct($stream);
|
||
|
$this->ref = array();
|
||
|
$this->arrayref = array();
|
||
|
}
|
||
|
private function writeRef(&$obj, $checkRef, $writeBegin, $writeEnd) {
|
||
|
if (is_string($obj)) {
|
||
|
$key = 's_' . $obj;
|
||
|
}
|
||
|
elseif (is_array($obj)) {
|
||
|
if (($i = array_ref_search($obj, $this->arrayref)) === false) {
|
||
|
$i = count($this->arrayref);
|
||
|
$this->arrayref[$i] = &$obj;
|
||
|
}
|
||
|
$key = 'a_' . $i;
|
||
|
}
|
||
|
else {
|
||
|
$key = 'o_' . spl_object_hash($obj);
|
||
|
}
|
||
|
if ($checkRef && array_key_exists($key, $this->ref)) {
|
||
|
$this->stream->write(HproseTags::TagRef . $this->ref[$key] . HproseTags::TagSemicolon);
|
||
|
}
|
||
|
else {
|
||
|
$result = $writeBegin ? call_user_func_array($writeBegin, array(&$obj)) : false;
|
||
|
$index = count($this->ref);
|
||
|
$this->ref[$key] = $index;
|
||
|
call_user_func_array($writeEnd, array(&$obj, $result));
|
||
|
}
|
||
|
}
|
||
|
public function writeDate($date, $checkRef = false) {
|
||
|
$this->writeRef($date, $checkRef, NULL, array(&$this, 'parent::writeDate'));
|
||
|
}
|
||
|
public function writeTime($time, $checkRef = false) {
|
||
|
$this->writeRef($time, $checkRef, NULL, array(&$this, 'parent::writeTime'));
|
||
|
}
|
||
|
public function writeBytes($bytes, $checkRef = false) {
|
||
|
$this->writeRef($bytes, $checkRef, NULL, array(&$this, 'parent::writeBytes'));
|
||
|
}
|
||
|
public function writeString($str, $checkRef = false) {
|
||
|
$this->writeRef($str, $checkRef, NULL, array(&$this, 'parent::writeString'));
|
||
|
}
|
||
|
public function writeList(&$list, $checkRef = false) {
|
||
|
$this->writeRef($list, $checkRef, NULL, array(&$this, 'parent::writeList'));
|
||
|
}
|
||
|
public function writeMap(&$map, $checkRef = false) {
|
||
|
$this->writeRef($map, $checkRef, NULL, array(&$this, 'parent::writeMap'));
|
||
|
}
|
||
|
public function writeStdObject($obj, $checkRef = false) {
|
||
|
$this->writeRef($obj, $checkRef, NULL, array(&$this, 'parent::writeStdObject'));
|
||
|
}
|
||
|
public function writeObject($obj, $checkRef = false) {
|
||
|
$this->writeRef($obj, $checkRef, array(&$this, 'writeObjectBegin'), array(&$this, 'writeObjectEnd'));
|
||
|
}
|
||
|
public function reset() {
|
||
|
parent::reset();
|
||
|
$this->ref = array();
|
||
|
$this->arrayref = array();
|
||
|
}
|
||
|
}
|
||
|
?>
|