<?php

$tmp_dir = "/tmp/";
if (!is_writable("$tmp_dir")) { die("Unable to write to tempdir $tmp_dir"); }

if (!empty($_GET['source'])) { highlight_file(__FILE__); exit; }

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

print "<h1>Compare serialize/unserialize PHP functions</h1>";

if (!empty($_GET['real_data'])) {
    $str  = file_get_contents("sample.json");
    $hash = json_decode($str, true);
    printf("<p>Using %d bytes of source data</p>", strlen($str));
} else {
    for ($i = 0; $i < 100000; $i++) {
        $hash[$i] = random_int(0,99999);
    }
    printf("<p>Using %d element array as source data</p>", count($hash));
}

////////////////////////////////////////////////////////////////////////////////////

sw();
$file     = "$tmp_dir/foo.ser";
$ok       = save_serial($hash, $file);
$ms       = sw();
$stat     = stat($file);
$size     = $stat['size'];
$size_str = human_size($size);
print "Serialize save: $ms ms ($size_str)<br />";

sw();
$ok = read_serial($file);
$ms = sw();
print "Serialize read: $ms ms<br /><br />";

unlink($file);

if ($ok !== $hash) { print "<p>Serialize does not match</p>"; }

////////////////////////////////////////////////////////////////////////////////////

if (function_exists('json_encode')) {
    sw();
    $file = "$tmp_dir/foo.json";
    $ok   = save_json($hash, $file);
    $ms   = sw();

    $stat     = stat($file);
    $size     = $stat['size'];
    $size_str = human_size($size);
    print "JSON save: $ms ms ($size_str)<br />";

    sw();
    $ok = read_json($file);
    $ms = sw();
    print "JSON read: $ms ms<br /><br />";

    unlink($file);

    if ($ok !== $hash) { print "<p>JSON does not match</p>"; }
}

////////////////////////////////////////////////////////////////////////////////////

sw();
$file = "$tmp_dir/foo.php";
$ok = save_php_raw($hash, $file);
$ms = sw();

$stat     = stat($file);
$size     = $stat['size'];
$size_str = human_size($size);
print "PHP save: $ms ms ($size_str)<br />";

sw();
$ok = read_php_raw($file);
$ms = sw();
print "PHP read: $ms ms<br /><br />";

unlink($file);

if ($ok !== $hash) { print "<p>PHP does not match</p>"; }

////////////////////////////////////////////////////////////////////////////////////

if (class_exists('Memcached')) {
    $m = new Memcached();
    $m->addServer('127.0.0.1',11211);

    sw();
    $ckey = 'serial_test_key';
    $ok = $m->set($ckey, $hash, time() + 3600);

    if (!$ok) {
        $err_num = $m->getResultCode();
        print "<p>Error adding item to memcache (error #$err_num)</p>";
        $ms = sw(); // Reset the stopwatch
    } else {
        $ms = sw();
        print "Memcache set: $ms ms<br />";

        sw();
        $ok = $m->get($ckey);
        $ms = sw();
        print "Memcache get: $ms ms<br /><br />";

        if ($ok !== $hash) { print "<p>Memcache does not match</p>"; }
    }
}

////////////////////////////////////////////////////////////////////////////////////

if (function_exists('igbinary_serialize')) {
    sw();
    $file = "$tmp_dir/foo.ig";
    $ok   = save_igbinary($hash, $file);
    $ms   = sw();

    $stat     = stat($file);
    $size     = $stat['size'];
    $size_str = human_size($size);
    print "IGBinary save: $ms ms ($size_str)<br />";

    sw();
    $ok = read_igbinary($file);
    $ms = sw();
    print "IGBinary read: $ms ms<br /><br />";

    unlink($file);

    if ($ok !== $hash) { print "<p>IGBinary does not match</p>"; }
}

////////////////////////////////////////////////////////////////////////////////////

if (function_exists('msgpack_pack')) {
    sw();
    $file = "$tmp_dir/foo.mp";
    $ok   = save_msgpack($hash, $file);
    $ms   = sw();

    $stat     = stat($file);
    $size     = $stat['size'];
    $size_str = human_size($size);
    print "MsgPack save: $ms ms ($size_str)<br />";

    sw();
    $ok = read_msgpack($file);
    $ms = sw();
    print "MsgPack read: $ms ms<br />";

    unlink($file);

    if ($ok !== $hash) { print "<p>MsgPack does not match</p>"; }
}

////////////////////////////////////////////////////////////////////////////////////

print "<p><a href=\"?real_data=true\">[Use sample JSON]</a> <a href=\"?source=true\">[View source]</a></p>";

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

function read_serial($file) {
    $str = file_get_contents($file);
    $ret = unserialize($str);

    return $ret;
}

function save_serial($obj, $file) {
    $str = serialize($obj);
    $ret = file_put_contents($file, $str);

    return $ret;
}

function read_json($file) {
    $str = file_get_contents($file);
    $ret = json_decode($str, true);

    return $ret;
}

function save_json($obj, $file) {
    $str = json_encode($obj);
    $ret = file_put_contents($file, $str);

    return $ret;
}

function read_igbinary($file) {
    $str = file_get_contents($file);
    $ret = igbinary_unserialize($str);

    return $ret;
}

function save_igbinary($obj, $file) {
    $str = igbinary_serialize($obj);
    $ret = file_put_contents($file, $str);

    return $ret;
}

function read_msgpack($file) {
    $str = file_get_contents($file);
    $ret = msgpack_unpack($str);

    return $ret;
}

function save_msgpack($obj, $file) {
    $str = msgpack_pack($obj);
    $ret = file_put_contents($file, $str);

    return $ret;
}

function read_php_raw($file) {
    $ret = include $file;

    return $ret;
}

function save_php_raw($obj, $file) {
    $ret = file_put_contents($file, "<?php\n\nreturn " . var_export($obj, true) . ";");

    return $ret;
}

function human_size($size) {
    # If the size is 0 or less, return 0 B this stops math errors from occurring
    if ($size <= 0) {
        return '0B';
    } else {
        $unit=array('B','K','M','G','T','P');
        return @round($size/pow(1024,($i=floor(log($size,1024)))),2) . $unit[$i];
    }
}

// Stopwatch function: returns milliseconds
function sw() {
    static $start = null;

    if (!$start) {
        $start = hrtime(1);
    } else {
        $ret   = (hrtime(1) - $start) / 1000000;
        $start = null; // Reset the start time
        return sprintf("%0.3f", $ret);
    }
}