Location: PHPKode > scripts > DX0 > dx0/dx0/pickle.inc
<?
if (!defined("_PICKLE_INCLUDED_"))
{
	define("_PICKLE_INCLUDED_", 1);
}
else
	return;

// this is pickle.inc
//
// The pickle function may be passed an associative array or object.  It returns a 
// string that can be used in python.
//
class pickleClass {
  var $STEP = 0;
  var $LINE = 0;
  var $FLAGS = "";
  var $BIN = 0;
  var $ESC = 0;
  var $KEYFLAG = 0;

  // these are the pickling functions
  function dumps($obj, $bin = 0, $esc = 0) {
    $this->STEP = 0;
    $this->FLAGS = "";
    $this->BIN = $bin;
    $this->ESC = $esc;

    $pickled = $this->_process($obj);
    $pickled .= $this->FLAGS.".";
    return $pickled;
  }

  function dump($obj, $fp, $bin = 0) {
    fwrite($fp, $this->dumps($obj, $bin));
  }

  function _process($obj) {
    $pickleBuf = $this->_signal(0);
    reset($obj);
    while(list($objKey, $objVal) = each($obj)) {
      $pickleBuf .= $this->_signal(1, $objKey);
      if (is_array($objVal)) $pickleBuf .= $this->_process($objVal);
      else $pickleBuf .= $this->_signal(1, $objVal);
      if (!$this->BIN) {
      	$this->FLAGS .= "s";
      }
    }
    if ($this->BIN) $this->FLAGS .= "u";
    return $pickleBuf;
  }

  function _signal($proc, $str = "") {
    switch($proc) {
      case 0:   // 'BEGIN ARRAY'
        if ($this->BIN) {
	  $sigBuf = "}";
	  $this->FLAGS .= "(";
	} else {
          $sigBuf = $this->FLAGS."(d";
    	  $this->FLAGS = "";
	}
        break;
      case 1:   // 'STRING'
        if ($this->BIN) {
	  $num = strlen($str);
	  if ($this->ESC) { $str = ereg_replace('"', '\"', $str); }
	  if ($num > 255) {
	  	$sigBuf = $this->FLAGS . "T";
		for ($i = 0; $i < 4; $i++) {
			$sigBuf .= $this->_char($num % 256);
			$num /= 256;
		}
	  } else {
	  	$sigBuf = $this->FLAGS . "U" . $this->_char($num);
	  }
	  $sigBuf .= $str;
	} else {
          $sigBuf = $this->FLAGS."S'".$this->_format($str)."'".$this->_char(10);
	}
    	$this->FLAGS = "";
        break;
      case 2:   // 'INTEGER'
        if ($this->BIN) {
	  $k = ord("K");
	  $num = intval($str);
	  if ($num > 255) {
	  	$i = 2;
		if ($num > 65535) {
			$i = 4;
		}
		$k = "\"".($k + $i)."\"";
		while ($i) {
			$k .= $this->_char($num % 256);
			$k /= 256;
			$i--;
		}
	  } else {
	  	$k = "\"".$k."\"".$this->_char($num);
	  }
	  $sigBuf = $this->FLAGS . $k;
	} else {
          $sigBuf = $this->FLAGS."I$str".$this->_char(10);
	}
	$this->FLAGS = "";
        break;
    }
    if ($this->BIN) {
      $sigBuf .= "q" . $this->_char($this->STEP);
    } else {
      $sigBuf .= "p".$this->STEP.$this->_char(10);
    }
    $this->STEP++;
    return $sigBuf;
  }

  function _format($str) {
    $str = ereg_replace("'", "\\\'", $str);
    $str = ereg_replace('"', '\"', $str);
    return $str;
  }

  function _char($ch) {
    $ch = intval($ch);
    if ($this->ESC) {
      return "\\" . sprintf("%03o", $ch);
    } else {
      return chr($ch);
    }
  }

  function _detect($str) {
  	// crappy, but very simple detection (returns 0 on ascii; 1 on binary)
  	return (ereg("^\(?[SIFdlpg]", $str) ? 0 : 1); 
  }

  // these are the unpickling functions
  function loads($str) {
    $this->STEP = 0;
    $this->LINE = 0;
    $this->EOF = 0;
    $this->KEYFLAG = 0;
    $this->DEPTH = array('PARENT');
    $this->TYPES = array();
    $this->LAST = '\$obj';
    $this->INDEX = array();
    $this->BIN = $this->_detect($str);  

    $str = $this->_raw($str);
    if ($this->BIN) {
      $this->PT = 0;
      //print $str."<BR>";
      while ($prog = $this->_binary($str)) {
        //print $prog."<BR>";
	if (substr($prog, 0, 4) == "\$obj") {
	  eval($prog);
	} else if (substr($prog, 0, 4) == "DONE") {
	  //print $prog."<BR>";
	  break;
	}
      }
    } else {
      $str = split("\n", $str);
      while (list(, $line) = each($str)) {
        //print $line."<BR>";
        $prog = $this->_ascii($line);
	//print $prog."<BR>";
	if (substr($prog, 0, 4) == "\$obj") {
	  eval($prog);
	}
      }
    }
    return $obj;
  }

