| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 | <?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();    }}?>
 |