Re: Storing data structires in DB

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ok, I wrote something that fits my needs. But, as I said, it is slow. Too slow. Is anyone except me interested in human-editable serialize? Can anyone help me with optimization? And please do not tell me that I need to write it in C++. The thing should be portable.

==========================

define('CMS_ARR_BEGIN', 1);
define('CMS_ARR_END', 2);
define('CMS_COMA', 3);
define('CMS_ARROW', 4);
define('CMS_SCALAR', 5);

function encode($var) {
   if (is_array($var)) {
       $code = '(';
       foreach ($var as $key => $value) {
           $code .= encode($key).'='.encode($value).',';
       }
       $code = chop($code, ','); //remove unnecessary coma
       $code .= ')';
       return $code;
   } else {
       if (is_string($var)) {
           if (strpos($var, "'") !== FALSE) {
               $var = str_replace("'", "''", $var);
           }
           return "'".$var."'";
       } elseif (is_numeric($var)) {
           return $var;
       } elseif (is_bool($var)) {
           return ($var ? 'T' : 'F');
       } else {
           return 'N';
       }
   }
}

function decode($str){
    $stack = array();
    $scalars = array();
    $strLen = strlen($str);
    while ($ptr < $strLen) {
        $ptrChar = $str{$ptr};
        if (preg_match('/\s/', $ptrChar )) {
            //do nothing
        } else {
            if ($ptrChar == '(') {
                $stack[] = CMS_ARR_BEGIN;
            } elseif ($ptrChar == ')') {
                $arrBegins = array_pop(array_keys($stack, CMS_ARR_BEGIN));
                if ($arrBegins === FALSE) {
                    user_error("Unexpected ')'", E_USER_WARNING);
                    return;
                }
                $arrTokens = array_splice($stack, $arrBegins + 1); //get array content
                array_pop($stack); //remove beginning token
                if (empty($arrTokens)) { //empty array
                    $scalars[] =  array();
                    $stack[] = CMS_SCALAR;
                    continue;
                }

$arrScalars = array();
foreach ($arrTokens as $token) {
if ($token == CMS_SCALAR) {
$arrScalars[] = array_pop($scalars); /*arrScalars are now reversed, so first token is the last scalar*/
}
}


                if ($arrTokens[sizeof($arrTokens) - 1] != CMS_COMMA) {//for symmetry
                    array_push($arrTokens, CMS_COMMA);
                }

$arrBuffer = array();
reset($arrTokens);
while (list(, $token) = each($arrTokens)) {
if ($token == CMS_SCALAR) {
list(,$nextTok) = each($arrTokens);
if ($nextTok == CMS_COMMA) {
$arrBuffer[] = array_pop($arrScalars);
continue;
} elseif ($nextTok == CMS_ARROW) {
list(, $valTok) = each($arrTokens);
if ($valTok != CMS_SCALAR) {
var_dump($arrTokens);
var_dump($arrScalars);
user_error("Invalid token encountered during array compression: $valKey => $valTok", E_USER_WARNING);
return;
}
$arrBuffer[array_pop($arrScalars)] = array_pop($arrScalars);
list($valKey, $valTok) = each($arrTokens);
if ($valTok != CMS_COMMA) {
var_dump($arrTokens);
var_dump($arrScalars);
user_error("Invalid token encountered during array compression: $valKey => $valTok", E_USER_WARNING);
return;
}
} else {
echo "Array compression dump:\n";
var_dump($arrTokens);
var_dump($arrScalars);
user_error("Invalid token encountered during array compression:$ntk => $nextTok", E_USER_WARNING);
return;
}
} else {
echo "Array compression dump:\n";
var_dump($arrTokens);
var_dump($arrScalars);
user_error("Invalid token encountered during array compression:$key => $token", E_USER_WARNING);
return;
}
}


                $scalars[] = $arrBuffer; //now multiple scalars replaced with array itself
                $stack[] = CMS_SCALAR;
            } elseif (preg_match('/["\']/', $ptrChar)) {
                $qEnd = strpos($str, $ptrChar, $ptr + 1);
                while ($str{$qEnd + 1} == $str{$qEnd}) { //deal with escapes
                    $qEnd = strpos($str, $ptrChar, $qEnd + 2);
                }

if ($qEnd === FALSE) {
user_error("String is not terminated", E_USER_WARNING);
return NULL;
}
$stack[] = CMS_SCALAR;
$scalars[] = str_replace($ptrChar.$ptrChar, $ptrChar, substr($str, $ptr + 1, $qEnd - ($ptr+1)));
$ptr = $qEnd;
//} elseif (in_array($ptrChar, $numerics)) {
} elseif (preg_match('/^[0-9\+\-]$/', $ptrChar)) {
$numEndComma = strpos($str, ',', $ptr);
$numEndArrow = strpos($str, '=', $ptr);
if ($numEndComma === FALSE) { $numEndComma = $strLen; }
if ($numEndArrow === FALSE) { $numEndArrow = $strLen; }
$numEnd = ($numEndComma < $numEndArrow ? $numEndComma : $numEndArrow);
$num = trim(substr($str, $ptr, $numEnd - $ptr));
if (is_numeric($num)) {
$scalars[] = $num + 0;
} else {
user_error("Invalid numeric '$num' at $ptr", E_USER_WARNING);
return;
}
$stack[] = CMS_SCALAR;
$ptr = $numEnd - 1;
} elseif ($ptrChar == ',') {
$stack[] = CMS_COMMA;
} elseif ($ptrChar == '=') {
$stack[] = CMS_ARROW;
} elseif(preg_match('/t/i', $ptrChar)) {
$stack[] = CMS_SCALAR;
$scalars[] = TRUE;
} elseif(preg_match('/f/i', $ptrChar)) {
$stack[] = CMS_SCALAR;
$scalars[] = FALSE;
} elseif(preg_match('/n/i', $ptrChar)) {
$stack[] = CMS_SCALAR;
$scalars[] = NULL;
} else {
user_error("Invalid character at $ptr", E_USER_WARNING);
return NULL;
}
}
++$ptr;
}


    if (sizeof($scalars == 1)) { //it was singular variable
        return $scalars[0];
    } else {
        return $scalars;
    }
}

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux