Sunday 7 April 2019

Quick & dirty php serilaization

 class MYENC {
  private $STRESC = [ '"' => """, "'" => "'", '&' => "&", '>' => ">", '<' => "<", ];
  function STRENC($s) { 
   if (is_null($s)) return "N";
   $opc = 'P'; $rv = [];
   foreach (str_split($s) as $c) {
    $n = ord($c);
    if ($n <= 0x20 || $n > 126 || $n == ord('\\')) array_push($rv, sprintf(strtoupper("&#%x;"), $n));
    elseif (array_key_exists($c, $this->STRESC))  array_push($rv, $this->STRESC[$c]); 
    else array_push($rv, $c);
   }
   return join('',$rv);
  }
  function STRDEC($s) {
   if (is_null($s)) return $s;
   preg_match_all("/[&][^;]*;/", $s, $m, PREG_OFFSET_CAPTURE); 
   if (count($m) <= 0) return $s;
   $p = $m[0];
   if (count($p) <= 0) return $s;
   $ESC = array_flip($this->STRESC);
   for ($i = count($p)-1; $i >= 0; $i--) {
    $rep = ''; $x = $p[$i];
    if (array_key_exists($x[0], $ESC)) $rep = $ESC[$x[0]];
    else if (preg_match("/^[&][#]([0-9A-F]+);/i", $x[0], $h) > 0) $rep = chr(hexdec($h[1]));
    $s = substr_replace($s, $rep, $x[1], strlen($x[0]));
   }
   return $s;
  }
  private $CONTROL = [ "N" => [ 'arg' => 0, 'func' => '_N'],
              "A" => [ 'opc' => 'A', 'arg' => 0, 'func' => '_A'],
              "C" => [ 'opc' => 'C', 'arg' => 0, 'func' => '_C'],
              "P" => [ 'opc' => 'P', 'arg' => 1, 'func' => '_P'],
              "=" => [ 'opc' => '=', 'arg' => 0, 'func' => '_EQ'],
              "#" => [ 'opc' => '#', 'arg' => 0, 'func' => '_HASH'],
              "i" => [ 'opc' => 'i', 'arg' => 0, 'func' => '_INT'],
              "b" => [ 'opc' => 'b', 'arg' => 0, 'func' => '_BOOL'],
              "f" => [ 'opc' => 'f', 'arg' => 0, 'func' => '_FLOAT'],
  ];
  function __construct() { }
  private function    _N(&$S,$v) { array_push($S, NULL); }
  private function    _A(&$S,$v) { array_push($S, []); }
  private function    _C(&$S,$v) { array_push($S, new stdClass); }
  private function    _P(&$S,$v) { array_push($S, $v); }
  private function   _EQ(&$S,$v) { $v = array_pop($S); $f = array_pop($S); $C = array_pop($S); $C->$f = $v; array_push($S, $C); }
  private function _HASH(&$S,$v) { $v = array_pop($S); $f = array_pop($S); $A = array_pop($S); $A[$f] = $v; array_push($S, $A); }
  private function  _INT(&$S,$v) { $v = array_pop($S); array_push($S, intVal($v)); }
  private function _BOOL(&$S,$v) { $v = array_pop($S); array_push($S, !!intVal($v)); }
  private function _FLOAT(&$S,$v) { $v = array_pop($S); if ($v == 'NAN') $v = NAN; elseif ($v == 'INF') $v = INF; else $v = floatVal($v); array_push($S, $v); }
  private function NEXTOPC($P, $_off, &$opr, &$v) {
   $opr = NULL; $v = NULL;
   $idx = $_off;
   $CTL = $this->CONTROL;
   if ($idx < 0 || $idx >= strlen($P)) return 0;
   $op = $P[$idx];
   $idx++;
   if (!array_key_exists($op, $CTL)) return 0;
   $opr = $CTL[$op];
   if ($opr['arg'] == 0) return $idx - $_off;
   if (preg_match("/([0-9]+)[.]/", $P, $m, PREG_OFFSET_CAPTURE, $idx) <= 0) return 0;
   $k = $m[1];
   $idx += strlen($k[0]) + 1;
   $len = intVal($k[0]);
   if ($idx+$len > strlen($P)) return 0;
   $v = substr($P, $idx, $len);
   $idx += $len;
   return $idx - $_off;
  }
  function DECODE($P) {
   $STACK = []; $off = 0;
   for (;;) {
    $i = $this->NEXTOPC($P, $off, $opr, $v);
    if ($i <= 0) break;
    $off += $i;
    $func = $opr['func'];
    $this->$func($STACK, $v);
    #print "OPC " . $opr['opc'] . "\$i=${i} \$off=${off}\n";
   }
   return array_pop($STACK);
  }
  private function EMIT(&$K, ... $s) { $K .= join('', $s); }
  private function EMITS(&$K, ... $params) {
   foreach ($params as $s) {
    if (is_null($s)) { $this->EMIT($K, "N"); return; }
    $post = '';
    if (is_float($s)) {
     $post = 'f';
     if (is_nan($s)) $s = 'NAN'; elseif (is_infinite($s)) $s = 'INF'; else $s = sprintf("%.17e", $s);
    }
    elseif (is_int($s)) $post = 'i';
    elseif (is_bool($s)) $post = 'b';

    $this->EMIT($K, "P", strlen($s), ".", $s, $post);
   }
  }
  private function ENC(&$K, $X) {
   if (is_array($X)) {
    $this->EMIT($K, "A");
    foreach ($X as $k => $v) {
     if (is_array($v)) { $this->EMITS($K, $k); $this->ENC($K, $v); continue; }
     if (is_object($v)) { $this->EMITS($K, $k); $this->ENC($K, $v); continue; }
     $this->EMITS($K, $k, $v);
     $this->EMIT($K, "#");
    }
    return;
   }
   if (is_object($X)) {
    $this->EMIT($K, "C");
    foreach (get_object_vars ($X) as $k => $v) {
     if (is_array($v)) { $this->EMITS($K, $k); $this->ENC($K, $v); continue; }
     if (is_object($v)) { $this->EMITS($K, $k); $this->ENC($K, $v); continue; }
     $this->EMITS($K, $k, $v);
     $this->EMIT($K, "=");
    }
    return;
   }
   $this->EMITS($K,$X);
  }
  function ENCODE($X) { $K = ''; $this->ENC($K, $X); return $K; }
 }

No comments:

Post a Comment