├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── COPYING ├── CREDITS ├── ChangeLog ├── EXPERIMENTAL ├── Makefile.bench ├── NEWS ├── README.md ├── README_OLD.md ├── apc_serializer.h ├── benchmark ├── .gitignore ├── bench.php ├── l10n-en.ser ├── run-bench.php ├── serialize-objectarray.b.php ├── serialize-scalar-int.b.php ├── serialize-scalararray.b.php ├── serialize-stringarray.b.php ├── unserialize-objectarray.b.php ├── unserialize-scalar-int.b.php ├── unserialize-scalararray.b.php └── unserialize-stringarray.b.php ├── config.m4 ├── config.w32 ├── hash.h ├── hash_ptr.h ├── hash_si.c ├── hash_si_ptr.c ├── ig_win32.h ├── igbinary.c ├── igbinary.h ├── igbinary.php ├── igbinary.php.ini ├── igbinary.spec ├── package.xml ├── php_igbinary.h ├── tags.sh └── tests ├── igbinary_001.phpt ├── igbinary_002.phpt ├── igbinary_003.phpt ├── igbinary_004.phpt ├── igbinary_005.phpt ├── igbinary_006.phpt ├── igbinary_007.phpt ├── igbinary_008.phpt ├── igbinary_009.phpt ├── igbinary_009b.phpt ├── igbinary_010.phpt ├── igbinary_012.phpt ├── igbinary_013.phpt ├── igbinary_014.phpt ├── igbinary_015.phpt ├── igbinary_015b.phpt ├── igbinary_016.phpt ├── igbinary_017.phpt ├── igbinary_018.phpt ├── igbinary_019.phpt ├── igbinary_020.phpt ├── igbinary_021.phpt ├── igbinary_022.phpt ├── igbinary_023.phpt ├── igbinary_024.phpt ├── igbinary_025.phpt ├── igbinary_026.phpt ├── igbinary_026b.phpt ├── igbinary_027.phpt ├── igbinary_028.phpt ├── igbinary_029.phpt ├── igbinary_030.phpt ├── igbinary_031.phpt ├── igbinary_032.phpt ├── igbinary_033.phpt ├── igbinary_034.phpt ├── igbinary_040.phpt ├── igbinary_041.phpt ├── igbinary_042.phpt ├── igbinary_043.phpt ├── igbinary_044.phpt ├── igbinary_045.phpt ├── igbinary_045b.phpt ├── igbinary_046.phpt ├── igbinary_046b.phpt ├── igbinary_046c.phpt ├── igbinary_046d.phpt ├── igbinary_047.phpt ├── igbinary_048.phpt ├── igbinary_048b.phpt ├── igbinary_049.phpt ├── igbinary_049b.phpt ├── igbinary_050.phpt ├── igbinary_051.phpt ├── igbinary_052.phpt ├── igbinary_053.phpt ├── igbinary_054.phpt ├── igbinary_055.phpt ├── igbinary_bug54662.phpt ├── igbinary_bug72134.phpt └── igbinary_unserialize_v1_compatible.phpt /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | This repo is no longer being updated. 2 | Use the latest release from [PECL](https://pecl.php.net/package/igbinary) or [igbinary/igbinary](https://github.com/igbinary/igbinary), 3 | and if your issue persists, file an issue in [the igbinary/igbinary issue tracker](https://github.com/igbinary/igbinary/issues) 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.lo 3 | *.la 4 | .deps 5 | .libs 6 | Makefile 7 | Makefile.fragments 8 | Makefile.global 9 | Makefile.objects 10 | acinclude.m4 11 | aclocal.m4 12 | autom4te.cache 13 | build 14 | config.cache 15 | config.guess 16 | config.h 17 | config.h.in 18 | config.log 19 | config.nice 20 | config.status 21 | config.sub 22 | configure 23 | configure.in 24 | conftest 25 | conftest.c 26 | include 27 | install-sh 28 | libtool 29 | ltmain.sh 30 | missing 31 | mkinstalldirs 32 | modules 33 | scan_makefile_in.awk 34 | *.dsw 35 | *.plg 36 | *.opt 37 | *.ncb 38 | Release 39 | Release_inline 40 | Debug 41 | Release_TS 42 | Release_TSDbg 43 | Release_TS_inline 44 | Debug_TS 45 | run-tests.php 46 | cscope.out 47 | tests/*.out 48 | tests/*.php 49 | tests/*.mem 50 | tests/*.diff 51 | tests/*.log 52 | tests/*.exp 53 | tests/*.sh 54 | tmp-php.ini 55 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.0 4 | 5 | env: 6 | - CC=clang CFLAGS="" 7 | - CC=clang CFLAGS="-g -O0" 8 | - CC=gcc-4.6 CFLAGS="" 9 | - CC=gcc-4.6 CFLAGS="-g -O0 -fstack-protector -fstack-protector-all" 10 | - CC=gcc-4.6 CFLAGS="-g" VALGRIND=1 11 | 12 | install: 13 | - sudo apt-get update -qq 14 | - if [ "$VALGRIND" -eq 1 ]; then sudo apt-get install -qq valgrind; export TEST_PHP_ARGS="-m"; fi 15 | - sudo apt-get install -qq $CC 16 | - if [ "$VALGRIND" -eq 1 ]; then valgrind --version; fi 17 | - $CC --version 18 | 19 | script: 20 | - phpize 21 | - ./configure --enable-igbinary 22 | # Fix not failing makes in php 5.2 and 5.3 23 | - perl -i -pe 's/\-\@if/\@if/' Makefile 24 | - make 25 | - REPORT_EXIT_STATUS=1 NO_INTERACTION=1 make test 26 | 27 | branches: 28 | only: 29 | - master 30 | - php7-dev 31 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Sulake Dynamoid Oy, 2008-2014 Oleg Grenrus, Teddy Grenman, 2 | igbinary contributors 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | - Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | - Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | - Neither the name of the 'igbinary' nor the names of its contributors may 17 | be used to endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | igbinary is written for IRC-Galleria by Sulake Dynamoid Oy and its employees. 2 | 3 | Author 4 | * Oleg Grenrus 5 | 6 | Contributors 7 | * Teddy Grenman (fixes, tests, docs) 8 | * Kari Lavikka (docs) 9 | * Pierre Joye (Windows support) 10 | * Mikko Koppanen (PECL and RPM spec files) 11 | 12 | Other 13 | * Original hash functions - Bob Jenkins 14 | 15 | --- 16 | 17 | http://irc-galleria.net/ - a finnish social networking site 18 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2008-06-29 Oleg Grenrus 2 | * config.m4: fixed CFLAGS 3 | * igbinary.c: do not init object & string hashes if serializing scalars. 4 | unserialize_callback_func support. 5 | igbinary_serialize and igbinary_unserialize for the external use. 6 | * intbinary.h: header for external use 7 | * tests/022.phpt: unserialize_callback_func test 8 | * tests/023.phpt: resource serializes to null test 9 | * tests/002.phpt tests/003.phpt tests/004.phpt tests/005.phpt tests/006.phpt: == -> === 10 | * tests/015b.phpt: pointed out http://bugs.net/bug.php?id=45406 11 | -------------------------------------------------------------------------------- /EXPERIMENTAL: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/igbinary/igbinary7/17752e0b0bc8b869243c4a451a56f2db5c467a89/EXPERIMENTAL -------------------------------------------------------------------------------- /Makefile.bench: -------------------------------------------------------------------------------- 1 | benchmark: all 2 | -@if test ! -z "$(PHP_EXECUTABLE)" && test -x "$(PHP_EXECUTABLE)"; then \ 3 | cd benchmark; \ 4 | BENCH_PHP_EXECUTABLE="$(PHP_EXECUTABLE)" \ 5 | BENCH_PHP_ARGS="-n -d extension_dir=$(top_builddir)/modules/ $(PHP_TEST_SHARED_EXTENSIONS)" \ 6 | $(PHP_EXECUTABLE) -n ./run-bench.php; \ 7 | else \ 8 | echo "ERROR: Cannot run tests without CLI sapi."; \ 9 | fi 10 | 11 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 1.2.2 xxxx-xx-xx 2 | ======== 3 | * TBD 4 | 5 | 1.2.1 2014-08-29 6 | ======== 7 | * Compatible with PHP 5.2 - 5.6 8 | 9 | 1.2.0 2014-08-28 10 | ======== 11 | * PECL bug #22614, igbinary_unserialize(FALSE) must return FALSE 12 | * PHP bug #54662, unserializing nested objects cause crash 13 | * Other fixes 14 | 15 | 1.1.1 2011-01-17 16 | ======== 17 | * Critical crash fix. Thanks to Ilia Alshanetsky for spotting and fixing. 18 | 19 | 1.1.0 2011-01-17 20 | ======== 21 | * New ini setting to disable duplicate string compacting 22 | * APC serializer registration (APC 3.1.7 beta) 23 | * Windows support (PHP 5.3) 24 | * Updated serialized binary format (1.1 reads 1.0.x format) 25 | * Minor performance improvements 26 | * Bug fixes 27 | * New source repository at https://github.com/igbinary/igbinary 28 | 29 | 1.0.2 30 | ======== 31 | * Bug fix release 32 | 33 | 1.0.1 2008-07-05 34 | ======== 35 | * unserialize_callback_func support 36 | * slight speedup when serializing scalars 37 | 38 | 1.0.0 2008-06-25 39 | ======== 40 | * Public version 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This is no longer being updated. Use [igbinary/igbinary](https://github.com/igbinary/igbinary) for the php 5 and php 7 source and releases. 2 | 3 | For the old README, see [README\_OLD.md](./README_OLD.md) 4 | 5 | This is kept around to track the commit and issue history. 6 | -------------------------------------------------------------------------------- /README_OLD.md: -------------------------------------------------------------------------------- 1 | igbinary 2 | ======== 3 | 4 | **This has been merged into the master branch of [igbinary/igbinary](https://github.com/igbinary/igbinary)**, 5 | in [a subfolder](https://github.com/igbinary/igbinary/tree/master/src/php7). 6 | Installation steps and PRs should refer to igbinary/igbinary instead. 7 | (igbinary/igbinary is compatible with both php5 and php7 now) 8 | 9 | [![Build Status](https://travis-ci.org/igbinary/igbinary7.svg?branch=master)](https://travis-ci.org/igbinary/igbinary7) 10 | 11 | Igbinary is a drop in replacement for the standard php serializer. Instead of 12 | time and space consuming textual representation, igbinary stores php data 13 | structures in compact binary form. Savings are significant when using 14 | memcached or similar memory based storages for serialized data. About 50% 15 | reduction in storage requirement can be expected. Specific number depends on 16 | your data. 17 | 18 | Unserialization performance is at least on par with the standard PHP serializer. 19 | Serialization performance depends on the "compact_strings" option which enables 20 | duplicate string tracking. String are inserted to a hash table which adds some 21 | overhead. In usual scenarios this does not have much significance since usage 22 | pattern is "serialize rarely, unserialize often". With "compact_strings" 23 | option igbinary is usually a bit slower than the standard serializer. Without 24 | it, a bit faster. 25 | 26 | Features 27 | -------- 28 | 29 | - Supports same data types as the standard PHP serializer: null, bool, int, 30 | float, string, array and objects. 31 | - `__autoload` & `unserialize_callback_func` 32 | - `__sleep` & `__wakeup` 33 | - Serializable -interface 34 | - Data portability between platforms (32/64bit, endianess) 35 | - Tested on Linux amd64, Linux ARM, Mac OSX x86, HP-UX PA-RISC and NetBSD sparc64 36 | - Hooks up to APC opcode cache as a serialization handler (APC 3.1.7+) 37 | - Compatible with PHP 5.2 – 5.6 38 | 39 | Implementation details 40 | ---------------------- 41 | 42 | Storing complex PHP data structures like arrays of associative arrays 43 | with the standard PHP serializer is not very space efficient. The main 44 | reasons in order of significance are (at least in our applications): 45 | 46 | 1. Array keys are repeated redundantly. 47 | 2. Numerical values are plain text. 48 | 3. Human readability adds some overhead. 49 | 50 | Igbinary uses two specific strategies to minimize the size of the serialized 51 | output. 52 | 53 | 1. Repetitive strings are stored only once. Collections of objects benefit 54 | significantly from this. See "compact_strings" option. 55 | 56 | 2. Numerical values are stored in the smallest primitive data type 57 | available: 58 | *123* = `int8_t`, 59 | *1234* = `int16_t`, 60 | *123456* = `int32_t` 61 | ... and so on. 62 | 63 | 3. ( Well, it is not human readable ;) 64 | 65 | How to use 66 | ---------- 67 | 68 | Add the following lines to your php.ini: 69 | 70 | ; Load igbinary extension 71 | extension=igbinary.so 72 | 73 | ; Use igbinary as session serializer 74 | session.serialize_handler=igbinary 75 | 76 | ; Enable or disable compacting of duplicate strings 77 | ; The default is On. 78 | igbinary.compact_strings=On 79 | 80 | ; Use igbinary as serializer in APC cache (3.1.7 or later) 81 | ;apc.serializer=igbinary 82 | 83 | .. and in your php code replace serialize and unserialize function calls 84 | with `igbinary_serialize` and `igbinary_unserialize`. 85 | 86 | Installing 87 | ---------- 88 | 89 | Note: 90 | Sometimes phpize must be substituted with phpize5. In such cases the following 91 | option must be given to configure script: "--with-php-config=.../php-config5" 92 | 93 | 1. `phpize` 94 | 2. `./configure: 95 | - With GCC: `./configure CFLAGS="-O2 -g" --enable-igbinary` 96 | - With ICC (Intel C Compiler) `./configure CFLAGS=" -no-prec-div -O3 -xO -unroll2 -g" CC=icc --enable-igbinary` 97 | - With clang: `./configure CC=clang CFLAGS="-O0 -g" --enable-igbinary` 98 | 3. `make` 99 | 4. `make test` 100 | 5. `make install` 101 | 6. igbinary.so is installed to the default extension directory 102 | 103 | ### To run APCu test 104 | 105 | ``` 106 | # go to modules directory 107 | cd modules 108 | 109 | # ... and create symlink to apcu extension 110 | # it will be loaded during test suite 111 | /opt/lib/php/extensions/no-debug-non-zts-20121212/apcu.so 112 | ``` 113 | 114 | Similar approach should work for APC. 115 | 116 | Bugs & Contributions 117 | -------------------- 118 | 119 | Mailing list for bug reports and other development discussion can be found 120 | at http://groups.google.com/group/igbinary 121 | 122 | Fill bug reports at 123 | https://github.com/igbinary/igbinary/issues 124 | 125 | The preferred ways for contributions are pull requests and email patches 126 | (in git format). Feel free to fork at http://github.com/igbinary/igbinary 127 | 128 | Utilizing in other extensions 129 | ----------------------------- 130 | 131 | Igbinary can be called from other extensions fairly easily. Igbinary installs 132 | its header file to _ext/igbinary/igbinary.h_. There are just two straighforward 133 | functions: `igbinary_serialize` and `igbinary_unserialize`. Look at _igbinary.h_ for 134 | prototypes and usage. 135 | 136 | Add `PHP_ADD_EXTENSION_DEP(yourextension, igbinary)` to your _config.m4_ in case 137 | someone wants to compile both of them statically into php. 138 | 139 | Trivia 140 | ------ 141 | 142 | Where does the name "igbinary" come from? There was once a similar project 143 | called fbinary but it has disappeared from the Internet a long time ago. Its 144 | architecture wasn't particularly clean either. IG is an abbreviation for a 145 | finnish social networking site IRC-Galleria (http://irc-galleria.net/) 146 | 147 | 148 | -------------------------------------------------------------------------------- /apc_serializer.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | APC | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2006-2011 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt. | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Gopal Vijayaraghavan | 16 | +----------------------------------------------------------------------+ 17 | 18 | */ 19 | 20 | /* $Id: $ */ 21 | 22 | #ifndef APC_SERIALIZER_H 23 | #define APC_SERIALIZER_H 24 | 25 | /* this is a shipped .h file, do not include any other header in this file */ 26 | #define APC_SERIALIZER_NAME(module) module##_apc_serializer 27 | #define APC_UNSERIALIZER_NAME(module) module##_apc_unserializer 28 | 29 | #define APC_SERIALIZER_ARGS unsigned char **buf, size_t *buf_len, const zval *value, void *config TSRMLS_DC 30 | #define APC_UNSERIALIZER_ARGS zval **value, unsigned char *buf, size_t buf_len, void *config TSRMLS_DC 31 | 32 | typedef int (*apc_serialize_t)(APC_SERIALIZER_ARGS); 33 | typedef int (*apc_unserialize_t)(APC_UNSERIALIZER_ARGS); 34 | 35 | typedef int (*apc_register_serializer_t)(const char* name, 36 | apc_serialize_t serialize, 37 | apc_unserialize_t unserialize, 38 | void *config TSRMLS_DC); 39 | 40 | /* 41 | * ABI version for constant hooks. Increment this any time you make any changes 42 | * to any function in this file. 43 | */ 44 | #define APC_SERIALIZER_ABI "0" 45 | #define APC_SERIALIZER_CONSTANT "\000apc_register_serializer-" APC_SERIALIZER_ABI 46 | 47 | #if !defined(APC_UNUSED) 48 | # if defined(__GNUC__) 49 | # define APC_UNUSED __attribute__((unused)) 50 | # else 51 | # define APC_UNUSED 52 | # endif 53 | #endif 54 | 55 | static APC_UNUSED int apc_register_serializer(const char* name, 56 | apc_serialize_t serialize, 57 | apc_unserialize_t unserialize, 58 | void *config TSRMLS_DC) 59 | { 60 | zval *apc_magic_constant = NULL; 61 | (void)config; 62 | 63 | ALLOC_INIT_ZVAL(apc_magic_constant); 64 | 65 | if (zend_get_constant(APC_SERIALIZER_CONSTANT, sizeof(APC_SERIALIZER_CONSTANT)-1, apc_magic_constant TSRMLS_CC)) { 66 | if(apc_magic_constant) { 67 | apc_register_serializer_t register_func = (apc_register_serializer_t)(Z_LVAL_P(apc_magic_constant)); 68 | if(register_func) { 69 | zval_dtor(apc_magic_constant); 70 | return register_func(name, serialize, unserialize, NULL TSRMLS_CC); 71 | } 72 | } 73 | } 74 | 75 | zval_dtor(apc_magic_constant); 76 | 77 | return 0; 78 | } 79 | 80 | #endif 81 | 82 | /* 83 | * Local variables: 84 | * tab-width: 4 85 | * c-basic-offset: 4 86 | * End: 87 | * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker 88 | * vim<600: expandtab sw=4 ts=4 sts=4 89 | */ 90 | -------------------------------------------------------------------------------- /benchmark/.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | -------------------------------------------------------------------------------- /benchmark/bench.php: -------------------------------------------------------------------------------- 1 | name = $name; 19 | } 20 | 21 | private function getResourceUsage() { 22 | $rusage = getrusage(); 23 | $time = $rusage['ru_utime.tv_sec'] * 1000000 + $rusage['ru_utime.tv_usec']; 24 | $time += $rusage['ru_stime.tv_sec'] * 1000000 + $rusage['ru_stime.tv_usec']; 25 | 26 | return $time; 27 | } 28 | 29 | public function start() { 30 | if ($this->started) { 31 | throw new RuntimeException("Already started."); 32 | } 33 | $this->startTime = microtime(true); 34 | $this->stopTime = $this->startTime; 35 | 36 | $rusage = getrusage(); 37 | 38 | $this->startUsage = $this->getResourceUsage(); 39 | $this->stopUsage = $this->startUsage; 40 | $this->started = true; 41 | } 42 | 43 | public function stop($i = 1) { 44 | if (!$this->started) { 45 | throw new RuntimeException("Not started."); 46 | } 47 | 48 | $this->stopTime = microtime(true); 49 | $this->stopUsage = $this->getResourceUsage(); 50 | 51 | $this->iterations = (int)$i; 52 | $this->started = false; 53 | } 54 | 55 | public function writeHeader() { 56 | $header = implode("\t", array( 57 | 'name', 'start time', 'iterations', 'duration', 'rusage', 58 | )); 59 | echo $header, "\n"; 60 | $this->headerWritten = true; 61 | } 62 | 63 | public function write() { 64 | if ($this->started) { 65 | $this->stop(); 66 | } 67 | 68 | if (!$this->headerWritten) { 69 | $this->writeHeader(); 70 | } 71 | 72 | printf("%s\t%.6f\t%d\t%.8f\t%.6f\n", 73 | $this->name, 74 | $this->startTime, 75 | $this->iterations, 76 | $this->stopTime - $this->startTime, 77 | $this->stopUsage - $this->startUsage); 78 | } 79 | } 80 | 81 | 82 | -------------------------------------------------------------------------------- /benchmark/run-bench.php: -------------------------------------------------------------------------------- 1 | getBasename(); 13 | $name = $fileInfo->getBasename('.b.php'); 14 | 15 | if (!preg_match('/\.b\.php$/', $fn)) { 16 | continue; 17 | } 18 | 19 | $file = $fileInfo->openFile(); 20 | $file->setFlags(SplFileObject::DROP_NEW_LINE | SplFileObject::SKIP_EMPTY); 21 | 22 | $desc = $fn; 23 | foreach ($file as $line) { 24 | if (preg_match('/Description:\s*(.*)/', $line, $m)) { 25 | $desc = trim($m[1]); 26 | } 27 | } 28 | 29 | fwrite($stderr, str_pad($desc, 50, '.')); 30 | $start = microtime(true); 31 | 32 | $php = getenv('BENCH_PHP_EXECUTABLE'); 33 | if ($php === false) { 34 | $php = 'php'; 35 | } 36 | 37 | $args = getenv('BENCH_PHP_ARGS'); 38 | if ($args === false) { 39 | $args = ''; 40 | } 41 | 42 | $output = shell_exec($php . ' ' . $args . ' ' . $fileInfo->getFilename()); 43 | 44 | $stop = microtime(true); 45 | fprintf($stderr, "DONE %.2fs\n", $stop - $start); 46 | 47 | file_put_contents($benchBaseName . '-' . $name . '.txt', $output); 48 | } 49 | -------------------------------------------------------------------------------- /benchmark/serialize-objectarray.b.php: -------------------------------------------------------------------------------- 1 | i = $i; 19 | 20 | $array[] = $o; 21 | } 22 | 23 | for ($i = 0; $i < 40; $i++) { 24 | $b->start(); 25 | for ($j = 0; $j < 2000; $j++) { 26 | $ser = igbinary_serialize($array); 27 | } 28 | $b->stop($j); 29 | $b->write(); 30 | } 31 | -------------------------------------------------------------------------------- /benchmark/serialize-scalar-int.b.php: -------------------------------------------------------------------------------- 1 | start(); 13 | for ($j = 0; $j < 3500000; $j++) { 14 | $ser = igbinary_serialize($var); 15 | } 16 | $b->stop($j); 17 | $b->write(); 18 | } 19 | -------------------------------------------------------------------------------- /benchmark/serialize-scalararray.b.php: -------------------------------------------------------------------------------- 1 | start(); 29 | for ($j = 0; $j < 12000; $j++) { 30 | $ser = igbinary_serialize($array); 31 | } 32 | $b->stop($j); 33 | $b->write(); 34 | } 35 | -------------------------------------------------------------------------------- /benchmark/serialize-stringarray.b.php: -------------------------------------------------------------------------------- 1 | start(); 13 | for ($j = 0; $j < 360; $j++) { 14 | $ser = igbinary_serialize($array); 15 | } 16 | $b->stop($j); 17 | $b->write(); 18 | } 19 | -------------------------------------------------------------------------------- /benchmark/unserialize-objectarray.b.php: -------------------------------------------------------------------------------- 1 | i = $i; 19 | 20 | $array[] = $o; 21 | } 22 | $ser = igbinary_serialize($array); 23 | 24 | for ($i = 0; $i < 40; $i++) { 25 | $b->start(); 26 | for ($j = 0; $j < 540; $j++) { 27 | $array = igbinary_unserialize($ser); 28 | } 29 | $b->stop($j); 30 | $b->write(); 31 | } 32 | -------------------------------------------------------------------------------- /benchmark/unserialize-scalar-int.b.php: -------------------------------------------------------------------------------- 1 | start(); 13 | for ($j = 0; $j < 3600000; $j++) { 14 | $var = igbinary_unserialize($ser); 15 | } 16 | $b->stop($j); 17 | $b->write(); 18 | } 19 | -------------------------------------------------------------------------------- /benchmark/unserialize-scalararray.b.php: -------------------------------------------------------------------------------- 1 | start(); 30 | for ($j = 0; $j < 5800; $j++) { 31 | $array = igbinary_unserialize($ser); 32 | } 33 | $b->stop($j); 34 | $b->write(); 35 | } 36 | -------------------------------------------------------------------------------- /benchmark/unserialize-stringarray.b.php: -------------------------------------------------------------------------------- 1 | start(); 13 | for ($j = 0; $j < 500; $j++) { 14 | $array = igbinary_unserialize($ser); 15 | } 16 | $b->stop($j); 17 | $b->write(); 18 | } 19 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl config.m4 for extension igbinary 2 | 3 | dnl Comments in this file start with the string 'dnl'. 4 | dnl Remove where necessary. This file will not work 5 | dnl without editing. 6 | 7 | dnl If your extension references something external, use with: 8 | 9 | dnl PHP_ARG_WITH(igbinary, for igbinary support, 10 | dnl Make sure that the comment is aligned: 11 | dnl [ --with-igbinary Include igbinary support]) 12 | 13 | dnl Otherwise use enable: 14 | 15 | PHP_ARG_ENABLE(igbinary, whether to enable igbinary support, 16 | [ --enable-igbinary Enable igbinary support]) 17 | 18 | if test "$PHP_IGBINARY" != "no"; then 19 | AC_CHECK_HEADERS([stdbool.h],, AC_MSG_ERROR([stdbool.h not exists])) 20 | AC_CHECK_HEADERS([stddef.h],, AC_MSG_ERROR([stddef.h not exists])) 21 | AC_CHECK_HEADERS([stdint.h],, AC_MSG_ERROR([stdint.h not exists])) 22 | 23 | AC_MSG_CHECKING([for APC/APCU includes]) 24 | if test -f "$phpincludedir/ext/apcu/apc_serializer.h"; then 25 | apc_inc_path="$phpincludedir" 26 | AC_MSG_RESULT([APCU in $apc_inc_path]) 27 | AC_DEFINE(HAVE_APCU_SUPPORT,1,[Whether to enable apcu support]) 28 | elif test -f "$phpincludedir/ext/apc/apc_serializer.h"; then 29 | apc_inc_path="$phpincludedir" 30 | AC_MSG_RESULT([APC in $apc_inc_path]) 31 | AC_DEFINE(HAVE_APC_SUPPORT,1,[Whether to enable apc support]) 32 | elif test -f "${srcdir}/apc_serializer.h"; then 33 | AC_MSG_RESULT([apc_serializer.h bundled]) 34 | AC_DEFINE(HAVE_APC_SUPPORT,1,[Whether to enable apc support]) 35 | AC_DEFINE(USE_BUNDLED_APC,1,[Whether to use bundled apc includes]) 36 | else 37 | AC_MSG_RESULT([not found]) 38 | fi 39 | 40 | AC_CHECK_SIZEOF([long]) 41 | 42 | dnl GCC 43 | AC_MSG_CHECKING(compiler type) 44 | if test ! -z "`$CC --version | grep -i GCC`"; then 45 | AC_MSG_RESULT(gcc) 46 | if test -z "`echo $CFLAGS | grep -- -O0`"; then 47 | PHP_IGBINARY_CFLAGS="$CFLAGS -Wall -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes -Wcast-align -Wshadow -Wwrite-strings -Wswitch -Winline -finline-limit=10000 --param large-function-growth=10000 --param inline-unit-growth=10000" 48 | fi 49 | elif test ! -z "`$CC --version | grep -i ICC`"; then 50 | AC_MSG_RESULT(icc) 51 | if test -z "`echo $CFLAGS | grep -- -O0`"; then 52 | PHP_IGBINARY_CFLAGS="$CFLAGS -no-prec-div -O3 -x0 -unroll2" 53 | fi 54 | elif test ! -z "`$CC --version | grep -i CLANG`"; then 55 | AC_MSG_RESULT(clang) 56 | if test -z "`echo $CFLAGS | grep -- -O0`"; then 57 | PHP_IGBINARY_CFLAGS="$CFLAGS -Wall -O2" 58 | fi 59 | else 60 | AC_MSG_RESULT(other) 61 | fi 62 | 63 | PHP_ADD_MAKEFILE_FRAGMENT(Makefile.bench) 64 | PHP_INSTALL_HEADERS([ext/igbinary], [igbinary.h]) 65 | PHP_NEW_EXTENSION(igbinary, igbinary.c hash_si.c hash_si_ptr.c, $ext_shared,, $PHP_IGBINARY_CFLAGS) 66 | PHP_ADD_EXTENSION_DEP(igbinary, session, true) 67 | PHP_SUBST(IGBINARY_SHARED_LIBADD) 68 | fi 69 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("igbinary", "whether to enable igbinary support", "no"); 5 | 6 | if (PHP_IGBINARY == "yes") { 7 | res = CHECK_HEADER_ADD_INCLUDE("apc_serializer.h", "CFLAGS_IGBINARY", "..\\pecl\\apc;ext\\apc"); 8 | if (res) { 9 | AC_DEFINE('HAVE_APC_SUPPORT', 1, 'Whether to enable apc support') 10 | } 11 | EXTENSION("igbinary", "igbinary.c hash_si.c hash_si_ptr.c"); 12 | AC_DEFINE('HAVE_IGBINARY', 1, 'Have igbinary support', false); 13 | ADD_EXTENSION_DEP('igbinary', 'session'); 14 | } 15 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | +----------------------------------------------------------------------+ 5 | | Author: Oleg Grenrus | 6 | | See CREDITS for contributors | 7 | +----------------------------------------------------------------------+ 8 | */ 9 | 10 | #ifndef HASH_H 11 | #define HASH_H 12 | 13 | #include 14 | 15 | #ifdef PHP_WIN32 16 | # include "ig_win32.h" 17 | #else 18 | # include /* defines uint32_t etc */ 19 | #endif 20 | 21 | #include 22 | 23 | /** Key/value pair of hash_si. 24 | * @author Oleg Grenrus 25 | * @see hash_si 26 | */ 27 | struct hash_si_pair 28 | { 29 | char *key; /**< Pointer to key. */ 30 | size_t key_len; /**< Key length. */ 31 | uint32_t value; /**< Value. */ 32 | }; 33 | 34 | /** Hash-array. 35 | * Like c++ map. 36 | * Current implementation uses linear probing. 37 | * @author Oleg Grenrus 38 | */ 39 | struct hash_si { 40 | size_t size; /**< Allocated size of array. */ 41 | size_t used; /**< Used size of array. */ 42 | struct hash_si_pair *data; /**< Pointer to array or pairs of data. */ 43 | }; 44 | 45 | /** Inits hash_si structure. 46 | * @param h pointer to hash_si struct. 47 | * @param size initial size of the hash array. 48 | * @return 0 on success, 1 else. 49 | */ 50 | int hash_si_init (struct hash_si *h, size_t size); 51 | 52 | /** Frees hash_si structure. 53 | * Doesn't call free(h). 54 | * @param h pointer to hash_si struct. 55 | */ 56 | void hash_si_deinit (struct hash_si *h); 57 | 58 | /** Inserts value into hash_si. 59 | * @param h Pointer to hash_si struct. 60 | * @param key Pointer to key. 61 | * @param key_len Key length. 62 | * @param value Value. 63 | * @return 0 on success, 1 or 2 else. 64 | */ 65 | int hash_si_insert (struct hash_si *h, const char *key, size_t key_len, uint32_t value); 66 | 67 | /** Finds value from hash_si. 68 | * Value returned thru value param. 69 | * @param h Pointer to hash_si struct. 70 | * @param key Pointer to key. 71 | * @param key_len Key length. 72 | * @param[out] value Found value. 73 | * @return 0 if found, 1 if not. 74 | */ 75 | int hash_si_find (struct hash_si *h, const char *key, size_t key_len, uint32_t * value); 76 | 77 | /** Remove value from hash_si. 78 | * Removed value is available thru value param. 79 | * @param h Pointer to hash_si struct. 80 | * @param key Pointer to key. 81 | * @param key_len Key length. 82 | * @param[out] value Removed value. 83 | * @return 0 ivalue removed, 1 if not existed. 84 | */ 85 | int hash_si_remove (struct hash_si *h, const char *key, size_t key_len, uint32_t * value); 86 | 87 | /** Travarses hash_si. 88 | * Calls traverse_function on every item. Traverse function should not modify hash 89 | * @param h Pointer to hash_si struct. 90 | * @param traverse_function Function to call on every item of hash_si. 91 | */ 92 | void hash_si_traverse (struct hash_si *h, int (*traverse_function) (const char *key, size_t key_len, uint32_t value)); 93 | 94 | /** Returns size of hash_si. 95 | * @param h Pointer to hash_si struct. 96 | * @return Size of hash_si. 97 | */ 98 | size_t hash_si_size (struct hash_si *h); 99 | 100 | /** Returns capacity of hash_si. 101 | * @param h Pointer to hash_si struct. 102 | * @return Capacity of hash_si. 103 | */ 104 | size_t hash_si_capacity (struct hash_si *h); 105 | 106 | #endif /* HASH_H */ 107 | -------------------------------------------------------------------------------- /hash_ptr.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | +----------------------------------------------------------------------+ 5 | | Author: Oleg Grenrus | 6 | | See CREDITS for contributors | 7 | | This defines hash_si_ptr. | 8 | | It is like hash_si, but the key is always a non-zero zend_uintptr_t | 9 | +----------------------------------------------------------------------+ 10 | */ 11 | 12 | #ifndef HASH_PTR_H 13 | #define HASH_PTR_H 14 | 15 | #include 16 | 17 | #ifdef PHP_WIN32 18 | # include "ig_win32.h" 19 | #else 20 | # include /* defines uint32_t etc */ 21 | #endif 22 | 23 | #include 24 | #include "zend_types.h" 25 | 26 | // NULL converted to an integer, on sane platforms. 27 | #define HASH_PTR_KEY_INVALID 0 28 | 29 | /** Key/value pair of hash_si_ptr. 30 | * @author Oleg Grenrus 31 | * @see hash_si_ptr 32 | */ 33 | struct hash_si_ptr_pair 34 | { 35 | zend_uintptr_t key; /**< The key: The address of a pointer, casted to an int (won't be dereferenced). */ 36 | uint32_t value; /**< Value. */ 37 | }; 38 | 39 | /** Hash-array. 40 | * Like c++ std::unordered_map, but does not allow HASH_PTR_KEY_INVALID as a key. 41 | * Current implementation uses linear probing. 42 | * @author Oleg Grenrus 43 | */ 44 | struct hash_si_ptr { 45 | size_t size; /**< Allocated size of array. */ 46 | size_t used; /**< Used size of array. */ 47 | struct hash_si_ptr_pair *data; /**< Pointer to array or pairs of data. */ 48 | }; 49 | 50 | /** Inits hash_si_ptr structure. 51 | * @param h pointer to hash_si_ptr struct. 52 | * @param size initial size of the hash array. 53 | * @return 0 on success, 1 else. 54 | */ 55 | int hash_si_ptr_init(struct hash_si_ptr *h, size_t size); 56 | 57 | /** Frees hash_si_ptr structure. 58 | * Doesn't call free(h). 59 | * @param h pointer to hash_si_ptr struct. 60 | */ 61 | void hash_si_ptr_deinit(struct hash_si_ptr *h); 62 | 63 | /** Inserts value into hash_si_ptr. 64 | * @param h Pointer to hash_si_ptr struct. 65 | * @param key Pointer to key. 66 | * @param key_len Key length. 67 | * @param value Value. 68 | * @return 0 on success, 1 or 2 else. 69 | */ 70 | int hash_si_ptr_insert (struct hash_si_ptr *h, const zend_uintptr_t key, uint32_t value); 71 | 72 | /** Finds value from hash_si_ptr. 73 | * Value returned thru value param. 74 | * @param h Pointer to hash_si_ptr struct. 75 | * @param key Pointer to key. 76 | * @param key_len Key length. 77 | * @param[out] value Found value. 78 | * @return 0 if found, 1 if not. 79 | */ 80 | int hash_si_ptr_find (struct hash_si_ptr *h, const zend_uintptr_t key, uint32_t * value); 81 | 82 | /** Returns size of hash_si_ptr. 83 | * @param h Pointer to hash_si_ptr struct. 84 | * @return Size of hash_si_ptr. 85 | */ 86 | size_t hash_si_ptr_size (struct hash_si_ptr *h); 87 | 88 | /** Returns capacity of hash_si_ptr. 89 | * @param h Pointer to hash_si_ptr struct. 90 | * @return Capacity of hash_si_ptr. 91 | */ 92 | size_t hash_si_ptr_capacity (struct hash_si_ptr *h); 93 | 94 | #endif /* HASH_PTR_H */ 95 | -------------------------------------------------------------------------------- /hash_si.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | +----------------------------------------------------------------------+ 5 | | Author: Oleg Grenrus | 6 | | See CREDITS for contributors | 7 | +----------------------------------------------------------------------+ 8 | */ 9 | 10 | #ifdef PHP_WIN32 11 | # include "ig_win32.h" 12 | #endif 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #include "hash.h" 21 | #include "zend.h" 22 | 23 | /* {{{ nextpow2 */ 24 | /** Next power of 2. 25 | * @param n Integer. 26 | * @return next to n power of 2 . 27 | */ 28 | inline static uint32_t nextpow2(uint32_t n) { 29 | uint32_t m = 1; 30 | while (m < n) { 31 | m = m << 1; 32 | } 33 | 34 | return m; 35 | } 36 | /* }}} */ 37 | /* {{{ hash_si_init */ 38 | int hash_si_init(struct hash_si *h, size_t size) { 39 | size = nextpow2(size); 40 | 41 | h->size = size; 42 | h->used = 0; 43 | h->data = (struct hash_si_pair *) malloc(sizeof(struct hash_si_pair) * size); 44 | if (h->data == NULL) { 45 | return 1; 46 | } 47 | 48 | memset(h->data, 0, sizeof(struct hash_si_pair) * size); 49 | 50 | return 0; 51 | } 52 | /* }}} */ 53 | /* {{{ hash_si_deinit */ 54 | void hash_si_deinit(struct hash_si *h) { 55 | size_t i; 56 | 57 | for (i = 0; i < h->size; i++) { 58 | if (h->data[i].key != NULL) { 59 | free(h->data[i].key); 60 | } 61 | } 62 | 63 | free(h->data); 64 | 65 | h->size = 0; 66 | h->used = 0; 67 | } 68 | /* }}} */ 69 | /* {{{ _hash_si_find */ 70 | /** Returns index of key, or where it should be. 71 | * @param h Pointer to hash_si struct. 72 | * @param key Pointer to key. 73 | * @param key_len Key length. 74 | * @return index. 75 | */ 76 | inline static size_t _hash_si_find(struct hash_si *h, const char *key, size_t key_len) { 77 | uint32_t hv; 78 | size_t size; 79 | 80 | assert(h != NULL); 81 | 82 | size = h->size; 83 | hv = zend_inline_hash_func(key, key_len) & (h->size-1); 84 | 85 | while (size > 0 && 86 | h->data[hv].key != NULL && 87 | (h->data[hv].key_len != key_len || memcmp(h->data[hv].key, key, key_len) != 0)) { 88 | /* linear prob */ 89 | hv = (hv + 1) & (h->size-1); 90 | size--; 91 | } 92 | 93 | return hv; 94 | } 95 | /* }}} */ 96 | /* {{{ hash_si_remove */ 97 | int hash_si_remove(struct hash_si *h, const char *key, size_t key_len, uint32_t *value) { 98 | uint32_t hv; 99 | uint32_t j, k; 100 | 101 | assert(h != NULL); 102 | 103 | hv = _hash_si_find(h, key, key_len); 104 | 105 | /* dont exists */ 106 | if (h->data[hv].key == NULL) { 107 | return 1; 108 | } 109 | 110 | h->used--; 111 | 112 | free(h->data[hv].key); 113 | 114 | if (value != NULL) 115 | *value = h->data[hv].value; 116 | 117 | j = (hv + 1) & (h->size-1); 118 | while (h->data[j].key != NULL) { 119 | k = zend_inline_hash_func(h->data[j].key, strlen(h->data[j].key)) & (h->size-1); 120 | if ((j > hv && (k <= hv || k > j)) || (j < hv && (k <= hv && k > j))) { 121 | h->data[hv].key = h->data[j].key; 122 | h->data[hv].key_len = h->data[j].key_len; 123 | h->data[hv].value = h->data[j].value; 124 | 125 | hv = j; 126 | } 127 | j = (j + 1) & (h->size-1); 128 | } 129 | h->data[hv].key = NULL; 130 | 131 | 132 | return 0; 133 | /* 134 | * loop 135 | * j := (j+1) modulo num_slots 136 | * if slot[j] is unoccupied 137 | * exit loop 138 | * k := hash(slot[j].key) modulo num_slots 139 | * if (j > i and (k <= i or k > j)) or 140 | * (j < i and (k <= i and k > j)) (note 2) 141 | * slot[i] := slot[j] 142 | * i := j 143 | * mark slot[i] as unoccupied 144 | * 145 | * For all records in a cluster, there must be no vacant slots between their natural 146 | * hash position and their current position (else lookups will terminate before finding 147 | * the record). At this point in the pseudocode, i is a vacant slot that might be 148 | * invalidating this property for subsequent records in the cluster. j is such a 149 | * subsequent record. k is the raw hash where the record at j would naturally land in 150 | * the hash table if there were no collisions. This test is asking if the record at j 151 | * is invalidly positioned with respect to the required properties of a cluster now 152 | * that i is vacant. 153 | * 154 | * Another technique for removal is simply to mark the slot as deleted. However 155 | * this eventually requires rebuilding the table simply to remove deleted records. 156 | * The methods above provide O(1) updating and removal of existing records, with 157 | * occasional rebuilding if the high water mark of the table size grows. 158 | */ 159 | } 160 | /* }}} */ 161 | /* {{{ hash_si_rehash */ 162 | /** Rehash/resize hash_si. 163 | * @param h Pointer to hash_si struct. 164 | */ 165 | inline static void hash_si_rehash(struct hash_si *h) { 166 | uint32_t hv; 167 | size_t i; 168 | struct hash_si newh; 169 | 170 | assert(h != NULL); 171 | 172 | hash_si_init(&newh, h->size * 2); 173 | 174 | for (i = 0; i < h->size; i++) { 175 | if (h->data[i].key != NULL) { 176 | hv = _hash_si_find(&newh, h->data[i].key, h->data[i].key_len); 177 | newh.data[hv].key = h->data[i].key; 178 | newh.data[hv].key_len = h->data[i].key_len; 179 | newh.data[hv].value = h->data[i].value; 180 | } 181 | } 182 | 183 | free(h->data); 184 | h->data = newh.data; 185 | h->size *= 2; 186 | } 187 | /* }}} */ 188 | /* {{{ hash_si_insert */ 189 | int hash_si_insert(struct hash_si *h, const char *key, size_t key_len, uint32_t value) { 190 | uint32_t hv; 191 | 192 | if (h->size / 4 * 3 < h->used + 1) { 193 | hash_si_rehash(h); 194 | } 195 | 196 | hv = _hash_si_find(h, key, key_len); 197 | 198 | if (h->data[hv].key == NULL) { 199 | h->data[hv].key = (char *) malloc(key_len + 1); 200 | if (h->data[hv].key == NULL) { 201 | return 1; 202 | } 203 | memcpy(h->data[hv].key, key, key_len); 204 | h->data[hv].key[key_len] = '\0'; 205 | h->data[hv].key_len = key_len; 206 | 207 | h->used++; 208 | } else { 209 | return 2; 210 | } 211 | 212 | h->data[hv].value = value; 213 | 214 | return 0; 215 | } 216 | /* }}} */ 217 | /* {{{ hash_si_find */ 218 | int hash_si_find(struct hash_si *h, const char *key, size_t key_len, uint32_t *value) { 219 | uint32_t hv; 220 | 221 | assert(h != NULL); 222 | 223 | hv = _hash_si_find(h, key, key_len); 224 | 225 | if (h->data[hv].key == NULL) { 226 | return 1; 227 | } else { 228 | *value = h->data[hv].value; 229 | return 0; 230 | } 231 | } 232 | /* }}} */ 233 | /* {{{ hash_si_traverse */ 234 | void hash_si_traverse(struct hash_si *h, int (*traverse_function) (const char *key, size_t key_len, uint32_t value)) { 235 | size_t i; 236 | 237 | assert(h != NULL && traverse_function != NULL); 238 | 239 | for (i = 0; i < h->size; i++) { 240 | if (h->data[i].key != NULL && traverse_function(h->data[i].key, h->data[i].key_len, h->data[i].value) != 1) { 241 | return; 242 | } 243 | } 244 | } 245 | /* }}} */ 246 | /* {{{ hash_si_size */ 247 | size_t hash_si_size(struct hash_si *h) { 248 | assert(h != NULL); 249 | 250 | return h->used; 251 | } 252 | /* }}} */ 253 | /* {{{ hash_si_capacity */ 254 | size_t hash_si_capacity(struct hash_si *h) { 255 | assert(h != NULL); 256 | 257 | return h->size; 258 | } 259 | /* }}} */ 260 | 261 | /* 262 | * Local variables: 263 | * tab-width: 2 264 | * c-basic-offset: 4 265 | * End: 266 | * vim600: noet sw=4 ts=4 fdm=marker 267 | * vim<600: noet sw=4 ts=4 268 | */ 269 | -------------------------------------------------------------------------------- /hash_si_ptr.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | | This is a specialized hash map mapping uintprt_t to int32_t | 5 | +----------------------------------------------------------------------+ 6 | | Author: Oleg Grenrus | 7 | | Modified by Tyson Andre for fixed size, removing unused functions | 8 | | See CREDITS for contributors | 9 | +----------------------------------------------------------------------+ 10 | */ 11 | 12 | #ifdef PHP_WIN32 13 | # include "ig_win32.h" 14 | #endif 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include "hash_ptr.h" 23 | #include "zend.h" 24 | 25 | /* Function similar to zend_inline_hash_func. This is not identical. */ 26 | inline static uint32_t inline_hash_of_address(zend_uintptr_t ptr) { 27 | register uint32_t hash = Z_UL(5381); 28 | /* Note: Hash the least significant bytes first - Those need to influence the final result as much as possible. */ 29 | hash = ((hash << 5) + hash) + (ptr & 0xff); 30 | hash = ((hash << 5) + hash) + ((ptr >> 8) & 0xff); 31 | hash = ((hash << 5) + hash) + ((ptr >> 16) & 0xff); 32 | hash = ((hash << 5) + hash) + ((ptr >> 24) & 0xff); 33 | #if SIZEOF_ZEND_LONG == 8 34 | hash = ((hash << 5) + hash) + ((ptr >> 32) & 0xff); 35 | hash = ((hash << 5) + hash) + ((ptr >> 40) & 0xff); 36 | hash = ((hash << 5) + hash) + ((ptr >> 48) & 0xff); 37 | hash = ((hash << 5) + hash) + ((ptr >> 56) & 0xff); 38 | #endif 39 | return hash; 40 | } 41 | 42 | /* {{{ nextpow2 */ 43 | /** Next power of 2. 44 | * @param n Integer. 45 | * @return next to n power of 2 . 46 | */ 47 | inline static uint32_t nextpow2(uint32_t n) { 48 | uint32_t m = 1; 49 | while (m < n) { 50 | m = m << 1; 51 | } 52 | 53 | return m; 54 | } 55 | /* }}} */ 56 | /* {{{ hash_si_ptr_init */ 57 | int hash_si_ptr_init(struct hash_si_ptr *h, size_t size) { 58 | size = nextpow2(size); 59 | 60 | h->size = size; 61 | h->used = 0; 62 | h->data = (struct hash_si_ptr_pair*) malloc(sizeof(struct hash_si_ptr_pair) * size); 63 | if (h->data == NULL) { 64 | return 1; 65 | } 66 | 67 | memset(h->data, 0, sizeof(struct hash_si_ptr_pair) * size); /* Set everything to 0. sets keys to HASH_PTR_KEY_INVALID. */ 68 | 69 | return 0; 70 | } 71 | /* }}} */ 72 | /* {{{ hash_si_ptr_deinit */ 73 | void hash_si_ptr_deinit(struct hash_si_ptr *h) { 74 | size_t i; 75 | 76 | free(h->data); 77 | h->data = NULL; 78 | 79 | h->size = 0; 80 | h->used = 0; 81 | } 82 | /* }}} */ 83 | /* {{{ _hash_si_ptr_find */ 84 | /** Returns index of key, or where it should be. 85 | * @param h Pointer to hash_si_ptr struct. 86 | * @param key Pointer to key. 87 | * @return index. 88 | */ 89 | inline static size_t _hash_si_ptr_find(struct hash_si_ptr *h, const zend_uintptr_t key) { 90 | uint32_t hv; 91 | size_t size; 92 | 93 | assert(h != NULL); 94 | 95 | size = h->size; 96 | hv = inline_hash_of_address(key) & (h->size-1); 97 | 98 | while (size > 0 && 99 | h->data[hv].key != HASH_PTR_KEY_INVALID && 100 | h->data[hv].key != key) { 101 | /* linear prob */ 102 | hv = (hv + 1) & (h->size-1); 103 | size--; 104 | } 105 | 106 | return hv; 107 | } 108 | /* }}} */ 109 | /* }}} */ 110 | /* {{{ hash_si_ptr_rehash */ 111 | /** Rehash/resize hash_si_ptr. 112 | * @param h Pointer to hash_si_ptr struct. 113 | */ 114 | inline static void hash_si_ptr_rehash(struct hash_si_ptr *h) { 115 | uint32_t hv; 116 | size_t i; 117 | struct hash_si_ptr newh; 118 | 119 | assert(h != NULL); 120 | 121 | hash_si_ptr_init(&newh, h->size * 2); 122 | 123 | for (i = 0; i < h->size; i++) { 124 | if (h->data[i].key != HASH_PTR_KEY_INVALID) { 125 | hv = _hash_si_ptr_find(&newh, h->data[i].key); 126 | newh.data[hv].key = h->data[i].key; 127 | newh.data[hv].value = h->data[i].value; 128 | } 129 | } 130 | 131 | free(h->data); 132 | h->data = newh.data; 133 | h->size *= 2; 134 | } 135 | /* }}} */ 136 | /* {{{ hash_si_ptr_insert */ 137 | int hash_si_ptr_insert(struct hash_si_ptr *h, const zend_uintptr_t key, uint32_t value) { 138 | uint32_t hv; 139 | 140 | if (h->size / 4 * 3 < h->used + 1) { 141 | hash_si_ptr_rehash(h); 142 | } 143 | 144 | hv = _hash_si_ptr_find(h, key); 145 | 146 | if (h->data[hv].key == HASH_PTR_KEY_INVALID) { 147 | h->data[hv].key = key; 148 | 149 | h->used++; 150 | } else { 151 | return 2; 152 | } 153 | 154 | h->data[hv].value = value; 155 | 156 | return 0; 157 | } 158 | /* }}} */ 159 | /* {{{ hash_si_ptr_find */ 160 | int hash_si_ptr_find(struct hash_si_ptr *h, const zend_uintptr_t key, uint32_t *value) { 161 | uint32_t hv; 162 | 163 | assert(h != NULL); 164 | 165 | hv = _hash_si_ptr_find(h, key); 166 | 167 | if (h->data[hv].key == HASH_PTR_KEY_INVALID) { 168 | return 1; 169 | } else { 170 | *value = h->data[hv].value; 171 | return 0; 172 | } 173 | } 174 | /* }}} */ 175 | /* {{{ hash_si_ptr_size */ 176 | size_t hash_si_ptr_size(struct hash_si_ptr *h) { 177 | assert(h != NULL); 178 | 179 | return h->used; 180 | } 181 | /* }}} */ 182 | /* {{{ hash_si_ptr_capacity */ 183 | size_t hash_si_ptr_capacity(struct hash_si_ptr *h) { 184 | assert(h != NULL); 185 | 186 | return h->size; 187 | } 188 | /* }}} */ 189 | 190 | /* 191 | * Local variables: 192 | * tab-width: 2 193 | * c-basic-offset: 4 194 | * End: 195 | * vim600: noet sw=4 ts=4 fdm=marker 196 | * vim<600: noet sw=4 ts=4 197 | */ 198 | -------------------------------------------------------------------------------- /ig_win32.h: -------------------------------------------------------------------------------- 1 | #ifndef _IG_WIN32_H 2 | #define _IG_WIN32_H 3 | 4 | #if PHP_WIN32 5 | # include "win32/php_stdint.h" 6 | # ifndef inline 7 | # define inline __inline 8 | # endif 9 | 10 | # if _MSC_VER >= 1900 11 | # include 12 | # else 13 | # ifndef __cplusplus 14 | # if !0 15 | typedef enum { false = 0, true = 1 } _Bool; 16 | # endif 17 | # else 18 | typedef bool _Bool; 19 | # endif 20 | # define bool _Bool 21 | 22 | # define false 0 23 | # define true 1 24 | # define __bool_true_false_are_defined 1 25 | # endif 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /igbinary.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | +----------------------------------------------------------------------+ 5 | | Author: Oleg Grenrus | 6 | | See CREDITS for contributors | 7 | +----------------------------------------------------------------------+ 8 | */ 9 | 10 | #ifndef IGBINARY_H 11 | #define IGBINARY_H 12 | #ifdef PHP_WIN32 13 | # include "ig_win32.h" 14 | #else 15 | # include 16 | #endif 17 | #include "php.h" 18 | 19 | #ifdef PHP_WIN32 20 | # if defined(IGBINARY_EXPORTS) || (!defined(COMPILE_DL_IGBINARY)) 21 | # define IGBINARY_API __declspec(dllexport) 22 | # elif defined(COMPILE_DL_IGBINARY) 23 | # define IGBINARY_API __declspec(dllimport) 24 | # else 25 | # define IGBINARY_API /* nothing special */ 26 | # endif 27 | #elif defined(__GNUC__) && __GNUC__ >= 4 28 | # define IGBINARY_API __attribute__ ((visibility("default"))) 29 | #else 30 | # define IGBINARY_API /* nothing special */ 31 | #endif 32 | 33 | #define PHP_IGBINARY_VERSION "1.2.2-dev" 34 | 35 | /** Struct that contains pointers to memory allocation and deallocation functions. 36 | * @see igbinary_serialize_data 37 | */ 38 | struct igbinary_memory_manager { 39 | void *(*alloc)(size_t size, void *context); 40 | void *(*realloc)(void *ptr, size_t new_size, void *context); 41 | void (*free)(void *ptr, void *context); 42 | void *context; 43 | }; 44 | 45 | /** Serialize zval. 46 | * Return buffer is allocated by this function with emalloc. 47 | * @param[out] ret Return buffer 48 | * @param[out] ret_len Size of return buffer 49 | * @param[in] z Variable to be serialized 50 | * @return 0 on success, 1 elsewhere. 51 | */ 52 | IGBINARY_API int igbinary_serialize(uint8_t **ret, size_t *ret_len, zval *z TSRMLS_DC); 53 | 54 | /** Serialize zval. 55 | * Return buffer is allocated by this function with emalloc. 56 | * @param[out] ret Return buffer 57 | * @param[out] ret_len Size of return buffer 58 | * @param[in] z Variable to be serialized 59 | * @param[in] memory_manager Pointer to the structure that contains memory allocation functions. 60 | * @return 0 on success, 1 elsewhere. 61 | */ 62 | IGBINARY_API int igbinary_serialize_ex(uint8_t **ret, size_t *ret_len, zval *z, struct igbinary_memory_manager *memory_manager TSRMLS_DC); 63 | 64 | /** Unserialize to zval. 65 | * @param[in] buf Buffer with serialized data. 66 | * @param[in] buf_len Buffer length. 67 | * @param[out] z Unserialized zval 68 | * @return 0 on success, 1 elsewhere. 69 | */ 70 | IGBINARY_API int igbinary_unserialize(const uint8_t *buf, size_t buf_len, zval *z TSRMLS_DC); 71 | 72 | #endif /* IGBINARY_H */ 73 | -------------------------------------------------------------------------------- /igbinary.php: -------------------------------------------------------------------------------- 1 | 29 | * @version 1.0.0 30 | * @package igbinary 31 | */ 32 | 33 | /** Generates a storable representation of a value. 34 | * This is useful for storing or passing PHP values around without losing their type and structure. 35 | * To make the serialized string into a PHP value again, use {@link igbinary_unserialize}. 36 | * 37 | * igbinary_serialize() handles all types, except the resource-type. 38 | * You can even serialize() arrays that contain references to itself. 39 | * Circular references inside the array/object you are serialize()ing will also be stored. 40 | * 41 | * If object implements {@link http://www.php.net/~helly/php/ext/spl/interfaceSerializable.html Serializable} -interface, 42 | * PHP will call the member function serialize to get serialized representation of object. 43 | * 44 | * When serializing objects, PHP will attempt to call the member function __sleep prior to serialization. 45 | * This is to allow the object to do any last minute clean-up, etc. prior to being serialized. 46 | * Likewise, when the object is restored using unserialize() the __wakeup member function is called. 47 | * 48 | * @param mixed $value The value to be serialized. 49 | * @return string Returns a string containing a byte-stream representation of value that can be stored anywhere. 50 | * @link http://www.php.net/serialize PHP default serialize 51 | */ 52 | function igbinary_serialize($value); 53 | 54 | /** Creates a PHP value from a stored representation. 55 | * igbinary_unserialize() takes a single serialized variable and converts it back into a PHP value. 56 | * 57 | * If the variable being unserialized is an object, after successfully reconstructing the object 58 | * PHP will automatically attempt to call the __wakeup() member function (if it exists). 59 | * In case the passed string is not unserializeable, NULL is returned and E_WARNING is issued. 60 | * 61 | * @param string $str The serialized string. 62 | * @return mixed The converted value is returned, and can be a boolean, integer, float, string, array or object. 63 | * @link http://www.php.net/manual/en/function.unserialize.php PHP default unserialize 64 | * @link http://www.php.net/~helly/php/ext/spl/interfaceSerializable.html Serializable 65 | */ 66 | function igbinary_unserialize($str); 67 | 68 | ?> 69 | -------------------------------------------------------------------------------- /igbinary.php.ini: -------------------------------------------------------------------------------- 1 | [igbinary] 2 | extension=igbinary.so 3 | 4 | ; Enable or disable compacting of duplicate strings 5 | ; The default is On. 6 | ;igbinary.compact_strings=On 7 | -------------------------------------------------------------------------------- /igbinary.spec: -------------------------------------------------------------------------------- 1 | # Define version and release number 2 | %define version 1.0.2 3 | %define release 1 4 | 5 | Name: php-igbinary 6 | Version: %{version} 7 | Release: %{release}%{?dist} 8 | Packager: Mikko Koppanen 9 | Summary: PHP igbinary extension 10 | License: PHP Style License (http://opensource.dynamoid.com/#license) 11 | Group: Web/Applications 12 | URL: http://opensource.dynamoid.com/ 13 | # pear package creates .tgz file and the original source was .tar.gz 14 | Source: http://opensource.dynamoid.com/igbinary-%{version}.tgz 15 | Prefix: %{_prefix} 16 | Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root 17 | BuildRequires: php-devel, make, gcc, /usr/bin/phpize 18 | 19 | %description 20 | Igbinary is a drop in replacement for the standard PHP serializer. 21 | Instead of time and space consuming textual representation, 22 | igbinary stores PHP data structures in a compact binary form. 23 | 24 | %prep 25 | %setup -q -n igbinary-%{version} 26 | 27 | %build 28 | /usr/bin/phpize && %configure && %{__make} %{?_smp_mflags} 29 | 30 | # Clean the buildroot so that it does not contain any stuff from previous builds 31 | [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} 32 | 33 | # Install the extension 34 | %{__make} install INSTALL_ROOT=%{buildroot} 35 | 36 | # Create the ini location 37 | %{__mkdir} -p %{buildroot}/etc/php.d 38 | 39 | # Preliminary extension ini 40 | echo "extension=igbinary.so" > %{buildroot}/%{_sysconfdir}/php.d/igbinary.ini 41 | 42 | %clean 43 | [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} 44 | 45 | %files 46 | %{_libdir}/php/modules/igbinary.so 47 | %{_sysconfdir}/php.d/igbinary.ini 48 | %{_includedir}/php/ext/igbinary/igbinary.h 49 | 50 | %changelog 51 | * Fri Oct 02 2009 Mikko Koppanen 52 | - Initial spec file 53 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | igbinary 4 | pecl.php.net 5 | igbinary extension 6 | Igbinary is a drop in replacement for the standard php serializer. Instead of 7 | time and space consuming textual representation, igbinary stores php data 8 | structures in a compact binary form. Savings are significant when using 9 | memcached or similar memory based storages for serialized data. 10 | 11 | Oleg Grenrus 12 | phadej 13 | oleg.grenrus@iki.fi 14 | yes 15 | 16 | 17 | Pierre Joye 18 | pajoye 19 | pierre@php.net 20 | yes 21 | 22 | 23 | Teddy Grenman 24 | tricky 25 | teddy.pecl@luuseri.com 26 | yes 27 | 28 | 2014-08-29 29 | 30 | 31 | 1.2.2-dev 32 | 1.1.1 33 | 34 | 35 | stable 36 | stable 37 | 38 | New BSD 39 | 40 | - Compatible with PHP 5.2 - 5.6 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 5.2.0 119 | 120 | 121 | 1.4.0b1 122 | 123 | 124 | 125 | igbinary 126 | 127 | 128 | 129 | 2014-08-29 130 | 131 | 132 | 1.2.1 133 | 1.1.1 134 | 135 | 136 | stable 137 | stable 138 | 139 | New BSD 140 | 141 | - Compatible with PHP 5.2 - 5.6 142 | 143 | 144 | 145 | 2014-08-29 146 | 147 | 148 | 1.2.0 149 | 1.1.1 150 | 151 | 152 | stable 153 | stable 154 | 155 | New BSD 156 | 157 | - PECL bug #22614, igbinary_unserialize(FALSE) must return FALSE 158 | - PHP bug #54662, unserializing nested objects cause crash 159 | - Other fixes 160 | 161 | 162 | 163 | 2011-03-14 164 | 165 | 166 | 1.1.1 167 | 1.1.1 168 | 169 | 170 | stable 171 | stable 172 | 173 | New BSD 174 | 175 | - Initial PECL release 176 | 177 | 178 | 179 | 2009-09-02 180 | 181 | 1.0.2 182 | 1.0.2 183 | 184 | 185 | stable 186 | stable 187 | 188 | PHP like license 189 | 190 | - Use Z_ADDREF_PP or Z_ADDREF et al. when increasing refcount. 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /php_igbinary.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | See COPYING file for further copyright information | 4 | +----------------------------------------------------------------------+ 5 | | Author: Oleg Grenrus | 6 | | See CREDITS for contributors | 7 | +----------------------------------------------------------------------+ 8 | */ 9 | 10 | #ifndef PHP_IGBINARY_H 11 | #define PHP_IGBINARY_H 12 | 13 | /** Module entry of igbinary. */ 14 | extern zend_module_entry igbinary_module_entry; 15 | #define phpext_igbinary_ptr &igbinary_module_entry 16 | 17 | #ifdef PHP_WIN32 18 | #define PHP_IGBINARY_API __declspec(dllexport) 19 | #else 20 | #define PHP_IGBINARY_API 21 | #endif 22 | 23 | ZEND_BEGIN_MODULE_GLOBALS(igbinary) 24 | zend_bool compact_strings; 25 | ZEND_END_MODULE_GLOBALS(igbinary) 26 | 27 | #ifdef ZTS 28 | #include "TSRM.h" 29 | #endif 30 | 31 | #include "ext/standard/php_smart_string.h" 32 | 33 | /** Module init function. */ 34 | PHP_MINIT_FUNCTION(igbinary); 35 | 36 | /** Module shutdown function. */ 37 | PHP_MSHUTDOWN_FUNCTION(igbinary); 38 | 39 | /** Request init function. */ 40 | PHP_RINIT_FUNCTION(igbinary); 41 | 42 | /** Request shutdown function. */ 43 | PHP_RSHUTDOWN_FUNCTION(igbinary); 44 | 45 | /** Module info function for phpinfo(). */ 46 | PHP_MINFO_FUNCTION(igbinary); 47 | 48 | /** string igbinary_serialize(mixed value). 49 | * Returns the binary serialized value. 50 | */ 51 | PHP_FUNCTION(igbinary_serialize); 52 | 53 | /** mixed igbinary_unserialize(string data). 54 | * Unserializes the given inputstring (value). 55 | */ 56 | PHP_FUNCTION(igbinary_unserialize); 57 | 58 | #ifdef ZTS 59 | #define IGBINARY_G(v) TSRMG(igbinary_globals_id, zend_igbinary_globals *, v) 60 | #else 61 | #define IGBINARY_G(v) (igbinary_globals.v) 62 | #endif 63 | 64 | /** Binary protocol version of igbinary. */ 65 | #define IGBINARY_FORMAT_VERSION 0x00000002 66 | 67 | /** Backport macros from php 5.3 */ 68 | #ifndef Z_ISREF_P 69 | #define Z_ISREF_P(pz) PZVAL_IS_REF(pz) 70 | #endif 71 | 72 | #ifndef Z_ISREF_PP 73 | #define Z_ISREF_PP(ppz) Z_ISREF_P(*(ppz)) 74 | #endif 75 | 76 | #ifndef Z_SET_ISREF_TO_P 77 | #define Z_SET_ISREF_TO_P(pz, isref) (Z_ISREF_P(pz) = (isref)) 78 | #endif 79 | 80 | #ifndef Z_SET_ISREF_TO_PP 81 | #define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref) 82 | #endif 83 | 84 | #ifndef Z_ADDREF_P 85 | #define Z_ADDREF_P(pz) ZVAL_ADDREF(pz) 86 | #endif 87 | 88 | #ifndef Z_ADDREF_PP 89 | #define Z_ADDREF_PP(ppz) Z_ADDREF_P(*(ppz)) 90 | #endif 91 | #endif /* PHP_IGBINARY_H */ 92 | 93 | 94 | /* 95 | * Local variables: 96 | * tab-width: 2 97 | * c-basic-offset: 0 98 | * End: 99 | * vim600: noet sw=2 ts=2 fdm=marker 100 | * vim<600: noet sw=2 ts=2 101 | */ 102 | -------------------------------------------------------------------------------- /tags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # This generates the tags file for vim or emacs. (vim -t igbinary_serialize8) 4 | # 5 | # Try with "vim -t igbinary_serialize8" 6 | # 7 | 8 | find . -name "*.h" -o -name "*.c" | ctags-exuberant --language-force=c -L - 9 | -------------------------------------------------------------------------------- /tests/igbinary_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for igbinary presence 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 20 | --EXPECT-- 21 | igbinary extension is available 22 | -------------------------------------------------------------------------------- /tests/igbinary_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for null serialisation 3 | --SKIPIF-- 4 | --FILE-- 5 | 36 | --EXPECT-- 37 | null 38 | 00 39 | OK 40 | -------------------------------------------------------------------------------- /tests/igbinary_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for bool serialisation 3 | --SKIPIF-- 4 | --FILE-- 5 | 35 | --EXPECT-- 36 | bool true 37 | 05 38 | OK 39 | bool false 40 | 04 41 | OK 42 | -------------------------------------------------------------------------------- /tests/igbinary_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for integer serialisation 3 | --SKIPIF-- 4 | --FILE-- 5 | 40 | --EXPECT-- 41 | zero: 0 42 | 0600 43 | OK 44 | small: 1 45 | 0601 46 | OK 47 | small: -1 48 | 0701 49 | OK 50 | medium: 1000 51 | 0803e8 52 | OK 53 | medium: -1000 54 | 0903e8 55 | OK 56 | large: 100000 57 | 0a000186a0 58 | OK 59 | large: -100000 60 | 0b000186a0 61 | OK 62 | -------------------------------------------------------------------------------- /tests/igbinary_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for double serialisation 3 | --SKIPIF-- 4 | --FILE-- 5 | 34 | --EXPECT-- 35 | double: 123.456 36 | 0c405edd2f1a9fbe77 37 | OK 38 | -------------------------------------------------------------------------------- /tests/igbinary_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for simple string serialization 3 | --SKIPIF-- 4 | --FILE-- 5 | 35 | --EXPECT-- 36 | empty: "" 37 | 0d 38 | OK 39 | string: "foobar" 40 | 1106666f6f626172 41 | OK 42 | -------------------------------------------------------------------------------- /tests/igbinary_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for simple array serialization 3 | --SKIPIF-- 4 | --FILE-- 5 | 36 | --EXPECT-- 37 | empty array: 38 | 1400 39 | OK 40 | array(1, 2, 3) 41 | 1403060006010601060206020603 42 | OK 43 | array(array(1, 2, 3), arr... 44 | 1403060014030600060106010602060206030601140306000604060106050602060606021403060006070601060806020609 45 | OK 46 | -------------------------------------------------------------------------------- /tests/igbinary_008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for array+string serialization 3 | --SKIPIF-- 4 | --FILE-- 5 | 1, "two" => 2))', array("one" => 1, "two" => 2)); 29 | test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek")); 30 | test('array("" => "empty")', array("" => "empty")); 31 | 32 | ?> 33 | --EXPECT-- 34 | array("foo", "foo", "foo") 35 | 140306001103666f6f06010e0006020e00 36 | OK 37 | array("one" => 1, "two" => 2)) 38 | 140211036f6e650601110374776f0602 39 | OK 40 | array("kek" => "lol", "lol" => "kek") 41 | 140211036b656b11036c6f6c0e010e00 42 | OK 43 | array("" => "empty") 44 | 14010d1105656d707479 45 | OK 46 | -------------------------------------------------------------------------------- /tests/igbinary_009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for reference serialisation 3 | --SKIPIF-- 4 | array( 22 | 'b' => 'c', 23 | 'd' => 'e' 24 | ), 25 | 'f' => array( 26 | 'g' => 'h' 27 | ) 28 | ); 29 | 30 | test('array', $a, false); 31 | 32 | /* 33 | * you can add regression tests for your extension here 34 | * 35 | * the output of your test code has to be equal to the 36 | * text in the --EXPECT-- section below for the tests 37 | * to pass, differences between the output and the 38 | * expected text are interpreted as failure 39 | * 40 | * see php5/README.TESTING for further information on 41 | * writing regression tests 42 | */ 43 | ?> 44 | --EXPECT-- 45 | array 46 | 140211016114021101621101631101641101651101661401110167110168 47 | OK 48 | -------------------------------------------------------------------------------- /tests/igbinary_012.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 30 | $this->b = $b; 31 | $this->c = $c; 32 | } 33 | } 34 | 35 | $o = new Obj(1, 2, 3); 36 | 37 | 38 | test('object', $o, false); 39 | 40 | /* 41 | * you can add regression tests for your extension here 42 | * 43 | * the output of your test code has to be equal to the 44 | * text in the --EXPECT-- section below for the tests 45 | * to pass, differences between the output and the 46 | * expected text are interpreted as failure 47 | * 48 | * see php5/README.TESTING for further information on 49 | * writing regression tests 50 | */ 51 | ?> 52 | --EXPECT-- 53 | object 54 | 17034f626a140311016106011104002a006206021106004f626a00630603 55 | OK 56 | -------------------------------------------------------------------------------- /tests/igbinary_013.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object-Array test 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 26 | $this->b = $b; 27 | } 28 | } 29 | 30 | $o = array(new Obj(1, 2), new Obj(3, 4)); 31 | 32 | 33 | test('object', $o, false); 34 | 35 | /* 36 | * you can add regression tests for your extension here 37 | * 38 | * the output of your test code has to be equal to the 39 | * text in the --EXPECT-- section below for the tests 40 | * to pass, differences between the output and the 41 | * expected text are interpreted as failure 42 | * 43 | * see php5/README.TESTING for further information on 44 | * writing regression tests 45 | */ 46 | ?> 47 | --EXPECT-- 48 | object 49 | 1402060017034f626a14021101610601110162060206011a0014020e0106030e020604 50 | OK 51 | -------------------------------------------------------------------------------- /tests/igbinary_014.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object-Reference test 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 29 | $this->b = $b; 30 | } 31 | } 32 | 33 | $o = new Obj(1, 2); 34 | $a = array(&$o, &$o); 35 | 36 | test('object', $a, false); 37 | 38 | --EXPECT-- 39 | object 40 | 140206002517034f626a1402110161060111016206020601252201 41 | OK 42 | -------------------------------------------------------------------------------- /tests/igbinary_015.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for serialization handler 3 | --SKIPIF-- 4 | 75 | --EXPECT-- 76 | 2 77 | 14011103666f6f0602 78 | -------------------------------------------------------------------------------- /tests/igbinary_015b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for serialization handler, ini-directive 3 | --SKIPIF-- 4 | 75 | --EXPECT-- 76 | 2 77 | 14011103666f6f0602 78 | -------------------------------------------------------------------------------- /tests/igbinary_016.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __sleep 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 28 | $this->b = $b; 29 | $this->c = $c; 30 | $this->d = $d; 31 | } 32 | 33 | function __sleep() { 34 | return array('a', 'b', 'c'); 35 | } 36 | 37 | # function __wakeup() { 38 | # $this->d = $this->a + $this->b + $this->c; 39 | # } 40 | } 41 | 42 | $o = new Obj(1, 2, 3, 4); 43 | 44 | 45 | test('object', $o, true); 46 | 47 | /* 48 | * you can add regression tests for your extension here 49 | * 50 | * the output of your test code has to be equal to the 51 | * text in the --EXPECT-- section below for the tests 52 | * to pass, differences between the output and the 53 | * expected text are interpreted as failure 54 | * 55 | * see php5/README.TESTING for further information on 56 | * writing regression tests 57 | */ 58 | ?> 59 | --EXPECT-- 60 | object 61 | 17034f626a140311016106011104002a006206021106004f626a00630603 62 | OK 63 | -------------------------------------------------------------------------------- /tests/igbinary_017.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __wakeup 3 | --SKIPIF-- 4 | --FILE-- 5 | b == 3 ? 'OK' : 'ERROR'; 17 | echo "\n"; 18 | } 19 | 20 | class Obj { 21 | var $a; 22 | var $b; 23 | 24 | function __construct($a, $b) { 25 | $this->a = $a; 26 | $this->b = $b; 27 | } 28 | 29 | function __wakeup() { 30 | $this->b = $this->a * 3; 31 | } 32 | } 33 | 34 | $o = new Obj(1, 2); 35 | 36 | 37 | test('object', $o, false); 38 | 39 | /* 40 | * you can add regression tests for your extension here 41 | * 42 | * the output of your test code has to be equal to the 43 | * text in the --EXPECT-- section below for the tests 44 | * to pass, differences between the output and the 45 | * expected text are interpreted as failure 46 | * 47 | * see php5/README.TESTING for further information on 48 | * writing regression tests 49 | */ 50 | ?> 51 | --EXPECT-- 52 | object 53 | 17034f626a140211016106011101620602 54 | OK 55 | -------------------------------------------------------------------------------- /tests/igbinary_018.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __sleep error cases 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 28 | $this->b = $b; 29 | } 30 | 31 | function __sleep() { 32 | return array('c'); 33 | } 34 | 35 | # function __wakeup() { 36 | # $this->b = $this->a * 3; 37 | # } 38 | } 39 | 40 | class Opj { 41 | var $a; 42 | var $b; 43 | 44 | function __construct($a, $b) { 45 | $this->a = $a; 46 | $this->b = $b; 47 | } 48 | 49 | function __sleep() { 50 | return array(1); 51 | } 52 | 53 | # function __wakeup() { 54 | # 55 | # } 56 | } 57 | 58 | $o = new Obj(1, 2); 59 | $p = new Opj(1, 2); 60 | 61 | test('nonexisting', $o, true); 62 | test('wrong', $p, true); 63 | 64 | /* 65 | * you can add regression tests for your extension here 66 | * 67 | * the output of your test code has to be equal to the 68 | * text in the --EXPECT-- section below for the tests 69 | * to pass, differences between the output and the 70 | * expected text are interpreted as failure 71 | * 72 | * see php5/README.TESTING for further information on 73 | * writing regression tests 74 | */ 75 | ?> 76 | --EXPECT-- 77 | nonexisting 78 | 17034f626a140111016300 79 | OK 80 | wrong 81 | 17034f706a140100 82 | OK 83 | -------------------------------------------------------------------------------- /tests/igbinary_019.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __autoload 3 | --SKIPIF-- 4 | --FILE-- 5 | b == 2 ? 'OK' : 'ERROR'; 17 | echo "\n"; 18 | } 19 | 20 | function __autoload($classname) { 21 | class Obj { 22 | var $a; 23 | var $b; 24 | 25 | function __construct($a, $b) { 26 | $this->a = $a; 27 | $this->b = $b; 28 | } 29 | } 30 | } 31 | 32 | test('autoload', '0000000217034f626a140211016106011101620602', false); 33 | 34 | /* 35 | * you can add regression tests for your extension here 36 | * 37 | * the output of your test code has to be equal to the 38 | * text in the --EXPECT-- section below for the tests 39 | * to pass, differences between the output and the 40 | * expected text are interpreted as failure 41 | * 42 | * see php5/README.TESTING for further information on 43 | * writing regression tests 44 | */ 45 | ?> 46 | --EXPECT-- 47 | autoload 48 | 17034f626a140211016106011101620602 49 | OK 50 | -------------------------------------------------------------------------------- /tests/igbinary_020.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, incomplete class 3 | --SKIPIF-- 4 | --FILE-- 5 | 34 | --EXPECTF-- 35 | incom 36 | 17034f626a140211016106011101620602 37 | object(__PHP_Incomplete_Class)#%d (3) { 38 | ["__PHP_Incomplete_Class_Name"]=> 39 | string(3) "Obj" 40 | ["a"]=> 41 | int(1) 42 | ["b"]=> 43 | int(2) 44 | } 45 | -------------------------------------------------------------------------------- /tests/igbinary_021.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object Serializable interface 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 26 | $this->b = $b; 27 | } 28 | 29 | public function serialize() { 30 | return pack('NN', $this->a, $this->b); 31 | } 32 | 33 | public function unserialize($serialized) { 34 | $tmp = unpack('N*', $serialized); 35 | $this->__construct($tmp[1], $tmp[2]); 36 | } 37 | } 38 | 39 | $o = new Obj(1, 2); 40 | 41 | test('object', $o, false); 42 | 43 | /* 44 | * you can add regression tests for your extension here 45 | * 46 | * the output of your test code has to be equal to the 47 | * text in the --EXPECT-- section below for the tests 48 | * to pass, differences between the output and the 49 | * expected text are interpreted as failure 50 | * 51 | * see php5/README.TESTING for further information on 52 | * writing regression tests 53 | */ 54 | ?> 55 | --EXPECT-- 56 | object 57 | 17034f626a1d080000000100000002 58 | OK 59 | -------------------------------------------------------------------------------- /tests/igbinary_022.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, unserialize_callback_func 3 | --SKIPIF-- 4 | --INI-- 5 | unserialize_callback_func=autoload 6 | --FILE-- 7 | b == 2 ? 'OK' : 'ERROR'; 19 | echo "\n"; 20 | } 21 | 22 | function autoload($classname) { 23 | class Obj { 24 | var $a; 25 | var $b; 26 | 27 | function __construct($a, $b) { 28 | $this->a = $a; 29 | $this->b = $b; 30 | } 31 | } 32 | } 33 | 34 | test('autoload', '0000000217034f626a140211016106011101620602', false); 35 | 36 | /* 37 | * you can add regression tests for your extension here 38 | * 39 | * the output of your test code has to be equal to the 40 | * text in the --EXPECT-- section below for the tests 41 | * to pass, differences between the output and the 42 | * expected text are interpreted as failure 43 | * 44 | * see php5/README.TESTING for further information on 45 | * writing regression tests 46 | */ 47 | ?> 48 | --EXPECT-- 49 | autoload 50 | 17034f626a140211016106011101620602 51 | OK 52 | -------------------------------------------------------------------------------- /tests/igbinary_023.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Resource 3 | --SKIPIF-- 4 | a = $a; 31 | $this->b = $b; 32 | $this->c = $c; 33 | } 34 | } 35 | 36 | class Obj2 { 37 | public $aa; 38 | protected $bb; 39 | private $cc; 40 | private $obj; 41 | 42 | function __construct($a, $b, $c) { 43 | $this->a = $a; 44 | $this->b = $b; 45 | $this->c = $c; 46 | 47 | $this->obj = new Obj($a, $b, $c); 48 | } 49 | } 50 | 51 | class Obj3 { 52 | private $objs; 53 | 54 | function __construct($a, $b, $c) { 55 | $this->objs = array(); 56 | 57 | for ($i = $a; $i < $c; $i += $b) { 58 | $this->objs[] = new Obj($a, $i, $c); 59 | } 60 | } 61 | } 62 | 63 | class Obj4 { 64 | private $a; 65 | private $obj; 66 | 67 | function __construct($a) { 68 | $this->a = $a; 69 | } 70 | 71 | public function set($obj) { 72 | $this->obj = $obj; 73 | } 74 | } 75 | 76 | $o2 = new Obj2(1, 2, 3); 77 | test('objectrec', $o2, false); 78 | 79 | $o3 = new Obj3(0, 1, 4); 80 | test('objectrecarr', $o3, false); 81 | 82 | $o4 = new Obj4(100); 83 | $o4->set($o4); 84 | test('objectselfrec', $o4, true); 85 | 86 | /* 87 | * you can add regression tests for your extension here 88 | * 89 | * the output of your test code has to be equal to the 90 | * text in the --EXPECT-- section below for the tests 91 | * to pass, differences between the output and the 92 | * expected text are interpreted as failure 93 | * 94 | * see php5/README.TESTING for further information on 95 | * writing regression tests 96 | */ 97 | ?> 98 | --EXPECT-- 99 | objectrec 100 | 17044f626a32140711026161001105002a006262001108004f626a32006363001109004f626a32006f626a17034f626a140311016106011104002a006206021106004f626a006306030e06060111016206021101630603 101 | OK 102 | objectrecarr 103 | 17044f626a331401110a004f626a33006f626a731404060017034f626a140311016106001104002a006206001106004f626a0063060406011a0214030e0306000e0406010e05060406021a0214030e0306000e0406020e05060406031a0214030e0306000e0406030e050604 104 | OK 105 | objectselfrec 106 | 17044f626a3414021107004f626a34006106641109004f626a34006f626a2200 107 | OK 108 | -------------------------------------------------------------------------------- /tests/igbinary_025.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, array of objects with __sleep 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 26 | $this->b = $b; 27 | $this->c = $c; 28 | $this->d = $d; 29 | } 30 | 31 | function __sleep() { 32 | return array('a', 'b', 'c'); 33 | } 34 | 35 | # function __wakeup() { 36 | # $this->d = $this->a + $this->b + $this->c; 37 | # } 38 | } 39 | 40 | $array = array( 41 | new Obj("aa", "bb", "cc", "dd"), 42 | new Obj("ee", "ff", "gg", "hh"), 43 | new Obj(1, 2, 3, 4), 44 | ); 45 | 46 | 47 | test('array', $array, true); 48 | 49 | ?> 50 | --EXPECTREGEX-- 51 | array\(3\) { 52 | \[0\]=> 53 | object\(Obj\)#1 \(4\) { 54 | \["a"\]=> 55 | string\(2\) "aa" 56 | \[("b":protected|"b:protected")\]=> 57 | string\(2\) "bb" 58 | \["?c"?:("Obj":)?private"?\]=> 59 | string\(2\) "cc" 60 | \["d"\]=> 61 | string\(2\) "dd" 62 | } 63 | \[1\]=> 64 | object\(Obj\)#2 \(4\) { 65 | \["a"\]=> 66 | string\(2\) "ee" 67 | \["?b"?:protected"?\]=> 68 | string\(2\) "ff" 69 | \["?c"?:("Obj":)?private"?\]=> 70 | string\(2\) "gg" 71 | \["d"\]=> 72 | string\(2\) "hh" 73 | } 74 | \[2\]=> 75 | object\(Obj\)#3 \(4\) { 76 | \["a"\]=> 77 | int\(1\) 78 | \["?b"?:protected"?\]=> 79 | int\(2\) 80 | \["?c"?:("Obj":)?private"?\]=> 81 | int\(3\) 82 | \["d"\]=> 83 | int\(4\) 84 | } 85 | } 86 | array\(3\) { 87 | \[0\]=> 88 | object\(Obj\)#4 \(4\) { 89 | \["a"\]=> 90 | string\(2\) "aa" 91 | \["?b"?:protected"?\]=> 92 | string\(2\) "bb" 93 | \["?c"?:("Obj":)?private"?\]=> 94 | string\(2\) "cc" 95 | \["d"\]=> 96 | NULL 97 | } 98 | \[1\]=> 99 | object\(Obj\)#5 \(4\) { 100 | \["a"\]=> 101 | string\(2\) "ee" 102 | \["?b"?:protected"?\]=> 103 | string\(2\) "ff" 104 | \["?c"?:("Obj":)?private"?\]=> 105 | string\(2\) "gg" 106 | \["d"\]=> 107 | NULL 108 | } 109 | \[2\]=> 110 | object\(Obj\)#6 \(4\) { 111 | \["a"\]=> 112 | int\(1\) 113 | \["?b"?:protected"?\]=> 114 | int\(2\) 115 | \["?c"?:("Obj":)?private"?\]=> 116 | int\(3\) 117 | \["d"\]=> 118 | NULL 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/igbinary_026.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Cyclic array test 3 | --INI-- 4 | report_memleaks=0 5 | --SKIPIF-- 6 | array( 24 | 'b' => 'c', 25 | 'd' => 'e' 26 | ), 27 | ); 28 | 29 | $a['f'] = &$a; 30 | 31 | test('array', $a, false); 32 | 33 | $a = array("foo" => &$b); 34 | $b = array(1, 2, $a); 35 | 36 | $exp = $a; 37 | $act = igbinary_unserialize(igbinary_serialize($a)); 38 | 39 | ob_start(); 40 | var_dump($exp); 41 | $dump_exp = ob_get_clean(); 42 | ob_start(); 43 | var_dump($act); 44 | $dump_act = ob_get_clean(); 45 | 46 | if ($dump_act !== $dump_exp) { 47 | echo "Var dump differs:\n", $dump_act, "\n", $dump_exp, "\n"; 48 | } else { 49 | echo "Var dump OK\n"; 50 | } 51 | 52 | $act['foo'][1] = 'test value'; 53 | $exp['foo'][1] = 'test value'; 54 | if ($act['foo'][1] !== $act['foo'][2]['foo'][1]) { 55 | echo "Recursive elements differ:\n"; 56 | var_dump($act); 57 | var_dump($act['foo']); 58 | var_dump($exp); 59 | var_dump($exp['foo']); 60 | } 61 | 62 | ?> 63 | --EXPECT-- 64 | array 65 | 140211016114021101621101631101641101651101662514020e0001010e05250102 66 | OK 67 | Var dump OK 68 | -------------------------------------------------------------------------------- /tests/igbinary_026b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Cyclic array test 2 3 | --INI-- 4 | report_memleaks=0 5 | --SKIPIF-- 6 | &$b); 19 | $b = array(1, 2, $a); 20 | 21 | /* all three statements below should produce same output however PHP stock 22 | * unserialize/serialize produces different output (5.2.16). I consider this is 23 | * a PHP bug. - Oleg Grenrus 24 | */ 25 | 26 | //$k = $a; 27 | //$k = unserialize(serialize($a)); 28 | $k = igbinary_unserialize(igbinary_serialize($a)); 29 | 30 | function check($a, $k) { 31 | ob_start(); 32 | var_dump($a); 33 | $a_str = ob_get_clean(); 34 | ob_start(); 35 | var_dump($k); 36 | $k_str = ob_get_clean(); 37 | 38 | if ($a_str !== $k_str) { 39 | echo "Output differs\n"; 40 | echo "Expected:\n", $a_str, "\n"; 41 | echo "Actual:\n", $k_str, "\n"; 42 | } else { 43 | echo "OK\n"; 44 | } 45 | } 46 | 47 | check($a, $k); 48 | 49 | $a["foo"][2]["foo"][1] = "b"; 50 | $k["foo"][2]["foo"][1] = "b"; 51 | 52 | check($a, $k); 53 | 54 | ?> 55 | --EXPECT-- 56 | OK 57 | OK 58 | -------------------------------------------------------------------------------- /tests/igbinary_027.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for serialization handler 3 | --SKIPIF-- 4 | 88 | --EXPECT-- 89 | bool(true) 90 | read 91 | wrote: 14021103666f6f06011104746573741106666f6f626172 92 | -------------------------------------------------------------------------------- /tests/igbinary_028.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Serialize object into session, full set 3 | --SKIPIF-- 4 | d1 = $foo; 34 | $this->d2 = $foo; 35 | $this->d3 = $foo; 36 | } 37 | } 38 | 39 | class Bar { 40 | private static $s1 = array(); 41 | protected static $s2 = array(); 42 | public static $s3 = array(); 43 | 44 | public $d1; 45 | private $d2; 46 | protected $d3; 47 | 48 | public function __construct() { 49 | } 50 | 51 | public function set($foo) { 52 | $this->d1 = $foo; 53 | $this->d2 = $foo; 54 | $this->d3 = $foo; 55 | } 56 | } 57 | 58 | if(!extension_loaded('igbinary')) { 59 | dl('igbinary.' . PHP_SHLIB_SUFFIX); 60 | } 61 | 62 | $output = ''; 63 | 64 | function open($path, $name) { 65 | return true; 66 | } 67 | 68 | function close() { 69 | return true; 70 | } 71 | 72 | function read($id) { 73 | global $output; 74 | $output .= "read\n"; 75 | $a = new Bar(); 76 | $b = new Foo($a); 77 | $a->set($b); 78 | $session = array('old' => $b); 79 | return igbinary_serialize($session); 80 | } 81 | 82 | function write($id, $data) { 83 | global $output; 84 | $output .= "write: "; 85 | $output .= substr(bin2hex($data), 8). "\n"; 86 | return true; 87 | } 88 | 89 | function destroy($id) { 90 | return true; 91 | } 92 | 93 | function gc($time) { 94 | return true; 95 | } 96 | 97 | ini_set('session.serialize_handler', 'igbinary'); 98 | 99 | session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc'); 100 | 101 | session_start(); 102 | 103 | $_SESSION['test'] = "foobar"; 104 | $a = new Bar(); 105 | $b = new Foo($a); 106 | $a->set($b); 107 | $_SESSION['new'] = $a; 108 | 109 | session_write_close(); 110 | 111 | echo $output; 112 | 113 | /* 114 | * you can add regression tests for your extension here 115 | * 116 | * the output of your test code has to be equal to the 117 | * text in the --EXPECT-- section below for the tests 118 | * to pass, differences between the output and the 119 | * expected text are interpreted as failure 120 | * 121 | * see php5/README.TESTING for further information on 122 | * writing regression tests 123 | */ 124 | ?> 125 | --EXPECT-- 126 | read 127 | write: 140311036f6c641703466f6f1403110700466f6f0064311703426172140311026431220111070042617200643222011105002a00643322011105002a00643222021102643322021104746573741106666f6f62617211036e65771a0314030e041a0114030e0222030e0722030e0822030e0522040e062204 128 | -------------------------------------------------------------------------------- /tests/igbinary_029.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Igbinary module info 3 | --SKIPIF-- 4 | 7 | --FILE-- 8 | enabled 21 | igbinary version => %s 22 | igbinary AP%s serializer ABI => %s 23 | igbinary session support => %s 24 | igbinary.compact_strings => %s => %s 25 | -------------------------------------------------------------------------------- /tests/igbinary_030.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Unserialize invalid data 3 | --SKIPIF-- 4 | 10, "foo"), 15 | true, 16 | false, 17 | 0.187182, 18 | "dakjdh98389\000", 19 | null, 20 | (object)array(1,2,3,4,5,6,7,8,9,"asdfkjlas dlfjl asjdlkfklashlkdflhkahsd"), 21 | ); 22 | 23 | error_reporting(0); 24 | foreach ($datas as $data) { 25 | $str = igbinary_serialize($data); 26 | $len = strlen($str); 27 | 28 | // truncated 29 | for ($i = 0; $i < $len - 1; $i++) { 30 | $v = igbinary_unserialize(substr($str, 0, $i)); 31 | if (is_object($data) && $v !== null && $v == $data) { 32 | continue; 33 | } elseif ($v !== null && $v != FALSE && $v !== $data) { 34 | echo "output at $i:\n"; 35 | var_dump($v); 36 | echo "vs.\n"; 37 | var_dump($data); 38 | } 39 | } 40 | 41 | // padded 42 | $str .= "98398afa\000y21_ "; 43 | $v = igbinary_unserialize($str); 44 | if ($v !== $data && !(is_object($data) && $v == $data)) { 45 | echo "padded should get original\n"; 46 | var_dump($v); 47 | echo "vs.\n"; 48 | var_dump($data); 49 | } 50 | } 51 | 52 | --EXPECT-- 53 | -------------------------------------------------------------------------------- /tests/igbinary_031.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object Serializable interface throws exceptions 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 23 | $this->b = $b; 24 | } 25 | 26 | public function serialize() { 27 | $c = self::$count++; 28 | echo "call serialize, ", ($this->a ? "throw" : "no throw"),"\n"; 29 | if ($this->a) { 30 | throw new Exception("exception in serialize $c"); 31 | } 32 | return pack('NN', $this->a, $this->b); 33 | } 34 | 35 | public function unserialize($serialized) { 36 | $tmp = unpack('N*', $serialized); 37 | $this->__construct($tmp[1], $tmp[2]); 38 | $c = self::$count++; 39 | echo "call unserialize, ", ($this->b ? "throw" : "no throw"),"\n"; 40 | if ($this->b) { 41 | throw new Exception("exception in unserialize $c"); 42 | } 43 | } 44 | } 45 | 46 | $a = new Obj(1, 0); 47 | $a = new Obj(0, 0); 48 | $b = new Obj(0, 0); 49 | $c = new Obj(1, 0); 50 | $d = new Obj(0, 1); 51 | 52 | echo "a, a, c\n"; 53 | try { 54 | test(array($a, $a, $c)); 55 | } catch (Exception $e) { 56 | if (version_compare(phpversion(), "5.3.0", ">=")) { 57 | if ($e->getPrevious()) { 58 | $e = $e->getPrevious(); 59 | } 60 | } 61 | 62 | echo $e->getMessage(), "\n"; 63 | } 64 | 65 | echo "b, b, d\n"; 66 | 67 | try { 68 | test(array($b, $b, $d)); 69 | } catch (Exception $e) { 70 | if (version_compare(phpversion(), "5.3.0", ">=")) { 71 | if ($e->getPrevious()) { 72 | $e = $e->getPrevious(); 73 | } 74 | } 75 | 76 | echo $e->getMessage(), "\n"; 77 | } 78 | 79 | --EXPECT-- 80 | a, a, c 81 | call serialize, no throw 82 | call serialize, throw 83 | exception in serialize 2 84 | b, b, d 85 | call serialize, no throw 86 | call serialize, no throw 87 | call unserialize, no throw 88 | call unserialize, throw 89 | exception in unserialize 6 90 | -------------------------------------------------------------------------------- /tests/igbinary_032.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __sleep and __wakeup exceptions 3 | --SKIPIF-- 4 | a = $a; 23 | $this->b = $b; 24 | } 25 | 26 | function __sleep() { 27 | $c = self::$count++; 28 | if ($this->a) { 29 | throw new Exception("exception in __sleep $c"); 30 | } 31 | return array('a', 'b'); 32 | } 33 | 34 | function __wakeup() { 35 | $c = self::$count++; 36 | if ($this->b) { 37 | throw new Exception("exception in __wakeup $c"); 38 | } 39 | $this->b = $this->a * 3; 40 | } 41 | } 42 | 43 | 44 | $a = new Obj(1, 0); 45 | $b = new Obj(0, 1); 46 | $c = new Obj(0, 0); 47 | 48 | try { 49 | test($a); 50 | } catch (Exception $e) { 51 | echo $e->getMessage(), "\n"; 52 | } 53 | 54 | try { 55 | test($b); 56 | } catch (Exception $e) { 57 | echo $e->getMessage(), "\n"; 58 | } 59 | 60 | try { 61 | test($c); 62 | } catch (Exception $e) { 63 | echo $e->getMessage(), "\n"; 64 | } 65 | 66 | /* 67 | * you can add regression tests for your extension here 68 | * 69 | * the output of your test code has to be equal to the 70 | * text in the --EXPECT-- section below for the tests 71 | * to pass, differences between the output and the 72 | * expected text are interpreted as failure 73 | * 74 | * see php5/README.TESTING for further information on 75 | * writing regression tests 76 | */ 77 | ?> 78 | --EXPECT-- 79 | exception in __sleep 0 80 | exception in __wakeup 2 81 | -------------------------------------------------------------------------------- /tests/igbinary_033.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, cyclic references 3 | --SKIPIF-- 4 | parent = null; 17 | $this->children = array(); 18 | } 19 | 20 | public function addChild(Foo $obj) { 21 | $this->children[] = $obj; 22 | $obj->setParent($this); 23 | } 24 | 25 | public function setParent(Foo $obj) { 26 | $this->parent = $obj; 27 | } 28 | } 29 | 30 | $obj1 = new Foo(); 31 | 32 | for ($i = 0; $i < 10; $i++) { 33 | $obj = new Foo(); 34 | $obj1->addChild($obj); 35 | } 36 | 37 | $o = igbinary_unserialize(igbinary_serialize($obj1->children)); 38 | 39 | foreach ($obj1->children as $k => $v) { 40 | $obj_v = $v; 41 | $o_v = $o[$k]; 42 | 43 | echo gettype($obj_v), "\t", gettype($o_v), "\n"; 44 | } 45 | --EXPECT-- 46 | object object 47 | object object 48 | object object 49 | object object 50 | object object 51 | object object 52 | object object 53 | object object 54 | object object 55 | object object 56 | -------------------------------------------------------------------------------- /tests/igbinary_034.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Unserialize invalid random data 3 | --SKIPIF-- 4 | 10, "foo"), 15 | true, 16 | false, 17 | 0.187182, 18 | "dakjdh98389\000", 19 | null, 20 | (object)array(1,2,3), 21 | ); 22 | 23 | error_reporting(0); 24 | foreach ($datas as $data) { 25 | $str = igbinary_serialize($data); 26 | $len = strlen($str); 27 | 28 | for ($j = 0; $j < 200; $j++) { 29 | for ($i = 0; $i < $len - 1; $i++) { 30 | $sub = substr($str, 0, $i); 31 | $sub .= mcrypt_create_iv(30, MCRYPT_DEV_URANDOM); 32 | $php_errormsg = null; 33 | $v = igbinary_unserialize($sub); 34 | } 35 | } 36 | } 37 | 38 | --EXPECT-- 39 | -------------------------------------------------------------------------------- /tests/igbinary_040.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | b0rked random data test 3 | --SKIPIF-- 4 | --FILE-- 5 | 43 | --EXPECT-- 44 | -------------------------------------------------------------------------------- /tests/igbinary_041.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for double NaN, Inf, -Inf, 0, and -0. IEEE 754 doubles 3 | --FILE-- 4 | 9 | --INI-- 10 | igbinary.compact_strings=Off 11 | --FILE-- 12 | $object) { 31 | if (!isset($actual_array[$key])) { 32 | $error = 'ERROR'; 33 | echo "Key $key is missing from result.\n"; 34 | echo "Expected key/value:\n"; 35 | var_dump($key, $object); 36 | var_dump($object); 37 | 38 | break; 39 | } 40 | 41 | if (!is_object($actual_array[$key]) || 42 | get_class($object) !== get_class($actual_array[$key])) { 43 | $error = 'ERROR'; 44 | echo "Array mismatch on $key\n"; 45 | echo "Expected key/value:\n"; 46 | var_dump($key, $object); 47 | echo "Actual key/value:\n"; 48 | var_dump($key, $actual_array[$key]); 49 | 50 | break; 51 | } 52 | 53 | } 54 | 55 | echo $error, "\n"; 56 | 57 | --EXPECT-- 58 | OK 59 | -------------------------------------------------------------------------------- /tests/igbinary_044.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for double extremes 3 | --FILE-- 4 | getVersion(), '3.1.7', '<')) { 11 | echo "skip require APC version 3.1.7 or above"; 12 | } 13 | 14 | --INI-- 15 | apc.enable_cli=1 16 | apc.serializer=igbinary 17 | --FILE-- 18 | 34 | int(10) 35 | } 36 | -------------------------------------------------------------------------------- /tests/igbinary_045b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | APCu serializer registration 3 | --SKIPIF-- 4 | getVersion(), '4.0.2', '<')) { 11 | echo "skip require APCu version 4.0.2 or above"; 12 | } 13 | 14 | --INI-- 15 | apc.enable_cli=1 16 | apc.serializer=igbinary 17 | --FILE-- 18 | 34 | int(10) 35 | } 36 | -------------------------------------------------------------------------------- /tests/igbinary_046.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize scalar refs. 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | 21 | &string(1) "V" 22 | [1]=> 23 | &string(1) "V" 24 | [2]=> 25 | &string(1) "V" 26 | [3]=> 27 | &string(1) "V" 28 | } 29 | -------------------------------------------------------------------------------- /tests/igbinary_046b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize multiple object refs. 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | 26 | &string(1) "V" 27 | [1]=> 28 | &string(1) "V" 29 | [2]=> 30 | &string(1) "V" 31 | [3]=> 32 | &string(1) "V" 33 | } 34 | -------------------------------------------------------------------------------- /tests/igbinary_046c.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize multiple array refs. 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | 26 | &string(1) "V" 27 | [1]=> 28 | &string(1) "V" 29 | [2]=> 30 | &string(1) "V" 31 | [3]=> 32 | &string(1) "V" 33 | } 34 | -------------------------------------------------------------------------------- /tests/igbinary_046d.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize multiple object refs and non-refs. 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | 27 | object(stdClass)#%d (0) { 28 | } 29 | [1]=> 30 | &object(stdClass)#%d (0) { 31 | } 32 | [2]=> 33 | &object(stdClass)#%d (0) { 34 | } 35 | [3]=> 36 | object(stdClass)#%d (0) { 37 | } 38 | } 39 | a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;r:2;} 40 | 00000002140406001708737464436c61737314000601252201060225220106032201 41 | a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;r:2;} 42 | array(4) { 43 | [0]=> 44 | object(stdClass)#%d (0) { 45 | } 46 | [1]=> 47 | &object(stdClass)#%d (0) { 48 | } 49 | [2]=> 50 | &object(stdClass)#%d (0) { 51 | } 52 | [3]=> 53 | object(stdClass)#%d (0) { 54 | } 55 | } 56 | array(4) { 57 | [0]=> 58 | object(stdClass)#%d (0) { 59 | } 60 | [1]=> 61 | &string(1) "V" 62 | [2]=> 63 | &string(1) "V" 64 | [3]=> 65 | object(stdClass)#%d (0) { 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /tests/igbinary_047.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for serialization handler, SessionHandlerInterface 3 | --SKIPIF-- 4 | = 5.4.0) 6 | if (version_compare(phpversion(), "5.4.0", "<")) { 7 | exit("skip php version less than 5.4.x"); 8 | } 9 | 10 | if (!extension_loaded('session')) { 11 | exit('skip session extension not loaded'); 12 | } 13 | 14 | ob_start(); 15 | phpinfo(INFO_MODULES); 16 | $str = ob_get_clean(); 17 | 18 | $array = explode("\n", $str); 19 | $array = preg_grep('/^igbinary session support.*yes/', $array); 20 | if (!$array) { 21 | exit('skip igbinary session handler not available'); 22 | } 23 | 24 | 25 | --FILE-- 26 | 96 | --EXPECT-- 97 | bool(true) 98 | read 99 | wrote: 14021103666f6f06011104746573741106666f6f626172 100 | -------------------------------------------------------------------------------- /tests/igbinary_048.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __set not called for private attr in extended class 3 | --SKIPIF-- 4 | a = [1, 2, 3]; 27 | $x->nonexistent = 'aaa'; 28 | 29 | igbinary_unserialize(igbinary_serialize($x)); 30 | --EXPECT-- 31 | magic function called for nonexistent with 'aaa' 32 | -------------------------------------------------------------------------------- /tests/igbinary_048b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __set not called for private attr in extended class 3 | --FILE-- 4 | a = [1, 2, 3]; 22 | $x->nonexistent = 'aaa'; 23 | 24 | unserialize(serialize($x)); 25 | --EXPECT-- 26 | magic function called for nonexistent with 'aaa' 27 | -------------------------------------------------------------------------------- /tests/igbinary_049.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize multiple references in arrays 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | prop = &$a[8]; 21 | $a[11] = &$a[10]; 22 | $a[12] = $a[9]; 23 | $ig_ser = igbinary_serialize($a); 24 | printf("ig_ser=%s\n", bin2hex($ig_ser)); 25 | $ig = igbinary_unserialize($ig_ser); 26 | var_dump($ig); 27 | $f = &$ig[3]; 28 | $f = 'V'; 29 | $g = &$ig[5]; 30 | $g = 'H'; 31 | $h = $ig[10]; 32 | $h->prop = 'S'; 33 | var_dump($ig); 34 | --EXPECTF-- 35 | ig_ser=00000002140d0600251101410601250101060225010106032501010604250406052501020606251703466f6f1400060725220306082522030609140106000621060a251708737464436c6173731401110470726f70252203060b252205060c0104 36 | array(13) { 37 | [0]=> 38 | &string(1) "A" 39 | [1]=> 40 | &string(1) "A" 41 | [2]=> 42 | &string(1) "A" 43 | [3]=> 44 | &string(1) "A" 45 | [4]=> 46 | &bool(false) 47 | [5]=> 48 | &bool(false) 49 | [6]=> 50 | &object(Foo)#%d (0) { 51 | } 52 | [7]=> 53 | &object(Foo)#%d (0) { 54 | } 55 | [8]=> 56 | &object(Foo)#%d (0) { 57 | } 58 | [9]=> 59 | array(1) { 60 | [0]=> 61 | int(33) 62 | } 63 | [10]=> 64 | &object(stdClass)#%d (1) { 65 | ["prop"]=> 66 | &object(Foo)#%d (0) { 67 | } 68 | } 69 | [11]=> 70 | &object(stdClass)#%d (1) { 71 | ["prop"]=> 72 | &object(Foo)#%d (0) { 73 | } 74 | } 75 | [12]=> 76 | array(1) { 77 | [0]=> 78 | int(33) 79 | } 80 | } 81 | array(13) { 82 | [0]=> 83 | &string(1) "V" 84 | [1]=> 85 | &string(1) "V" 86 | [2]=> 87 | &string(1) "V" 88 | [3]=> 89 | &string(1) "V" 90 | [4]=> 91 | &string(1) "H" 92 | [5]=> 93 | &string(1) "H" 94 | [6]=> 95 | &string(1) "S" 96 | [7]=> 97 | &string(1) "S" 98 | [8]=> 99 | &string(1) "S" 100 | [9]=> 101 | array(1) { 102 | [0]=> 103 | int(33) 104 | } 105 | [10]=> 106 | &object(stdClass)#%d (1) { 107 | ["prop"]=> 108 | &string(1) "S" 109 | } 110 | [11]=> 111 | &object(stdClass)#%d (1) { 112 | ["prop"]=> 113 | &string(1) "S" 114 | } 115 | [12]=> 116 | array(1) { 117 | [0]=> 118 | int(33) 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/igbinary_049b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize multiple references in objects 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | x0 = NULL; 11 | $a->x1 = &$a->x0; 12 | $a->x2 = &$a->x1; 13 | $a->x3 = &$a->x2; 14 | $a->x4 = false; 15 | $a->x5 = &$a->x4; 16 | $a->x6 = new Foo(); 17 | $a->x7 = &$a->x6; 18 | $a->x8 = &$a->x7; 19 | $a->x9 = [33]; 20 | $a->x10 = new stdClass(); 21 | $a->x10->prop = &$a->x8; 22 | $a->x11 = &$a->x10; 23 | $a->x12 = $a->x9; 24 | $ig_ser = igbinary_serialize($a); 25 | printf("ig_ser=%s\n", bin2hex($ig_ser)); 26 | $ig = igbinary_unserialize($ig_ser); 27 | $f = &$ig->x3; 28 | $f = 'V'; 29 | $g = &$ig->x5; 30 | $g = 'H'; 31 | $h = $ig->x10; 32 | $h->prop = 'S'; 33 | var_dump($ig); 34 | --EXPECTF-- 35 | ig_ser=000000021708737464436c617373140d1102783025001102783125010111027832250101110278332501011102783425041102783525010211027836251703466f6f14001102783725220311027838252203110278391401060006211103783130251a001401110470726f70252203110378313125220511037831320104 36 | object(stdClass)#%d (13) { 37 | ["x0"]=> 38 | &string(1) "V" 39 | ["x1"]=> 40 | &string(1) "V" 41 | ["x2"]=> 42 | &string(1) "V" 43 | ["x3"]=> 44 | &string(1) "V" 45 | ["x4"]=> 46 | &string(1) "H" 47 | ["x5"]=> 48 | &string(1) "H" 49 | ["x6"]=> 50 | &string(1) "S" 51 | ["x7"]=> 52 | &string(1) "S" 53 | ["x8"]=> 54 | &string(1) "S" 55 | ["x9"]=> 56 | array(1) { 57 | [0]=> 58 | int(33) 59 | } 60 | ["x10"]=> 61 | &object(stdClass)#%d (1) { 62 | ["prop"]=> 63 | &string(1) "S" 64 | } 65 | ["x11"]=> 66 | &object(stdClass)#%d (1) { 67 | ["prop"]=> 68 | &string(1) "S" 69 | } 70 | ["x12"]=> 71 | array(1) { 72 | [0]=> 73 | int(33) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/igbinary_050.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Correctly unserialize cyclic object references 3 | --SKIPIF-- 4 | --INI-- 5 | igbinary.compact_strings = On 6 | --FILE-- 7 | foo = &$a; 10 | $a->bar = &$a; 11 | $b = new stdClass(); 12 | $b->cyclic = &$a; 13 | printf("%s\n", serialize($b)); 14 | $ig_ser = igbinary_serialize($b); 15 | printf("%s\n", bin2hex($ig_ser)); 16 | $ig = igbinary_unserialize($ig_ser); 17 | printf("%s\n", serialize($ig)); 18 | var_dump($ig); 19 | $f = &$ig->cyclic->foo; 20 | $f = 'V'; 21 | var_dump($ig); 22 | // Note: While the php7 unserializer consistently makes a distinction between refs to an object and non-refs, 23 | // the php5 serializer does not yet. 24 | --EXPECTF-- 25 | O:8:"stdClass":1:{s:6:"cyclic";O:8:"stdClass":2:{s:3:"foo";R:2;s:3:"bar";R:2;}} 26 | 000000021708737464436c617373140111066379636c6963251a0014021103666f6f2522011103626172252201 27 | O:8:"stdClass":1:{s:6:"cyclic";O:8:"stdClass":2:{s:3:"foo";R:2;s:3:"bar";R:2;}} 28 | object(stdClass)#3 (1) { 29 | ["cyclic"]=> 30 | &object(stdClass)#4 (2) { 31 | ["foo"]=> 32 | *RECURSION* 33 | ["bar"]=> 34 | *RECURSION* 35 | } 36 | } 37 | object(stdClass)#3 (1) { 38 | ["cyclic"]=> 39 | &string(1) "V" 40 | } 41 | -------------------------------------------------------------------------------- /tests/igbinary_051.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object test, __wakeup (With multiple references) 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 16 | $this->b = $b; 17 | } 18 | 19 | function __wakeup() { 20 | $this->b = $this->a * 3; 21 | } 22 | } 23 | 24 | function main() { 25 | $o = new Obj(1, 2); 26 | $variable = [&$o, &$o]; 27 | $serialized = igbinary_serialize($variable); 28 | $unserialized = igbinary_unserialize($serialized); 29 | 30 | echo substr(bin2hex($serialized), 8), "\n"; 31 | echo $unserialized[0]->b === 3 && $unserialized[0]->a === 1 ? 'OK' : 'ERROR'; 32 | echo "\n"; 33 | $unserialized[0] = 'a'; 34 | var_dump($unserialized); 35 | } 36 | 37 | main(); 38 | --EXPECT-- 39 | 140206002517034f626a1402110161060111016206020601252201 40 | OK 41 | array(2) { 42 | [0]=> 43 | &string(1) "a" 44 | [1]=> 45 | &string(1) "a" 46 | } 47 | -------------------------------------------------------------------------------- /tests/igbinary_052.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Object Serializable interface can be serialized in references 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 23 | $this->b = $b; 24 | } 25 | 26 | public function serialize() { 27 | $c = self::$count++; 28 | echo "call serialize\n"; 29 | return pack('NN', $this->a, $this->b); 30 | } 31 | 32 | public function unserialize($serialized) { 33 | $tmp = unpack('N*', $serialized); 34 | $this->__construct($tmp[1], $tmp[2]); 35 | $c = self::$count++; 36 | echo "call unserialize\n"; 37 | } 38 | } 39 | 40 | function main() { 41 | $a = new Obj(1, 0); 42 | $b = new Obj(42, 43); 43 | $variable = [&$a, &$a, $b]; 44 | $serialized = igbinary_serialize($variable); 45 | printf("%s\n", bin2hex($serialized)); 46 | $unserialized = igbinary_unserialize($serialized); 47 | var_dump($unserialized); 48 | $unserialized[0] = 'A'; 49 | var_dump($unserialized[1]); 50 | } 51 | main(); 52 | --EXPECTF-- 53 | call serialize 54 | call serialize 55 | 00000002140306002517034f626a1d080000000100000000060125220106021a001d080000002a0000002b 56 | call unserialize 57 | call unserialize 58 | array(3) { 59 | [0]=> 60 | &object(Obj)#%d (2) { 61 | ["a"]=> 62 | int(1) 63 | ["b"]=> 64 | int(0) 65 | } 66 | [1]=> 67 | &object(Obj)#%d (2) { 68 | ["a"]=> 69 | int(1) 70 | ["b"]=> 71 | int(0) 72 | } 73 | [2]=> 74 | object(Obj)#%d (2) { 75 | ["a"]=> 76 | int(42) 77 | ["b"]=> 78 | int(43) 79 | } 80 | } 81 | string(1) "A" 82 | -------------------------------------------------------------------------------- /tests/igbinary_053.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | __wakeup can modify properties without affecting other objects 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 14 | } 15 | 16 | public function __wakeup() { 17 | echo "call wakeup\n"; 18 | $this->a[] = "end"; 19 | } 20 | } 21 | 22 | function main() { 23 | $array = ["test"]; // array (not a reference, but should be copied on write) 24 | $a = new Obj($array); 25 | $b = new Obj($array); 26 | $variable = [$a, $b]; 27 | $serialized = igbinary_serialize($variable); 28 | printf("%s\n", bin2hex($serialized)); 29 | $unserialized = igbinary_unserialize($serialized); 30 | var_dump($unserialized); 31 | } 32 | main(); 33 | --EXPECTF-- 34 | 000000021402060017034f626a14011101611401060011047465737406011a0014010e010102 35 | call wakeup 36 | call wakeup 37 | array(2) { 38 | [0]=> 39 | object(Obj)#%d (1) { 40 | ["a"]=> 41 | array(2) { 42 | [0]=> 43 | string(4) "test" 44 | [1]=> 45 | string(3) "end" 46 | } 47 | } 48 | [1]=> 49 | object(Obj)#%d (1) { 50 | ["a"]=> 51 | array(2) { 52 | [0]=> 53 | string(4) "test" 54 | [1]=> 55 | string(3) "end" 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/igbinary_054.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | __wakeup can add dynamic properties without affecting other objects 3 | --SKIPIF-- 4 | --FILE-- 5 | a being a dynamic property. 9 | 10 | function __construct($a) { 11 | $this->a = $a; 12 | } 13 | 14 | public function __wakeup() { 15 | echo "Calling __wakeup\n"; 16 | for ($i = 0; $i < 10000; $i++) { 17 | $this->{'b' . $i} = 42; 18 | } 19 | } 20 | } 21 | 22 | function main() { 23 | $array = ["roh"]; // array (not a reference, but should be copied on write) 24 | $a = new Obj($array); 25 | $b = new Obj($array); 26 | $c = new Obj(null); 27 | $variable = [$a, $b, $c]; 28 | $serialized = igbinary_serialize($variable); 29 | printf("%s\n", bin2hex($serialized)); 30 | $unserialized = igbinary_unserialize($serialized); 31 | echo "Called igbinary_unserialize\n"; 32 | for ($a = 0; $a < 3; $a++) { 33 | for ($i = 0; $i < 10000; $i++) { 34 | if ($unserialized[$a]->{'b' . $i} !== 42) { 35 | echo "Fail $a b$i\n"; 36 | return; 37 | } 38 | unset($unserialized[$a]->{'b' . $i}); 39 | } 40 | } 41 | var_dump($unserialized); 42 | } 43 | main(); 44 | --EXPECTF-- 45 | 000000021403060017034f626a1401110161140106001103726f6806011a0014010e01010206021a0014010e0100 46 | Calling __wakeup 47 | Calling __wakeup 48 | Calling __wakeup 49 | Called igbinary_unserialize 50 | array(3) { 51 | [0]=> 52 | object(Obj)#%d (1) { 53 | ["a"]=> 54 | array(1) { 55 | [0]=> 56 | string(3) "roh" 57 | } 58 | } 59 | [1]=> 60 | object(Obj)#%d (1) { 61 | ["a"]=> 62 | array(1) { 63 | [0]=> 64 | string(3) "roh" 65 | } 66 | } 67 | [2]=> 68 | object(Obj)#%d (1) { 69 | ["a"]=> 70 | NULL 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /tests/igbinary_055.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | __wakeup can replace a copy of the object referring to the root node. 3 | --SKIPIF-- 4 | --FILE-- 5 | a = $a; 10 | } 11 | 12 | public function __wakeup() { 13 | echo "Calling __wakeup\n"; 14 | $this->a = "replaced"; 15 | } 16 | } 17 | 18 | $a = new stdClass(); 19 | $a->obj = new Obj($a);; 20 | $serialized = igbinary_serialize($a); 21 | printf("%s\n", bin2hex($serialized)); 22 | $unserialized = igbinary_unserialize($serialized); 23 | var_dump($unserialized); 24 | --EXPECTF-- 25 | 000000021708737464436c617373140111036f626a17034f626a14011101612200 26 | Calling __wakeup 27 | object(stdClass)#%d (1) { 28 | ["obj"]=> 29 | object(Obj)#%d (1) { 30 | ["a"]=> 31 | string(8) "replaced" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/igbinary_bug54662.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Nested objects cause segfault, php bug #54662 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | append(new Storage); 22 | 23 | $ser = igbinary_serialize($collection); 24 | $new_collection = igbinary_unserialize($ser); 25 | 26 | var_dump($new_collection[0]->storage); 27 | --EXPECT-- 28 | string(8) "a string" 29 | -------------------------------------------------------------------------------- /tests/igbinary_bug72134.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | igbinary_unserialize causes segfault on 3rd call for objects with dynamic property 3 | --FILE-- 4 | i = 1; 11 | $igb = igbinary_serialize($value); 12 | for ($i=0; $i < 30; $i++) 13 | { 14 | // This used to segfault at the third attempt 15 | echo igbinary_unserialize($igb)->bar . PHP_EOL; 16 | } 17 | --EXPECT-- 18 | test 19 | test 20 | test 21 | test 22 | test 23 | test 24 | test 25 | test 26 | test 27 | test 28 | test 29 | test 30 | test 31 | test 32 | test 33 | test 34 | test 35 | test 36 | test 37 | test 38 | test 39 | test 40 | test 41 | test 42 | test 43 | test 44 | test 45 | test 46 | test 47 | test 48 | -------------------------------------------------------------------------------- /tests/igbinary_unserialize_v1_compatible.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Unserialize backwards compatible with v1. 3 | --SKIPIF-- 4 | --FILE-- 5 | 'b:1;', 9 | 'type' => 'boolean', 10 | 'description' => 'bool true', 11 | 'data' => 'AAAAAQU=', 12 | 'version' => 1, 13 | ), 14 | array( 15 | 'var' => 'b:0;', 16 | 'type' => 'boolean', 17 | 'description' => 'bool false', 18 | 'data' => 'AAAAAQQ=', 19 | 'version' => 1, 20 | ), 21 | array( 22 | 'var' => 'd:1.2881887378882661554513333612703718245029449462890625;', 23 | 'type' => 'double', 24 | 'description' => 'double', 25 | 'data' => 'AAAAAQw/9Jxry0Tj0Q==', 26 | 'version' => 1, 27 | ), 28 | array( 29 | 'var' => 'i:29913;', 30 | 'type' => 'integer', 31 | 'description' => 'int', 32 | 'data' => 'AAAAAQh02Q==', 33 | 'version' => 1, 34 | ), 35 | array( 36 | 'var' => 'N;', 37 | 'type' => 'NULL', 38 | 'description' => 'null', 39 | 'data' => 'AAAAAQA=', 40 | 'version' => 1, 41 | ), 42 | array( 43 | 'var' => 's:0:"";', 44 | 'type' => 'string', 45 | 'description' => 'string', 46 | 'data' => 'AAAAAQ0=', 47 | 'version' => 1, 48 | ), 49 | array( 50 | 'var' => 's:13:"asdf' . "\0" . 'asdfasdf";', 51 | 'type' => 'string', 52 | 'description' => 'string', 53 | 'data' => 'AAAAARENYXNkZgBhc2RmYXNkZg==', 54 | 'version' => 1, 55 | ), 56 | array( 57 | 'var' => 'a:4:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;}', 58 | 'type' => 'array', 59 | 'description' => 'array', 60 | 'data' => 'AAAAARQEBgAGAQYBBgIGAgYDBgMGBA==', 61 | 'version' => 1, 62 | ), 63 | array( 64 | 'var' => 'O:8:"stdClass":4:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;}', 65 | 'var_e' => (object)array(1, 2, 3, 4), 66 | 'type' => 'object', 67 | 'description' => 'object', 68 | 'data' => 'AAAAARcIc3RkQ2xhc3MUBAYABgEGAQYCBgIGAwYDBgQ=', 69 | 'version' => 1, 70 | ), 71 | array( 72 | 'var' => 'a:2:{i:0;a:3:{i:0;s:1:"a";i:1;s:1:"b";i:2;s:1:"c";}i:1;R:2;}', 73 | 'type' => 'array', 74 | 'description' => 'reference', 75 | 'data' => 'AAAAARQCBgAUAwYAEQFhBgERAWIGAhEBYwYBAQE=', 76 | 'version' => 1, 77 | ), 78 | ); 79 | 80 | $all_passed = true; 81 | foreach ($data as $item) { 82 | if (isset($item['var_e'])) { 83 | $var = $item['var_e']; 84 | } else { 85 | $var = unserialize($item['var']); 86 | } 87 | $unserialized = igbinary_unserialize(base64_decode($item['data'])); 88 | 89 | ob_start(); 90 | var_dump($var); 91 | $dump_expected = ob_get_clean(); 92 | 93 | ob_start(); 94 | var_dump($unserialized); 95 | $dump_actual = ob_get_clean(); 96 | 97 | // replace all object ids to 0 98 | $dump_expected = preg_replace('/#\d+/', '#0', $dump_expected); 99 | $dump_actual = preg_replace('/#\d+/', '#0', $dump_actual); 100 | 101 | if ($dump_expected !== $dump_actual) { 102 | if ($item['description'] == 'reference') { 103 | echo "reference deserialization works, but the result is not a reference.\n"; 104 | continue; 105 | } 106 | 107 | echo "Differing unserialized: {$item['description']}\n"; 108 | echo "Expected:\n", $dump_expected, "\n"; 109 | echo "Actual:\n", $dump_actual, "\n"; 110 | } 111 | } 112 | 113 | echo $all_passed ? 'OK' : 'ERROR', "\n"; 114 | 115 | --EXPECT-- 116 | reference deserialization works, but the result is not a reference. 117 | OK 118 | --------------------------------------------------------------------------------