<?php
/**
* Copyright (c) 2009, PHPServer
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Cesar Rodas nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY CESAR RODAS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CESAR RODAS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
if (defined("_BSERIALIZE")) {
return;
}
define("_BSERIALIZE",dirname(__FILE__));
include(_BSERIALIZE."/error.php");
define("V_ZERO", 0x01);
/* integers */
define("V_1INT_POS", 0x10);
define("V_1INT_NEG", 0x11);
define("V_2INT_POS", 0x12);
define("V_2INT_NEG", 0x13);
define("V_4INT_POS", 0x14);
define("V_4INT_NEG", 0x15);
/* floats */
define("V_FLOAT_POS", 0x20);
define("V_FLOAT_NEG", 0x21);
/* boolean */
define("V_BOOL_TRUE", 0x30);
define("V_BOOL_FALSE", 0x31);
/* array */
define("V_ARRAY", 0x40);
/* object */
define("V_OBJECT", 0x50);
/* string */
define("V_STRING", 0x60);
class bserialize {
function bserialize() {
}
function unserialize(&$var) {
$i=0;
return $this->_unserialize($var,false,$i);
}
function _unserialize(&$var,$just_first=false,&$start) {
$len = strlen($var);
$out = null;
for($i = &$start; $i < $len; $i++) {
$type = ord($var[$i++]);
switch ($type) {
case V_ZERO:
$out = 0;
break;
case V_1INT_POS:
case V_1INT_NEG:
$out = ord($var[$i]);
if ($type==V_1INT_NEG) $out *= -1;
$i++;
break;
case V_2INT_POS:
case V_2INT_NEG:
$out = $this->__toint(substr($var,$i,2),2);
if ($type == V_2INT_NEG) $out *= -1;
$i += 2;
break;
case V_4INT_POS:
case V_4INT_NEG:
$out = $this->__toint(substr($var,$i,4),4);
if ($type == V_4INT_NEG) $out *= -1;
$i += 4;
break;
case V_FLOAT_POS:
case V_FLOAT_NEG:
$out = $this->__tofloat(substr($var,$i,6));
if ($type == V_FLOAT_NEG) $out *= -1;
$i += 6;
break;
case V_BOOL_TRUE:
$out = true;
break;
case V_BOOL_FALSE:
$out = false;
break;
case V_STRING:
$xlen = $this->_unserialize($var,true,$i);
if (!is_numeric($xlen)) {
trigger_error(STR_LEN);
return;
}
$out = substr($var,$i,$xlen);
$i += $xlen;
break;
case V_ARRAY:
$xlen = $this->_unserialize($var,true,$i);
if (!is_numeric($xlen)) {
trigger_error(ARR_LEN);
return;
}
$out = array();
$tmp = substr($var,$i,$xlen);
$itmp = 0;
while ($itmp < $xlen) {
$key = $this->_unserialize($tmp,true,$itmp);
$value = $this->_unserialize($tmp,true,$itmp);
$out[$key] = $value;
}
$i += $xlen;
break;
case V_OBJECT:
$class_name = $this->_unserialize($var,true,$i);
$xlen = $this->_unserialize($var,true,$i);
if (!is_numeric($xlen)) {
trigger_error(OBJ_LEN);
return;
}
/**/
$class_name = class_exists($class_name) ? $class_name : stdClass;
$out = new $class_name;
/**/
$tmp = substr($var,$i,$xlen);
$itmp = 0;
while ($itmp < $xlen) {
$key = $this->_unserialize($tmp,true,$itmp);
$value = $this->_unserialize($tmp,true,$itmp);
$out->$key = $value;
}
$i += $xlen;
break;
default:
trigger_error(sprintf(UNKNOW_TYPE,$type));
}
if (!is_null($out)) {
break;
}
}
return $out;
}
function serialize($var) {
$str = "";
if (is_integer($var) && $var==0) {
return chr(V_ZERO);
}
switch( ($type=gettype($var)) ) {
case "string":
$str .= chr(V_STRING);
$str .= $this->serialize((int)strlen($var));
$str .= $var;
break;
case "float":
case "double":
$str .= chr($var > 0 ? V_FLOAT_POS : V_FLOAT_NEG);
$str .= $this->__fromfloat($var);
break;
case "integer":
case "numeric":
$t = abs($var);
if ($t < 255) {
$str .= chr($var > 0 ? V_1INT_POS : V_1INT_NEG);
$str .= chr($t);
} else if ($t < 65536) {
$str .= chr($var > 0 ? V_2INT_POS : V_2INT_NEG);
$str .= $this->__fromint($var,2);
} else {
$str .= chr($var > 0 ? V_4INT_POS : V_4INT_NEG);
$str .= $this->__fromint($var);
}
break;
case "boolean":
$str .= chr($var ? V_BOOL_TRUE : V_BOOL_FALSE);
break;
case "array":
$str .= chr(V_ARRAY);
$tmp = "";
foreach($var as $key => $value) {
$tmp .= $this->serialize($key);
$tmp .= $this->serialize($value);
}
$str .= $this->serialize(strlen($tmp));
$str .= $tmp;
break;
case "object":
$str .= chr(V_OBJECT);
$str .= $this->serialize(get_class($var));
$tmp = "";
foreach(get_object_vars($var) as $key => $value) {
$tmp .= $this->serialize($key);
$tmp .= $this->serialize($value);
}
$str .= $this->serialize(strlen($tmp));
$str .= $tmp;
break;
default:
trigger_error(sprintf(UNKNOW_TYPE,$type));
break;
}
return $str;
}
function __toint($string,$blen=4) {
$out = 0;
$n = ($blen-1) * 8;
for($bits=0; $bits < $blen; $bits++) {
$out |= ord($string[$bits]) << $n;
$n -= 8;
}
return $out;
}
function __fromint($int,$blen=4) {
$int = (int)($int < 0) ? (-1*$int) : $int;
$bytes=str_repeat(" ",$blen);
$n = ($blen-1) * 8;
for($bits=0; $bits < $blen; $bits++) {
$bytes[$bits] = chr($int >> $n);
$int -= $bytes[$bits] << $n;
$n -= 8;
}
return $bytes;
}
function __fromfloat($float) {
$str = $this->__fromint($float);
$str .= $this->__fromint( round(($float-(int)$float)*1000) , 2 );
return $str;
}
function __tofloat($string) {
$float = $this->__toint(substr($string,0,4));
$float += $this->__toint(substr($string,4,2),2)/1000;
return $float;
}
}
?>
|