diff options
Diffstat (limited to 'preload-zstd.inc')
-rw-r--r-- | preload-zstd.inc | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/preload-zstd.inc b/preload-zstd.inc new file mode 100644 index 0000000..de8abd0 --- /dev/null +++ b/preload-zstd.inc @@ -0,0 +1,89 @@ +<?php +/** + * ZSTD compressor using FFI and libzstd + * PoC, only for documentation purpose + * + * Copyright (c) 2019 Remi Collet + * License: CC-BY-SA + * http://creativecommons.org/licenses/by-sa/4.0/ + */ +namespace Remi; + +class Zstd { + static private $ffi = null; + + public static function init() { + if (self::$ffi) { + return; + } + // Try if preloaded + try { + self::$ffi = \FFI::scope("_REMI_ZSTD_"); + } catch (\FFI\Exception $e) { + // Try direct load + if (PHP_SAPI === 'cli' || (int)ini_get("ffi.enable")) { + self::$ffi = \FFI::load(__DIR__ . '/preload-zstd.h'); + } else { + throw $e; + } + } + if (!self::$ffi) { + throw new \RuntimeException("FFI parse fails"); + } + } + + public static function compress($in, $out) { + self::init(); + + $ret = []; + $src = file_get_contents($in); + if ($src === false) { + throw new \RuntimeException("Read fails"); + } + $len = strlen($src); + $ret['in_len'] = $len; + + $max = self::$ffi->ZSTD_compressBound($len); + $ret['max_len'] = $max; + + $comp = str_repeat(' ', $max); + $clen = self::$ffi->ZSTD_compress($comp, $max, $src, $len, 6); + if (self::$ffi->ZSTD_isError($clen)) { + throw new \RuntimeException("Compression fails"); + } + $ret['out_len'] = $clen; + if (file_put_contents($out, substr($comp, 0, $clen)) !== $clen) { + throw new \RuntimeException("Save fails"); + } + + return $ret; + } + + public static function decompress($in, $out) { + self::init(); + + $ret = []; + $comp = file_get_contents($in); + if ($comp === false) { + throw new \RuntimeException("Read fails"); + } + $clen = strlen($comp); + $ret['in_len'] = $clen; + + $max = self::$ffi->ZSTD_decompressBound($comp, $clen); + $ret['max_len'] = $max; + + $unco = str_repeat(' ', $max); + $ulen = self::$ffi->ZSTD_decompress($unco, $max, $comp, $clen); + if (self::$ffi->ZSTD_isError($clen)) { + throw new \RuntimeException("Compression fails"); + } + $ret['out_len'] = $ulen; + if (file_put_contents($out, substr($unco, 0, $ulen)) !== $ulen) { + throw new \RuntimeException("Save fails"); + } + + return $ret; + } +} + |