<?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; 
    } 
} 
 
?> 
 
 |