  function load($fp) {
    $this->STEP = 0;
    $this->LINE = 0;
    $this->KEYFLAG = 0;
    $this->PT = 0;
    $this->EOF = 0;
    $this->DEPTH = array('PARENT');
    $this->TYPES = array();
    $this->LAST = '\$obj';
    $this->INDEX = array();

    $pt = ftell($fp);
    $str = fgets($fp, 40);
    $this->BIN = $this->_detect($str);  
    fseek($fp, $pt);
    if ($this->BIN) {
      while (!$this->EOF) {
        $prog = $this->_binary($fp);
	//print $prog."\n";
	if (substr($prog, 0, 4) == "\$obj") {
	  eval($prog);
	} else if (substr($prog, 0, 4) == "DONE") {
	  return $obj;
	}
      }
    } else {
      while (!feof($fp)) {
        $pt = ftell($fp);
        $line = fgets($fp, 4096);
        //print $line."<BR>";
        $prog = $this->_ascii($line);
	//print $prog."<BR>";
	if (substr($prog, 0, 4) == "\$obj") {
	  eval($prog);
	} else if (substr($prog, 0, 4) == "DONE") {
	  $off = intval(substr($prog, 5));
	  fseek($fp, intval($pt + $off + 1));
	  return $obj;
	}
      }
    }
    return $obj;
  }

  function _ascii($line) {
    $val = "";
    $prog = "";
    $cl = $op = $r = 0;
    while (strlen($val) < 1) {
      $ch = substr($line, $r, 1);
      if ($ch == "p") {
        $this->LINE = intval(substr($line, $r + 1));
	return "LINE ".$this->LINE;
      } else if ($ch == "a" || $ch == "s") {
        $cl++;
      } else if ($ch == "(") {
        $op++;
        if (substr($line, $r + 1, 1) == "l") {
	  $val = "[]";
	} else {
	  $val = "{}";
	}
	if (substr($line, $r + 2, 1) == "p") {
	  $this->LINE = intval(substr($line, $r + 3));
	}
      } else if ($ch == "S") {
        $val = substr($line, $r + 1);
      } else if ($ch == "I") {
        $val = intval(substr($line, $r + 1));
      } else if ($ch == ".") {
        return "DONE ".$r;
      }
      $r++;
    }
    if ($cl) {
      $this->STEP -= $cl - 1;
      if (strlen($val) > 0 && !$this->KEYFLAG 
        && $this->TYPES[$this->STEP - 1] == "{}") {
	$this->KEYFLAG = 1;
      } else if ($this->KEYFLAG && $this->TYPES[$this->PKSTEP - 1] == "[]") {
        $this->KEYFLAG = 0;
      }
      if ($this->TYPES[$this->STEP - 1] == "[]") {
        $this->DEPTH[$this->STEP]++;
      }
    }
    if (strlen($val) > 0) {
      //print "[$cl, $op] $val : $this->STEP<BR>";
      if ($this->KEYFLAG) {
        $this->DEPTH[$this->STEP] = $val;
	$this->KEYFLAG = 0;
      } else {
        if ($val == "[]") {
	  $this->TYPES[$this->STEP] = $val;
	  $this->DEPTH[$this->STEP + 1] = 0;
	  $val = "array()";
	} else if ($val == "{}") {
	  $this->KEYFLAG = 1;
	  $this->TYPES[$this->STEP] = $val;
	  $val = "array()";
	} else if ($this->TYPES[$this->STEP - 1] == "{}") {
	  $this->KEYFLAG = 1;
	}
	for ($dp = 1; $dp <= $this->STEP; $dp++) {
	  $prog .= "[".$this->DEPTH[$dp]."]";
	  if ($this->TYPES[$dp - 1] == "[]" && $dp == $this->STEP
	    && !$op) {
	    $this->DEPTH[$dp]++;
	  }
	}
	$prog = "\$obj$prog = $val;";
      }
    }
    $this->STEP += $op;

    return $prog;
  }

