├── EXPERIMENTAL ├── CREDITS ├── .gitmodules ├── tests ├── endianness.inc ├── info.phpt ├── 004.phpt ├── 003.phpt ├── 003_b.phpt ├── 001.phpt ├── 001_b.phpt ├── 002.phpt ├── 005.phpt ├── 002_b.phpt ├── 005_b.phpt ├── apcu_serializer.phpt └── data.inc ├── snappy.stub.php ├── .github └── workflows │ ├── submodule.ps1 │ ├── test.ps1 │ ├── vcpkg.ps1 │ ├── build.ps1 │ ├── install.ps1 │ ├── linux.yaml │ └── windows.yaml ├── composer.json ├── .gitignore ├── config.w32 ├── php_snappy.h ├── README.md ├── COPYING.snappy ├── package.xml.in ├── LICENSE ├── config.m4 └── snappy.c /EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | snappy 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "snappy"] 2 | path = snappy 3 | url = https://github.com/google/snappy.git 4 | -------------------------------------------------------------------------------- /tests/endianness.inc: -------------------------------------------------------------------------------- 1 | enabled 16 | Extension Version => %d.%d.%d 17 | Snappy Version => %s 18 | %a 19 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kjdev/snappy", 3 | "type": "php-ext", 4 | "license": "MIT", 5 | "description": "A compression/decompression with Snappy", 6 | "require": { 7 | "php": ">= 5.2.0" 8 | }, 9 | "php-ext": { 10 | "extension-name": "snappy", 11 | "download-url-method": "pre-packaged-source", 12 | "configure-options": [] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile* 2 | *.la 3 | *.lo 4 | acinclude.m4 5 | aclocal.m4 6 | config.guess 7 | config.h* 8 | config.sub 9 | config.log 10 | config.nice 11 | config.status 12 | configure* 13 | install-sh 14 | libtool 15 | ltmain.sh 16 | missing 17 | mkinstalldirs 18 | .deps 19 | .libs/ 20 | autom4te.cache/ 21 | modules/ 22 | build/ 23 | run-tests.php 24 | tmp-php.ini 25 | ltmain.sh.backup 26 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_uncompress() function : basic functionality 3 | --SKIPIF-- 4 | --FILE-- 5 | 16 | ===DONE=== 17 | --EXPECT-- 18 | *** Testing snappy_uncompress() : basic functionality *** 19 | 20 | -- Basic decompress -- 21 | int(0) 22 | ===DONE=== 23 | -------------------------------------------------------------------------------- /.github/workflows/vcpkg.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | 3 | if (-not (Test-Path 'C:\php\deps')) { 4 | [void](New-Item 'C:\php\deps' -ItemType 'directory') 5 | } 6 | 7 | $package = "$env:VCPKG_LIBRARY" 8 | $arch = "$env:ARCH-windows" 9 | 10 | vcpkg install "${package}:${arch}" 11 | if (-not $?) { 12 | throw "installing failed with errorlevel $LastExitCode" 13 | } 14 | 15 | Copy-Item "C:\vcpkg\installed\$arch\bin" "C:\php\deps" -Recurse -Force 16 | Copy-Item "C:\vcpkg\installed\$arch\include" "C:\php\deps" -Recurse -Force 17 | Copy-Item "C:\vcpkg\installed\$arch\lib" "C:\php\deps" -Recurse -Force 18 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : variation 3 | --SKIPIF-- 4 | 23 | ===Done=== 24 | --EXPECTF-- 25 | *** Testing snappy_compress() : variation *** 26 | 27 | -- Testing multiple compression -- 28 | bool(false) 29 | bool(true) 30 | ===Done=== 31 | -------------------------------------------------------------------------------- /tests/003_b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : variation 3 | --SKIPIF-- 4 | 23 | ===Done=== 24 | --EXPECTF-- 25 | *** Testing snappy_compress() : variation *** 26 | 27 | -- Testing multiple compression -- 28 | bool(false) 29 | bool(true) 30 | ===Done=== 31 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | ARG_ENABLE("snappy", "enable snappy support", "yes"); 2 | 3 | if (PHP_SNAPPY != "no") { 4 | if (CHECK_LIB("snappy.lib;libsnappy.lib", "snappy", PHP_SNAPPY) && 5 | CHECK_HEADER_ADD_INCLUDE("snappy-c.h", "CFLAGS_SNAPPY", PHP_SNAPPY)) { 6 | EXTENSION("snappy", "snappy.c", PHP_SNAPPY_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 7 | } else { 8 | EXTENSION("snappy", "snappy.c", PHP_SNAPPY_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 9 | ADD_SOURCES("snappy", "snappy-c.cc snappy.cc snappy-stubs-internal.cc snappy-sinksource.cc", "snappy", "snappy"); 10 | ADD_FLAG("CFLAGS_SNAPPY", " /I" + configure_module_dirname + " /I" + configure_module_dirname + "/snappy"); 11 | // TODO: Need to create snappy/snappy-stubs-public.h 12 | } 13 | PHP_INSTALL_HEADERS("ext/snappy/", "php_snappy.h"); 14 | } 15 | -------------------------------------------------------------------------------- /php_snappy.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef PHP_SNAPPY_H 3 | #define PHP_SNAPPY_H 4 | 5 | #define SNAPPY_EXT_VERSION "0.2.3" 6 | 7 | extern zend_module_entry snappy_module_entry; 8 | #define phpext_snappy_ptr &snappy_module_entry 9 | 10 | /* Support PHP < 5.3.7 */ 11 | #ifndef ZEND_FE_END 12 | #define ZEND_FE_END {NULL, NULL, NULL} 13 | #endif 14 | 15 | #ifdef PHP_WIN32 16 | # define PHP_SNAPPY_API __declspec(dllexport) 17 | #elif defined(__GNUC__) && __GNUC__ >= 4 18 | # define PHP_SNAPPY_API __attribute__ ((visibility("default"))) 19 | #else 20 | # define PHP_SNAPPY_API 21 | #endif 22 | 23 | #ifdef ZTS 24 | #include "TSRM.h" 25 | #endif 26 | 27 | #ifdef ZTS 28 | #define SNAPPY_G(v) TSRMG(snappy_globals_id, zend_snappy_globals *, v) 29 | #else 30 | #define SNAPPY_G(v) (snappy_globals.v) 31 | #endif 32 | 33 | #if ZEND_MODULE_API_NO >= 20190128 34 | #ifndef TSRMLS_CC 35 | #define TSRMLS_CC 36 | #endif 37 | #ifndef TSRMLS_DC 38 | #define TSRMLS_DC 39 | #endif 40 | #endif 41 | 42 | #endif /* PHP_SNAPPY_H */ 43 | -------------------------------------------------------------------------------- /.github/workflows/build.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | 3 | $env:PATH = "C:\php\devel;C:\php\bin;C:\php\deps\bin;$env:PATH" 4 | 5 | $task = New-Item 'task.bat' -Force 6 | Add-Content $task 'call phpize 2>&1' 7 | Add-Content $task "call configure --with-php-build=C:\php\deps --enable-$env:PHP_EXT --enable-debug-pack 2>&1" 8 | Add-Content $task 'nmake /nologo 2>&1' 9 | Add-Content $task 'exit %errorlevel%' 10 | & "C:\php\php-sdk-$env:BIN_SDK_VER\phpsdk-$env:VS-$env:ARCH.bat" -t $task 11 | if (-not $?) { 12 | throw "building failed with errorlevel $LastExitCode" 13 | } 14 | 15 | $dname = '' 16 | if ($env:ARCH -eq 'x64') { 17 | $dname += 'x64\' 18 | } 19 | $dname += 'Release'; 20 | if ($env:TS -eq 'ts') { 21 | $dname += '_TS' 22 | } 23 | Copy-Item "$dname\php_$env:PHP_EXT.dll" "C:\php\bin\ext\php_$env:PHP_EXT.dll" 24 | Copy-Item "$dname\php_$env:PHP_EXT.dll" "php_$env:PHP_EXT.dll" 25 | 26 | $ini = New-Item "C:\php\bin\php.ini" -Force 27 | Add-Content $ini "extension_dir=C:\php\bin\ext" 28 | Add-Content $ini "extension=php_openssl.dll" 29 | Add-Content $ini "extension=php_$env:PHP_EXT.dll" 30 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : basic functionality 3 | --SKIPIF-- 4 | 38 | ===Done=== 39 | --EXPECT-- 40 | *** Testing snappy_compress() : basic functionality *** 41 | -- Compression -- 42 | int(0) 43 | -- Compression -- 44 | string(58) "1b684120736d616c6c20737472696e6720746f20636f6d70726573730a" 45 | int(0) 46 | 47 | -- Testing with no specified compression -- 48 | string(58) "1b684120736d616c6c20737472696e6720746f20636f6d70726573730a" 49 | ===Done=== 50 | -------------------------------------------------------------------------------- /tests/001_b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : basic functionality 3 | --SKIPIF-- 4 | 38 | ===Done=== 39 | --EXPECT-- 40 | *** Testing snappy_compress() : basic functionality *** 41 | -- Compression -- 42 | int(0) 43 | -- Compression -- 44 | string(58) "1b684120736d616c6c20737472696e6720746f20636f6d70726573730a" 45 | int(0) 46 | 47 | -- Testing with no specified compression -- 48 | string(58) "1b684120736d616c6c20737472696e6720746f20636f6d70726573730a" 49 | ===Done=== 50 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : error conditions 3 | --SKIPIF-- 4 | =')) die('skip PHP is too old'); 6 | --FILE-- 7 | 32 | ===Done=== 33 | --EXPECTF-- 34 | *** Testing snappy_compress() : error conditions *** 35 | 36 | -- Testing snappy_compress() function with Zero arguments -- 37 | 38 | Warning: snappy_compress() expects exactly 1 parameter, 0 given in %s on line %d 39 | bool(false) 40 | 41 | -- Testing snappy_compress() function with more than expected no. of arguments -- 42 | 43 | Warning: snappy_compress() expects exactly 1 parameter, 2 given in %s on line %d 44 | bool(false) 45 | 46 | -- Testing with incorrect parameters -- 47 | 48 | Warning: snappy_compress : expects parameter to be string. in %s on line %d 49 | bool(false) 50 | ===Done=== 51 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_uncompress() function : error conditions 3 | --SKIPIF-- 4 | =')) die('skip PHP is too old'); 6 | --FILE-- 7 | 36 | ===DONE=== 37 | --EXPECTF-- 38 | *** Testing snappy_uncompress() : error conditions *** 39 | 40 | -- Testing snappy_uncompress() function with Zero arguments -- 41 | 42 | Warning: snappy_uncompress() expects exactly 1 parameter, 0 given in %s on line %d 43 | bool(false) 44 | 45 | -- Testing snappy_uncompress() function with more than expected no. of arguments -- 46 | 47 | Warning: snappy_uncompress() expects exactly 1 parameter, 2 given in %s on line %d 48 | bool(false) 49 | 50 | -- Testing with incorrect arguments -- 51 | 52 | Warning: snappy_uncompress : expects parameter to be string. in %s on line %d 53 | bool(false) 54 | 55 | Warning: snappy_uncompress : expects parameter to be string. in %s on line %d 56 | bool(false) 57 | ===DONE=== 58 | -------------------------------------------------------------------------------- /tests/002_b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_compress() function : error conditions 3 | --SKIPIF-- 4 | 44 | ===Done=== 45 | --EXPECTF-- 46 | *** Testing snappy_compress() : error conditions *** 47 | 48 | -- Testing snappy_compress() function with Zero arguments -- 49 | ArgumentCountError: snappy_compress() expects exactly 1 %s, 0 given in %s:%d 50 | Stack trace: 51 | #0 %s(%d): snappy_compress() 52 | #1 {main} 53 | 54 | -- Testing snappy_compress() function with more than expected no. of arguments -- 55 | ArgumentCountError: snappy_compress() expects exactly 1 %s, 2 given in %s:%d 56 | Stack trace: 57 | #0 %s(%d): snappy_compress(%s) 58 | #1 {main} 59 | 60 | -- Testing with incorrect parameters -- 61 | 62 | Warning: snappy_compress : expects parameter to be string. in %s on line %d 63 | bool(false) 64 | ===Done=== 65 | -------------------------------------------------------------------------------- /tests/005_b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test snappy_uncompress() function : error conditions 3 | --SKIPIF-- 4 | 51 | ===DONE=== 52 | --EXPECTF-- 53 | *** Testing snappy_uncompress() : error conditions *** 54 | 55 | -- Testing snappy_uncompress() function with Zero arguments -- 56 | ArgumentCountError: snappy_uncompress() expects exactly 1 %s, 0 given in %s:%d 57 | Stack trace: 58 | #0 %s(%d): snappy_uncompress() 59 | #1 {main} 60 | 61 | -- Testing snappy_uncompress() function with more than expected no. of arguments -- 62 | ArgumentCountError: snappy_uncompress() expects exactly 1 %s, 2 given in %s:%d 63 | Stack trace: 64 | #0 %s(%d): snappy_uncompress(%s) 65 | #1 {main} 66 | 67 | -- Testing with incorrect arguments -- 68 | 69 | Warning: snappy_uncompress : expects parameter to be string. in %s on line %d 70 | bool(false) 71 | 72 | Warning: snappy_uncompress : expects parameter to be string. in %s on line %d 73 | bool(false) 74 | ===DONE=== 75 | -------------------------------------------------------------------------------- /tests/apcu_serializer.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | APCu serializer registration 3 | --INI-- 4 | apc.enable_cli=1 5 | apc.serializer=snappy 6 | --SKIPIF-- 7 | getVersion(), '5.1.6') < 0) { 18 | echo 'skip require apcu version 5.1.6 or above'; 19 | die; 20 | } 21 | ?> 22 | --FILE-- 23 | foo = 10; 32 | apcu_store('foo', $a); 33 | unset($a); 34 | 35 | var_dump(apcu_fetch('foo')); 36 | 37 | $a = new Bar(); 38 | $a->foo = $a; 39 | apcu_store('objloop', $a); 40 | unset($a); 41 | 42 | var_dump(apcu_fetch('objloop')); 43 | 44 | apcu_store('nullval', null); 45 | var_dump(apcu_fetch('nullval')); 46 | 47 | apcu_store('intval', 777); 48 | var_dump(apcu_fetch('intval')); 49 | 50 | $o = new stdClass(); 51 | $o->prop = 5; 52 | $a = [$o, $o]; 53 | apcu_store('simplearrayval', $a); 54 | $unserialized = apcu_fetch('simplearrayval'); 55 | var_dump($unserialized); 56 | if ($unserialized[0] === $unserialized[1]) { 57 | echo "SAME\n"; 58 | } 59 | unset($o); 60 | unset($a); 61 | unset($unserialized); 62 | 63 | $o = new stdClass(); 64 | $o->prop = 6; 65 | $a = [&$o, &$o]; 66 | apcu_store('refarrayval', $a); 67 | $unserialized = apcu_fetch('refarrayval'); 68 | var_dump($unserialized); 69 | if ($unserialized[0] === $unserialized[1]) { 70 | echo "SAME\n"; 71 | } 72 | ?> 73 | --EXPECTF-- 74 | snappy 75 | object(Bar)#%d (1) { 76 | ["foo"]=> 77 | int(10) 78 | } 79 | object(Bar)#%d (1) { 80 | ["foo"]=> 81 | *RECURSION* 82 | } 83 | NULL 84 | int(777) 85 | array(2) { 86 | [0]=> 87 | object(stdClass)#%d (1) { 88 | ["prop"]=> 89 | int(5) 90 | } 91 | [1]=> 92 | object(stdClass)#%d (1) { 93 | ["prop"]=> 94 | int(5) 95 | } 96 | } 97 | SAME 98 | array(2) { 99 | [0]=> 100 | &object(stdClass)#%d (1) { 101 | ["prop"]=> 102 | int(6) 103 | } 104 | [1]=> 105 | &object(stdClass)#%d (1) { 106 | ["prop"]=> 107 | int(6) 108 | } 109 | } 110 | SAME 111 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Snappy Extension for PHP 2 | 3 | [![Linux](https://github.com/kjdev/php-ext-snappy/actions/workflows/linux.yaml/badge.svg?branch=master)](https://github.com/kjdev/php-ext-snappy/actions/workflows/linux.yaml) 4 | [![Windows](https://github.com/kjdev/php-ext-snappy/actions/workflows/windows.yaml/badge.svg?branch=master)](https://github.com/kjdev/php-ext-snappy/actions/workflows/windows.yaml) 5 | 6 | This extension allows Snappy. 7 | 8 | Documentation for Snappy can be found at 9 | [» http://google.github.io/snappy/](http://google.github.io/snappy/). 10 | 11 | ## Build from sources 12 | 13 | ```shell 14 | git clone --recursive --depth=1 https://github.com/kjdev/php-ext-snappy.git 15 | cd php-ext-snappy 16 | phpize 17 | ./configure 18 | make 19 | make install 20 | ``` 21 | 22 | To use the system library 23 | 24 | ```shell 25 | ./configure --with-snappy-includedir=/usr 26 | ``` 27 | 28 | ## Distribution binary packages 29 | 30 | ### Fedora / CentOS / RHEL 31 | 32 | RPM packages of this extension are available in [» Remi's RPM repository](https://rpms.remirepo.net/) and are named **php-snappy**. 33 | 34 | ## Configuration 35 | 36 | php.ini: 37 | 38 | ```ini 39 | extension=snappy.so 40 | ``` 41 | 42 | ### Function : `snappy_compress()` 43 | 44 | string snappy_compress( string $data ) 45 | 46 | #### parameters 47 | 48 | data: 49 | 50 | The data to compress. 51 | 52 | #### return values 53 | 54 | The compressed string or FALSE if an error occurred. 55 | 56 | ### Function : `snappy_uncompress()` 57 | 58 | string snappy_uncompress( string $data ) 59 | 60 | #### parameters 61 | 62 | name: 63 | 64 | The data compressed by snappy_compress(). 65 | 66 | #### return values 67 | 68 | The original uncompressed data or FALSE on error. 69 | 70 | ## Example 71 | 72 | ```php 73 | $compressed = snappy_compress('Compress me'); 74 | 75 | $uncompressed = snappy_uncompress($compressed); 76 | 77 | echo $uncompressed; 78 | ``` 79 | 80 | ## Troubleshooting 81 | 82 | ### Ubuntu / OSX 83 | 84 | Snappy requires C++ and therefore might require for you to install the g++ or build-essential package. 85 | 86 | If you get an error about "this file requires compiler and library support" or [compilation errors on OSX](https://github.com/kjdev/php-ext-snappy/issues/19), you need to enforce the compilation with `-std=c++11` flag: 87 | 88 | ```shell 89 | export CXXFLAGS=-std=c++11 90 | phpize 91 | ./configure 92 | make 93 | ``` 94 | -------------------------------------------------------------------------------- /COPYING.snappy: -------------------------------------------------------------------------------- 1 | Copyright 2011, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | === 31 | 32 | Some of the benchmark data in testdata/ is licensed differently: 33 | 34 | - fireworks.jpeg is Copyright 2013 Steinar H. Gunderson, and 35 | is licensed under the Creative Commons Attribution 3.0 license 36 | (CC-BY-3.0). See https://creativecommons.org/licenses/by/3.0/ 37 | for more information. 38 | 39 | - kppkn.gtb is taken from the Gaviota chess tablebase set, and 40 | is licensed under the MIT License. See 41 | https://sites.google.com/site/gaviotachessengine/Home/endgame-tablebases-1 42 | for more information. 43 | 44 | - paper-100k.pdf is an excerpt (bytes 92160 to 194560) from the paper 45 | “Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA 46 | Replication Timing in _Drosophila_” by Federico Comoglio and Renato Paro, 47 | which is licensed under the CC-BY license. See 48 | http://www.ploscompbiol.org/static/license for more ifnormation. 49 | 50 | - alice29.txt, asyoulik.txt, plrabn12.txt and lcet10.txt are from Project 51 | Gutenberg. The first three have expired copyrights and are in the public 52 | domain; the latter does not have expired copyright, but is still in the 53 | public domain according to the license information 54 | (http://www.gutenberg.org/ebooks/53). 55 | -------------------------------------------------------------------------------- /package.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | snappy 4 | pecl.php.net 5 | Snappy extension 6 | A compression/decompression with Snappy 7 | 8 | Tatsuya KAMIJO 9 | kjdev 10 | kjdev@php.net 11 | yes 12 | 13 | ${DATE} 14 | 15 | ${VERSION} 16 | ${VERSION} 17 | 18 | 19 | ${STABILITY} 20 | ${STABILITY} 21 | 22 | MIT 23 | 24 | ${NOTES} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 5.2 64 | 65 | 66 | 1.4.0 67 | 68 | 69 | 70 | snappy 71 | 72 | 73 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------- 2 | The PHP License, version 3.01 3 | Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. 4 | -------------------------------------------------------------------- 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, is permitted provided that the following conditions 8 | are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | 3. The name "PHP" must not be used to endorse or promote products 19 | derived from this software without prior written permission. For 20 | written permission, please contact group@php.net. 21 | 22 | 4. Products derived from this software may not be called "PHP", nor 23 | may "PHP" appear in their name, without prior written permission 24 | from group@php.net. You may indicate that your software works in 25 | conjunction with PHP by saying "Foo for PHP" instead of calling 26 | it "PHP Foo" or "phpfoo" 27 | 28 | 5. The PHP Group may publish revised and/or new versions of the 29 | license from time to time. Each version will be given a 30 | distinguishing version number. 31 | Once covered code has been published under a particular version 32 | of the license, you may always continue to use it under the terms 33 | of that version. You may also choose to use such covered code 34 | under the terms of any subsequent version of the license 35 | published by the PHP Group. No one other than the PHP Group has 36 | the right to modify the terms applicable to covered code created 37 | under this License. 38 | 39 | 6. Redistributions of any form whatsoever must retain the following 40 | acknowledgment: 41 | "This product includes PHP software, freely available from 42 | ". 43 | 44 | THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 45 | ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 46 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 47 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP 48 | DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 49 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 50 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 53 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 55 | OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | -------------------------------------------------------------------- 58 | 59 | This software consists of voluntary contributions made by many 60 | individuals on behalf of the PHP Group. 61 | 62 | The PHP Group can be contacted via Email at group@php.net. 63 | 64 | For more information on the PHP Group and the PHP project, 65 | please see . 66 | 67 | PHP includes the Zend Engine, freely available at 68 | . 69 | -------------------------------------------------------------------------------- /.github/workflows/install.ps1: -------------------------------------------------------------------------------- 1 | $ErrorActionPreference = "Stop" 2 | 3 | if (-not (Test-Path 'C:\php')) { 4 | [void](New-Item 'C:\php' -ItemType 'directory') 5 | } 6 | 7 | # PHP SDK 8 | $bname = "php-sdk-$env:BIN_SDK_VER.zip" 9 | if (-not (Test-Path C:\php\$bname)) { 10 | echo "Download: https://github.com/php/php-sdk-binary-tools/archive/$bname" 11 | Invoke-WebRequest "https://github.com/php/php-sdk-binary-tools/archive/$bname" -OutFile "C:\php\$bname" 12 | } 13 | $dname0 = "php-sdk-binary-tools-php-sdk-$env:BIN_SDK_VER" 14 | $dname1 = "php-sdk-$env:BIN_SDK_VER" 15 | if (-not (Test-Path "C:\php\$dname1")) { 16 | Expand-Archive "C:\php\$bname" "C:\php" 17 | Move-Item "C:\php\$dname0" "C:\php\$dname1" 18 | } 19 | 20 | # PHP releases 21 | if (-not (Test-Path C:\php\releases.json)) { 22 | echo "Download: https://windows.php.net/downloads/releases/releases.json" 23 | Invoke-WebRequest "https://windows.php.net/downloads/releases/releases.json" -OutFile "C:\php\releases.json" 24 | } 25 | $php_version = (Get-Content -Path "C:\php\releases.json" | ConvertFrom-Json | ForEach-Object { 26 | if ($_."$env:PHP_VER") { 27 | return $_."$env:PHP_VER".version 28 | } else { 29 | return "$env:PHP_VER" 30 | } 31 | }) 32 | 33 | # PHP devel pack: "C:\php\devel" 34 | $ts_part = '' 35 | if ('nts' -eq $env:TS) { 36 | $ts_part = '-nts' 37 | } 38 | $bname = "php-devel-pack-$php_version$ts_part-Win32-$env:VS-$env:ARCH.zip" 39 | if (-not (Test-Path "C:\php\$bname")) { 40 | try { 41 | echo "Download: https://windows.php.net/downloads/releases/$bname" 42 | Invoke-WebRequest "https://windows.php.net/downloads/releases/$bname" -OutFile "C:\php\$bname" 43 | } catch [System.Net.WebException] { 44 | echo "Downlaod: https://windows.php.net/downloads/releases/archives/$bname" 45 | Invoke-WebRequest "https://windows.php.net/downloads/releases/archives/$bname" -OutFile "C:\php\$bname" 46 | } 47 | } 48 | $dname = "php-$php_version-devel-$env:VS-$env:ARCH" 49 | if (-not (Test-Path "C:\php\devel")) { 50 | Expand-Archive "C:\php\$bname" 'C:\php' 51 | if (-not (Test-Path "C:\php\$dname")) { 52 | $php_normalize_version = $php_version.Split("-")[0] 53 | $dname = "php-$php_normalize_version-devel-$env:VS-$env:ARCH" 54 | } 55 | if (-not (Test-Path "C:\php\devel")) { 56 | Move-Item "C:\php\$dname" "C:\php\devel" 57 | } 58 | } 59 | 60 | # PHP binary: "C:\php\bin" 61 | $bname = "php-$php_version$ts_part-Win32-$env:VS-$env:ARCH.zip" 62 | if (-not (Test-Path "C:\php\$bname")) { 63 | try { 64 | echo "Download: https://windows.php.net/downloads/releases/$bname" 65 | Invoke-WebRequest "https://windows.php.net/downloads/releases/$bname" -OutFile "C:\php\$bname" 66 | } catch [System.Net.WebException] { 67 | echo "Download: https://windows.php.net/downloads/releases/archives/$bname" 68 | Invoke-WebRequest "https://windows.php.net/downloads/releases/archives/$bname" -OutFile "C:\php\$bname" 69 | } 70 | } 71 | if (-not (Test-Path "C:\php\bin")) { 72 | Expand-Archive "C:\php\$bname" "C:\php\bin" 73 | } 74 | 75 | # # library dependency: "C:\php\deps" 76 | # $bname = "$env:DEP-$env:VS-$env:ARCH.zip" 77 | # if (-not (Test-Path "C:\php\$bname")) { 78 | # echo "Download: https://windows.php.net/downloads/pecl/deps/$bname" 79 | # Invoke-WebRequest "https://windows.php.net/downloads/pecl/deps/$bname" -OutFile "C:\php\$bname" 80 | # Expand-Archive "C:\php\$bname" 'C:\php\deps' 81 | # } 82 | -------------------------------------------------------------------------------- /.github/workflows/linux.yaml: -------------------------------------------------------------------------------- 1 | name: Linux 2 | 3 | on: [push] 4 | 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | php: 12 | - '8.4-alpine' 13 | - '8.4-zts-alpine' 14 | - '8.3-alpine' 15 | - '8.3-zts-alpine' 16 | - '8.2-alpine' 17 | - '8.2-zts-alpine' 18 | - '8.1-alpine' 19 | - '8.1-zts-alpine' 20 | library: 21 | - '' 22 | - 'system' 23 | apcu: 24 | - '' 25 | - 'apcu' 26 | image: [php] 27 | include: 28 | - php: '8.0-alpine' 29 | image: ghcr.io/kjdev/php 30 | - php: '7.4-alpine' 31 | image: ghcr.io/kjdev/php 32 | - php: '7.3-alpine' 33 | image: ghcr.io/kjdev/php 34 | - php: '7.2-alpine' 35 | image: ghcr.io/kjdev/php 36 | - php: '7.1-alpine' 37 | image: ghcr.io/kjdev/php 38 | - php: '7.0-alpine' 39 | image: ghcr.io/kjdev/php 40 | - php: '5.6-alpine' 41 | image: ghcr.io/kjdev/php 42 | - php: '5.5-alpine' 43 | image: ghcr.io/kjdev/php 44 | - php: '5.4-alpine' 45 | image: ghcr.io/kjdev/php 46 | - php: '5.3-alpine' 47 | image: ghcr.io/kjdev/php 48 | - php: '5.2-alpine' 49 | image: ghcr.io/kjdev/php 50 | 51 | container: 52 | image: ${{ matrix.image }}:${{ matrix.php }} 53 | 54 | steps: 55 | - name: Prepare required command 56 | run: | 57 | apk upgrade --no-cache 58 | apk add --no-cache autoconf gcc git g++ libtool make musl-dev 59 | 60 | - name: adding github workspace as safe directory 61 | run: git config --global --add safe.directory $GITHUB_WORKSPACE 62 | - name: Checkout repository 63 | uses: actions/checkout@v4 64 | 65 | - name: Checkout submodules 66 | run: | 67 | git submodule update --init --recursive 68 | if: ${{ ! matrix.library }} 69 | - name: Install dependency library 70 | run: | 71 | apk add --no-cache snappy-dev 72 | if: ${{ matrix.library }} 73 | 74 | - name: Install PHP APCu extension 75 | run: | 76 | printf "\n" | pecl install apcu 77 | echo 'extension=apcu.so' > $(php --ini | grep 'Scan for' | sed 's|.* \(/.*\)$|\1|')/apcu.ini 78 | if: ${{ matrix.apcu }} 79 | 80 | - name: Build 81 | run: | 82 | phpize 83 | ./configure 84 | make 85 | if: ${{ ! matrix.library }} 86 | - name: Build with library 87 | run: | 88 | phpize 89 | ./configure --with-snappy-includedir 90 | make 91 | if: ${{ matrix.library }} 92 | 93 | - name: Test Preparation APCu 94 | run: | 95 | cp $(php-config --extension-dir)/apcu.so modules/ 96 | sed -i 's/\$(PHP_TEST_SHARED_EXTENSIONS)/-d extension=apcu \$(PHP_TEST_SHARED_EXTENSIONS)/' Makefile 97 | if: ${{ matrix.apcu }} 98 | - name: Test 99 | run: | 100 | make test TESTS="--show-diff" | tee test-output.txt 101 | grep 'TEST SUMMARY$' test-output.txt > /dev/null && exit 1 || exit 0 102 | env: 103 | REPORT_EXIT_STATUS: 1 104 | NO_INTERACTION: 1 105 | - name: Failure Test 106 | run: | 107 | for FILE in $(find ./tests -name '*.diff'); do 108 | echo echo $FILE 109 | cat $FILE 110 | echo 111 | done 112 | if: ${{ failure() }} 113 | -------------------------------------------------------------------------------- /tests/data.inc: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/workflows/windows.yaml: -------------------------------------------------------------------------------- 1 | name: Windows 2 | 3 | on: 4 | push: 5 | release: 6 | types: [published] 7 | 8 | env: 9 | PHP_EXT: snappy 10 | PHP_EXT_VERSION: ${{ github.event.release.tag_name }} 11 | BIN_SDK_VER: 2.3.0 12 | 13 | jobs: 14 | ci: 15 | strategy: 16 | matrix: 17 | php: 18 | - '8.4' 19 | - '8.3' 20 | - '8.2' 21 | - '8.1' 22 | arch: 23 | - x64 24 | - x86 25 | ts: 26 | - 'nts' 27 | - 'ts' 28 | vs: 29 | - vs16 30 | - vs17 31 | library: 32 | - '' 33 | - 'vcpkg' 34 | exclude: 35 | - php: '8.4' 36 | vs: vs16 37 | - php: '8.3' 38 | vs: vs17 39 | - php: '8.2' 40 | vs: vs17 41 | - php: '8.1' 42 | vs: vs17 43 | 44 | runs-on: ${{ matrix.vs == 'vs17' && 'windows-2022' || 'windows-2019' }} 45 | 46 | env: 47 | PHP_VER: ${{ matrix.php }} 48 | VS: ${{ matrix.vs }} 49 | ARCH: ${{ matrix.arch }} 50 | TS: ${{ matrix.ts }} 51 | 52 | steps: 53 | - name: Checkout repository 54 | uses: actions/checkout@v4 55 | with: 56 | persist-credentials: false 57 | 58 | - name: Checkout submodule 59 | run: .\.github\workflows\submodule.ps1 60 | shell: pwsh 61 | if: ${{ matrix.library == '' }} 62 | - name: Install dependency library 63 | run: .\.github\workflows\vcpkg.ps1 64 | shell: pwsh 65 | env: 66 | VCPKG_LIBRARY: snappy 67 | if: ${{ matrix.library }} 68 | 69 | - uses: actions/cache@v4 70 | with: 71 | path: | 72 | C:\php\php-*.zip 73 | key: ${{ runner.os }}-php-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.vs }}-${{ matrix.arch }} 74 | restore-keys: | 75 | ${{ runner.os }}-php- 76 | 77 | - name: Install build command 78 | run: .\.github\workflows\install.ps1 79 | shell: pwsh 80 | 81 | - name: Build 82 | run: .\.github\workflows\build.ps1 83 | shell: pwsh 84 | 85 | - name: Test 86 | run: .\.github\workflows\test.ps1 87 | shell: pwsh 88 | env: 89 | REPORT_EXIT_STATUS: 1 90 | NO_INTERACTION: 1 91 | 92 | - if: ${{ github.event_name == 'release' && matrix.library == '' }} 93 | name: Archive DLL 94 | run: |- 95 | Copy-Item .\php_${{ env.PHP_EXT }}.dll .\$env:EXT_NAME.dll 96 | Compress-Archive -Path .\$env:EXT_NAME.dll -Destination .\$env:EXT_NAME.zip 97 | shell: pwsh 98 | env: 99 | EXT_NAME: php_${{ env.PHP_EXT }}-${{ env.PHP_EXT_VERSION }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.vs }}-${{ matrix.arch == 'x64' && 'x86_64' || matrix.arch }} 100 | 101 | - if: ${{ github.event_name == 'release' && matrix.library == '' }} 102 | name: Store archive DLL 103 | uses: actions/upload-artifact@v4 104 | with: 105 | name: ${{ env.PHP_EXT_VERSION }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.vs }}-${{ matrix.arch == 'x64' && 'x86_64' || matrix.arch }} 106 | path: .\php_${{ env.PHP_EXT }}-${{ env.PHP_EXT_VERSION }}-${{ matrix.php }}-${{ matrix.ts }}-${{ matrix.vs }}-${{ matrix.arch == 'x64' && 'x86_64' || matrix.arch }}.zip 107 | overwrite: true 108 | 109 | release: 110 | permissions: 111 | contents: write 112 | needs: ci 113 | 114 | runs-on: ubuntu-latest 115 | 116 | if: ${{ github.event_name == 'release' }} 117 | 118 | steps: 119 | - name: Checkout 120 | uses: actions/checkout@v4 121 | with: 122 | persist-credentials: false 123 | 124 | - name: Get artifacts 125 | uses: actions/download-artifact@v4 126 | with: 127 | path: artifacts 128 | merge-multiple: true 129 | 130 | - name: Upload artifacts 131 | run: gh release upload ${{ env.PHP_EXT_VERSION }} artifacts/php* --clobber 132 | shell: bash 133 | env: 134 | GH_TOKEN: ${{ github.token }} 135 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl config.m4 for extension snappy 2 | 3 | dnl Check PHP version: 4 | AC_MSG_CHECKING(PHP version) 5 | if test ! -z "$phpincludedir"; then 6 | PHP_VERSION=`grep 'PHP_VERSION ' $phpincludedir/main/php_version.h | sed -e 's/.*"\([[0-9\.]]*\)".*/\1/g' 2>/dev/null` 7 | elif test ! -z "$PHP_CONFIG"; then 8 | PHP_VERSION=`$PHP_CONFIG --version 2>/dev/null` 9 | fi 10 | 11 | if test x"$PHP_VERSION" = "x"; then 12 | AC_MSG_WARN([none]) 13 | else 14 | PHP_MAJOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/g' 2>/dev/null` 15 | PHP_MINOR_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/g' 2>/dev/null` 16 | PHP_RELEASE_VERSION=`echo $PHP_VERSION | sed -e 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/g' 2>/dev/null` 17 | AC_MSG_RESULT([$PHP_VERSION]) 18 | fi 19 | 20 | if test $PHP_MAJOR_VERSION -lt 5; then 21 | AC_MSG_ERROR([need at least PHP 5 or newer]) 22 | fi 23 | 24 | PHP_ARG_ENABLE(snappy, whether to enable snappy support, 25 | [ --enable-snappy Enable snappy support]) 26 | 27 | PHP_ARG_WITH(snappy-includedir, for snappy header, 28 | [ --with-snappy-includedir=DIR snappy header files], no, no) 29 | 30 | if test "$PHP_SNAPPY" != "no"; then 31 | 32 | AC_MSG_CHECKING([searching for libsnappy]) 33 | 34 | if test "$PHP_SNAPPY_INCLUDEDIR" != "no"; then 35 | for i in $PHP_SNAPPY_INCLUDEDIR /usr/local /usr; do 36 | if test -r $i/include/snappy-c.h; then 37 | LIBSNAPPY_CFLAGS="-I$i/include" 38 | LIBSNAPPY_LIBDIR="$i/$PHP_LIBDIR" 39 | AC_MSG_RESULT(found in $i) 40 | break 41 | fi 42 | done 43 | if test -z "$LIBSNAPPY_LIBDIR"; then 44 | AC_MSG_RESULT(not found) 45 | AC_MSG_ERROR(Please reinstall the snappy library distribution) 46 | fi 47 | PHP_CHECK_LIBRARY(snappy, snappy_compress, 48 | [ 49 | PHP_ADD_LIBRARY_WITH_PATH(snappy, $LIBSNAPPY_LIBDIR, SNAPPY_SHARED_LIBADD) 50 | AC_DEFINE(HAVE_LIBSNAPPY,1,[ ]) 51 | ], [ 52 | AC_MSG_ERROR(could not find usable libsnappy) 53 | ], [ 54 | -L$LIBSNAPPY_LIBDIR 55 | ]) 56 | 57 | AC_LANG_PUSH([C++]) 58 | AC_RUN_IFELSE([ 59 | AC_LANG_PROGRAM( 60 | [#include 61 | #include ], 62 | [printf("%d.%d.%d\n", SNAPPY_MAJOR, SNAPPY_MINOR, SNAPPY_PATCHLEVEL)])], 63 | [cw_cv_system_version=$(./conftest$EXEEXT)], 64 | [AC_MSG_ERROR(Failed to compile a version program!?)]) 65 | AC_LANG_POP([C++]) 66 | eval "LIBSNAPPY_VERSON=$cw_cv_system_version" 67 | 68 | AC_DEFINE_UNQUOTED(SNAPPY_LIB_VERSION, "$LIBSNAPPY_VERSON", [ ]) 69 | 70 | PHP_SUBST(SNAPPY_SHARED_LIBADD) 71 | PHP_NEW_EXTENSION(snappy, snappy.c, $ext_shared,, $LIBSNAPPY_CFLAGS) 72 | else 73 | AC_MSG_RESULT(use bundled version) 74 | 75 | dnl compiler C++: 76 | PHP_REQUIRE_CXX() 77 | 78 | dnl snappy 79 | AC_SUBST([SNAPPY_VERSION_MAJOR], [1]) 80 | AC_SUBST([SNAPPY_VERSION_MINOR], [2]) 81 | AC_SUBST([SNAPPY_VERSION_PATCH], [1]) 82 | 83 | AC_PROG_CXX 84 | AC_LANG_PUSH([C++]) 85 | AC_C_BIGENDIAN([AC_DEFINE([SNAPPY_IS_BIG_ENDIAN], [1], [snappy is big endian])]) 86 | AC_CHECK_HEADERS([stdint.h stddef.h sys/mman.h sys/resource.h windows.h byteswap.h sys/byteswap.h sys/endian.h sys/time.h sys/uio.h]) 87 | 88 | AC_CHECK_FUNC([mmap]) 89 | 90 | AC_MSG_CHECKING([if the compiler supports __builtin_expect]) 91 | AC_TRY_COMPILE(, [ 92 | return __builtin_expect(1, 1) ? 1 : 0 93 | ], [ 94 | snappy_have_builtin_expect=yes 95 | AC_MSG_RESULT([yes]) 96 | ], [ 97 | snappy_have_builtin_expect=no 98 | AC_MSG_RESULT([no]) 99 | ]) 100 | if test x$snappy_have_builtin_expect = xyes ; then 101 | AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], [Define to 1 if the compiler supports __builtin_expect.]) 102 | fi 103 | 104 | AC_MSG_CHECKING([if the compiler supports __builtin_ctzll]) 105 | AC_TRY_COMPILE(, [ 106 | return (__builtin_ctzll(0x100000000LL) == 32) ? 1 : 0 107 | ], [ 108 | snappy_have_builtin_ctz=yes 109 | AC_MSG_RESULT([yes]) 110 | ], [ 111 | snappy_have_builtin_ctz=no 112 | AC_MSG_RESULT([no]) 113 | ]) 114 | if test x$snappy_have_builtin_ctz = xyes ; then 115 | AC_DEFINE([HAVE_BUILTIN_CTZ], [1], [Define to 1 if the compiler supports __builtin_ctz and friends.]) 116 | fi 117 | AC_LANG_POP([C++]) 118 | 119 | if test "$ac_cv_header_stdint_h" = "yes"; then 120 | AC_SUBST([ac_cv_have_stdint_h], [1]) 121 | AC_SUBST([HAVE_STDINT_H_01], [1]) 122 | else 123 | AC_SUBST([ac_cv_have_stdint_h], [0]) 124 | AC_SUBST([HAVE_STDINT_H_01], [0]) 125 | fi 126 | if test "$ac_cv_header_stddef_h" = "yes"; then 127 | AC_SUBST([ac_cv_have_stddef_h], [1]) 128 | AC_SUBST([HAVE_STDDEF_H_01], [1]) 129 | else 130 | AC_SUBST([ac_cv_have_stddef_h], [0]) 131 | AC_SUBST([HAVE_STDDEF_H_01], [0]) 132 | fi 133 | if test "$ac_cv_header_sys_uio_h" = "yes"; then 134 | AC_SUBST([ac_cv_have_sys_uio_h], [1]) 135 | AC_SUBST([HAVE_SYS_UIO_H_01], [1]) 136 | dnl HAVE_SYS_UIO_H_01=1 137 | else 138 | AC_SUBST([ac_cv_have_sys_uio_h], [0]) 139 | AC_SUBST([HAVE_SYS_UIO_H_01], [0]) 140 | dnl HAVE_SYS_UIO_H_01=0 141 | fi 142 | 143 | dnl Check for stdc++ 144 | LIBNAME=stdc++ 145 | AC_MSG_CHECKING([for stdc++]) 146 | AC_LANG_SAVE 147 | AC_LANG_CPLUSPLUS 148 | AC_TRY_COMPILE( 149 | [ 150 | #include 151 | using namespace std; 152 | ],[ 153 | string dummy; 154 | ],[ 155 | AC_MSG_RESULT(yes) 156 | PHP_ADD_LIBRARY($LIBNAME, , SNAPPY_SHARED_LIBADD) 157 | ],[ 158 | AC_MSG_ERROR([wrong stdc++ library not found]) 159 | ]) 160 | AC_LANG_RESTORE 161 | 162 | PHP_SUBST(SNAPPY_SHARED_LIBADD) 163 | 164 | dnl Sources 165 | SNAPPY_SOURCES="snappy/snappy-c.cc snappy/snappy.cc snappy/snappy-stubs-internal.cc snappy/snappy-sinksource.cc" 166 | 167 | PHP_NEW_EXTENSION(snappy, snappy.c $SNAPPY_SOURCES, $ext_shared) 168 | 169 | if test -f "$ext_srcdir/snappy/snappy-stubs-public.h.in"; then 170 | mv $ext_srcdir/snappy/snappy-stubs-public.h.in \ 171 | $ext_srcdir/snappy/snappy-stubs-public.h.in.orig 172 | 173 | dnl sed -e "s/\${HAVE_SYS_UIO_H_01}/$HAVE_SYS_UIO_H_01/" \ 174 | dnl -e "s/\${PROJECT_VERSION_MAJOR}/$SNAPPY_VERSION_MAJOR/" \ 175 | dnl -e "s/\${PROJECT_VERSION_MINOR}/$SNAPPY_VERSION_MINOR/" \ 176 | dnl -e "s/\${PROJECT_VERSION_PATCH}/$SNAPPY_VERSION_PATCH/" \ 177 | dnl $ext_srcdir/snappy/snappy-stubs-public.h.in.orig > \ 178 | dnl $ext_srcdir/snappy/snappy-stubs-public.h.in 179 | 180 | sed -e 's/${\(HAVE_[[A-Z\_]]*_H_01\)}/@\1@/' \ 181 | -e 's/${PROJECT_VERSION_\([[A-Z]]*\)}/@SNAPPY_VERSION_\1@/' \ 182 | $ext_srcdir/snappy/snappy-stubs-public.h.in.orig > \ 183 | $ext_srcdir/snappy/snappy-stubs-public.h.in 184 | fi 185 | AC_CONFIG_FILES([$ext_srcdir/snappy/snappy-stubs-public.h]) 186 | AC_OUTPUT 187 | PHP_ADD_BUILD_DIR($ext_builddir/snappy, 1) 188 | PHP_ADD_INCLUDE([$ext_srcdir/snappy]) 189 | 190 | AC_DEFINE_UNQUOTED(SNAPPY_LIB_VERSION, "$SNAPPY_VERSION_MAJOR.$SNAPPY_VERSION_MINOR.$SNAPPY_VERSION_PATCH", [ ]) 191 | fi 192 | 193 | AC_MSG_CHECKING([for APCu includes]) 194 | if test -f "$phpincludedir/ext/apcu/apc_serializer.h"; then 195 | apc_inc_path="$phpincludedir" 196 | AC_MSG_RESULT([APCu in $apc_inc_path]) 197 | AC_DEFINE(HAVE_APCU_SUPPORT,1,[Whether to enable APCu support]) 198 | else 199 | AC_MSG_RESULT([not found]) 200 | fi 201 | fi 202 | -------------------------------------------------------------------------------- /snappy.c: -------------------------------------------------------------------------------- 1 | 2 | #ifdef HAVE_CONFIG_H 3 | #include "config.h" 4 | #endif 5 | 6 | #include "php.h" 7 | #include "php_ini.h" 8 | #include "ext/standard/info.h" 9 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 10 | #include "ext/standard/php_var.h" 11 | #include "ext/apcu/apc_serializer.h" 12 | #include "zend_smart_str.h" 13 | #endif 14 | #include "php_snappy.h" 15 | 16 | /* snappy */ 17 | #include 18 | 19 | static ZEND_FUNCTION(snappy_compress); 20 | static ZEND_FUNCTION(snappy_uncompress); 21 | 22 | ZEND_BEGIN_ARG_INFO_EX(arginfo_snappy_compress, 0, 0, 1) 23 | ZEND_ARG_INFO(0, data) 24 | ZEND_END_ARG_INFO() 25 | 26 | ZEND_BEGIN_ARG_INFO_EX(arginfo_snappy_uncompress, 0, 0, 1) 27 | ZEND_ARG_INFO(0, data) 28 | ZEND_END_ARG_INFO() 29 | 30 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 31 | static int APC_SERIALIZER_NAME(snappy)(APC_SERIALIZER_ARGS); 32 | static int APC_UNSERIALIZER_NAME(snappy)(APC_UNSERIALIZER_ARGS); 33 | #endif 34 | 35 | static const zend_function_entry snappy_functions[] = { 36 | ZEND_FE(snappy_compress, arginfo_snappy_compress) 37 | ZEND_FE(snappy_uncompress, arginfo_snappy_uncompress) 38 | ZEND_FE_END 39 | }; 40 | 41 | PHP_MINIT_FUNCTION(snappy) 42 | { 43 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 44 | apc_register_serializer("snappy", 45 | APC_SERIALIZER_NAME(snappy), 46 | APC_UNSERIALIZER_NAME(snappy), 47 | NULL); 48 | #endif 49 | return SUCCESS; 50 | } 51 | 52 | PHP_MINFO_FUNCTION(snappy) 53 | { 54 | php_info_print_table_start(); 55 | php_info_print_table_row(2, "Snappy support", "enabled"); 56 | php_info_print_table_row(2, "Extension Version", SNAPPY_EXT_VERSION); 57 | #ifdef SNAPPY_LIB_VERSION 58 | php_info_print_table_row(2, "Snappy Version", SNAPPY_LIB_VERSION); 59 | #else 60 | php_info_print_table_row(2, "Snappy Version", "system library"); 61 | #endif 62 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 63 | php_info_print_table_row(2, "Snappy APCu serializer ABI", 64 | APC_SERIALIZER_ABI); 65 | #endif 66 | php_info_print_table_end(); 67 | } 68 | 69 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 70 | static const zend_module_dep snappy_module_deps[] = { 71 | ZEND_MOD_OPTIONAL("apcu") 72 | ZEND_MOD_END 73 | }; 74 | #endif 75 | 76 | zend_module_entry snappy_module_entry = { 77 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 78 | STANDARD_MODULE_HEADER_EX, 79 | NULL, 80 | snappy_module_deps, 81 | #elif ZEND_MODULE_API_NO >= 20010901 82 | STANDARD_MODULE_HEADER, 83 | #endif 84 | "snappy", 85 | snappy_functions, 86 | PHP_MINIT(snappy), 87 | NULL, 88 | NULL, 89 | NULL, 90 | PHP_MINFO(snappy), 91 | #if ZEND_MODULE_API_NO >= 20010901 92 | SNAPPY_EXT_VERSION, 93 | #endif 94 | STANDARD_MODULE_PROPERTIES 95 | }; 96 | 97 | #ifdef COMPILE_DL_SNAPPY 98 | ZEND_GET_MODULE(snappy) 99 | #endif 100 | 101 | #define SNAPPY_BUFFER_SIZE 4096 102 | 103 | static int php_snappy_compress(const char* in, const size_t in_len, 104 | char** out, size_t* out_len) 105 | { 106 | *out_len = snappy_max_compressed_length(in_len); 107 | *out = (char*)emalloc(*out_len); 108 | if (!*out) { 109 | zend_error(E_WARNING, "snappy_compress : memory error"); 110 | *out_len = 0; 111 | return FAILURE; 112 | } 113 | 114 | if (snappy_compress(in, in_len, *out, out_len) != SNAPPY_OK) { 115 | zend_error(E_WARNING, "snappy_compress : data error"); 116 | efree(*out); 117 | *out = NULL; 118 | *out_len = 0; 119 | return FAILURE; 120 | } 121 | 122 | return SUCCESS; 123 | } 124 | 125 | static int php_snappy_uncompress(const char* in, const size_t in_len, 126 | char** out, size_t* out_len) 127 | { 128 | if (snappy_uncompressed_length(in, in_len, out_len) != SNAPPY_OK) { 129 | zend_error(E_WARNING, "snappy_uncompress : output length error"); 130 | return FAILURE; 131 | } 132 | 133 | *out = (char*)emalloc(*out_len); 134 | if (!*out) { 135 | zend_error(E_WARNING, "snappy_uncompress : memory error"); 136 | *out_len = 0; 137 | return FAILURE; 138 | } 139 | 140 | if (snappy_uncompress(in, in_len, *out, out_len) != SNAPPY_OK) { 141 | zend_error(E_WARNING, "snappy_uncompress : data error"); 142 | efree(*out); 143 | *out = NULL; 144 | *out_len = 0; 145 | return FAILURE; 146 | } 147 | 148 | return SUCCESS; 149 | } 150 | 151 | static ZEND_FUNCTION(snappy_compress) 152 | { 153 | zval *data; 154 | char *output; 155 | size_t output_len; 156 | 157 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 158 | "z", &data) == FAILURE) { 159 | RETURN_FALSE; 160 | } 161 | 162 | if (Z_TYPE_P(data) != IS_STRING) { 163 | zend_error(E_WARNING, 164 | "snappy_compress : expects parameter to be string."); 165 | RETURN_FALSE; 166 | } 167 | 168 | if (php_snappy_compress(Z_STRVAL_P(data), Z_STRLEN_P(data), 169 | &output, &output_len) == FAILURE) { 170 | RETURN_FALSE; 171 | } 172 | 173 | #if ZEND_MODULE_API_NO >= 20141001 174 | RETVAL_STRINGL(output, output_len); 175 | #else 176 | RETVAL_STRINGL(output, output_len, 1); 177 | #endif 178 | 179 | efree(output); 180 | } 181 | 182 | static ZEND_FUNCTION(snappy_uncompress) 183 | { 184 | zval *data; 185 | char *output = NULL; 186 | size_t output_len; 187 | 188 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 189 | "z", &data) == FAILURE) { 190 | RETURN_FALSE; 191 | } 192 | 193 | if (Z_TYPE_P(data) != IS_STRING) { 194 | zend_error(E_WARNING, 195 | "snappy_uncompress : expects parameter to be string."); 196 | RETURN_FALSE; 197 | } 198 | 199 | if (php_snappy_uncompress(Z_STRVAL_P(data), Z_STRLEN_P(data), 200 | &output, &output_len) == FAILURE) { 201 | RETURN_FALSE; 202 | } 203 | 204 | #if ZEND_MODULE_API_NO >= 20141001 205 | RETVAL_STRINGL(output, output_len); 206 | #else 207 | RETVAL_STRINGL(output, output_len, 1); 208 | #endif 209 | 210 | efree(output); 211 | } 212 | 213 | #if PHP_MAJOR_VERSION >= 7 && defined(HAVE_APCU_SUPPORT) 214 | static int APC_SERIALIZER_NAME(snappy)(APC_SERIALIZER_ARGS) 215 | { 216 | int result; 217 | php_serialize_data_t var_hash; 218 | smart_str var = {0}; 219 | 220 | PHP_VAR_SERIALIZE_INIT(var_hash); 221 | php_var_serialize(&var, (zval*) value, &var_hash); 222 | PHP_VAR_SERIALIZE_DESTROY(var_hash); 223 | if (var.s == NULL) { 224 | return 0; 225 | } 226 | 227 | if (php_snappy_compress(ZSTR_VAL(var.s), ZSTR_LEN(var.s), 228 | (char **)buf, buf_len) == SUCCESS) { 229 | result = 1; 230 | } else { 231 | result = 0; 232 | } 233 | 234 | smart_str_free(&var); 235 | 236 | return result; 237 | } 238 | 239 | static int APC_UNSERIALIZER_NAME(snappy)(APC_UNSERIALIZER_ARGS) 240 | { 241 | const unsigned char* tmp; 242 | int result; 243 | php_unserialize_data_t var_hash; 244 | size_t var_len; 245 | unsigned char* var; 246 | 247 | if (php_snappy_uncompress(buf, buf_len, 248 | (char **)&var, &var_len) != SUCCESS) { 249 | ZVAL_NULL(value); 250 | return 0; 251 | } 252 | 253 | PHP_VAR_UNSERIALIZE_INIT(var_hash); 254 | tmp = var; 255 | result = php_var_unserialize(value, &tmp, var + var_len, &var_hash); 256 | PHP_VAR_UNSERIALIZE_DESTROY(var_hash); 257 | 258 | if (!result) { 259 | php_error_docref(NULL, E_NOTICE, 260 | "Error at offset %ld of %ld bytes", 261 | (zend_long)(tmp - var), (zend_long)var_len); 262 | ZVAL_NULL(value); 263 | result = 0; 264 | } else { 265 | result = 1; 266 | } 267 | 268 | efree(var); 269 | 270 | return result; 271 | } 272 | #endif 273 | --------------------------------------------------------------------------------