|
Posted by GamblerZG on 10/17/95 11:12
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;
}
}
Navigation:
[Reply to this message]
|