  function _binary($str) {
    $val = "";
    $prog = "";
    $cl = $op = 0;
    while ($val == "" && !$this->EOF) { 
      $ch = $this->_read($str, 1);
      if ($ch == "a" || $ch == "e" || $ch == "u" || $ch == "s") {
        $cl++;
      } else if ($ch == "}") {
        $op++;
	$val = "{}";
      } else if ($ch == "]") {
        $op++;
	$val = "[]";
      } else if ($ch == "U") {
        $len = ord($this->_read($str, 1));
        $val = "'".addslashes($this->_read($str, $len))."'";
      } else if ($ch == "T") {
        $len = ord($this->_read($str, 1)) + (ord($this->_read($str, 1)) * 256)
	  + (ord($this->_read($str,1)) * 256 * 256) + (ord($this->_read($str, 1)) * 256 * 256 * 256);
        $val = "'".addslashes($this->_read($str, $len))."'";
      } else if ($ch == "K") {
        $val = "'".ord($this->_read($str, 1))."'";
      } else if ($ch == "M") {
        $val = ord($this->_read($str, 1)) + (ord($this->_read($str, 1)) * 256);
      } else if ($ch == "J") {
        $val = ord($this->_read($str, 1)) + (ord($this->_read($str, 1)) * 256)
	  + (ord($this->_read($str,1)) * 256 * 256) + (ord($this->_read($str, 1)) * 256 * 256 * 256);
      } else if ($ch == ".") {
        return "DONE ".$this->PT;
      } else if ($ch == "h") {
        $val = ord($this->_read($str, 1));
        $val = $this->INDEX[$val];
      } else if ($ch == "q") {
        $val = ord($this->_read($str, 1));
        $this->INDEX[$val] = $this->LAST;
        $this->LAST = "";
        return "LINE ".$val;
      }
    }
    if ($cl) {
      $this->STEP -= $cl;
      if (strlen($val) > 0 && !$this->KEYFLAG 
        && $this->TYPES[$this->STEP - 1] == "{}") {
	$this->KEYFLAG = 1;
      } else if ($this->KEYFLAG && $this->TYPES[$this->PKSTEP - 1] == "[]") {
        $this->KEYFLAG = 0;
      }
      if ($this->TYPES[$this->STEP - 1] == "[]") {
        $this->DEPTH[$this->STEP]++;
      }
    }
    //print "[$cl, $op] $val : $this->PT\n";
    if ($val != "") {
      $this->LAST = $val;
      if ($this->KEYFLAG) {
        $this->DEPTH[$this->STEP] = $val;
	$this->KEYFLAG = 0;
      } else {
        if ($val == "[]") {
	  $this->TYPES[$this->STEP] = $val;
	  $this->DEPTH[$this->STEP + 1] = 0;
	  $val = "array()";
	} else if ($val == "{}") {
	  $this->KEYFLAG = 1;
	  $this->TYPES[$this->STEP] = $val;
	  $val = "array()";
	} else if ($this->TYPES[$this->STEP - 1] == "{}") {
	  $this->KEYFLAG = 1;
	}
	for ($dp = 1; $dp <= $this->STEP; $dp++) {
	  $prog .= "[".$this->DEPTH[$dp]."]";
	  if ($this->TYPES[$dp - 1] == "[]" && $dp == $this->STEP
	    && !$op) {
	    $this->DEPTH[$dp]++;
	  }
	}
        $this->LAST = "\$obj$prog";
        if ($ch == "K") $val = "intval($val)"; 
	$prog = "\$obj$prog = $val;";
      }
    }
    $this->STEP += $op;

    if ($this->EOF) $prog = "DONE";
    return ($prog ? $prog : "PASS");
  }

  function _read($in, $len) {
    if (is_string($in)) {
      $v = substr($in, $this->PT, $len);
    } else {
      $v = fread($in, $len);
      if (feof($in)) $this->EOF = 1;
    }
    $this->PT += $len;
    return $v;
  }

  function _raw($str) {
    $pl = 0;
    while ($pl = strpos($str, "\\", $pl)) {
      if (strpos($str, "\\", $pl) == $pl + 1) {
        $pl += 2; continue;
      }
      $pre = substr($str, 0, $pl);
      $o = substr($str, $pl + 1, 3);
      $post = substr($str, $pl + 4);
      $str = $pre . chr(octdec($o)) . $post;
    }
    return $str;
  }
}

function pickle_load($ref) {
  $pickle = new pickleClass;
  return $pickle->load($ref);
}

function pickle_loads($ref) {
  $pickle = new pickleClass;
  return $pickle->loads($ref);
}

function pickle_dump($obj, $ref, $bin = 0) {
  $pickle = new pickleClass;
  return $pickle->dump($obj, $ref, $bin);
}

function pickle_dumps($obj, $bin = 0, $esc = 0) {
  $pickle = new pickleClass;
  return $pickle->dumps($obj, $bin, $esc);
}

?>
Return current item: DX0