| 
	
 | 
 Posted by GamblerZG on 06/16/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] 
 |