From 78f542f6c0205a7771f273175518db02f461f8e5 Mon Sep 17 00:00:00 2001 From: advect Date: Sat, 17 Jul 2010 18:46:28 +0900 Subject: [PATCH 1/2] Update PHP Extension --- php/CREDITS | 2 +- php/ChangeLog | 40 ++ php/LICENSE | 26 ++ php/README | 11 + php/benchmark.php | 248 ++++++++++ php/config.m4 | 73 ++- php/config.w32 | 3 +- php/msgpack.c | 803 +++++++++----------------------- php/msgpack.php | 8 +- php/msgpack/pack_define.h | 26 -- php/msgpack/pack_template.h | 741 ------------------------------ php/msgpack/unpack_define.h | 129 ------ php/msgpack/unpack_template.h | 361 --------------- php/msgpack_class.c | 340 ++++++++++++++ php/msgpack_class.h | 7 + php/msgpack_pack.c | 514 +++++++++++++++++++++ php/msgpack_pack.h | 17 + php/msgpack_unpack.c | 829 ++++++++++++++++++++++++++++++++++ php/msgpack_unpack.h | 26 ++ php/package.xml | 98 ++++ php/php-msgpack.spec | 59 +++ php/php_msgpack.h | 85 +--- php/test_normal.php | 0 php/test_streaming.php | 9 +- php/tests/001.phpt | 10 + php/tests/002.phpt | 26 ++ php/tests/003.phpt | 31 ++ php/tests/004.phpt | 56 +++ php/tests/005.phpt | 26 ++ php/tests/006.phpt | 31 ++ php/tests/007.phpt | 72 +++ php/tests/008.phpt | 61 +++ php/tests/009.phpt | 115 +++++ php/tests/010.phpt | 49 ++ php/tests/012.phpt | 48 ++ php/tests/013.phpt | 54 +++ php/tests/014.phpt | 54 +++ php/tests/015.phpt | 58 +++ php/tests/015b.phpt | 58 +++ php/tests/016.phpt | 60 +++ php/tests/017.phpt | 48 ++ php/tests/018.phpt | 84 ++++ php/tests/019.phpt | 43 ++ php/tests/020.phpt | 31 ++ php/tests/021.phpt | 52 +++ php/tests/022.phpt | 45 ++ php/tests/023.phpt | 54 +++ php/tests/024.phpt | 166 +++++++ php/tests/025.phpt | 119 +++++ php/tests/026.phpt | 143 ++++++ php/tests/027.phpt | 73 +++ php/tests/028.phpt | 667 +++++++++++++++++++++++++++ php/tests/029.phpt | 20 + php/tests/030.phpt | 233 ++++++++++ php/tests/031.phpt | 90 ++++ php/tests/032.phpt | 76 ++++ php/tests/033.phpt | 55 +++ php/tests/034.phpt | 38 ++ php/tests/035.phpt | 34 ++ php/tests/040.phpt | 43 ++ php/tests/041.phpt | 47 ++ php/tests/042.phpt | 40 ++ php/tests/050.phpt | 111 +++++ php/tests/060.phpt | 315 +++++++++++++ php/tests/061.phpt | 320 +++++++++++++ php/tests/062.phpt | 64 +++ php/tests/063.phpt | 68 +++ php/tests/070.phpt | 299 ++++++++++++ php/tests/071.phpt | 301 ++++++++++++ php/tests/072.phpt | 341 ++++++++++++++ php/tests/test_pack.phpt | 169 ------- 71 files changed, 7345 insertions(+), 2108 deletions(-) create mode 100644 php/ChangeLog create mode 100644 php/LICENSE create mode 100644 php/benchmark.php delete mode 100644 php/msgpack/pack_define.h delete mode 100644 php/msgpack/pack_template.h delete mode 100644 php/msgpack/unpack_define.h delete mode 100644 php/msgpack/unpack_template.h create mode 100644 php/msgpack_class.c create mode 100644 php/msgpack_class.h create mode 100644 php/msgpack_pack.c create mode 100644 php/msgpack_pack.h create mode 100644 php/msgpack_unpack.c create mode 100644 php/msgpack_unpack.h create mode 100644 php/package.xml create mode 100644 php/php-msgpack.spec mode change 100755 => 100644 php/test_normal.php mode change 100755 => 100644 php/test_streaming.php create mode 100644 php/tests/001.phpt create mode 100644 php/tests/002.phpt create mode 100644 php/tests/003.phpt create mode 100644 php/tests/004.phpt create mode 100644 php/tests/005.phpt create mode 100644 php/tests/006.phpt create mode 100644 php/tests/007.phpt create mode 100644 php/tests/008.phpt create mode 100644 php/tests/009.phpt create mode 100644 php/tests/010.phpt create mode 100644 php/tests/012.phpt create mode 100644 php/tests/013.phpt create mode 100644 php/tests/014.phpt create mode 100644 php/tests/015.phpt create mode 100644 php/tests/015b.phpt create mode 100644 php/tests/016.phpt create mode 100644 php/tests/017.phpt create mode 100644 php/tests/018.phpt create mode 100644 php/tests/019.phpt create mode 100644 php/tests/020.phpt create mode 100644 php/tests/021.phpt create mode 100644 php/tests/022.phpt create mode 100644 php/tests/023.phpt create mode 100644 php/tests/024.phpt create mode 100644 php/tests/025.phpt create mode 100644 php/tests/026.phpt create mode 100644 php/tests/027.phpt create mode 100644 php/tests/028.phpt create mode 100644 php/tests/029.phpt create mode 100644 php/tests/030.phpt create mode 100644 php/tests/031.phpt create mode 100644 php/tests/032.phpt create mode 100644 php/tests/033.phpt create mode 100644 php/tests/034.phpt create mode 100644 php/tests/035.phpt create mode 100644 php/tests/040.phpt create mode 100644 php/tests/041.phpt create mode 100644 php/tests/042.phpt create mode 100644 php/tests/050.phpt create mode 100644 php/tests/060.phpt create mode 100644 php/tests/061.phpt create mode 100644 php/tests/062.phpt create mode 100644 php/tests/063.phpt create mode 100644 php/tests/070.phpt create mode 100644 php/tests/071.phpt create mode 100644 php/tests/072.phpt delete mode 100644 php/tests/test_pack.phpt diff --git a/php/CREDITS b/php/CREDITS index 3aae276b..b3ae8a01 100644 --- a/php/CREDITS +++ b/php/CREDITS @@ -1 +1 @@ -msgpack +msgpack \ No newline at end of file diff --git a/php/ChangeLog b/php/ChangeLog new file mode 100644 index 00000000..5481c1fc --- /dev/null +++ b/php/ChangeLog @@ -0,0 +1,40 @@ +msgpack extension changelog + +Version 0.2.1 +------------- + * Fix stream deserializer + +Version 0.2.0 +------------- + * Add stream deserializer / class MessagePackUnpacker interface + * Add alias functions + * Add class MessagePack interface + +Version 0.1.5 +------------- + * Add msgpack_pack.c + * Add msgpack_unpack.c + * Update msgpack.c + +Version 0.1.4 +------------- + * Change broken random data. + * Support PHP 5.2.x version. + +Version 0.1.3 +------------- + * Fix broken random data. + * Change arrays and objects. + +Version 0.1.2 +------------- + * Add Serializable class support. + * Fix arrays and objects reference. + +Version 0.1.1 +------------- + * Add session support. + +Version 0.1.0 +------------- + * Initial release. diff --git a/php/LICENSE b/php/LICENSE new file mode 100644 index 00000000..c0688fcf --- /dev/null +++ b/php/LICENSE @@ -0,0 +1,26 @@ +Copyright (c) 2010, advect +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the advect nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. diff --git a/php/README b/php/README index e69de29b..ac8e4857 100644 --- a/php/README +++ b/php/README @@ -0,0 +1,11 @@ +Description +----------- +This extension provide API for communicating with MessagePack serialization. + +MessagePack is a binary-based efficient object serialization library. +It enables to exchange structured objects between many languages like JSON. +But unlike JSON, it is very fast and small. + +Resources +--------- + * [msgpack](http://msgpack.sourceforge.net/) diff --git a/php/benchmark.php b/php/benchmark.php new file mode 100644 index 00000000..559801cb --- /dev/null +++ b/php/benchmark.php @@ -0,0 +1,248 @@ + md5(rand()), + md5(rand()) => md5(rand()), + md5(rand()) => md5(rand()), + md5(rand()) => md5(rand()), + md5(rand()) => md5(rand())); + break; + case 6: + //object + $value = new stdClass; + $value->param1 = rand(); + $value->param2 = md5(uniqid()); + $value->param3 = array(md5(uniqid())); + $value->param4 = array(md5(uniqid()) => md5(uniqid())); + $value->param5 = null; + break; + default: + //null + $value = null; + } + + if (!is_numeric($retry) || empty($retry)) + { + $retry = 1; + } + + $serialize_pack = 0; + $serialize_unpack = 0; + $serialize_size = 0; + $serialize_status = '*NG*'; + $json_pack = 0; + $json_unpack = 0; + $json_size = 0; + $json_status = '*NG*'; + $igbinary_pack = 0; + $igbinary_unpack = 0; + $igbinary_size = 0; + $igbinary_status = '*NG*'; + $msgpack_pack = 0; + $msgpack_unpack = 0; + $msgpack_size = 0; + $msgpack_status = '*NG*'; + + for ($c = 0; $c < $retry; $c++) + { + //default (serialize) + $pack = null; + $unpack = null; + $t = new Benchmark_Timer; + $t->start(); + for ($i = 0; $i < $loop; $i++) + { + $pack = serialize($value); + } + $t->setMarker('serialize'); + for ($i = 0; $i < $loop; $i++) + { + $unpack = unserialize($pack); + } + $t->stop(); + //$t->display(); + $profiling = $t->getProfiling(); + unset($t); + + $serialize_pack += $profiling[1]['diff']; + $serialize_unpack += $profiling[2]['diff']; + $serialize_size += strlen($pack); + if ($unpack === $value || + (is_object($value) && $unpack == $value)) + { + $serialize_status = 'OK'; + } + + //json + $pack = null; + $unpack = null; + $opt = false; + if (is_array($value)) + { + $opt = true; + } + $t = new Benchmark_Timer; + $t->start(); + for ($i = 0; $i < $loop; $i++) + { + $pack = json_encode($value); + } + $t->setMarker('json_encode'); + for ($i = 0; $i < $loop; $i++) + { + $unpack = json_decode($pack, $opt); + } + $t->stop(); + //$t->display(); + $profiling = $t->getProfiling(); + unset($t); + + $json_pack += $profiling[1]['diff']; + $json_unpack += $profiling[2]['diff']; + $json_size += strlen($pack); + if ($unpack === $value || + (is_object($value) && $unpack == $value) || + (is_float($value) && + number_format($value, 10, '.', '') === + number_format($unpack, 10, '.', ''))) + { + $json_status = 'OK'; + } + + //igbinary + if (extension_loaded('igbinary')) + { + $pack = null; + $unpack = null; + $t = new Benchmark_Timer; + $t->start(); + for ($i = 0; $i < $loop; $i++) + { + $pack = igbinary_serialize($value); + } + $t->setMarker('igbinary_serialize'); + for ($i = 0; $i < $loop; $i++) + { + $unpack = igbinary_unserialize($pack); + } + $t->stop(); + //$t->display(); + $profiling = $t->getProfiling(); + unset($t); + + $igbinary_pack += $profiling[1]['diff']; + $igbinary_unpack += $profiling[2]['diff']; + $igbinary_size += strlen($pack); + if ($unpack === $value || + (is_object($value) && $unpack == $value)) + { + $igbinary_status = 'OK'; + } + } + + //msgpack + $pack = null; + $unpack = null; + $t = new Benchmark_Timer; + $t->start(); + for ($i = 0; $i < $loop; $i++) + { + $pack = msgpack_serialize($value); + } + $t->setMarker('msgpack_serialize'); + for ($i = 0; $i < $loop; $i++) + { + $unpack = msgpack_unserialize($pack); + } + $t->stop(); + //$t->display(); + $profiling = $t->getProfiling(); + unset($t); + + $msgpack_pack += $profiling[1]['diff']; + $msgpack_unpack += $profiling[2]['diff']; + $msgpack_size += strlen($pack); + if ($unpack === $value || + (is_object($value) && $unpack == $value)) + { + $msgpack_status = 'OK'; + } + } + + $serialize_pack /= $retry; + $serialize_unpack /= $retry; + $serialize_size /= $retry; + $json_pack /= $retry; + $json_unpack /= $retry; + $json_size /= $retry; + $igbinary_pack /= $retry; + $igbinary_unpack /= $retry; + $igbinary_size /= $retry; + $msgpack_pack /= $retry; + $msgpack_unpack /= $retry; + $msgpack_size /= $retry; + + printf("[%-10s] %13s %13s %13s %13s\n", + gettype($value), 'default', 'json', 'igbinary', 'msgpack'); + printf("status : %12s %12s %12s %12s\n", + $serialize_status, $json_status, $igbinary_status, $msgpack_status); + printf("serialize : %.4f (100%%) %.4f (%3d%%) %.4f (%3d%%) %.4f (%3d%%)\n", + $serialize_pack, + $json_pack, ($json_pack / $serialize_pack * 100), + $igbinary_pack, ($igbinary_pack / $serialize_pack * 100), + $msgpack_pack, ($msgpack_pack / $serialize_pack * 100)); + printf("unserialize: %.4f (100%%) %.4f (%3d%%) %.4f (%3d%%) %.4f (%3d%%)\n", + $serialize_unpack, + $json_unpack, ($json_unpack / $serialize_unpack * 100), + $igbinary_unpack, ($igbinary_unpack / $serialize_unpack * 100), + $msgpack_unpack, ($msgpack_unpack / $serialize_unpack * 100)); + printf("size : %6d (100%%) %6d (%3d%%) %6d (%3d%%) %6d (%3d%%)\n\n", + $serialize_size, + $json_size, ($json_size / $serialize_size * 100), + $igbinary_size, ($igbinary_size / $serialize_size * 100), + $msgpack_size, ($msgpack_size / $serialize_size * 100)); + if ($value_display === true) + { + var_dump($value); + echo PHP_EOL; + } +} diff --git a/php/config.m4 b/php/config.m4 index 751b4712..d319684f 100644 --- a/php/config.m4 +++ b/php/config.m4 @@ -1,14 +1,73 @@ -dnl $Id$ dnl config.m4 for extension msgpack -PHP_ARG_ENABLE(msgpack, whether to enable MessagePack support, +dnl Comments in this file start with the string 'dnl'. +dnl Remove where necessary. This file will not work +dnl without editing. + +dnl Check PHP version: + +AC_MSG_CHECKING(PHP version) +AC_TRY_COMPILE([#include "php/main/php_version.h"], [ +#if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 2) +#error this extension requires at least PHP version 5.2.0 +#endif +], +[AC_MSG_RESULT(ok)], +[AC_MSG_ERROR([need at least PHP 5.2.0])]) + +dnl If your extension references something external, use with: + +PHP_ARG_WITH(msgpack, for msgpack support, Make sure that the comment is aligned: -[ --enable-msgpack Enable MessagePack support]) +[ --with-msgpack Include msgpack support]) + +dnl PHP_ARG_ENABLE(msgpack, whether to enable msgpack support, +dnl Make sure that the comment is aligned: +dnl [ --enable-msgpack Enable msgpack support]) if test "$PHP_MSGPACK" != "no"; then - dnl AC_DEFINE([HAVE_MSGPACK],1 ,[whether to enable MessagePack support]) - dnl AC_HEADER_STDC + dnl Write more examples of tests here... - PHP_NEW_EXTENSION(msgpack, msgpack.c, $ext_shared) - dnl PHP_SUBST(MSGPACK_SHARED_LIBADD) + dnl --with-msgpack -> check with-path + SEARCH_PATH="/usr/local /usr" # you might want to change this + SEARCH_FOR="/include/msgpack.h" # you most likely want to change this + if test -r $PHP_MSGPACK/$SEARCH_FOR; then # path given as parameter + MSGPACK_DIR=$PHP_MSGPACK + else # search default path list + AC_MSG_CHECKING([for msgpack files in default path]) + for i in $SEARCH_PATH ; do + if test -r $i/$SEARCH_FOR; then + MSGPACK_DIR=$i + AC_MSG_RESULT(found in $i) + fi + done + fi + + if test -z "$MSGPACK_DIR"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Please reinstall the msgpack distribution]) + fi + + dnl --with-msgpack -> add include path + PHP_ADD_INCLUDE($MSGPACK_DIR/include) + + dnl --with-msgpack -> check for lib and symbol presence + LIBNAME=msgpack # you may want to change this + LIBSYMBOL=msgpack_pack_object # you most likely want to change this + + PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + [ + PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MSGPACK_DIR/lib, MSGPACK_SHARED_LIBADD) + AC_DEFINE(HAVE_MSGPACKLIB,1,[ ]) + ],[ + AC_MSG_ERROR([wrong msgpack lib version or lib not found]) + ],[ + -L$MSGPACK_DIR/lib -lm + ]) + + PHP_SUBST(MSGPACK_SHARED_LIBADD) + + PHP_NEW_EXTENSION(msgpack, msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c, $ext_shared) + + PHP_INSTALL_HEADERS([ext/msgpack], [php_msgpack.h]) fi diff --git a/php/config.w32 b/php/config.w32 index 50e9bec2..f2153e6b 100644 --- a/php/config.w32 +++ b/php/config.w32 @@ -8,6 +8,5 @@ // ARG_ENABLE("msgpack", "enable msgpack support", "no"); if (PHP_MSGPACK != "no") { - EXTENSION("msgpack", "msgpack.c"); + EXTENSION("msgpack", "msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c"); } - diff --git a/php/msgpack.c b/php/msgpack.c index b38eb18c..62fb68d7 100644 --- a/php/msgpack.c +++ b/php/msgpack.c @@ -1,22 +1,3 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2007 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: Hideyuki TAKEI | - +----------------------------------------------------------------------+ -*/ - -/* $Id: header 226204 2007-01-01 19:32:10Z iliaa $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -26,631 +7,259 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/php_smart_str.h" +#include "ext/standard/php_incomplete_class.h" +#include "ext/standard/php_var.h" +#include "ext/session/php_session.h" + #include "php_msgpack.h" +#include "msgpack_pack.h" +#include "msgpack_unpack.h" +#include "msgpack_class.h" -#define PHP_EXT_VERSION "0.01" +static ZEND_FUNCTION(msgpack_serialize); +static ZEND_FUNCTION(msgpack_unserialize); -#ifndef TRUE -# define TRUE 1 -# define FALSE 0 -#endif +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_serialize, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unserialize, 0, 0, 1) + ZEND_ARG_INFO(0, str) +ZEND_END_ARG_INFO() -/* pack */ -#include "msgpack/pack_define.h" +PS_SERIALIZER_FUNCS(msgpack); -#define msgpack_pack_inline_func(name) \ - static inline void msgpack_pack ## name - -#define msgpack_pack_inline_func_cint(name) \ - static inline void msgpack_pack ## name - -#define msgpack_pack_user smart_str* - -#define msgpack_pack_append_buffer(user, buf, len) \ - smart_str_appendl(user, (const void*)buf, len) - -#include "msgpack/pack_template.h" - - -/* unpack */ -#include "msgpack/unpack_define.h" - -typedef struct { - int finished; - char* source; -} unpack_user; - -#define msgpack_unpack_struct(name) \ - struct template ## name - -#define msgpack_unpack_func(ret, name) \ - ret template ## name - -#define msgpack_unpack_callback(name) \ - template_callback ## name - -#define msgpack_unpack_object zval* - -#define msgpack_unpack_user unpack_user - -struct template_context; -typedef struct template_context msgpack_unpack_t; - -static void template_init(msgpack_unpack_t* u); -static msgpack_unpack_object template_data(msgpack_unpack_t* u); -static int template_execute(msgpack_unpack_t* u, - const char* data, size_t len, size_t* off); - -ZEND_BEGIN_MODULE_GLOBALS(msgpack) - msgpack_unpack_t *global_mp; -ZEND_END_MODULE_GLOBALS(msgpack) - -#ifdef ZTS -#define MSGPACK_G(v) TSRMG(msgpack_globals_id, zend_msgpack_globals *, v) -#else -#define MSGPACK_G(v) (msgpack_globals.v) -#endif - -static inline msgpack_unpack_object template_callback_root(unpack_user* u) -{ - msgpack_unpack_object data; - ALLOC_INIT_ZVAL(data); - ZVAL_NULL(data); - return data; -} - -static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; } - -static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; } - -static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; } - -static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; } - -static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; } - -static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; } - -static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, (long)d); return 0; } - -static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_LONG(*o, d); return 0; } - -static inline int template_callback_float(unpack_user* u, float d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_DOUBLE(*o, d); return 0; } - -static inline int template_callback_double(unpack_user* u, double d, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_DOUBLE(*o, d); return 0; } - -static inline int template_callback_nil(unpack_user* u, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_NULL(*o); return 0; } - -static inline int template_callback_true(unpack_user* u, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_BOOL(*o, 1); return 0; } - -static inline int template_callback_false(unpack_user* u, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); ZVAL_BOOL(*o, 0); return 0;} - -static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); array_init(*o); return 0; } - -static inline int template_callback_array_item(unpack_user* u, msgpack_unpack_object* c, msgpack_unpack_object o) -{ add_next_index_zval(*c, o); return 0; } - -static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_unpack_object* o) -{ ALLOC_INIT_ZVAL(*o); array_init(*o); return 0; } - -static inline int template_callback_map_item(unpack_user* u, msgpack_unpack_object* c, msgpack_unpack_object k, msgpack_unpack_object v) -{ - switch(k->type) { - case IS_LONG: - add_index_zval(*c, Z_LVAL(*k), v); - break; - case IS_STRING: - add_assoc_zval_ex(*c, Z_STRVAL(*k), Z_STRLEN(*k)+1, v); - break; - default: - zend_error(E_WARNING, "[msgpack] (php_msgpack_decode) illegal offset type, skip this decoding"); - break; - } - return 0; -} - - -static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_unpack_object* o) -{ - ALLOC_INIT_ZVAL(*o); - if (l == 0) { - ZVAL_STRINGL(*o, "", 0, 1); - } else { - ZVAL_STRINGL(*o, p, l, 1); - } - return 0; -} - -#include "msgpack/unpack_template.h" - -static PHP_GINIT_FUNCTION(msgpack); - -ZEND_DECLARE_MODULE_GLOBALS(msgpack) - -/* True global resources - no need for thread safety here */ -static int le_msgpack; - -/* {{{ msgpack_functions[] - * - * Every user visible function must have an entry in msgpack_functions[]. - */ -zend_function_entry msgpack_functions[] = { - PHP_FE(msgpack_pack, NULL) - PHP_FE(msgpack_unpack, NULL) - PHP_FE(msgpack_unpack_limit, NULL) - PHP_ME(msgpack, initialize, NULL, 0) - PHP_ME(msgpack, execute, NULL, 0) - PHP_ME(msgpack, execute_limit, NULL, 0) - PHP_ME(msgpack, finished, NULL, 0) - PHP_ME(msgpack, data, NULL, 0) - {NULL, NULL, NULL} /* Must be the last line in msgpack_functions[] */ +static const zend_function_entry msgpack_functions[] = { + ZEND_FE(msgpack_serialize, arginfo_msgpack_serialize) + ZEND_FE(msgpack_unserialize, arginfo_msgpack_unserialize) + ZEND_FALIAS(msgpack_pack, msgpack_serialize, arginfo_msgpack_serialize) + ZEND_FALIAS(msgpack_unpack, msgpack_unserialize, + arginfo_msgpack_unserialize) + {NULL, NULL, NULL} }; -/* }}} */ -/* {{{ msgpack_module_entry - */ +static ZEND_MINIT_FUNCTION(msgpack) +{ + MSGPACK_G(error_display) = 1; + +#if HAVE_PHP_SESSION + php_session_register_serializer("msgpack", + PS_SERIALIZER_ENCODE_NAME(msgpack), + PS_SERIALIZER_DECODE_NAME(msgpack)); +#endif + + msgpack_init_class(TSRMLS_CC); + + return SUCCESS; +} + +static ZEND_MINFO_FUNCTION(msgpack) +{ + php_info_print_table_start(); + php_info_print_table_row(2, "msgpack support", "enabled"); + php_info_print_table_row(2, "msgpack version", MSGPACK_VERSION); +#if HAVE_PHP_SESSION + php_info_print_table_row(2, "msgpack Session Support", "enabled" ); +#endif + php_info_print_table_end(); +} + zend_module_entry msgpack_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, + STANDARD_MODULE_HEADER, #endif - "msgpack", - msgpack_functions, - PHP_MINIT(msgpack), - PHP_MSHUTDOWN(msgpack), - PHP_RINIT(msgpack), /* Replace with NULL if there's nothing to do at request start */ - PHP_RSHUTDOWN(msgpack), /* Replace with NULL if there's nothing to do at request end */ - PHP_MINFO(msgpack), + "msgpack", + msgpack_functions, + ZEND_MINIT(msgpack), + NULL, + NULL, + NULL, + ZEND_MINFO(msgpack), #if ZEND_MODULE_API_NO >= 20010901 - "0.1", /* Replace with version number for your extension */ + MSGPACK_VERSION, #endif - PHP_MODULE_GLOBALS(msgpack), - PHP_GINIT(msgpack), - NULL, - NULL, - STANDARD_MODULE_PROPERTIES_EX + STANDARD_MODULE_PROPERTIES }; -/* }}} */ #ifdef COMPILE_DL_MSGPACK ZEND_GET_MODULE(msgpack) #endif -/* {{{ PHP_GINIT_FUNCTION */ -static PHP_GINIT_FUNCTION(msgpack) +PS_SERIALIZER_ENCODE_FUNC(msgpack) { - msgpack_globals->global_mp = NULL; -} -/* }}} */ + smart_str buf = {0}; + php_serialize_data_t var_hash; -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(msgpack) -{ - zend_class_entry ce; - INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_functions); - msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC); + PHP_VAR_SERIALIZE_INIT(var_hash); - return SUCCESS; -} -/* }}} */ + msgpack_serialize_zval(&buf, PS(http_session_vars), &var_hash TSRMLS_CC); -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(msgpack) -{ - /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); - */ - if (MSGPACK_G(global_mp)) { - efree(MSGPACK_G(global_mp)); - MSGPACK_G(global_mp) = NULL; - } - - return SUCCESS; -} -/* }}} */ - -/* Remove if there's nothing to do at request start */ -/* {{{ PHP_RINIT_FUNCTION - */ -PHP_RINIT_FUNCTION(msgpack) -{ - return SUCCESS; -} -/* }}} */ - -/* Remove if there's nothing to do at request end */ -/* {{{ PHP_RSHUTDOWN_FUNCTION - */ -PHP_RSHUTDOWN_FUNCTION(msgpack) -{ - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(msgpack) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "msgpack support", "enabled"); - php_info_print_table_row(2, "php extension version", PHP_EXT_VERSION); - php_info_print_table_row(2, "author", "Hideyuki TAKEI"); - php_info_print_table_row(2, "homepage", "http://msgpack.sourceforge.net"); - php_info_print_table_row(2, "open sourced by", "KLab inc."); - php_info_print_table_end(); -} -/* }}} */ - -PHP_MSGPACK_API int msgpack_determine_array_type(zval **val TSRMLS_DC) /* {{{ */ -{ - int i; - HashTable *myht = HASH_OF(*val); - - i = myht ? zend_hash_num_elements(myht) : 0; - if (i > 0) { - char *key; - ulong index, idx; - uint key_len; - HashPosition pos; - - zend_hash_internal_pointer_reset_ex(myht, &pos); - idx = 0; - for (;; zend_hash_move_forward_ex(myht, &pos)) { - i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos); - if (i == HASH_KEY_NON_EXISTANT) - break; - if (i == HASH_KEY_IS_STRING) { - return 1; - } else { - if (index != idx) { - return 1; - } - } - idx++; - } - } - return 0; -} -/* }}} */ - -PHP_MSGPACK_API void msgpack_pack_array_hash(smart_str *pk, zval **val TSRMLS_DC) /* {{{ */ -{ - int i, r; - HashTable *myht; - - if(Z_TYPE_PP(val) == IS_ARRAY){ - myht = HASH_OF(*val); - r = msgpack_determine_array_type(val TSRMLS_CC); - } - else{ - myht = Z_OBJPROP_PP(val); - r = 1; - } - - i = myht ? zend_hash_num_elements(myht) : 0; - - if(r == 0){ - msgpack_pack_array(pk, i); - } - else{ - msgpack_pack_map(pk, i); - } - - if(i>0){ - char *key; - zval **data; - ulong index; - uint key_len; - HashPosition pos; - HashTable *tmp_ht; - int need_comma = 0; - - zend_hash_internal_pointer_reset_ex(myht, &pos); - for(;; zend_hash_move_forward_ex(myht, &pos)){ - i = zend_hash_get_current_key_ex(myht, &key, &key_len, &index, 0, &pos); - if(i==HASH_KEY_NON_EXISTANT) - break; - if(zend_hash_get_current_data_ex(myht, (void **) &data, &pos) == SUCCESS){ - tmp_ht = HASH_OF(*data); - if (tmp_ht) - tmp_ht->nApplyCount++; - - if(r==0) - php_msgpack_pack(pk, *data TSRMLS_CC); - else if(r==1){ - if(i==HASH_KEY_IS_STRING){ - if(key[0]=='\0' && Z_TYPE_PP(val)==IS_OBJECT){ - // Skip protected and private members. - if(tmp_ht) - tmp_ht->nApplyCount--; - continue; - } - msgpack_pack_raw(pk, key_len-1); - msgpack_pack_raw_body(pk, key, key_len-1); - php_msgpack_pack(pk, *data TSRMLS_CC); - } - else{ - msgpack_pack_long(pk, index); - php_msgpack_pack(pk, *data TSRMLS_CC); - } - } - - if(tmp_ht){ - tmp_ht->nApplyCount--; - } - } - } - - } -} -/* }}} */ - -PHP_MSGPACK_API void php_msgpack_pack(smart_str *pk, zval *val TSRMLS_DC) /* {{{ */ -{ - switch(Z_TYPE_P(val)){ - case IS_NULL: - msgpack_pack_nil(pk); - break; - case IS_BOOL: - if (Z_BVAL_P(val)) - msgpack_pack_true(pk); - else - msgpack_pack_false(pk); - break; - case IS_LONG: - msgpack_pack_long(pk, Z_LVAL_P(val)); - break; - case IS_DOUBLE: - { - double dbl = Z_DVAL_P(val); - if (zend_isinf(dbl) || zend_isnan(dbl)) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_pack) double %.9g does not conform to the MSGPACK spec, encoded as 0", dbl); - ZVAL_LONG(val, 0); - } - msgpack_pack_double(pk, Z_DVAL_P(val)); - } - break; - case IS_STRING: - msgpack_pack_raw(pk, Z_STRLEN_P(val)); - msgpack_pack_raw_body(pk, Z_STRVAL_P(val), Z_STRLEN_P(val)); - break; - case IS_ARRAY: - case IS_OBJECT: - msgpack_pack_array_hash(pk, &val TSRMLS_CC); - break; - defalut: - zend_error(E_WARNING, "[msgpack] (php_msgpack_pack) type is unsupported, encoded as null"); - msgpack_pack_nil(pk); - break; - } - - return; -} -/* }}} */ - -PHP_MSGPACK_API void php_msgpack_unpack_limit(zval *return_value, const char *buf, int len, zend_bool assoc TSRMLS_DC) /* {{{ */ -{ - if (len<=0) { - RETURN_NUL(); - } - - msgpack_unpack_t mp; - template_init(&mp); - unpack_user u = {0, ""}; - - size_t from = 0; - char* dptr = (char*)buf; - long dlen = len; - int ret; - - (&mp)->user.source = (char*)buf; - ret = template_execute(&mp, dptr, (size_t)dlen, &from); - (&mp)->user.source = ""; - - if(ret < 0) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) parse error"); - } else if(ret == 0) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) insufficient bytes"); - } else { - if(from < dlen) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) extra bytes"); - } - - *return_value = *template_data(&mp); - FREE_ZVAL(template_data(&mp)); - } -} -/* }}} */ - - -PHP_FUNCTION(msgpack_pack) -{ - zval *parameter; - smart_str buf = {0}; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) { - return; - } - - php_msgpack_pack(&buf, parameter TSRMLS_CC); - - ZVAL_STRINGL(return_value, buf.c, buf.len, 1); - - smart_str_free(&buf); -} - -PHP_FUNCTION(msgpack_unpack) -{ - char *parameter; - int parameter_len; - zend_bool assoc = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", - ¶meter, ¶meter_len, &assoc) == FAILURE) { - return; - } - - if (!parameter_len) { - RETURN_NULL(); - } - - php_msgpack_unpack_limit(return_value, parameter, parameter_len, assoc TSRMLS_CC); -} - -PHP_FUNCTION(msgpack_unpack_limit) -{ - char *parameter; - int parameter_len; - int limit; - zend_bool assoc = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|b", - ¶meter, ¶meter_len, &limit, &assoc) == FAILURE) { - return; - } - - if (!parameter_len) { - RETURN_NULL(); - } - else if (parameter_len < limit) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) limit greater than data_len"); - limit = parameter_len; - } - - php_msgpack_unpack_limit(return_value, parameter, limit, assoc TSRMLS_CC); -} - - -PHP_MSGPACK_API void php_msgpack_unpacker_execute_limit(zval *return_value, const char *buf, int off, int len, zend_bool assoc TSRMLS_DC) /* {{{ */ -{ - if (len<=0) { - RETURN_NUL(); - } - - size_t from = off; - char* dptr = (char*)buf; - long dlen = len; - int ret; - - if(from >= dlen) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpacker_execute_limit) offset is bigger than data buffer size"); + if (newlen) + { + *newlen = buf.len; } - MSGPACK_G(global_mp)->user.source = (char*)buf; - ret = template_execute(MSGPACK_G(global_mp), dptr, (size_t)dlen, &from); - MSGPACK_G(global_mp)->user.source = ""; + smart_str_0(&buf); + *newstr = buf.c; - if(ret < 0) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpacker_execute_limit) parse error"); - } else if(ret > 0) { - MSGPACK_G(global_mp)->user.finished = 1; - RETVAL_LONG(from); - } else { - MSGPACK_G(global_mp)->user.finished = 0; - RETVAL_LONG(from); - } + PHP_VAR_SERIALIZE_DESTROY(var_hash); + + return SUCCESS; } -/* }}} */ -PHP_MSGPACK_API void php_msgpack_unpacker_reset(TSRMLS_D) /* {{{ */ +PS_SERIALIZER_DECODE_FUNC(msgpack) { - if(MSGPACK_G(global_mp)) { - efree(MSGPACK_G(global_mp)); - MSGPACK_G(global_mp) = NULL; - } - MSGPACK_G(global_mp) = safe_emalloc(sizeof(msgpack_unpack_t), 1, 0); + php_unserialize_data_t var_hash; + int ret; + HashTable *tmp_hash; + HashPosition tmp_hash_pos; + char *key_str; + ulong key_long; + uint key_len; + zval *tmp; + zval **data; + msgpack_unserialize_data mpsd; - template_init(MSGPACK_G(global_mp)); - unpack_user u = {0, ""}; - MSGPACK_G(global_mp)->user = u; - return; + PHP_VAR_UNSERIALIZE_INIT(var_hash); + + MAKE_STD_ZVAL(tmp); + + mpsd.data = (unsigned char *)val;; + mpsd.length = vallen; + mpsd.offset = 0; + + ret = msgpack_unserialize_zval(&tmp, &mpsd, &var_hash TSRMLS_CC); + + switch (ret) + { + case MSGPACK_UNPACK_EXTRA_BYTES: + case MSGPACK_UNPACK_SUCCESS: + break; + case MSGPACK_UNPACK_PARSE_ERROR: + case MSGPACK_UNPACK_CONTINUE: + default: + zval_ptr_dtor(&tmp); + return FAILURE; + } + + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + + tmp_hash = HASH_OF(tmp); + + zend_hash_internal_pointer_reset_ex(tmp_hash, &tmp_hash_pos); + while (zend_hash_get_current_data_ex( + tmp_hash, (void *)&data, &tmp_hash_pos) == SUCCESS) + { + ret = zend_hash_get_current_key_ex( + tmp_hash, &key_str, &key_len, &key_long, 0, &tmp_hash_pos); + switch (ret) + { + case HASH_KEY_IS_LONG: + /* ??? */ + break; + case HASH_KEY_IS_STRING: + php_set_session_var(key_str, key_len - 1, *data, NULL TSRMLS_CC); + php_add_session_var(key_str, key_len - 1 TSRMLS_CC); + break; + } + zend_hash_move_forward_ex(tmp_hash, &tmp_hash_pos); + } + + zval_ptr_dtor(&tmp); + + return SUCCESS; } -/* }}} */ -PHP_METHOD(msgpack, initialize) +PHP_MSGPACK_API void php_msgpack_serialize(smart_str *buf, zval *val TSRMLS_DC) { - php_msgpack_unpacker_reset(TSRMLS_C); - return; + php_serialize_data_t var_hash; + + PHP_VAR_SERIALIZE_INIT(var_hash); + + msgpack_serialize_zval(buf, val, &var_hash TSRMLS_CC); + + PHP_VAR_SERIALIZE_DESTROY(var_hash); } -PHP_METHOD(msgpack, execute) +PHP_MSGPACK_API void php_msgpack_unserialize( + zval *return_value, char *str, size_t str_len TSRMLS_DC) { - char *data; - int off; - int data_len; - zend_bool assoc = 0; + int ret; + php_unserialize_data_t var_hash; + msgpack_unserialize_data mpsd; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|b", - &data, &data_len, &off, &assoc) == FAILURE) { - return; - } + if (str_len <= 0) + { + RETURN_NULL(); + } - if (!data_len) { - RETURN_NULL(); - } + PHP_VAR_UNSERIALIZE_INIT(var_hash); - php_msgpack_unpacker_execute_limit(return_value, data, off, data_len, assoc TSRMLS_CC); + mpsd.data = (unsigned char *)str; + mpsd.length = str_len; + mpsd.offset = 0; + + ret = msgpack_unserialize_zval(&return_value, &mpsd, &var_hash TSRMLS_CC); + + switch (ret) + { + case MSGPACK_UNPACK_PARSE_ERROR: + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Parse error"); + break; + case MSGPACK_UNPACK_CONTINUE: + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) " + "Insufficient data for unserializeng"); + break; + case MSGPACK_UNPACK_EXTRA_BYTES: + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Extra bytes"); + break; + case MSGPACK_UNPACK_SUCCESS: + break; + default: + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Unknown result"); + break; + } + + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } -PHP_METHOD(msgpack, execute_limit) +static ZEND_FUNCTION(msgpack_serialize) { - char *data; - int off; - int data_len; - int limit; - zend_bool assoc = 0; + zval *parameter; + smart_str buf = {0}; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|b", - &data, &data_len, &off, &limit, &assoc) == FAILURE) { - return; - } + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) + { + return; + } - if (!data_len) { - RETURN_NULL(); - } - else if (data_len < limit) { - zend_error(E_WARNING, "[msgpack] (php_msgpack_unpack) limit greater than (data+off)_len"); - limit = data_len; - } + php_msgpack_serialize(&buf, parameter TSRMLS_CC); - php_msgpack_unpacker_execute_limit(return_value, data, off, limit, assoc TSRMLS_CC); + ZVAL_STRINGL(return_value, buf.c, buf.len, 1); + + smart_str_free(&buf); } -PHP_METHOD(msgpack, finished) +static ZEND_FUNCTION(msgpack_unserialize) { - if(MSGPACK_G(global_mp)->user.finished == 1) { - RETURN_TRUE; - } - RETURN_FALSE; -} + char *str; + int str_len; -PHP_METHOD(msgpack, data) -{ - *return_value = *template_data(MSGPACK_G(global_mp)); - return; -} + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) + { + return; + } -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ + if (!str_len) + { + RETURN_NULL(); + } + + php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); +} diff --git a/php/msgpack.php b/php/msgpack.php index c2498dda..51547818 100644 --- a/php/msgpack.php +++ b/php/msgpack.php @@ -2,7 +2,7 @@ $br = (php_sapi_name() == "cli")? "":"
"; if(!extension_loaded('msgpack')) { - dl('msgpack.' . PHP_SHLIB_SUFFIX); + dl('msgpack.' . PHP_SHLIB_SUFFIX); } $module = 'msgpack'; $functions = get_extension_funcs($module); @@ -11,11 +11,11 @@ foreach($functions as $func) { echo $func."$br\n"; } echo "$br\n"; -$function = 'confirm_' . $module . '_compiled'; +$function = $module . '_serialize'; if (extension_loaded($module)) { - $str = $function($module); + $str = $function($module); } else { - $str = "Module $module is not compiled into PHP"; + $str = "Module $module is not compiled into PHP"; } echo "$str\n"; ?> diff --git a/php/msgpack/pack_define.h b/php/msgpack/pack_define.h deleted file mode 100644 index 33408e58..00000000 --- a/php/msgpack/pack_define.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * MessagePack unpacking routine template - * - * Copyright (C) 2008-2009 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MSGPACK_PACK_DEFINE_H__ -#define MSGPACK_PACK_DEFINE_H__ - -#include -#include -#include - -#endif /* msgpack/pack_define.h */ - diff --git a/php/msgpack/pack_template.h b/php/msgpack/pack_template.h deleted file mode 100644 index aa620f53..00000000 --- a/php/msgpack/pack_template.h +++ /dev/null @@ -1,741 +0,0 @@ -/* - * MessagePack packing routine template - * - * Copyright (C) 2008-2009 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define __LITTLE_ENDIAN__ -#elif __BYTE_ORDER == __BIG_ENDIAN -#define __BIG_ENDIAN__ -#endif -#endif - - -#ifdef __LITTLE_ENDIAN__ - -#define STORE8_BE8(d) \ - ((uint8_t*)&d)[0] - - -#define STORE16_BE8(d) \ - ((uint8_t*)&d)[0] - -#define STORE16_BE16(d) \ - ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - - -#define STORE32_BE8(d) \ - ((uint8_t*)&d)[0] - -#define STORE32_BE16(d) \ - ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - -#define STORE32_BE32(d) \ - ((uint8_t*)&d)[3], ((uint8_t*)&d)[2], ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - - -#define STORE64_BE8(d) \ - ((uint8_t*)&d)[0] - -#define STORE64_BE16(d) \ - ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - -#define STORE64_BE32(d) \ - ((uint8_t*)&d)[3], ((uint8_t*)&d)[2], ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - -#define STORE64_BE64(d) \ - ((uint8_t*)&d)[7], ((uint8_t*)&d)[6], ((uint8_t*)&d)[5], ((uint8_t*)&d)[4], \ - ((uint8_t*)&d)[3], ((uint8_t*)&d)[2], ((uint8_t*)&d)[1], ((uint8_t*)&d)[0] - - -#elif __BIG_ENDIAN__ - -#define STORE8_BE8(d) \ - ((uint8_t*)&d)[0] - - -#define STORE16_BE8(d) \ - ((uint8_t*)&d)[1] - -#define STORE16_BE16(d) \ - ((uint8_t*)&d)[0], ((uint8_t*)&d)[1] - - -#define STORE32_BE8(d) \ - ((uint8_t*)&d)[3] - -#define STORE32_BE16(d) \ - ((uint8_t*)&d)[2], ((uint8_t*)&d)[3] - -#define STORE32_BE32(d) \ - ((uint8_t*)&d)[0], ((uint8_t*)&d)[1], ((uint8_t*)&d)[2], ((uint8_t*)&d)[3] - - -#define STORE64_BE8(d) \ - ((uint8_t*)&d)[7] - -#define STORE64_BE16(d) \ - ((uint8_t*)&d)[6], ((uint8_t*)&d)[7] - -#define STORE64_BE32(d) \ - ((uint8_t*)&d)[4], ((uint8_t*)&d)[5], ((uint8_t*)&d)[6], ((uint8_t*)&d)[7] - -#define STORE64_BE64(d) \ - ((uint8_t*)&d)[0], ((uint8_t*)&d)[1], ((uint8_t*)&d)[2], ((uint8_t*)&d)[3], \ - ((uint8_t*)&d)[4], ((uint8_t*)&d)[5], ((uint8_t*)&d)[6], ((uint8_t*)&d)[7] - -#endif - -#ifndef msgpack_pack_inline_func -#error msgpack_pack_inline_func template is not defined -#endif - -#ifndef msgpack_pack_user -#error msgpack_pack_user type is not defined -#endif - -#ifndef msgpack_pack_append_buffer -#error msgpack_pack_append_buffer callback is not defined -#endif - - -/* - * Integer - */ - -#define msgpack_pack_real_uint8(x, d) \ -do { \ - if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE8_BE8(d), 1); \ - } else { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE8_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ -} while(0) - -#define msgpack_pack_real_uint16(x, d) \ -do { \ - if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE16_BE8(d), 1); \ - } else if(d < (1<<8)) { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE16_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } else { \ - /* unsigned 16 */ \ - const unsigned char buf[3] = {0xcd, STORE16_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } \ -} while(0) - -#define msgpack_pack_real_uint32(x, d) \ -do { \ - if(d < (1<<8)) { \ - if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE32_BE8(d), 1); \ - } else { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE32_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ - } else { \ - if(d < (1<<16)) { \ - /* unsigned 16 */ \ - const unsigned char buf[3] = {0xcd, STORE32_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else { \ - /* unsigned 32 */ \ - const unsigned char buf[5] = {0xce, STORE32_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } \ - } \ -} while(0) - -#define msgpack_pack_real_uint64(x, d) \ -do { \ - if(d < (1ULL<<8)) { \ - if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE64_BE8(d), 1); \ - } else { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE64_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ - } else { \ - if(d < (1ULL<<16)) { \ - /* signed 16 */ \ - const unsigned char buf[3] = {0xcd, STORE64_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else if(d < (1ULL<<32)) { \ - /* signed 32 */ \ - const unsigned char buf[5] = {0xce, STORE64_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } else { \ - /* signed 64 */ \ - const unsigned char buf[9] = {0xcf, STORE64_BE64(d)}; \ - msgpack_pack_append_buffer(x, buf, 9); \ - } \ - } \ -} while(0) - -#define msgpack_pack_real_int8(x, d) \ -do { \ - if(d < -(1<<5)) { \ - /* signed 8 */ \ - const unsigned char buf[2] = {0xd0, STORE8_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } else { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE8_BE8(d), 1); \ - } \ -} while(0) - -#define msgpack_pack_real_int16(x, d) \ -do { \ - if(d < -(1<<5)) { \ - if(d < -(1<<7)) { \ - /* signed 16 */ \ - const unsigned char buf[3] = {0xd1, STORE16_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else { \ - /* signed 8 */ \ - const unsigned char buf[2] = {0xd0, STORE16_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ - } else if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE16_BE8(d), 1); \ - } else { \ - if(d < (1<<8)) { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE16_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } else { \ - /* unsigned 16 */ \ - const unsigned char buf[3] = {0xcd, STORE16_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } \ - } \ -} while(0) - -#define msgpack_pack_real_int32(x, d) \ -do { \ - if(d < -(1<<5)) { \ - if(d < -(1<<15)) { \ - /* signed 32 */ \ - const unsigned char buf[5] = {0xd2, STORE32_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } else if(d < -(1<<7)) { \ - /* signed 16 */ \ - const unsigned char buf[3] = {0xd1, STORE32_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else { \ - /* signed 8 */ \ - const unsigned char buf[2] = {0xd0, STORE32_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ - } else if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE32_BE8(d), 1); \ - } else { \ - if(d < (1<<8)) { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE32_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } else if(d < (1<<16)) { \ - /* unsigned 16 */ \ - const unsigned char buf[3] = {0xcd, STORE32_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else { \ - /* unsigned 32 */ \ - const unsigned char buf[5] = {0xce, STORE32_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } \ - } \ -} while(0) - -#define msgpack_pack_real_int64(x, d) \ -do { \ - if(d < -(1LL<<5)) { \ - if(d < -(1LL<<15)) { \ - if(d < -(1LL<<31)) { \ - /* signed 64 */ \ - const unsigned char buf[9] = {0xd3, STORE64_BE64(d)}; \ - msgpack_pack_append_buffer(x, buf, 9); \ - } else { \ - /* signed 32 */ \ - const unsigned char buf[5] = {0xd2, STORE64_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } \ - } else { \ - if(d < -(1<<7)) { \ - /* signed 16 */ \ - const unsigned char buf[3] = {0xd1, STORE64_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } else { \ - /* signed 8 */ \ - const unsigned char buf[2] = {0xd0, STORE64_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } \ - } \ - } else if(d < (1<<7)) { \ - /* fixnum */ \ - msgpack_pack_append_buffer(x, &STORE64_BE8(d), 1); \ - } else { \ - if(d < (1LL<<16)) { \ - if(d < (1<<8)) { \ - /* unsigned 8 */ \ - const unsigned char buf[2] = {0xcc, STORE64_BE8(d)}; \ - msgpack_pack_append_buffer(x, buf, 2); \ - } else { \ - /* unsigned 16 */ \ - const unsigned char buf[3] = {0xcd, STORE64_BE16(d)}; \ - msgpack_pack_append_buffer(x, buf, 3); \ - } \ - } else { \ - if(d < (1LL<<32)) { \ - /* unsigned 32 */ \ - const unsigned char buf[5] = {0xce, STORE64_BE32(d)}; \ - msgpack_pack_append_buffer(x, buf, 5); \ - } else { \ - /* unsigned 64 */ \ - const unsigned char buf[9] = {0xcf, STORE64_BE64(d)}; \ - msgpack_pack_append_buffer(x, buf, 9); \ - } \ - } \ - } \ -} while(0) - - -#ifdef msgpack_pack_inline_func_fastint - -msgpack_pack_inline_func_fastint(_uint8)(msgpack_pack_user x, uint8_t d) -{ - const unsigned char buf[2] = {0xcc, STORE8_BE8(d)}; - msgpack_pack_append_buffer(x, buf, 2); -} - -msgpack_pack_inline_func_fastint(_uint16)(msgpack_pack_user x, uint16_t d) -{ - const unsigned char buf[3] = {0xcd, STORE16_BE16(d)}; - msgpack_pack_append_buffer(x, buf, 3); -} - -msgpack_pack_inline_func_fastint(_uint32)(msgpack_pack_user x, uint32_t d) -{ - const unsigned char buf[5] = {0xce, STORE32_BE32(d)}; - msgpack_pack_append_buffer(x, buf, 5); -} - -msgpack_pack_inline_func_fastint(_uint64)(msgpack_pack_user x, uint64_t d) -{ - const unsigned char buf[9] = {0xcf, STORE64_BE64(d)}; - msgpack_pack_append_buffer(x, buf, 9); -} - -msgpack_pack_inline_func_fastint(_int8)(msgpack_pack_user x, int8_t d) -{ - const unsigned char buf[2] = {0xd0, STORE8_BE8(d)}; - msgpack_pack_append_buffer(x, buf, 2); -} - -msgpack_pack_inline_func_fastint(_int16)(msgpack_pack_user x, int16_t d) -{ - const unsigned char buf[3] = {0xd1, STORE16_BE16(d)}; - msgpack_pack_append_buffer(x, buf, 3); -} - -msgpack_pack_inline_func_fastint(_int32)(msgpack_pack_user x, int32_t d) -{ - const unsigned char buf[5] = {0xd2, STORE32_BE32(d)}; - msgpack_pack_append_buffer(x, buf, 5); -} - -msgpack_pack_inline_func_fastint(_int64)(msgpack_pack_user x, int64_t d) -{ - const unsigned char buf[9] = {0xd3, STORE64_BE64(d)}; - msgpack_pack_append_buffer(x, buf, 9); -} - -#undef msgpack_pack_inline_func_fastint -#endif - - -msgpack_pack_inline_func(_uint8)(msgpack_pack_user x, uint8_t d) -{ - msgpack_pack_real_uint8(x, d); -} - -msgpack_pack_inline_func(_uint16)(msgpack_pack_user x, uint16_t d) -{ - msgpack_pack_real_uint16(x, d); -} - -msgpack_pack_inline_func(_uint32)(msgpack_pack_user x, uint32_t d) -{ - msgpack_pack_real_uint32(x, d); -} - -msgpack_pack_inline_func(_uint64)(msgpack_pack_user x, uint64_t d) -{ - msgpack_pack_real_uint64(x, d); -} - -msgpack_pack_inline_func(_int8)(msgpack_pack_user x, int8_t d) -{ - msgpack_pack_real_int8(x, d); -} - -msgpack_pack_inline_func(_int16)(msgpack_pack_user x, int16_t d) -{ - msgpack_pack_real_int16(x, d); -} - -msgpack_pack_inline_func(_int32)(msgpack_pack_user x, int32_t d) -{ - msgpack_pack_real_int32(x, d); -} - -msgpack_pack_inline_func(_int64)(msgpack_pack_user x, int64_t d) -{ - msgpack_pack_real_int64(x, d); -} - - -#ifdef msgpack_pack_inline_func_cint - -msgpack_pack_inline_func_cint(_short)(msgpack_pack_user x, short d) -{ -#if defined(SIZEOF_SHORT) || defined(SHRT_MAX) -#if SIZEOF_SHORT == 2 || SHRT_MAX == 0x7fff - msgpack_pack_real_int16(x, d); -#elif SIZEOF_SHORT == 4 || SHRT_MAX == 0x7fffffff - msgpack_pack_real_int32(x, d); -#else - msgpack_pack_real_int64(x, d); -#endif -#else -if(sizeof(short) == 2) { - msgpack_pack_real_int16(x, d); -} else if(sizeof(short) == 4) { - msgpack_pack_real_int32(x, d); -} else { - msgpack_pack_real_int64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_int)(msgpack_pack_user x, int d) -{ -#if defined(SIZEOF_INT) || defined(INT_MAX) -#if SIZEOF_INT == 2 || INT_MAX == 0x7fff - msgpack_pack_real_int16(x, d); -#elif SIZEOF_INT == 4 || INT_MAX == 0x7fffffff - msgpack_pack_real_int32(x, d); -#else - msgpack_pack_real_int64(x, d); -#endif -#else -if(sizeof(int) == 2) { - msgpack_pack_real_int16(x, d); -} else if(sizeof(int) == 4) { - msgpack_pack_real_int32(x, d); -} else { - msgpack_pack_real_int64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_long)(msgpack_pack_user x, long d) -{ -#if defined(SIZEOF_LONG) || defined(LONG_MAX) -#if SIZEOF_LONG == 2 || LONG_MAX == 0x7fffL - msgpack_pack_real_int16(x, d); -#elif SIZEOF_LONG == 4 || LONG_MAX == 0x7fffffffL - msgpack_pack_real_int32(x, d); -#else - msgpack_pack_real_int64(x, d); -#endif -#else -if(sizeof(long) == 2) { - msgpack_pack_real_int16(x, d); -} else if(sizeof(long) == 4) { - msgpack_pack_real_int32(x, d); -} else { - msgpack_pack_real_int64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_long_long)(msgpack_pack_user x, long long d) -{ -#if defined(SIZEOF_LONG_LONG) || defined(LLONG_MAX) -#if SIZEOF_LONG_LONG == 2 || LLONG_MAX == 0x7fffL - msgpack_pack_real_int16(x, d); -#elif SIZEOF_LONG_LONG == 4 || LLONG_MAX == 0x7fffffffL - msgpack_pack_real_int32(x, d); -#else - msgpack_pack_real_int64(x, d); -#endif -#else -if(sizeof(long long) == 2) { - msgpack_pack_real_int16(x, d); -} else if(sizeof(long long) == 4) { - msgpack_pack_real_int32(x, d); -} else { - msgpack_pack_real_int64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_unsigned_short)(msgpack_pack_user x, unsigned short d) -{ -#if defined(SIZEOF_SHORT) || defined(USHRT_MAX) -#if SIZEOF_SHORT == 2 || USHRT_MAX == 0xffffU - msgpack_pack_real_uint16(x, d); -#elif SIZEOF_SHORT == 4 || USHRT_MAX == 0xffffffffU - msgpack_pack_real_uint32(x, d); -#else - msgpack_pack_real_uint64(x, d); -#endif -#else -if(sizeof(unsigned short) == 2) { - msgpack_pack_real_uint16(x, d); -} else if(sizeof(unsigned short) == 4) { - msgpack_pack_real_uint32(x, d); -} else { - msgpack_pack_real_uint64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_unsigned_int)(msgpack_pack_user x, unsigned int d) -{ -#if defined(SIZEOF_INT) || defined(UINT_MAX) -#if SIZEOF_INT == 2 || UINT_MAX == 0xffffU - msgpack_pack_real_uint16(x, d); -#elif SIZEOF_INT == 4 || UINT_MAX == 0xffffffffU - msgpack_pack_real_uint32(x, d); -#else - msgpack_pack_real_uint64(x, d); -#endif -#else -if(sizeof(unsigned int) == 2) { - msgpack_pack_real_uint16(x, d); -} else if(sizeof(unsigned int) == 4) { - msgpack_pack_real_uint32(x, d); -} else { - msgpack_pack_real_uint64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_unsigned_long)(msgpack_pack_user x, unsigned long d) -{ -#if defined(SIZEOF_LONG) || defined(ULONG_MAX) -#if SIZEOF_LONG == 2 || ULONG_MAX == 0xffffUL - msgpack_pack_real_uint16(x, d); -#elif SIZEOF_LONG == 4 || ULONG_MAX == 0xffffffffUL - msgpack_pack_real_uint32(x, d); -#else - msgpack_pack_real_uint64(x, d); -#endif -#else -if(sizeof(unsigned int) == 2) { - msgpack_pack_real_uint16(x, d); -} else if(sizeof(unsigned int) == 4) { - msgpack_pack_real_uint32(x, d); -} else { - msgpack_pack_real_uint64(x, d); -} -#endif -} - -msgpack_pack_inline_func_cint(_unsigned_long_long)(msgpack_pack_user x, unsigned long long d) -{ -#if defined(SIZEOF_LONG_LONG) || defined(ULLONG_MAX) -#if SIZEOF_LONG_LONG == 2 || ULLONG_MAX == 0xffffUL - msgpack_pack_real_uint16(x, d); -#elif SIZEOF_LONG_LONG == 4 || ULLONG_MAX == 0xffffffffUL - msgpack_pack_real_uint32(x, d); -#else - msgpack_pack_real_uint64(x, d); -#endif -#else -if(sizeof(unsigned long long) == 2) { - msgpack_pack_real_uint16(x, d); -} else if(sizeof(unsigned long long) == 4) { - msgpack_pack_real_uint32(x, d); -} else { - msgpack_pack_real_uint64(x, d); -} -#endif -} - -#undef msgpack_pack_inline_func_cint -#endif - - - -/* - * Float - */ - -msgpack_pack_inline_func(_float)(msgpack_pack_user x, float d) -{ - union { char buf[4]; uint32_t num; } f; - *((float*)&f.buf) = d; // FIXME - const unsigned char buf[5] = {0xca, STORE32_BE32(f.num)}; - msgpack_pack_append_buffer(x, buf, 5); -} - -msgpack_pack_inline_func(_double)(msgpack_pack_user x, double d) -{ - union { char buf[8]; uint64_t num; } f; - *((double*)&f.buf) = d; // FIXME - const unsigned char buf[9] = {0xcb, STORE64_BE64(f.num)}; - msgpack_pack_append_buffer(x, buf, 9); -} - - -/* - * Nil - */ - -msgpack_pack_inline_func(_nil)(msgpack_pack_user x) -{ - static const unsigned char d = 0xc0; - msgpack_pack_append_buffer(x, &d, 1); -} - - -/* - * Boolean - */ - -msgpack_pack_inline_func(_true)(msgpack_pack_user x) -{ - static const unsigned char d = 0xc3; - msgpack_pack_append_buffer(x, &d, 1); -} - -msgpack_pack_inline_func(_false)(msgpack_pack_user x) -{ - static const unsigned char d = 0xc2; - msgpack_pack_append_buffer(x, &d, 1); -} - - -/* - * Array - */ - -msgpack_pack_inline_func(_array)(msgpack_pack_user x, unsigned int n) -{ - if(n < 16) { - unsigned char d = 0x90 | n; - msgpack_pack_append_buffer(x, &d, 1); - } else if(n < 65536) { - uint16_t d = (uint16_t)n; - unsigned char buf[3] = {0xdc, STORE16_BE16(d)}; - msgpack_pack_append_buffer(x, buf, 3); - } else { - uint32_t d = (uint32_t)n; - unsigned char buf[5] = {0xdd, STORE32_BE32(d)}; - msgpack_pack_append_buffer(x, buf, 5); - } -} - - -/* - * Map - */ - -msgpack_pack_inline_func(_map)(msgpack_pack_user x, unsigned int n) -{ - if(n < 16) { - unsigned char d = 0x80 | n; - msgpack_pack_append_buffer(x, &STORE8_BE8(d), 1); - } else if(n < 65536) { - uint16_t d = (uint16_t)n; - unsigned char buf[3] = {0xde, STORE16_BE16(d)}; - msgpack_pack_append_buffer(x, buf, 3); - } else { - uint32_t d = (uint32_t)n; - unsigned char buf[5] = {0xdf, STORE32_BE32(d)}; - msgpack_pack_append_buffer(x, buf, 5); - } -} - - -/* - * Raw - */ - -msgpack_pack_inline_func(_raw)(msgpack_pack_user x, size_t l) -{ - if(l < 32) { - unsigned char d = 0xa0 | l; - msgpack_pack_append_buffer(x, &STORE8_BE8(d), 1); - } else if(l < 65536) { - uint16_t d = (uint16_t)l; - unsigned char buf[3] = {0xda, STORE16_BE16(d)}; - msgpack_pack_append_buffer(x, buf, 3); - } else { - uint32_t d = (uint32_t)l; - unsigned char buf[5] = {0xdb, STORE32_BE32(d)}; - msgpack_pack_append_buffer(x, buf, 5); - } -} - -msgpack_pack_inline_func(_raw_body)(msgpack_pack_user x, const void* b, size_t l) -{ - msgpack_pack_append_buffer(x, (const unsigned char*)b, l); -} - -#undef msgpack_pack_inline_func -#undef msgpack_pack_user -#undef msgpack_pack_append_buffer - -#undef STORE8_BE8 - -#undef STORE16_BE8 -#undef STORE16_BE16 - -#undef STORE32_BE8 -#undef STORE32_BE16 -#undef STORE32_BE32 - -#undef STORE64_BE8 -#undef STORE64_BE16 -#undef STORE64_BE32 -#undef STORE64_BE64 - -#undef msgpack_pack_real_uint8 -#undef msgpack_pack_real_uint16 -#undef msgpack_pack_real_uint32 -#undef msgpack_pack_real_uint64 -#undef msgpack_pack_real_int8 -#undef msgpack_pack_real_int16 -#undef msgpack_pack_real_int32 -#undef msgpack_pack_real_int64 - diff --git a/php/msgpack/unpack_define.h b/php/msgpack/unpack_define.h deleted file mode 100644 index 63668c24..00000000 --- a/php/msgpack/unpack_define.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * MessagePack unpacking routine template - * - * Copyright (C) 2008-2009 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MSGPACK_UNPACK_DEFINE_H__ -#define MSGPACK_UNPACK_DEFINE_H__ - -#include -#include -#include -#include -#include -#ifndef __WIN32__ -#include -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef MSGPACK_MAX_STACK_SIZE -#define MSGPACK_MAX_STACK_SIZE 16 -#endif - - -#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define __LITTLE_ENDIAN__ -#elif __BYTE_ORDER == __BIG_ENDIAN -#define __BIG_ENDIAN__ -#endif -#endif - -#define msgpack_betoh16(x) ntohs(x) -#define msgpack_betoh32(x) ntohl(x) - -#ifdef __LITTLE_ENDIAN__ -#if defined(__bswap_64) -# define msgpack_betoh64(x) __bswap_64(x) -#elif defined(__DARWIN_OSSwapInt64) -# define msgpack_betoh64(x) __DARWIN_OSSwapInt64(x) -#else -static inline uint64_t msgpack_betoh64(uint64_t x) { - return ((x << 56) & 0xff00000000000000ULL ) | - ((x << 40) & 0x00ff000000000000ULL ) | - ((x << 24) & 0x0000ff0000000000ULL ) | - ((x << 8) & 0x000000ff00000000ULL ) | - ((x >> 8) & 0x00000000ff000000ULL ) | - ((x >> 24) & 0x0000000000ff0000ULL ) | - ((x >> 40) & 0x000000000000ff00ULL ) | - ((x >> 56) & 0x00000000000000ffULL ) ; -} -#endif -#else -#define msgpack_betoh64(x) (x) -#endif - - -typedef enum { - CS_HEADER = 0x00, // nil - - //CS_ = 0x01, - //CS_ = 0x02, // false - //CS_ = 0x03, // true - - //CS_ = 0x04, - //CS_ = 0x05, - //CS_ = 0x06, - //CS_ = 0x07, - - //CS_ = 0x08, - //CS_ = 0x09, - CS_FLOAT = 0x0a, - CS_DOUBLE = 0x0b, - CS_UINT_8 = 0x0c, - CS_UINT_16 = 0x0d, - CS_UINT_32 = 0x0e, - CS_UINT_64 = 0x0f, - CS_INT_8 = 0x10, - CS_INT_16 = 0x11, - CS_INT_32 = 0x12, - CS_INT_64 = 0x13, - - //CS_ = 0x14, - //CS_ = 0x15, - //CS_BIG_INT_16 = 0x16, - //CS_BIG_INT_32 = 0x17, - //CS_BIG_FLOAT_16 = 0x18, - //CS_BIG_FLOAT_32 = 0x19, - CS_RAW_16 = 0x1a, - CS_RAW_32 = 0x1b, - CS_ARRAY_16 = 0x1c, - CS_ARRAY_32 = 0x1d, - CS_MAP_16 = 0x1e, - CS_MAP_32 = 0x1f, - - //ACS_BIG_INT_VALUE, - //ACS_BIG_FLOAT_VALUE, - ACS_RAW_VALUE, -} msgpack_unpack_state; - - -typedef enum { - CT_ARRAY_ITEM, - CT_MAP_KEY, - CT_MAP_VALUE, -} msgpack_container_type; - - -#ifdef __cplusplus -} -#endif - -#endif /* msgpack/unpack_define.h */ - diff --git a/php/msgpack/unpack_template.h b/php/msgpack/unpack_template.h deleted file mode 100644 index d67fd1ef..00000000 --- a/php/msgpack/unpack_template.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * MessagePack unpacking routine template - * - * Copyright (C) 2008-2009 FURUHASHI Sadayuki - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef msgpack_unpack_func -#error msgpack_unpack_func template is not defined -#endif - -#ifndef msgpack_unpack_callback -#error msgpack_unpack_callback template is not defined -#endif - -#ifndef msgpack_unpack_struct -#error msgpack_unpack_struct template is not defined -#endif - -#ifndef msgpack_unpack_struct_decl -#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name) -#endif - -#ifndef msgpack_unpack_object -#error msgpack_unpack_object type is not defined -#endif - -#ifndef msgpack_unpack_user -#error msgpack_unpack_user type is not defined -#endif - - -msgpack_unpack_struct_decl(_stack) { - msgpack_unpack_object obj; - size_t count; - unsigned int ct; - msgpack_unpack_object map_key; -}; - -msgpack_unpack_struct_decl(_context) { - msgpack_unpack_user user; - unsigned int cs; - unsigned int trail; - unsigned int top; - msgpack_unpack_struct(_stack) stack[MSGPACK_MAX_STACK_SIZE]; -}; - - -msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) -{ - ctx->cs = CS_HEADER; - ctx->trail = 0; - ctx->top = 0; - ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); -} - -msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) -{ - return (ctx)->stack[0].obj; -} - - -msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off) -{ - assert(len >= *off); - - const unsigned char* p = (unsigned char*)data + *off; - const unsigned char* const pe = (unsigned char*)data + len; - const void* n = NULL; - - unsigned int trail = ctx->trail; - unsigned int cs = ctx->cs; - unsigned int top = ctx->top; - msgpack_unpack_struct(_stack)* stack = ctx->stack; - msgpack_unpack_user* user = &ctx->user; - - msgpack_unpack_object obj; - msgpack_unpack_struct(_stack)* c = NULL; - - int ret; - -#define push_simple_value(func) \ - if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \ - goto _push -#define push_fixed_value(func, arg) \ - if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \ - goto _push -#define push_variable_value(func, base, pos, len) \ - if(msgpack_unpack_callback(func)(user, \ - (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ - goto _push - -#define again_fixed_trail(_cs, trail_len) \ - trail = trail_len; \ - cs = _cs; \ - goto _fixed_trail_again -#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ - trail = trail_len; \ - if(trail == 0) { goto ifzero; } \ - cs = _cs; \ - goto _fixed_trail_again - -#define start_container(func, count_, ct_) \ - if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ - if((count_) == 0) { obj = stack[top].obj; goto _push; } \ - if(top >= MSGPACK_MAX_STACK_SIZE) { goto _failed; } \ - stack[top].ct = ct_; \ - stack[top].count = count_; \ - /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ - /*printf("stack push %d\n", top);*/ \ - ++top; \ - goto _header_again - -#define NEXT_CS(p) \ - ((unsigned int)*p & 0x1f) - -#define PTR_CAST_8(ptr) (*(uint8_t*)ptr) -#define PTR_CAST_16(ptr) msgpack_betoh16(*(uint16_t*)ptr) -#define PTR_CAST_32(ptr) msgpack_betoh32(*(uint32_t*)ptr) -#define PTR_CAST_64(ptr) msgpack_betoh64(*(uint64_t*)ptr) - - if(p == pe) { goto _out; } - do { - switch(cs) { - case CS_HEADER: - switch(*p) { - case 0x00 ... 0x7f: // Positive Fixnum - push_fixed_value(_uint8, *(uint8_t*)p); - case 0xe0 ... 0xff: // Negative Fixnum - push_fixed_value(_int8, *(int8_t*)p); - case 0xc0 ... 0xdf: // Variable - switch(*p) { - case 0xc0: // nil - push_simple_value(_nil); - //case 0xc1: // string - // again_terminal_trail(NEXT_CS(p), p+1); - case 0xc2: // false - push_simple_value(_false); - case 0xc3: // true - push_simple_value(_true); - //case 0xc4: - //case 0xc5: - //case 0xc6: - //case 0xc7: - //case 0xc8: - //case 0xc9: - case 0xca: // float - case 0xcb: // double - case 0xcc: // unsigned int 8 - case 0xcd: // unsigned int 16 - case 0xce: // unsigned int 32 - case 0xcf: // unsigned int 64 - case 0xd0: // signed int 8 - case 0xd1: // signed int 16 - case 0xd2: // signed int 32 - case 0xd3: // signed int 64 - again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); - //case 0xd4: - //case 0xd5: - //case 0xd6: // big integer 16 - //case 0xd7: // big integer 32 - //case 0xd8: // big float 16 - //case 0xd9: // big float 32 - case 0xda: // raw 16 - case 0xdb: // raw 32 - case 0xdc: // array 16 - case 0xdd: // array 32 - case 0xde: // map 16 - case 0xdf: // map 32 - again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01)); - default: - goto _failed; - } - case 0xa0 ... 0xbf: // FixRaw - again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero); - case 0x90 ... 0x9f: // FixArray - start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM); - case 0x80 ... 0x8f: // FixMap - start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY); - - default: - goto _failed; - } - // end CS_HEADER - - - _fixed_trail_again: - ++p; - - default: - if((size_t)(pe - p) < trail) { goto _out; } - n = p; p += trail - 1; - switch(cs) { - //case CS_ - //case CS_ - case CS_FLOAT: { - union { uint32_t num; char buf[4]; } f; - f.num = PTR_CAST_32(n); // FIXME - push_fixed_value(_float, *((float*)f.buf)); } - case CS_DOUBLE: { - union { uint64_t num; char buf[8]; } f; - f.num = PTR_CAST_64(n); // FIXME - push_fixed_value(_double, *((double*)f.buf)); } - case CS_UINT_8: - push_fixed_value(_uint8, (uint8_t)PTR_CAST_8(n)); - case CS_UINT_16: - push_fixed_value(_uint16, (uint16_t)PTR_CAST_16(n)); - case CS_UINT_32: - push_fixed_value(_uint32, (uint32_t)PTR_CAST_32(n)); - case CS_UINT_64: - push_fixed_value(_uint64, (uint64_t)PTR_CAST_64(n)); - - case CS_INT_8: - push_fixed_value(_int8, (int8_t)PTR_CAST_8(n)); - case CS_INT_16: - push_fixed_value(_int16, (int16_t)PTR_CAST_16(n)); - case CS_INT_32: - push_fixed_value(_int32, (int32_t)PTR_CAST_32(n)); - case CS_INT_64: - push_fixed_value(_int64, (int64_t)PTR_CAST_64(n)); - - //case CS_ - //case CS_ - //case CS_BIG_INT_16: - // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, (uint16_t)PTR_CAST_16(n), _big_int_zero); - //case CS_BIG_INT_32: - // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, (uint32_t)PTR_CAST_32(n), _big_int_zero); - //case ACS_BIG_INT_VALUE: - //_big_int_zero: - // // FIXME - // push_variable_value(_big_int, data, n, trail); - - //case CS_BIG_FLOAT_16: - // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, (uint16_t)PTR_CAST_16(n), _big_float_zero); - //case CS_BIG_FLOAT_32: - // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, (uint32_t)PTR_CAST_32(n), _big_float_zero); - //case ACS_BIG_FLOAT_VALUE: - //_big_float_zero: - // // FIXME - // push_variable_value(_big_float, data, n, trail); - - case CS_RAW_16: - again_fixed_trail_if_zero(ACS_RAW_VALUE, (uint16_t)PTR_CAST_16(n), _raw_zero); - case CS_RAW_32: - again_fixed_trail_if_zero(ACS_RAW_VALUE, (uint32_t)PTR_CAST_32(n), _raw_zero); - case ACS_RAW_VALUE: - _raw_zero: - push_variable_value(_raw, data, n, trail); - - case CS_ARRAY_16: - start_container(_array, (uint16_t)PTR_CAST_16(n), CT_ARRAY_ITEM); - case CS_ARRAY_32: - /* FIXME security guard */ - start_container(_array, (uint32_t)PTR_CAST_32(n), CT_ARRAY_ITEM); - - case CS_MAP_16: - start_container(_map, (uint16_t)PTR_CAST_16(n), CT_MAP_KEY); - case CS_MAP_32: - /* FIXME security guard */ - start_container(_map, (uint32_t)PTR_CAST_32(n), CT_MAP_KEY); - - default: - goto _failed; - } - } - -_push: - if(top == 0) { goto _finish; } - c = &stack[top-1]; - switch(c->ct) { - case CT_ARRAY_ITEM: - if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; } - if(--c->count == 0) { - obj = c->obj; - --top; - /*printf("stack pop %d\n", top);*/ - goto _push; - } - goto _header_again; - case CT_MAP_KEY: - c->map_key = obj; - c->ct = CT_MAP_VALUE; - goto _header_again; - case CT_MAP_VALUE: - if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; } - if(--c->count == 0) { - obj = c->obj; - --top; - /*printf("stack pop %d\n", top);*/ - goto _push; - } - c->ct = CT_MAP_KEY; - goto _header_again; - - default: - goto _failed; - } - -_header_again: - cs = CS_HEADER; - ++p; - } while(p != pe); - goto _out; - - -_finish: - stack[0].obj = obj; - ++p; - ret = 1; - /*printf("-- finish --\n"); */ - goto _end; - -_failed: - /*printf("** FAILED **\n"); */ - ret = -1; - goto _end; - -_out: - ret = 0; - goto _end; - -_end: - ctx->cs = cs; - ctx->trail = trail; - ctx->top = top; - *off = p - (const unsigned char*)data; - - return ret; -} - - -#undef msgpack_unpack_func -#undef msgpack_unpack_callback -#undef msgpack_unpack_struct -#undef msgpack_unpack_object -#undef msgpack_unpack_user - -#undef push_simple_value -#undef push_fixed_value -#undef push_variable_value -#undef again_fixed_trail -#undef again_fixed_trail_if_zero -#undef start_container - -#undef NEXT_CS -#undef PTR_CAST_8 -#undef PTR_CAST_16 -#undef PTR_CAST_32 -#undef PTR_CAST_64 - diff --git a/php/msgpack_class.c b/php/msgpack_class.c new file mode 100644 index 00000000..b728cb56 --- /dev/null +++ b/php/msgpack_class.c @@ -0,0 +1,340 @@ + +#include "php.h" + +#include "php_msgpack.h" +#include "msgpack_pack.h" +#include "msgpack_unpack.h" +#include "msgpack_class.h" + +typedef struct { + zend_object object; + smart_str buffer; + zval *retval; + long offset; +} php_msgpack_unpacker_t; + +#if ZEND_MODULE_API_NO >= 20060613 +#define MAGPACK_METHOD_BASE(classname, name) zim_##classname##_##name +#else +#define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name +#endif + +#define MSGPACK_METHOD(classname, name, retval, thisptr) \ + MAGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) + +#define MSGPACK_UNPACKER_OBJECT \ + php_msgpack_unpacker_t *unpacker; \ + unpacker =(php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); + +/* MessagePack */ +static zend_class_entry *msgpack_ce = NULL; + +static ZEND_METHOD(msgpack, pack); +static ZEND_METHOD(msgpack, unpack); +static ZEND_METHOD(msgpack, unpacker); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_pack, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_unpack, 0, 0, 1) + ZEND_ARG_INFO(0, str) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_unpacker, 0, 0, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry msgpack_base_methods[] = { + ZEND_ME(msgpack, pack, arginfo_msgpack_base_pack, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, unpack, arginfo_msgpack_base_unpack, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, unpacker, arginfo_msgpack_base_unpacker, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +/* MessagePackUnpacker */ +static zend_class_entry *msgpack_unpacker_ce = NULL; + +static ZEND_METHOD(msgpack, __construct); +static ZEND_METHOD(msgpack, __destruct); +static ZEND_METHOD(msgpack, feed); +static ZEND_METHOD(msgpack, execute); +static ZEND_METHOD(msgpack, data); +static ZEND_METHOD(msgpack, reset); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___construct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___destruct, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_feed, 0, 0, 1) + ZEND_ARG_INFO(0, str) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_execute, 1, 0, 0) + ZEND_ARG_INFO(0, str) + ZEND_ARG_INFO(1, offset) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_data, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_reset, 0, 0, 0) +ZEND_END_ARG_INFO() + +static const zend_function_entry msgpack_unpacker_methods[] = { + ZEND_ME(msgpack, __construct, + arginfo_msgpack_unpacker___construct, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, __destruct, + arginfo_msgpack_unpacker___destruct, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, feed, arginfo_msgpack_unpacker_feed, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, execute, arginfo_msgpack_unpacker_execute, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, data, arginfo_msgpack_unpacker_data, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, reset, arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) + {NULL, NULL, NULL} +}; + +static void php_msgpack_unpacker_free( + php_msgpack_unpacker_t *unpacker TSRMLS_DC) +{ + zend_object_std_dtor(&unpacker->object TSRMLS_CC); + efree(unpacker); +} + +static zend_object_value php_msgpack_unpacker_new( + zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + zval *tmp; + php_msgpack_unpacker_t *unpacker; + + unpacker = emalloc(sizeof(php_msgpack_unpacker_t)); + + zend_object_std_init(&unpacker->object, ce TSRMLS_CC); + + zend_hash_copy( + unpacker->object.properties, &ce->default_properties, + (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); + + retval.handle = zend_objects_store_put( + unpacker, (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)php_msgpack_unpacker_free, + NULL TSRMLS_CC); + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} + +/* MessagePack */ +static ZEND_METHOD(msgpack, pack) +{ + zval *parameter; + smart_str buf = {0}; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) + { + return; + } + + php_msgpack_serialize(&buf, parameter TSRMLS_CC); + + ZVAL_STRINGL(return_value, buf.c, buf.len, 1); + + smart_str_free(&buf); +} + +static ZEND_METHOD(msgpack, unpack) +{ + char *str; + int str_len; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) + { + return; + } + + if (!str_len) + { + RETURN_NULL(); + } + + php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); +} + +static ZEND_METHOD(msgpack, unpacker) +{ + zval temp; + + object_init_ex(return_value, msgpack_unpacker_ce); + + MSGPACK_METHOD(msgpack, __construct, &temp, return_value); +} + +/* MessagePackUnpacker */ +static ZEND_METHOD(msgpack, __construct) +{ + MSGPACK_UNPACKER_OBJECT; + + unpacker->buffer.c = NULL; + unpacker->buffer.len = 0; + unpacker->buffer.a = 0; + unpacker->retval = NULL; + unpacker->offset = 0; +} + +static ZEND_METHOD(msgpack, __destruct) +{ + MSGPACK_UNPACKER_OBJECT; + + smart_str_free(&unpacker->buffer); + + if (unpacker->retval != NULL) + { + zval_ptr_dtor(&unpacker->retval); + } +} + +static ZEND_METHOD(msgpack, feed) +{ + char *str; + int str_len; + MSGPACK_UNPACKER_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) + { + return; + } + + if (!str_len) + { + RETURN_FALSE; + } + + smart_str_appendl(&unpacker->buffer, str, str_len); + + RETURN_TRUE; +} + +static ZEND_METHOD(msgpack, execute) +{ + char *str = NULL; + long str_len = 0; + zval *offset; + int ret; + php_unserialize_data_t var_hash; + msgpack_unserialize_data mpsd; + MSGPACK_UNPACKER_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "|sz/", + &str, &str_len, &offset) == FAILURE) + { + return; + } + + if (str != NULL) + { + mpsd.data = (unsigned char *)str; + mpsd.length = str_len; + mpsd.offset = Z_LVAL_P(offset); + } + else + { + mpsd.data = (unsigned char *)unpacker->buffer.c; + mpsd.length = unpacker->buffer.len; + mpsd.offset = unpacker->offset; + } + + if (mpsd.length <= 0 || mpsd.length == mpsd.offset) + { + RETURN_FALSE; + } + + PHP_VAR_UNSERIALIZE_INIT(var_hash); + + if (unpacker->retval == NULL) + { + ALLOC_INIT_ZVAL(unpacker->retval); + } + + MSGPACK_G(error_display) = 0; + + ret = msgpack_unserialize_zval( + &unpacker->retval, &mpsd, &var_hash TSRMLS_CC); + + MSGPACK_G(error_display) = 1; + + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + + if (str != NULL) + { + ZVAL_LONG(offset, mpsd.offset); + } + else + { + unpacker->offset = mpsd.offset; + } + + switch (ret) + { + case MSGPACK_UNPACK_EXTRA_BYTES: + case MSGPACK_UNPACK_SUCCESS: + RETURN_TRUE; + default: + RETURN_FALSE; + } +} + +static ZEND_METHOD(msgpack, data) +{ + MSGPACK_UNPACKER_OBJECT; + + RETURN_ZVAL(unpacker->retval, 1, 1); +} + +static ZEND_METHOD(msgpack, reset) +{ + smart_str buffer = {0}; + MSGPACK_UNPACKER_OBJECT; + + if (unpacker->buffer.len > unpacker->offset) + { + smart_str_appendl(&buffer, unpacker->buffer.c + unpacker->offset, + unpacker->buffer.len - unpacker->offset); + } + + smart_str_free(&unpacker->buffer); + + unpacker->buffer.c = NULL; + unpacker->buffer.len = 0; + unpacker->buffer.a = 0; + unpacker->offset = 0; + + if (buffer.len > 0) + { + smart_str_appendl(&unpacker->buffer, buffer.c, buffer.len); + } + + smart_str_free(&buffer); + + if (unpacker->retval != NULL) + { + zval_ptr_dtor(&unpacker->retval); + unpacker->retval = NULL; + } +} + +void msgpack_init_class(TSRMLS_DC) +{ + zend_class_entry ce; + + INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_base_methods); + msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC); + + INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods); + msgpack_unpacker_ce = zend_register_internal_class(&ce TSRMLS_CC); + msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new; +} diff --git a/php/msgpack_class.h b/php/msgpack_class.h new file mode 100644 index 00000000..00ac9e7b --- /dev/null +++ b/php/msgpack_class.h @@ -0,0 +1,7 @@ + +#ifndef MSGPACL_CLASS_H +#define MSGPACL_CLASS_H + +void msgpack_init_class(TSRMLS_DC); + +#endif diff --git a/php/msgpack_pack.c b/php/msgpack_pack.c new file mode 100644 index 00000000..91a3d396 --- /dev/null +++ b/php/msgpack_pack.c @@ -0,0 +1,514 @@ + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/php_smart_str.h" +#include "ext/standard/php_incomplete_class.h" +#include "ext/standard/php_var.h" + +#include "php_msgpack.h" +#include "msgpack_pack.h" + +#include "msgpack/pack_define.h" +#define msgpack_pack_user smart_str* +#define msgpack_pack_inline_func(name) \ + static inline void msgpack_pack ## name +#define msgpack_pack_inline_func_cint(name) \ + static inline void msgpack_pack ## name +#define msgpack_pack_append_buffer(user, buf, len) \ + smart_str_appendl(user, (const void*)buf, len) +#include "msgpack/pack_template.h" + +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) +# define Z_ISREF_P(pz) PZVAL_IS_REF(pz) +#endif + +inline static int msgpack_var_add( + HashTable *var_hash, zval *var, void *var_old TSRMLS_DC) +{ + ulong var_no; + char id[32], *p; + int len; + + if ((Z_TYPE_P(var) == IS_OBJECT) && Z_OBJ_HT_P(var)->get_class_entry) + { + p = smart_str_print_long( + id + sizeof(id) - 1, + (((size_t)Z_OBJCE_P(var) << 5) + | ((size_t)Z_OBJCE_P(var) >> (sizeof(long) * 8 - 5))) + + (long)Z_OBJ_HANDLE_P(var)); + len = id + sizeof(id) - 1 - p; + } + else + { + p = smart_str_print_long(id + sizeof(id) - 1, (long)var); + len = id + sizeof(id) - 1 - p; + } + + if (var_old && zend_hash_find(var_hash, p, len, var_old) == SUCCESS) + { + if (!Z_ISREF_P(var)) + { + var_no = -1; + zend_hash_next_index_insert( + var_hash, &var_no, sizeof(var_no), NULL); + } + return FAILURE; + } + + var_no = zend_hash_num_elements(var_hash) + 1; + + zend_hash_add(var_hash, p, len, &var_no, sizeof(var_no), NULL); + + return SUCCESS; +} + +inline static void msgpack_serialize_string( + smart_str *buf, char *str, size_t len) +{ + msgpack_pack_raw(buf, len); + msgpack_pack_raw_body(buf, str, len); +} + +inline static void msgpack_serialize_class( + smart_str *buf, zval *val, zval *retval_ptr, HashTable *var_hash, + char *class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) +{ + int count; + HashTable *ht = HASH_OF(retval_ptr); + + count = zend_hash_num_elements(ht); + if (incomplete_class) + { + --count; + } + + if (count > 0) + { + char *key; + zval **data, **name; + ulong key_index; + HashPosition pos; + int n; + zval nval, *nvalp; + + msgpack_pack_map(buf, count + 1); + + msgpack_pack_nil(buf); + msgpack_serialize_string(buf, class_name, name_len); + + ZVAL_NULL(&nval); + nvalp = &nval; + + zend_hash_internal_pointer_reset_ex(ht, &pos); + + for (;; zend_hash_move_forward_ex(ht, &pos)) + { + n = zend_hash_get_current_key_ex( + ht, &key, NULL, &key_index, 0, &pos); + + if (n == HASH_KEY_NON_EXISTANT) + { + break; + } + if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) + { + continue; + } + + zend_hash_get_current_data_ex(ht, (void **)&name, &pos); + + if (Z_TYPE_PP(name) != IS_STRING) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "__sleep should return an array only " + "containing the names of " + "instance-variables to serialize."); + + msgpack_pack_nil(buf); + continue; + } + + if (zend_hash_find( + Z_OBJPROP_P(val), Z_STRVAL_PP(name), + Z_STRLEN_PP(name) + 1, (void *)&data) == SUCCESS) + { + msgpack_serialize_string( + buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + } + else + { + zend_class_entry *ce; + ce = zend_get_class_entry(val TSRMLS_CC); + if (ce) + { + char *prot_name, *priv_name; + int prop_name_length; + + do + { + zend_mangle_property_name( + &priv_name, &prop_name_length, ce->name, + ce->name_length, Z_STRVAL_PP(name), + Z_STRLEN_PP(name), + ce->type & ZEND_INTERNAL_CLASS); + if (zend_hash_find( + Z_OBJPROP_P(val), priv_name, + prop_name_length + 1, + (void *)&data) == SUCCESS) + { + msgpack_serialize_string( + buf, priv_name, prop_name_length); + + pefree(priv_name, + ce->type & ZEND_INTERNAL_CLASS); + + msgpack_serialize_zval( + buf, *data, var_hash TSRMLS_CC); + break; + } + + pefree(priv_name, + ce->type & ZEND_INTERNAL_CLASS); + + zend_mangle_property_name( + &prot_name, &prop_name_length, "*", 1, + Z_STRVAL_PP(name), Z_STRLEN_PP(name), + ce->type & ZEND_INTERNAL_CLASS); + + if (zend_hash_find( + Z_OBJPROP_P(val), prot_name, + prop_name_length + 1, + (void *)&data) == SUCCESS) + { + msgpack_serialize_string( + buf, prot_name, prop_name_length); + + pefree(prot_name, + ce->type & ZEND_INTERNAL_CLASS); + + msgpack_serialize_zval( + buf, *data, var_hash TSRMLS_CC); + break; + } + + pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); + + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "\"%s\" returned as member variable from " + "__sleep() but does not exist", + Z_STRVAL_PP(name)); + + msgpack_serialize_string( + buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + + msgpack_serialize_zval( + buf, nvalp, var_hash TSRMLS_CC); + } + while (0); + } + else + { + msgpack_serialize_string( + buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); + + msgpack_serialize_zval(buf, nvalp, var_hash TSRMLS_CC); + } + } + } + } +} + +inline static void msgpack_serialize_array( + smart_str *buf, zval *val, HashTable *var_hash, bool object, + char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) +{ + HashTable *ht; + size_t n; + + if (object) + { + ht = Z_OBJPROP_P(val); + } + else + { + ht = HASH_OF(val); + } + + if (ht) + { + n = zend_hash_num_elements(ht); + } + else + { + n = 0; + } + + if (n > 0 && incomplete_class) + { + --n; + } + + if (object) + { + msgpack_pack_map(buf, n + 1); + + msgpack_pack_nil(buf); + + msgpack_serialize_string(buf, class_name, name_len); + } + else if (n == 0) + { + msgpack_pack_array(buf, n); + } + else + { + msgpack_pack_map(buf, n); + } + + if (n > 0) + { + char *key; + uint key_len; + int key_type; + ulong key_index; + zval **data; + HashPosition pos; + + zend_hash_internal_pointer_reset_ex(ht, &pos); + for (;; zend_hash_move_forward_ex(ht, &pos)) + { + key_type = zend_hash_get_current_key_ex( + ht, &key, &key_len, &key_index, 0, &pos); + + if (key_type == HASH_KEY_NON_EXISTANT) + { + break; + } + if (incomplete_class && strcmp(key, MAGIC_MEMBER) == 0) + { + continue; + } + + switch (key_type) + { + case HASH_KEY_IS_LONG: + msgpack_pack_long(buf, key_index); + break; + case HASH_KEY_IS_STRING: + msgpack_serialize_string(buf, key, key_len - 1); + break; + default: + msgpack_serialize_string(buf, "", sizeof("")); + + zend_error(E_WARNING, "[msgpack] (msgpack_serialize_array) " + "key is not string nor array"); + break; + } + + if (zend_hash_get_current_data_ex( + ht, (void *)&data, &pos) != SUCCESS || + !data || data == &val || + (Z_TYPE_PP(data) == IS_ARRAY && + Z_ARRVAL_PP(data)->nApplyCount > 1)) + { + msgpack_pack_nil(buf); + } + else + { + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount++; + } + + msgpack_serialize_zval(buf, *data, var_hash TSRMLS_CC); + + if (Z_TYPE_PP(data) == IS_ARRAY) + { + Z_ARRVAL_PP(data)->nApplyCount--; + } + } + } + } +} + +inline static void msgpack_serialize_object( + smart_str *buf, zval *val, HashTable *var_hash, + char* class_name, zend_uint name_len, zend_bool incomplete_class TSRMLS_DC) +{ + zval *retval_ptr = NULL; + zval fname; + int res; + zend_class_entry *ce = NULL; + + if (Z_OBJ_HT_P(val)->get_class_entry) + { + ce = Z_OBJCE_P(val); + } + + if (ce && ce->serialize != NULL) + { + unsigned char *serialized_data = NULL; + zend_uint serialized_length; + + if (ce->serialize( + val, &serialized_data, &serialized_length, + (zend_serialize_data *)var_hash TSRMLS_CC) == SUCCESS && + !EG(exception)) + { + /* has custom handler */ + msgpack_pack_map(buf, 2); + + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT); + + msgpack_serialize_string(buf, ce->name, ce->name_length); + + msgpack_pack_raw(buf, serialized_length); + msgpack_pack_raw_body(buf, serialized_data, serialized_length); + } + else + { + msgpack_pack_nil(buf); + } + + if (serialized_data) + { + efree(serialized_data); + } + + return; + } + + if (ce && ce != PHP_IC_ENTRY && + zend_hash_exists(&ce->function_table, "__sleep", sizeof("__sleep"))) + { + INIT_PZVAL(&fname); + ZVAL_STRINGL(&fname, "__sleep", sizeof("__sleep") - 1, 0); + res = call_user_function_ex(CG(function_table), &val, &fname, + &retval_ptr, 0, 0, 1, NULL TSRMLS_CC); + if (res == SUCCESS && !EG(exception)) + { + if (retval_ptr) + { + if (HASH_OF(retval_ptr)) + { + msgpack_serialize_class( + buf, val, retval_ptr, var_hash, + class_name, name_len, incomplete_class TSRMLS_CC); + } + else + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_object) " + "__sleep should return an array only " + "containing the names of instance-variables " + "to serialize"); + msgpack_pack_nil(buf); + } + zval_ptr_dtor(&retval_ptr); + } + return; + } + } + + if (retval_ptr) + { + zval_ptr_dtor(&retval_ptr); + } + + msgpack_serialize_array( + buf, val, var_hash, true, + class_name, name_len, incomplete_class TSRMLS_CC); +} + +void msgpack_serialize_zval( + smart_str *buf, zval *val, HashTable *var_hash TSRMLS_DC) +{ + ulong *var_already; + + if (var_hash && + msgpack_var_add( + var_hash, val, (void *)&var_already TSRMLS_CC) == FAILURE) + { + if (Z_ISREF_P(val)) + { + msgpack_pack_map(buf, 2); + + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + + msgpack_pack_nil(buf); + msgpack_pack_long(buf, *var_already); + + return; + } + else if (Z_TYPE_P(val) == IS_OBJECT) + { + msgpack_pack_map(buf, 2); + + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_OBJECT); + + msgpack_pack_nil(buf); + msgpack_pack_long(buf, *var_already); + + return; + } + } + + switch (Z_TYPE_P(val)) + { + case IS_NULL: + msgpack_pack_nil(buf); + break; + case IS_BOOL: + if (Z_BVAL_P(val)) + { + msgpack_pack_true(buf); + } + else + { + msgpack_pack_false(buf); + } + break; + case IS_LONG: + msgpack_pack_long(buf, Z_LVAL_P(val)); + break; + case IS_DOUBLE: + { + double dbl = Z_DVAL_P(val); + msgpack_pack_double(buf, dbl); + } + break; + case IS_STRING: + msgpack_serialize_string( + buf, Z_STRVAL_P(val), Z_STRLEN_P(val)); + break; + case IS_ARRAY: + msgpack_serialize_array( + buf, val, var_hash, false, NULL, 0, 0 TSRMLS_CC); + break; + case IS_OBJECT: + { + PHP_CLASS_ATTRIBUTES; + PHP_SET_CLASS_ATTRIBUTES(val); + + msgpack_serialize_object( + buf, val, var_hash, class_name, name_len, + incomplete_class TSRMLS_CC); + + PHP_CLEANUP_CLASS_ATTRIBUTES(); + } + break; + default: + zend_error(E_WARNING, + "[msgpack] (php_msgpack_serialize) " + "type is unsupported, encoded as null"); + msgpack_pack_nil(buf); + break; + } + return; +} diff --git a/php/msgpack_pack.h b/php/msgpack_pack.h new file mode 100644 index 00000000..96cfd4e8 --- /dev/null +++ b/php/msgpack_pack.h @@ -0,0 +1,17 @@ + +#ifndef MSGPACL_PACK_H +#define MSGPACL_PACK_H + +#include "ext/standard/php_smart_str.h" + +enum msgpack_serialize_type +{ + MSGPACK_SERIALIZE_TYPE_REFERENCE = 1, + MSGPACK_SERIALIZE_TYPE_OBJECT, + MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT, +}; + +void msgpack_serialize_zval( + smart_str *buf, zval *val, HashTable *var_hash TSRMLS_DC); + +#endif diff --git a/php/msgpack_unpack.c b/php/msgpack_unpack.c new file mode 100644 index 00000000..c6b9b3f9 --- /dev/null +++ b/php/msgpack_unpack.c @@ -0,0 +1,829 @@ + +#include "php.h" +#include "php_ini.h" +#include "ext/standard/php_incomplete_class.h" +#include "ext/standard/php_var.h" + +#include "php_msgpack.h" +#include "msgpack_pack.h" +#include "msgpack_unpack.h" + +#include "msgpack/unpack_define.h" + +#define VAR_ENTRIES_MAX 1024 + +#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) +# define Z_ADDREF_PP(ppz) ZVAL_ADDREF(*(ppz)) +# define Z_SET_ISREF_PP(ppz) (*(ppz))->is_ref = 1 +# define Z_UNSET_ISREF_PP(ppz) (*(ppz))->is_ref = 0 +#endif + +typedef struct +{ + zval *data[VAR_ENTRIES_MAX]; + long used_slots; + void *next; +} var_entries; + +inline static void msgpack_var_push( + php_unserialize_data_t *var_hashx, zval **rval) +{ + var_entries *var_hash, *prev = NULL; + + if (!var_hashx) + { + return; + } + + var_hash = var_hashx->first; + + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) + { + prev = var_hash; + var_hash = var_hash->next; + } + + if (!var_hash) + { + var_hash = emalloc(sizeof(var_entries)); + var_hash->used_slots = 0; + var_hash->next = 0; + + if (!var_hashx->first) + { + var_hashx->first = var_hash; + } + else + { + prev->next = var_hash; + } + } + + var_hash->data[var_hash->used_slots++] = *rval; +} + +inline static int msgpack_var_access( + php_unserialize_data_t *var_hashx, long id, zval ***store) +{ + var_entries *var_hash = var_hashx->first; + + while (id >= VAR_ENTRIES_MAX && + var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) + { + var_hash = var_hash->next; + id -= VAR_ENTRIES_MAX; + } + + if (!var_hash) + { + return !SUCCESS; + } + + if (id < 0 || id >= var_hash->used_slots) + { + return !SUCCESS; + } + + *store = &var_hash->data[id]; + + return SUCCESS; +} + +inline static int msgpack_unserialize_array( + zval **return_value, msgpack_unserialize_data *mpsd, + ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) +{ + ulong i; + HashTable *ht; + + msgpack_var_push(var_hash, return_value); + + if (Z_TYPE_PP(return_value) != IS_ARRAY) + { + array_init(*return_value); + } + + ht = HASH_OF(*return_value); + + for (i = 0; i < ct; i++) + { + zval *val; + + /* value */ + ALLOC_INIT_ZVAL(val); + + if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_array) " + "Invalid value"); + } + zval_ptr_dtor(&val); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + /* update */ + zend_hash_index_update(ht, i, &val, sizeof(zval *), NULL); + } + + return MSGPACK_UNPACK_SUCCESS; +} + +inline static int msgpack_unserialize_object_type( + zval **return_value, msgpack_unserialize_data *mpsd, + php_unserialize_data_t *var_hash, zend_bool is_ref TSRMLS_DC) +{ + int ret = MSGPACK_UNPACK_SUCCESS; + zval *key, *val, **rval; + + ALLOC_INIT_ZVAL(key); + + if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) + { + zval_ptr_dtor(&key); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + ALLOC_INIT_ZVAL(val); + + if (is_ref) + { + ret = msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC); + } + else + { + ret = msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC); + } + + if (ret <= 0) + { + zval_ptr_dtor(&val); + zval_ptr_dtor(&key); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + if (!var_hash || + msgpack_var_access(var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object_key) " + "Invalid references value: %ld", + Z_LVAL_P(val) - 1); + } + ret = MSGPACK_UNPACK_CONTINUE; + } + else + { + if (*return_value != NULL) + { + zval_ptr_dtor(return_value); + } + + *return_value = *rval; + + Z_ADDREF_PP(return_value); + + if (is_ref) + { + Z_SET_ISREF_PP(return_value); + } + else + { + Z_UNSET_ISREF_PP(return_value); + } + } + + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + return ret; +} + +inline static int msgpack_unserialize_object( + zval **return_value, msgpack_unserialize_data *mpsd, + ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) +{ + int ret = MSGPACK_UNPACK_SUCCESS; + + zend_class_entry *ce, **pce; + bool incomplete_class = false; + zval *user_func, *retval_ptr, **args[1], *arg_func_name; + HashTable *ht; + + zval *key, *val; + + int object = 1; + int custom_object = 0; + + /* Get class */ + ALLOC_INIT_ZVAL(key); + + if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Invalid sign key"); + } + + zval_ptr_dtor(&key); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + ct--; + + if (Z_TYPE_P(key) == IS_NULL) + { + ALLOC_INIT_ZVAL(val); + + if (msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC) <= 0) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Invalid sign value"); + } + + zval_ptr_dtor(&val); + zval_ptr_dtor(&key); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + if (Z_TYPE_P(val) == IS_LONG) + { + switch (Z_LVAL_P(val)) + { + case MSGPACK_SERIALIZE_TYPE_REFERENCE: + ret = msgpack_unserialize_object_type( + return_value, mpsd, var_hash, 1 TSRMLS_CC); + + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + return ret; + case MSGPACK_SERIALIZE_TYPE_OBJECT: + ret = msgpack_unserialize_object_type( + return_value, mpsd, var_hash, 0 TSRMLS_CC); + + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + return ret; + case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: + custom_object = 1; + + zval_ptr_dtor(&val); + + ALLOC_INIT_ZVAL(val); + + if (msgpack_unserialize_zval( + &val, mpsd, NULL TSRMLS_CC) <= 0) + { + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + break; + default: + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + } + } + else + { + object = 0; + + msgpack_var_push(var_hash, return_value); + + if (Z_TYPE_PP(return_value) != IS_ARRAY) + { + array_init(*return_value); + } + + ht = HASH_OF(*return_value); + + ALLOC_INIT_ZVAL(val); + + if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Invalid sign value"); + } + + zval_ptr_dtor(&val); + zval_ptr_dtor(&key); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + /* update */ + switch (Z_TYPE_P(key)) + { + case IS_LONG: + zend_hash_index_update( + ht, Z_LVAL_P(key), &val, sizeof(zval *), NULL); + break; + case IS_STRING: + zend_symtable_update( + ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, + &val, sizeof(zval *), NULL); + break; + default: + zval_ptr_dtor(&key); + zval_ptr_dtor(&val); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + } + + zval_ptr_dtor(&key); + + if (object) + { + convert_to_string(val); + + do { + /* Try to find class directly */ + if (zend_lookup_class( + Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + break; + } + + /* Check for unserialize callback */ + if ((PG(unserialize_callback_func) == NULL) || + (PG(unserialize_callback_func)[0] == '\0')) + { + incomplete_class = 1; + ce = PHP_IC_ENTRY; + break; + } + + /* Call unserialize callback */ + ALLOC_INIT_ZVAL(user_func); + ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); + args[0] = &arg_func_name; + ALLOC_INIT_ZVAL(arg_func_name); + ZVAL_STRING(arg_func_name, Z_STRVAL_P(val), 1); + if (call_user_function_ex( + CG(function_table), NULL, user_func, &retval_ptr, + 1, args, 0, NULL TSRMLS_CC) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "defined (%s) but not found", Z_STRVAL_P(val)); + } + + incomplete_class = 1; + ce = PHP_IC_ENTRY; + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + break; + } + if (retval_ptr) + { + zval_ptr_dtor(&retval_ptr); + } + + /* The callback function may have defined the class */ + if (zend_lookup_class( + Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + } + else + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Function %s() hasn't defined the class" + "it was called for", Z_STRVAL_P(val)); + } + + incomplete_class = true; + ce = PHP_IC_ENTRY; + } + + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + } while(0); + + if (EG(exception)) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Exception error"); + } + + zval_ptr_dtor(&val); + + ZVAL_BOOL(*return_value, 0); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + msgpack_var_push(var_hash, return_value); + + object_init_ex(*return_value, ce); + + /* store incomplete class name */ + if (incomplete_class) + { + php_store_class_name( + *return_value, Z_STRVAL_P(val), Z_STRLEN_P(val)); + } + + zval_ptr_dtor(&val); + + /* implementing Serializable */ + if (custom_object) + { + zval *rval; + + if (ce->unserialize == NULL) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_object) " + "Class %s has no unserializer", ce->name); + } + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + /* value */ + ALLOC_INIT_ZVAL(rval); + + if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) + { + zval_ptr_dtor(&rval); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + ce->unserialize( + return_value, ce, + (const unsigned char *)Z_STRVAL_P(rval), Z_STRLEN_P(rval) + 1, + (zend_unserialize_data *)var_hash TSRMLS_CC); + + zval_ptr_dtor(&key); + zval_ptr_dtor(&rval); + + return ret; + } + + ht = HASH_OF(*return_value); + } + + /* object property */ + while (ct-- > 0) + { + zval *rval; + + /* key */ + ALLOC_INIT_ZVAL(key); + + if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) + { + zval_ptr_dtor(&key); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + /* value */ + ALLOC_INIT_ZVAL(rval); + + if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) + { + zval_ptr_dtor(&rval); + zval_ptr_dtor(&key); + + return MSGPACK_UNPACK_PARSE_ERROR; + + } + + /* update */ + switch (Z_TYPE_P(key)) + { + case IS_LONG: + zend_hash_index_update( + ht, Z_LVAL_P(key), &rval, sizeof(zval *), NULL); + break; + case IS_STRING: + zend_symtable_update( + ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, + &rval, sizeof(zval *), NULL); + break; + default: + zval_ptr_dtor(&key); + zval_ptr_dtor(&rval); + + return MSGPACK_UNPACK_PARSE_ERROR; + } + + zval_ptr_dtor(&key); + } + + /* wakeup */ + if (object && Z_OBJCE_PP(return_value) != PHP_IC_ENTRY && + zend_hash_exists(&Z_OBJCE_PP(return_value)->function_table, + "__wakeup", sizeof("__wakeup"))) + { + zval f, *h = NULL; + + INIT_PZVAL(&f); + ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0); + call_user_function_ex( + CG(function_table), return_value, &f, &h, 0, 0, 1, NULL TSRMLS_CC); + if (h) + { + zval_ptr_dtor(&h); + } + + if (EG(exception)) + { + ret = MSGPACK_UNPACK_PARSE_ERROR; + } + } + + return ret; +} + +int msgpack_unserialize_zval( + zval **return_value, msgpack_unserialize_data *mpsd, + php_unserialize_data_t *var_hash TSRMLS_DC) +{ + const unsigned char* data = mpsd->data; + const unsigned char* const pe = mpsd->data + mpsd->length; + const void* n = NULL; + + unsigned int trail = 0; + unsigned int cs = CS_HEADER; + + int ret; + unsigned int ct; + +#define next_cs(p) ((unsigned int)*p & 0x1f) + +#define finish_zval_long(val_) \ + msgpack_var_push(var_hash, return_value); \ + ZVAL_LONG(*return_value, val_); \ + goto _finish + +#define finish_zval_null() \ + msgpack_var_push(var_hash, return_value); \ + ZVAL_NULL(*return_value); \ + goto _finish + +#define finish_zval_bool(val_) \ + msgpack_var_push(var_hash, return_value); \ + ZVAL_BOOL(*return_value, val_); \ + goto _finish + +#define finish_zval_double(val_) \ + msgpack_var_push(var_hash, return_value); \ + ZVAL_DOUBLE(*return_value, val_); \ + goto _finish + +#define finish_zval_string(val_, len_) \ + msgpack_var_push(var_hash, return_value); \ + if (len_ == 0) { ZVAL_STRINGL(*return_value, "", 0, 1); } \ + else { ZVAL_STRINGL(*return_value, val_, len_, 1); } \ + goto _finish + +#define finish_zval_array(count_) \ + ct = count_; \ + cs = CS_HEADER; \ + ++(mpsd->data); \ + mpsd->length = (pe - mpsd->data); \ + if (msgpack_unserialize_array(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ + goto _finish_end + +#define finish_zval_object(count_) \ + ct = count_; \ + cs = CS_HEADER; \ + ++(mpsd->data); \ + mpsd->length = (pe - mpsd->data); \ + if (msgpack_unserialize_object(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ + goto _finish_end + +#define again_fixed_trail(_cs, trail_len) \ + trail = trail_len; \ + cs = _cs; \ + goto _fixed_trail_again + +#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ + trail = trail_len; \ + if(trail == 0) { goto ifzero; } \ + cs = _cs; \ + goto _fixed_trail_again + + if (mpsd->length <= 0) + { + goto _failed; + } + + if (mpsd->data == pe) + { + goto _out; + } + do + { + switch (cs) + { + case CS_HEADER: + switch (*(mpsd->data)) + { + case 0x00 ... 0x7f: /* Positive Fixnum */ + finish_zval_long(*(uint8_t*)mpsd->data); + case 0xe0 ... 0xff: /* Negative Fixnum */ + finish_zval_long(*(int8_t*)mpsd->data); + case 0xc0 ... 0xdf: /* Variable */ + switch (*(mpsd->data)) + { + case 0xc0: /* nil */ + finish_zval_null(); + case 0xc2: /* false */ + finish_zval_bool(0); + case 0xc3: /* true */ + finish_zval_bool(1); + case 0xca: /* float */ + case 0xcb: /* double */ + case 0xcc: /* unsigned int 8 */ + case 0xcd: /* unsigned int 16 */ + case 0xce: /* unsigned int 32 */ + case 0xcf: /* unsigned int 64 */ + case 0xd0: /* signed int 8 */ + case 0xd1: /* signed int 16 */ + case 0xd2: /* signed int 32 */ + case 0xd3: /* signed int 64 */ + again_fixed_trail( + next_cs(mpsd->data), + 1 << (((unsigned int)*(mpsd->data)) & 0x03)); + case 0xda: /* raw 16 */ + case 0xdb: /* raw 32 */ + case 0xdc: /* array 16 */ + case 0xdd: /* array 32 */ + case 0xde: /* map 16 */ + case 0xdf: /* map 32 */ + again_fixed_trail( + next_cs(mpsd->data), + 2 << (((unsigned int)*(mpsd->data)) & 0x01)); + default: + goto _failed; + } + case 0xa0 ... 0xbf: /* FixRaw */ + again_fixed_trail_if_zero( + ACS_RAW_VALUE, (unsigned int)*(mpsd->data) & 0x1f, + _raw_zero); + case 0x90 ... 0x9f: /* FixArray */ + finish_zval_array(((unsigned int)*(mpsd->data)) & 0x0f); + case 0x80 ... 0x8f: /* FixMap */ + finish_zval_object(((unsigned int)*(mpsd->data)) & 0x0f); + default: + goto _failed; + } +_fixed_trail_again: + ++(mpsd->data); + default: + if ((size_t)(pe - (mpsd->data)) < trail) + { + goto _out; + } + n = (mpsd->data); + mpsd->data += trail - 1; + switch (cs) + { + case CS_FLOAT: + { + union { uint32_t i; float f; } mem; + mem.i = _msgpack_load32(uint32_t, n); + finish_zval_double(mem.f); + } + case CS_DOUBLE: + { + union { uint64_t i; double f; } mem; + mem.i = _msgpack_load64(uint64_t, n); + finish_zval_double(mem.f); + } + case CS_UINT_8: + finish_zval_long(*(uint8_t*)n); + case CS_UINT_16: + finish_zval_long(_msgpack_load16(uint16_t, n)); + case CS_UINT_32: + finish_zval_long(_msgpack_load32(uint32_t, n)); + case CS_UINT_64: + finish_zval_long(_msgpack_load64(uint64_t, n)); + case CS_INT_8: + finish_zval_long(*(int8_t*)n); + case CS_INT_16: + finish_zval_long(_msgpack_load16(int16_t, n)); + case CS_INT_32: + finish_zval_long(_msgpack_load32(int32_t, n)); + case CS_INT_64: + finish_zval_long(_msgpack_load64(int64_t, n)); + case CS_RAW_16: + again_fixed_trail_if_zero( + ACS_RAW_VALUE, _msgpack_load16(uint16_t, n), + _raw_zero); + case CS_RAW_32: + again_fixed_trail_if_zero( + ACS_RAW_VALUE, _msgpack_load32(uint32_t, n), + _raw_zero); + case ACS_RAW_VALUE: +_raw_zero: + finish_zval_string(n, trail); + case CS_ARRAY_16: + finish_zval_array(_msgpack_load16(uint16_t, n)); + case CS_ARRAY_32: + finish_zval_array(_msgpack_load32(uint32_t, n)); + /* FIXME security guard */ + case CS_MAP_16: + finish_zval_object(_msgpack_load16(uint16_t, n)); + case CS_MAP_32: + finish_zval_object(_msgpack_load32(uint32_t, n)); + /* FIXME security guard */ + default: + goto _failed; + } + } + cs = CS_HEADER; + ++(mpsd->data); + } + while (mpsd->data != pe); + goto _out; + +_finish: + ++(mpsd->data); +_finish_end: + ret = MSGPACK_UNPACK_EXTRA_BYTES; + goto _end; + +_failed: + ret = MSGPACK_UNPACK_PARSE_ERROR; + goto _end; + +_out: + ret = MSGPACK_UNPACK_CONTINUE; + goto _end; + +_end: + mpsd->offset = mpsd->data - data; + mpsd->length = pe - mpsd->data; + + if (ret == MSGPACK_UNPACK_EXTRA_BYTES && mpsd->length == 0) + { + ret = MSGPACK_UNPACK_SUCCESS; + } + + return ret; +} + +#undef finish_zval_long +#undef finish_zval_null +#undef finish_zval_bool +#undef finish_zval_double +#undef finish_zval_string +#undef finish_zval_array +#undef finish_zval_object +#undef again_fixed_trail +#undef again_fixed_trail_if_zero + +#undef next_cs diff --git a/php/msgpack_unpack.h b/php/msgpack_unpack.h new file mode 100644 index 00000000..6c85d73f --- /dev/null +++ b/php/msgpack_unpack.h @@ -0,0 +1,26 @@ + +#ifndef MSGPACL_UNPACK_H +#define MSGPACL_UNPACK_H + +#include "ext/standard/php_var.h" + +typedef enum +{ + MSGPACK_UNPACK_SUCCESS = 2, + MSGPACK_UNPACK_EXTRA_BYTES = 1, + MSGPACK_UNPACK_CONTINUE = 0, + MSGPACK_UNPACK_PARSE_ERROR = -1, +} msgpack_unpack_return; + +typedef struct +{ + unsigned char *data; + size_t length; + size_t offset; +} msgpack_unserialize_data; + +int msgpack_unserialize_zval( + zval **return_value, msgpack_unserialize_data *mpsd, + php_unserialize_data_t *var_hash TSRMLS_DC); + +#endif diff --git a/php/package.xml b/php/package.xml new file mode 100644 index 00000000..48697704 --- /dev/null +++ b/php/package.xml @@ -0,0 +1,98 @@ + + + msgpack + pecl.php.net + PHP extension for interfacing with MessagePack + This extension provide API for communicating with MessagePack serialization. + + Advect + advect + advect@gmail.com + yes + + 2010-07-17 + + + 0.2.1 + 0.2.1 + + + beta + beta + + New BSD + Initial release. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.4.3 + + + + msgpack + + diff --git a/php/php-msgpack.spec b/php/php-msgpack.spec new file mode 100644 index 00000000..5726c434 --- /dev/null +++ b/php/php-msgpack.spec @@ -0,0 +1,59 @@ +%define php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1) +%{!?php_extdir: %{expand: %%define php_extdir %(php-config --extension-dir)}} + +Summary: PHP extension for interfacing with MessagePack +Name: php-msgpack +Version: 0.2.1 +Release: 1%{?dist} +Source: php-msgpack-%{version}.tar.gz +License: New BSD License +Group: Development/Libraries +Packager: advect +Provides: php-pecl-msgpack +BuildRoot: %{_tmppath}/%{name}-%{version}-root +BuildRequires: php-devel, msgpack-devel +Requires: msgpack +%if 0%{?php_zend_api} +Requires: php(zend-abi) = %{php_zend_api} +Requires: php(api) = %{php_core_api} +%else +Requires: php-api = %{php_apiver} +%endif + +%description +PHP extension for interfacing with MessagePack. + +%prep +%setup -q -n php-msgpack + +%build +phpize +%configure +%{__make} + +%install +%makeinstall INSTALL_ROOT=%{buildroot} + +%{__install} -d %{buildroot}%{_sysconfdir}/php.d +%{__cat} > %{buildroot}%{_sysconfdir}/php.d/msgpack.ini <= 4 +# define PHP_MSGPACK_API __attribute__ ((visibility("default"))) #else -#define PHP_MSGPACK_API +# define PHP_MSGPACK_API #endif #ifdef ZTS #include "TSRM.h" #endif -PHP_MINIT_FUNCTION(msgpack); -PHP_MSHUTDOWN_FUNCTION(msgpack); -PHP_RINIT_FUNCTION(msgpack); -PHP_RSHUTDOWN_FUNCTION(msgpack); -PHP_MINFO_FUNCTION(msgpack); - -PHP_FUNCTION(msgpack_pack); -PHP_FUNCTION(msgpack_unpack); -PHP_FUNCTION(msgpack_unpack_limit); - -PHP_METHOD(msgpack, initialize); -PHP_METHOD(msgpack, execute); -PHP_METHOD(msgpack, execute_limit); -PHP_METHOD(msgpack, finished); -PHP_METHOD(msgpack, data); - -static zend_class_entry *msgpack_ce; - -/* - Declare any global variables you may need between the BEGIN - and END macros here: - ZEND_BEGIN_MODULE_GLOBALS(msgpack) - long global_value; - char *global_string; + zend_bool error_display; ZEND_END_MODULE_GLOBALS(msgpack) -*/ -/* In every utility function you add that needs to use variables - in php_msgpack_globals, call TSRMLS_FETCH(); after declaring other - variables used by that function, or better yet, pass in TSRMLS_CC - after the last function argument and declare your utility function - with TSRMLS_DC after the last declared argument. Always refer to - the globals in your function as MSGPACK_G(variable). You are - encouraged to rename these macros something shorter, see - examples in any other php module directory. -*/ +ZEND_DECLARE_MODULE_GLOBALS(msgpack) +#ifdef ZTS +#define MSGPACK_G(v) TSRMG(msgpack_globals_id, zend_msgpack_globals *, v) +#else +#define MSGPACK_G(v) (msgpack_globals.v) +#endif -#endif /* PHP_MSGPACK_H */ +PHP_MSGPACK_API void php_msgpack_serialize( + smart_str *buf, zval *val TSRMLS_DC); +PHP_MSGPACK_API void php_msgpack_unserialize( + zval *return_value, char *str, size_t str_len TSRMLS_DC); - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: noet sw=4 ts=4 fdm=marker - * vim<600: noet sw=4 ts=4 - */ +#endif /* PHP_MSGPACK_H */ diff --git a/php/test_normal.php b/php/test_normal.php old mode 100755 new mode 100644 diff --git a/php/test_streaming.php b/php/test_streaming.php old mode 100755 new mode 100644 index 8f89f4c6..f2f470e3 --- a/php/test_streaming.php +++ b/php/test_streaming.php @@ -4,8 +4,7 @@ $msgs = array(pack("C*", 0x93, 0x01, 0x02, 0x03, 0x92), pack("C*", 0x03, 0x09, 0x04)); // streaming deserialize - $unpacker = new MessagePack(); - $unpacker->initialize(); + $unpacker = new MessagePackUnpacker(); $buffer = ""; $nread = 0; @@ -13,13 +12,11 @@ $buffer = $buffer . $msg; while(true){ - $nread = $unpacker->execute($buffer, $nread); - - if($unpacker->finished()){ + if($unpacker->execute($buffer, $nread)){ $msg = $unpacker->data(); var_dump($msg); - $unpacker->initialize(); + $unpacker->reset(); $buffer = substr($buffer, $nread); $nread = 0; diff --git a/php/tests/001.phpt b/php/tests/001.phpt new file mode 100644 index 00000000..840ae461 --- /dev/null +++ b/php/tests/001.phpt @@ -0,0 +1,10 @@ +--TEST-- +Check for msgpack presence +--SKIPIF-- + +--FILE-- + +--EXPECT-- +msgpack extension is available diff --git a/php/tests/002.phpt b/php/tests/002.phpt new file mode 100644 index 00000000..75b9488e --- /dev/null +++ b/php/tests/002.phpt @@ -0,0 +1,26 @@ +--TEST-- +Check for null serialisation +--SKIPIF-- +--FILE-- + +--EXPECT-- +null +c0 +NULL +OK diff --git a/php/tests/003.phpt b/php/tests/003.phpt new file mode 100644 index 00000000..8c85f904 --- /dev/null +++ b/php/tests/003.phpt @@ -0,0 +1,31 @@ +--TEST-- +Check for bool serialisation +--SKIPIF-- +--FILE-- + +--EXPECT-- +bool true +c3 +bool(true) +OK +bool false +c2 +bool(false) +OK diff --git a/php/tests/004.phpt b/php/tests/004.phpt new file mode 100644 index 00000000..8c352eca --- /dev/null +++ b/php/tests/004.phpt @@ -0,0 +1,56 @@ +--TEST-- +Check for integer serialisation +--SKIPIF-- +--FILE-- + +--EXPECT-- +zero: 0 +00 +int(0) +OK +small: 1 +01 +int(1) +OK +small: -1 +ff +int(-1) +OK +medium: 1000 +cd03e8 +int(1000) +OK +medium: -1000 +d1fc18 +int(-1000) +OK +large: 100000 +ce000186a0 +int(100000) +OK +large: -100000 +d2fffe7960 +int(-100000) +OK diff --git a/php/tests/005.phpt b/php/tests/005.phpt new file mode 100644 index 00000000..2156ffad --- /dev/null +++ b/php/tests/005.phpt @@ -0,0 +1,26 @@ +--TEST-- +Check for double serialisation +--SKIPIF-- +--FILE-- + +--EXPECT-- +double: 123.456 +cb405edd2f1a9fbe77 +float(123.456) +OK diff --git a/php/tests/006.phpt b/php/tests/006.phpt new file mode 100644 index 00000000..68323553 --- /dev/null +++ b/php/tests/006.phpt @@ -0,0 +1,31 @@ +--TEST-- +Check for simple string serialization +--SKIPIF-- +--FILE-- + +--EXPECT-- +empty: "" +a0 +string(0) "" +OK +string: "foobar" +a6666f6f626172 +string(6) "foobar" +OK diff --git a/php/tests/007.phpt b/php/tests/007.phpt new file mode 100644 index 00000000..db41185b --- /dev/null +++ b/php/tests/007.phpt @@ -0,0 +1,72 @@ +--TEST-- +Check for simple array serialization +--SKIPIF-- +--FILE-- + +--EXPECT-- +empty array: +90 +array(0) { +} +OK +array(1, 2, 3) +83000101020203 +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(array(1, 2, 3), arr... +83008300010102020301830004010502060283000701080209 +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK diff --git a/php/tests/008.phpt b/php/tests/008.phpt new file mode 100644 index 00000000..661c1cd6 --- /dev/null +++ b/php/tests/008.phpt @@ -0,0 +1,61 @@ +--TEST-- +Check for array+string serialization +--SKIPIF-- +--FILE-- + 1, "two" => 2))', array("one" => 1, "two" => 2)); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek")); +test('array("" => "empty")', array("" => "empty")); +?> +--EXPECT-- +array("foo", "foo", "foo") +8300a3666f6f01a3666f6f02a3666f6f +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array("one" => 1, "two" => 2)) +82a36f6e6501a374776f02 +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array("kek" => "lol", "lol" => "kek") +82a36b656ba36c6f6ca36c6f6ca36b656b +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array("" => "empty") +81a0a5656d707479 +array(1) { + [""]=> + string(5) "empty" +} +OK diff --git a/php/tests/009.phpt b/php/tests/009.phpt new file mode 100644 index 00000000..6baad5ee --- /dev/null +++ b/php/tests/009.phpt @@ -0,0 +1,115 @@ +--TEST-- +Check for reference serialisation +--SKIPIF-- +--FILE-- + + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(&$a, &$a) +82008100a3666f6f0182c001c002 +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +cyclic +81008100810082c001c002 +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} diff --git a/php/tests/010.phpt b/php/tests/010.phpt new file mode 100644 index 00000000..9eb77a61 --- /dev/null +++ b/php/tests/010.phpt @@ -0,0 +1,49 @@ +--TEST-- +Array test +--SKIPIF-- +--FILE-- + array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) +); + +test('array', $a, false); +?> +--EXPECT-- +array +82a16182a162a163a164a165a16681a167a168 +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK diff --git a/php/tests/012.phpt b/php/tests/012.phpt new file mode 100644 index 00000000..8121c960 --- /dev/null +++ b/php/tests/012.phpt @@ -0,0 +1,48 @@ +--TEST-- +Object test +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + $this->c = $c; + } +} + +$o = new Obj(1, 2, 3); + + +test('object', $o, false); +?> +--EXPECTF-- +object +84c0a34f626aa16101a4002a006202a6004f626a006303 +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK diff --git a/php/tests/013.phpt b/php/tests/013.phpt new file mode 100644 index 00000000..73f7d335 --- /dev/null +++ b/php/tests/013.phpt @@ -0,0 +1,54 @@ +--TEST-- +Object-Array test +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } +} + +$o = array(new Obj(1, 2), new Obj(3, 4)); + + +test('object', $o, false); +?> +--EXPECTF-- +object +820083c0a34f626aa16101a162020183c0a34f626aa16103a16204 +array(2) { + [0]=> + object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) + } + [1]=> + object(Obj)#%d (2) { + ["a"]=> + int(3) + ["b"]=> + int(4) + } +} +OK diff --git a/php/tests/014.phpt b/php/tests/014.phpt new file mode 100644 index 00000000..c663579d --- /dev/null +++ b/php/tests/014.phpt @@ -0,0 +1,54 @@ +--TEST-- +Object-Reference test +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } +} + +$o = new Obj(1, 2); +$a = array(&$o, &$o); + +test('object', $a, false); +?> +--EXPECTF-- +object +820083c0a34f626aa16101a162020182c001c002 +array(2) { + [0]=> + &object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) + } + [1]=> + &object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) + } +} +OK diff --git a/php/tests/015.phpt b/php/tests/015.phpt new file mode 100644 index 00000000..828800a2 --- /dev/null +++ b/php/tests/015.phpt @@ -0,0 +1,58 @@ +--TEST-- +Check for serialization handler +--SKIPIF-- +--FILE-- + +--EXPECT-- +2 +81a3666f6f02 +array(1) { + ["foo"]=> + int(2) +} diff --git a/php/tests/015b.phpt b/php/tests/015b.phpt new file mode 100644 index 00000000..829584b7 --- /dev/null +++ b/php/tests/015b.phpt @@ -0,0 +1,58 @@ +--TEST-- +Check for serialization handler, ini-directive +--SKIPIF-- +--INI-- +session.serialize_handler=msgpack +--FILE-- + +--EXPECT-- +2 +81a3666f6f02 +array(1) { + ["foo"]=> + int(2) +} diff --git a/php/tests/016.phpt b/php/tests/016.phpt new file mode 100644 index 00000000..f8f4779e --- /dev/null +++ b/php/tests/016.phpt @@ -0,0 +1,60 @@ +--TEST-- +Object test, __sleep +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + $this->c = $c; + $this->d = $d; + } + + function __sleep() { + return array('a', 'b', 'c'); + } + +# function __wakeup() { +# $this->d = $this->a + $this->b + $this->c; +# } +} + +$o = new Obj(1, 2, 3, 4); + + +test('object', $o, true); +?> +--EXPECTF-- +object +84c0a34f626aa16101a4002a006202a6004f626a006303 +object(Obj)#%d (4) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + ["d"]=> + NULL +} +OK diff --git a/php/tests/017.phpt b/php/tests/017.phpt new file mode 100644 index 00000000..6fbbd901 --- /dev/null +++ b/php/tests/017.phpt @@ -0,0 +1,48 @@ +--TEST-- +Object test, __wakeup +--SKIPIF-- +--FILE-- +b == 3 ? 'OK' : 'ERROR', PHP_EOL; +} + +class Obj { + var $a; + var $b; + + function __construct($a, $b) { + $this->a = $a; + $this->b = $b; + } + + function __wakeup() { + $this->b = $this->a * 3; + } +} + +$o = new Obj(1, 2); + + +test('object', $o, false); +?> +--EXPECTF-- +object +83c0a34f626aa16101a16202 +object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(3) +} +OK diff --git a/php/tests/018.phpt b/php/tests/018.phpt new file mode 100644 index 00000000..84ccafa2 --- /dev/null +++ b/php/tests/018.phpt @@ -0,0 +1,84 @@ +--TEST-- +Object test, __sleep error cases +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } + + function __sleep() { + return array('c'); + } + +# function __wakeup() { +# $this->b = $this->a * 3; +# } +} + +class Opj { + var $a; + var $b; + + function __construct($a, $b) { + $this->a = $a; + $this->b = $b; + } + + function __sleep() { + return array(1); + } + +# function __wakeup() { +# +# } +} + +$o = new Obj(1, 2); +$p = new Opj(1, 2); + +test('nonexisting', $o, true); +test('wrong', $p, true); +?> +--EXPECTF-- +nonexisting +82c0a34f626aa163c0 +object(Obj)#%d (3) { + ["a"]=> + NULL + ["b"]=> + NULL + ["c"]=> + NULL +} +OK +wrong +82c0a34f706ac0 +object(Opj)#%d (2) { + ["a"]=> + NULL + ["b"]=> + NULL +} +OK diff --git a/php/tests/019.phpt b/php/tests/019.phpt new file mode 100644 index 00000000..46cccb3f --- /dev/null +++ b/php/tests/019.phpt @@ -0,0 +1,43 @@ +--TEST-- +Object test, __autoload +--SKIPIF-- +--FILE-- +b == 2 ? 'OK' : 'ERROR', PHP_EOL; +} + +function __autoload($classname) { + class Obj { + var $a; + var $b; + + function __construct($a, $b) { + $this->a = $a; + $this->b = $b; + } + } +} + +test('autoload', '83c0a34f626aa16101a16202', false); +?> +--EXPECTF-- +autoload +83c0a34f626aa16101a16202 +object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} +OK diff --git a/php/tests/020.phpt b/php/tests/020.phpt new file mode 100644 index 00000000..4ed30e8b --- /dev/null +++ b/php/tests/020.phpt @@ -0,0 +1,31 @@ +--TEST-- +Object test, incomplete class +--SKIPIF-- +--FILE-- + +--EXPECTF-- +incom +83c0a34f626aa16101a16202 +object(__PHP_Incomplete_Class)#%d (3) { + ["__PHP_Incomplete_Class_Name"]=> + string(3) "Obj" + ["a"]=> + int(1) + ["b"]=> + int(2) +} diff --git a/php/tests/021.phpt b/php/tests/021.phpt new file mode 100644 index 00000000..7960a1f3 --- /dev/null +++ b/php/tests/021.phpt @@ -0,0 +1,52 @@ +--TEST-- +Object Serializable interface +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } + + public function serialize() { + return pack('NN', $this->a, $this->b); + } + + public function unserialize($serialized) { + $tmp = unpack('N*', $serialized); + $this->__construct($tmp[1], $tmp[2]); + } +} + +$o = new Obj(1, 2); + +test('object', $o, false); +?> +--EXPECTF-- +object +82c003a34f626aa80000000100000002 +object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} +OK diff --git a/php/tests/022.phpt b/php/tests/022.phpt new file mode 100644 index 00000000..7eab4b80 --- /dev/null +++ b/php/tests/022.phpt @@ -0,0 +1,45 @@ +--TEST-- +Object test, unserialize_callback_func +--SKIPIF-- +--INI-- +unserialize_callback_func=autoload +--FILE-- +b == 2 ? 'OK' : 'ERROR', PHP_EOL; +} + +function autoload($classname) { + class Obj { + var $a; + var $b; + + function __construct($a, $b) { + $this->a = $a; + $this->b = $b; + } + } +} + +test('autoload', '83c0a34f626aa16101a16202', false); +?> +--EXPECTF-- +autoload +83c0a34f626aa16101a16202 +object(Obj)#%d (2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} +OK diff --git a/php/tests/023.phpt b/php/tests/023.phpt new file mode 100644 index 00000000..46d9ade4 --- /dev/null +++ b/php/tests/023.phpt @@ -0,0 +1,54 @@ +--TEST-- +Resource +--SKIPIF-- + +--FILE-- +open('db.txt'); +} + +test('resource', $res, false); + +switch ($test) { + case 'curl': + curl_close($res); + break; + case 'sqlite': + if (isset($sqlite)) { + $sqlite->close(); + } + @unlink('db.txt'); + break; +} +?> +--EXPECT-- +resource +c0 +NULL +OK diff --git a/php/tests/024.phpt b/php/tests/024.phpt new file mode 100644 index 00000000..30fab759 --- /dev/null +++ b/php/tests/024.phpt @@ -0,0 +1,166 @@ +--TEST-- +Recursive objects +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + $this->c = $c; + } +} + +class Obj2 { + public $aa; + protected $bb; + private $cc; + private $obj; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + + $this->obj = new Obj($a, $b, $c); + } +} + +class Obj3 { + private $objs; + + function __construct($a, $b, $c) { + $this->objs = array(); + + for ($i = $a; $i < $c; $i += $b) { + $this->objs[] = new Obj($a, $i, $c); + } + } +} + +class Obj4 { + private $a; + private $obj; + + function __construct($a) { + $this->a = $a; + } + + public function set($obj) { + $this->obj = $obj; + } +} + +$o2 = new Obj2(1, 2, 3); +test('objectrec', $o2, false); + +$o3 = new Obj3(0, 1, 4); +test('objectrecarr', $o3, false); + +$o4 = new Obj4(100); +$o4->set($o4); +test('objectselfrec', $o4, true); +?> +--EXPECTF-- +objectrec +88c0a44f626a32a26161c0a5002a006262c0a8004f626a32006363c0a9004f626a32006f626a84c0a34f626aa16101a4002a006202a6004f626a006303a16101a16202a16303 +object(Obj2)#%d (7) { + ["aa"]=> + NULL + [%r"?bb"?:protected"?%r]=> + NULL + [%r"?cc"?:("Obj2":)?private"?%r]=> + NULL + [%r"?obj"?:("Obj2":)?private"?%r]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} +OK +objectrecarr +82c0a44f626a33aa004f626a33006f626a73840084c0a34f626aa16100a4002a006200a6004f626a0063040184c0a34f626aa16100a4002a006201a6004f626a0063040284c0a34f626aa16100a4002a006202a6004f626a0063040384c0a34f626aa16100a4002a006203a6004f626a006304 +object(Obj3)#%d (1) { + [%r"?objs"?:("Obj3":)?private"?%r]=> + array(4) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(0) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(1) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [2]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [3]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(3) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + } +} +OK +objectselfrec +83c0a44f626a34a7004f626a34006164a9004f626a34006f626a82c002c001 +object(Obj4)#%d (2) { + [%r"?a"?:("Obj4":)?private"?%r]=> + int(100) + [%r"?obj"?:("Obj4":)?private"?%r]=> + object(Obj4)#%d (2) { + [%r"?a"?:("Obj4":)?private"?%r]=> + int(100) + [%r"?obj"?:("Obj4":)?private"?%r]=> + *RECURSION* + } +} +OK diff --git a/php/tests/025.phpt b/php/tests/025.phpt new file mode 100644 index 00000000..234539d3 --- /dev/null +++ b/php/tests/025.phpt @@ -0,0 +1,119 @@ +--TEST-- +Object test, array of objects with __sleep +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + $this->c = $c; + $this->d = $d; + } + + function __sleep() { + return array('a', 'b', 'c'); + } + +# function __wakeup() { +# $this->d = $this->a + $this->b + $this->c; +# } +} + +$array = array( + new Obj("aa", "bb", "cc", "dd"), + new Obj("ee", "ff", "gg", "hh"), + new Obj(1, 2, 3, 4), +); + + +test('array', $array, true); +?> +--EXPECTF-- +array(3) { + [0]=> + object(Obj)#1 (4) { + ["a"]=> + string(2) "aa" + [%r"?b"?:protected"?%r]=> + string(2) "bb" + [%r"?c"?:("Obj":)?private"?%r]=> + string(2) "cc" + ["d"]=> + string(2) "dd" + } + [1]=> + object(Obj)#2 (4) { + ["a"]=> + string(2) "ee" + [%r"?b"?:protected"?%r]=> + string(2) "ff" + [%r"?c"?:("Obj":)?private"?%r]=> + string(2) "gg" + ["d"]=> + string(2) "hh" + } + [2]=> + object(Obj)#3 (4) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + ["d"]=> + int(4) + } +} +array(3) { + [0]=> + object(Obj)#4 (4) { + ["a"]=> + string(2) "aa" + [%r"?b"?:protected"?%r]=> + string(2) "bb" + [%r"?c"?:("Obj":)?private"?%r]=> + string(2) "cc" + ["d"]=> + NULL + } + [1]=> + object(Obj)#5 (4) { + ["a"]=> + string(2) "ee" + [%r"?b"?:protected"?%r]=> + string(2) "ff" + [%r"?c"?:("Obj":)?private"?%r]=> + string(2) "gg" + ["d"]=> + NULL + } + [2]=> + object(Obj)#6 (4) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + ["d"]=> + NULL + } +} diff --git a/php/tests/026.phpt b/php/tests/026.phpt new file mode 100644 index 00000000..2d3bb734 --- /dev/null +++ b/php/tests/026.phpt @@ -0,0 +1,143 @@ +--TEST-- +Cyclic array test +--INI-- +--SKIPIF-- +--FILE-- + array( + 'b' => 'c', + 'd' => 'e' + ), +); + +$a['f'] = &$a; + +test('array', $a, true); + +$a = array("foo" => &$b); +$b = array(1, 2, $a); +var_dump($a); +var_dump($k = msgpack_unserialize(msgpack_serialize($a))); + +$k["foo"][1] = "b"; +var_dump($k); +?> +--EXPECT-- +array +82a16182a162a163a164a165a16682a16182a162a163a164a165a16682c001c005 +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + &array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + &array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + *RECURSION* + } + } +} +OK +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + *RECURSION* + } + } + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } + } + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + string(1) "b" + [2]=> + array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + string(1) "b" + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } + } + } +} diff --git a/php/tests/027.phpt b/php/tests/027.phpt new file mode 100644 index 00000000..ecb87841 --- /dev/null +++ b/php/tests/027.phpt @@ -0,0 +1,73 @@ +--TEST-- +Check for serialization handler +--SKIPIF-- +--FILE-- + +--EXPECT-- +bool(true) +read +wrote: 82a3666f6f01a474657374a6666f6f626172 +array(2) { + ["foo"]=> + int(1) + ["test"]=> + string(6) "foobar" +} diff --git a/php/tests/028.phpt b/php/tests/028.phpt new file mode 100644 index 00000000..56805f9e --- /dev/null +++ b/php/tests/028.phpt @@ -0,0 +1,667 @@ +--TEST-- +Serialize object into session, full set +--SKIPIF-- +--FILE-- +d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +class Bar { + private static $s1 = array(); + protected static $s2 = array(); + public static $s3 = array(); + + public $d1; + private $d2; + protected $d3; + + public function __construct() { + } + + public function set($foo) { + $this->d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +$output = ''; + +function open($path, $name) { + return true; +} + +function close() { + return true; +} + +function read($id) { + global $output; + $output .= "read" . PHP_EOL; + $a = new Bar(); + $b = new Foo($a); + $a->set($b); + $session = array('old' => $b); + return msgpack_serialize($session); +} + +function write($id, $data) { + global $output; + $output .= "write: "; + $output .= bin2hex($data) . PHP_EOL; + return true; +} + +function destroy($id) { + return true; +} + +function gc($time) { + return true; +} + +ini_set('session.serialize_handler', 'msgpack'); + +session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc'); + +session_start(); + +$_SESSION['test'] = "foobar"; +$a = new Bar(); +$b = new Foo($a); +$a->set($b); +$_SESSION['new'] = $a; + +session_write_close(); + +echo $output; +var_dump($_SESSION); +?> +--EXPECTF-- +read +write: 83a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c002c002a70042617200643282c002c002a5002a00643382c002c002a5002a00643282c002c003a2643382c002c003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002c00aa5002a00643282c002c00aa2643382c002c00aa70042617200643282c002c00ba5002a00643382c002c00b +array(3) { + ["old"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + } + } + ["test"]=> + string(6) "foobar" + ["new"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + ["d3"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + ["d3"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + ["d3"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } + } + } +} diff --git a/php/tests/029.phpt b/php/tests/029.phpt new file mode 100644 index 00000000..3bd1e9dc --- /dev/null +++ b/php/tests/029.phpt @@ -0,0 +1,20 @@ +--TEST-- +Msgpack module info +--SKIPIF-- + +--FILE-- + enabled +msgpack version => %s +msgpack Session Support => enabled diff --git a/php/tests/030.phpt b/php/tests/030.phpt new file mode 100644 index 00000000..ec8622dc --- /dev/null +++ b/php/tests/030.phpt @@ -0,0 +1,233 @@ +--TEST-- +Unserialize invalid data +--SKIPIF-- +--FILE-- + 10, "foo"), + true, + false, + 0.187182, + "dakjdh98389\000", + null, + (object)array(1,2,3), +); + +error_reporting(0); + +foreach ($datas as $data) { + $str = msgpack_serialize($data); + $len = strlen($str); + + // truncated + for ($i = 0; $i < $len - 1; $i++) { + $v = msgpack_unserialize(substr($str, 0, $i)); + + if (is_object($data) || is_array($data)) { + if ($v !== null && $v !== false && $v != $data) { + echo "output at $i:\n"; + var_dump($v); + } + } else if ($v !== null && $v == $data) { + continue; + } else if ($v !== null && $v !== $data) { + echo "output at $i:\n"; + var_dump($v); + echo "vs.\n"; + var_dump($data); + } + } + + // padded + $str .= "98398afa\000y21_ "; + $v = msgpack_unserialize($str); + if ($v !== $data && !(is_object($data) && $v == $data)) { + echo "padded should get original\n"; + var_dump($v); + echo "vs.\n"; + var_dump($data); + } +} +?> +--EXPECTF-- +output at 2: +array(0) { +} +output at 3: +array(1) { + [0]=> + int(1) +} +output at 4: +array(1) { + [0]=> + int(1) +} +output at 5: +array(2) { + [0]=> + int(1) + [1]=> + int(2) +} +output at 6: +array(2) { + [0]=> + int(1) + [1]=> + int(2) +} +output at 7: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 8: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 9: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 10: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 11: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 12: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 13: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 14: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 15: +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +output at 16: +array(4) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + ["testing"]=> + int(10) +} +output at 17: +array(4) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + ["testing"]=> + int(10) +} +output at 18: +array(4) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + ["testing"]=> + int(10) +} +output at 19: +array(4) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + ["testing"]=> + int(10) +} +output at 11: +object(stdClass)#2 (0) { +} +output at 12: +object(stdClass)#3 (0) { +} +output at 13: +object(stdClass)#2 (1) { + [0]=> + int(1) +} +output at 14: +object(stdClass)#3 (1) { + [0]=> + int(1) +} +output at 15: +object(stdClass)#2 (2) { + [0]=> + int(1) + [1]=> + int(2) +} diff --git a/php/tests/031.phpt b/php/tests/031.phpt new file mode 100644 index 00000000..ce3ba49f --- /dev/null +++ b/php/tests/031.phpt @@ -0,0 +1,90 @@ +--TEST-- +Object Serializable interface throws exceptions +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } + + public function serialize() { + $c = self::$count++; + echo "call serialize, ", ($this->a ? "throw" : "no throw"), PHP_EOL; + if ($this->a) { + throw new Exception("exception in serialize $c"); + } + return pack('NN', $this->a, $this->b); + } + + public function unserialize($serialized) { + $tmp = unpack('N*', $serialized); + $this->__construct($tmp[1], $tmp[2]); + $c = self::$count++; + echo "call unserialize, ", ($this->b ? "throw" : "no throw"), PHP_EOL; + if ($this->b) { + throw new Exception("exception in unserialize $c"); + } + } +} + +$a = new Obj(1, 0); +$a = new Obj(0, 0); +$b = new Obj(0, 0); +$c = new Obj(1, 0); +$d = new Obj(0, 1); + +echo "a, a, c", PHP_EOL; +try { + test(array($a, $a, $c)); +} catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $e->getMessage(), PHP_EOL; +} + +echo "b, b, d", PHP_EOL; + +try { + test(array($b, $b, $d)); +} catch (Exception $e) { + if (version_compare(phpversion(), "5.3.0", ">=")) { + if ($e->getPrevious()) { + $e = $e->getPrevious(); + } + } + + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECT-- +a, a, c +call serialize, no throw +call serialize, throw +exception in serialize 2 +b, b, d +call serialize, no throw +call serialize, no throw +call unserialize, no throw +call unserialize, throw +exception in unserialize 6 diff --git a/php/tests/032.phpt b/php/tests/032.phpt new file mode 100644 index 00000000..b120ea91 --- /dev/null +++ b/php/tests/032.phpt @@ -0,0 +1,76 @@ +--TEST-- +Object test, __sleep and __wakeup exceptions +--SKIPIF-- +--FILE-- +a = $a; + $this->b = $b; + } + + function __sleep() { + $c = self::$count++; + if ($this->a) { + throw new Exception("exception in __sleep $c"); + } + return array('a', 'b'); + } + + function __wakeup() { + $c = self::$count++; + if ($this->b) { + throw new Exception("exception in __wakeup $c"); + } + $this->b = $this->a * 3; + } +} + + +$a = new Obj(1, 0); +$b = new Obj(0, 1); +$c = new Obj(0, 0); + +try { + test($a); +} catch (Exception $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + test($b); +} catch (Exception $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + test($c); +} catch (Exception $e) { + echo $e->getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +exception in __sleep 0 +exception in __wakeup 2 +object(Obj)#%d (2) { + ["a"]=> + int(0) + ["b"]=> + int(0) +} diff --git a/php/tests/033.phpt b/php/tests/033.phpt new file mode 100644 index 00000000..682fd4db --- /dev/null +++ b/php/tests/033.phpt @@ -0,0 +1,55 @@ +--TEST-- +Object test, cyclic references +--SKIPIF-- +--FILE-- +parent = null; + $this->children = array(); + } + + public function addChild(Foo $obj) { + $this->children[] = $obj; + $obj->setParent($this); + } + + public function setParent(Foo $obj) { + $this->parent = $obj; + } +} + +$obj1 = new Foo(); + +for ($i = 0; $i < 10; $i++) { + $obj = new Foo(); + $obj1->addChild($obj); +} + +$o = msgpack_unserialize(msgpack_serialize($obj1->children)); + +foreach ($obj1->children as $k => $v) { + $obj_v = $v; + $o_v = $o[$k]; + + echo gettype($obj_v), " ", gettype($o_v), PHP_EOL; +} +?> +--EXPECT-- +object object +object object +object object +object object +object object +object object +object object +object object +object object +object object diff --git a/php/tests/034.phpt b/php/tests/034.phpt new file mode 100644 index 00000000..6610c7c7 --- /dev/null +++ b/php/tests/034.phpt @@ -0,0 +1,38 @@ +--TEST-- +Unserialize invalid random data +--SKIPIF-- +--FILE-- + 10, "foo"), + true, + false, + 0.187182, + "dakjdh98389\000", + null, + (object)array(1,2,3), +); + +error_reporting(0); + +foreach ($datas as $data) { + $str = msgpack_serialize($data); + $len = strlen($str); + + for ($j = 0; $j < 200; $j++) { + for ($i = 0; $i < $len - 1; $i++) { + $sub = substr($str, 0, $i); + $sub .= mcrypt_create_iv(30, MCRYPT_DEV_URANDOM); + $php_errormsg = null; + $v = msgpack_unserialize($sub); + } + } +} + +--EXPECT-- diff --git a/php/tests/035.phpt b/php/tests/035.phpt new file mode 100644 index 00000000..d680565f --- /dev/null +++ b/php/tests/035.phpt @@ -0,0 +1,34 @@ +--TEST-- +Profiling perf test. +--SKIPIF-- + +--FILE-- + 400 ? "GOOD" : "BAD")); +} +?> +--EXPECTF-- +%d iterations took %f seconds: %d/s (GOOD) diff --git a/php/tests/040.phpt b/php/tests/040.phpt new file mode 100644 index 00000000..9a2d0384 --- /dev/null +++ b/php/tests/040.phpt @@ -0,0 +1,43 @@ +--TEST-- +b0rked random data test +--SKIPIF-- +--FILE-- + +--EXPECT-- diff --git a/php/tests/041.phpt b/php/tests/041.phpt new file mode 100644 index 00000000..6400fd97 --- /dev/null +++ b/php/tests/041.phpt @@ -0,0 +1,47 @@ +--TEST-- +Check for double NaN, Inf, -Inf, 0, and -0 +--FILE-- + +--EXPECT-- +empty array: +90 +array(0) { +} +array(1, 2, 3) +93010203 +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(array(1, 2, 3), arr... +93930102039304050693070809 +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +array("foo", "FOO", "Foo") +93a3666f6fa3464f4fa3466f6f +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "FOO" + [2]=> + string(3) "Foo" +} +array(1, 123.45, true, ... +9701cb405edccccccccccdc3c293010293090807c0a3666f6f +array(7) { + [0]=> + int(1) + [1]=> + float(123.45) + [2]=> + bool(true) + [3]=> + bool(false) + [4]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(3) { + [0]=> + int(9) + [1]=> + int(8) + [2]=> + int(7) + } + } + [5]=> + NULL + [6]=> + string(3) "foo" +} diff --git a/php/tests/060.phpt b/php/tests/060.phpt new file mode 100644 index 00000000..c0fda4c2 --- /dev/null +++ b/php/tests/060.phpt @@ -0,0 +1,315 @@ +--TEST-- +Check for buffered streaming unserialization +--SKIPIF-- +--FILE-- +feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/061.phpt b/php/tests/061.phpt new file mode 100644 index 00000000..ded494e0 --- /dev/null +++ b/php/tests/061.phpt @@ -0,0 +1,320 @@ +--TEST-- +Check for unbuffered streaming unserialization +--SKIPIF-- +--FILE-- +execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/062.phpt b/php/tests/062.phpt new file mode 100644 index 00000000..159e00de --- /dev/null +++ b/php/tests/062.phpt @@ -0,0 +1,64 @@ +--TEST-- +Extra bytes buffered streaming unserialization +--SKIPIF-- +--FILE-- +feed($str); + + while (true) { + if ($unpacker->execute()) { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } else { + break; + } + } + $i += $len; + } + } +} + +test('array(1, 2, 3)', array('9301020392')); +test('array(1, 2, 3), array(3, 9), 4', array('9301020392', '030904')); +--EXPECTF-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(2) { + [0]=> + int(3) + [1]=> + int(9) +} +int(4) diff --git a/php/tests/063.phpt b/php/tests/063.phpt new file mode 100644 index 00000000..5be7e099 --- /dev/null +++ b/php/tests/063.phpt @@ -0,0 +1,68 @@ +--TEST-- +Extra bytes unbuffered streaming unserialization +--SKIPIF-- +--FILE-- +execute($str, $offset)) { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = substr($str, $offset); + $offset = 0; + } else { + break; + } + } + $i += $len; + } + } +} + +test('array(1, 2, 3)', array('9301020392')); +test('array(1, 2, 3), array(3, 9), 4', array('9301020392', '030904')); +--EXPECTF-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(2) { + [0]=> + int(3) + [1]=> + int(9) +} +int(4) diff --git a/php/tests/070.phpt b/php/tests/070.phpt new file mode 100644 index 00000000..4a00ddf5 --- /dev/null +++ b/php/tests/070.phpt @@ -0,0 +1,299 @@ +--TEST-- +Check for alias functions +--SKIPIF-- +--FILE-- + 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/071.phpt b/php/tests/071.phpt new file mode 100644 index 00000000..cca351aa --- /dev/null +++ b/php/tests/071.phpt @@ -0,0 +1,301 @@ +--TEST-- +Check for class methods +--SKIPIF-- +--FILE-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/072.phpt b/php/tests/072.phpt new file mode 100644 index 00000000..d8cb1b99 --- /dev/null +++ b/php/tests/072.phpt @@ -0,0 +1,341 @@ +--TEST-- +Check for class methods unpacker +--SKIPIF-- +--FILE-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + &array(1) { + [0]=> + array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/test_pack.phpt b/php/tests/test_pack.phpt deleted file mode 100644 index 595e4d03..00000000 --- a/php/tests/test_pack.phpt +++ /dev/null @@ -1,169 +0,0 @@ ---TEST-- -Test msgpack_pack() function : basic functionality ---SKIPIF-- - ---FILE-- - -===DONE=== ---EXPECT-- -*** Testing msgpack_pack() : basic functionality *** --- Iteration 1 -- -string(4) "0xc0" --- Iteration 2 -- -string(4) "0xc0" --- Iteration 3 -- -string(4) "0xc2" --- Iteration 4 -- -string(4) "0xc2" --- Iteration 5 -- -string(4) "0xc3" --- Iteration 6 -- -string(4) "0xc3" --- Iteration 7 -- -string(4) "0x00" --- Iteration 8 -- -string(4) "0x7f" --- Iteration 9 -- -string(6) "0xcc80" --- Iteration 10 -- -string(8) "0xcd0100" --- Iteration 11 -- -string(4) "0xff" --- Iteration 12 -- -string(6) "0xd0df" --- Iteration 13 -- -string(8) "0xd1ff7f" --- Iteration 14 -- -string(8) "0x810101" --- Iteration 15 -- -string(20) "0xcb3ff0000000000000" --- Iteration 16 -- -string(4) "0x90" --- Iteration 17 -- -string(34) "0x9f000102030405060708090a0b0c0d0e" --- Iteration 18 -- -string(40) "0xdc0010000102030405060708090a0b0c0d0e0f" --- Iteration 19 -- -string(64) "0x8f0100020103020403050406050706080709080a090b0a0c0b0d0c0e0d0f0e" --- Iteration 20 -- -string(72) "0xde00100100020103020403050406050706080709080a090b0a0c0b0d0c0e0d0f0e100f" -===DONE=== From 2a0a84763479e6eebd30f685e5f64afd7e7cb3bc Mon Sep 17 00:00:00 2001 From: advect Date: Wed, 29 Sep 2010 08:47:06 +0900 Subject: [PATCH 2/2] php: update 0.3.0 --- php/ChangeLog | 15 +- php/config.m4 | 45 -- php/config.w32 | 3 - php/msgpack.c | 139 ++-- php/msgpack/pack_define.h | 26 + php/msgpack/pack_template.h | 766 +++++++++++++++++++++ php/msgpack/sysdep.h | 118 ++++ php/msgpack/unpack_define.h | 93 +++ php/msgpack/unpack_template.h | 409 +++++++++++ php/msgpack/version.h | 40 ++ php/msgpack_class.c | 315 +++++++-- php/msgpack_class.h | 6 +- php/msgpack_pack.c | 132 ++-- php/msgpack_pack.h | 7 +- php/msgpack_unpack.c | 1216 +++++++++++++++------------------ php/msgpack_unpack.h | 123 +++- php/package.xml | 85 ++- php/php-msgpack.spec | 4 +- php/php_msgpack.h | 3 +- php/tests/009.phpt | 18 +- php/tests/009b.phpt | 101 +++ php/tests/014.phpt | 2 +- php/tests/015.phpt | 2 +- php/tests/015b.phpt | 2 +- php/tests/018.phpt | 2 +- php/tests/024.phpt | 6 +- php/tests/024b.phpt | 165 +++++ php/tests/026.phpt | 6 +- php/tests/026b.phpt | 107 +++ php/tests/027.phpt | 2 +- php/tests/028.phpt | 6 +- php/tests/028b.phpt | 167 +++++ php/tests/029.phpt | 37 +- php/tests/030.phpt | 3 - php/tests/060.phpt | 18 +- php/tests/060b.phpt | 313 +++++++++ php/tests/061.phpt | 8 +- php/tests/061b.phpt | 318 +++++++++ php/tests/070.phpt | 8 +- php/tests/070b.phpt | 297 ++++++++ php/tests/071.phpt | 8 +- php/tests/071b.phpt | 299 ++++++++ php/tests/072.phpt | 8 +- php/tests/072b.phpt | 339 +++++++++ php/tests/073.phpt | 346 ++++++++++ php/tests/073b.phpt | 340 +++++++++ php/tests/080.phpt | 301 ++++++++ php/tests/081.phpt | 303 ++++++++ php/tests/082.phpt | 346 ++++++++++ php/tests/083.phpt | 347 ++++++++++ php/tests/084.phpt | 301 ++++++++ php/tests/085.phpt | 344 ++++++++++ php/tests/086.phpt | 345 ++++++++++ php/tests/087.phpt | 302 ++++++++ php/tests/088.phpt | 345 ++++++++++ php/tests/089.phpt | 347 ++++++++++ 56 files changed, 8804 insertions(+), 950 deletions(-) create mode 100644 php/msgpack/pack_define.h create mode 100644 php/msgpack/pack_template.h create mode 100644 php/msgpack/sysdep.h create mode 100644 php/msgpack/unpack_define.h create mode 100644 php/msgpack/unpack_template.h create mode 100644 php/msgpack/version.h create mode 100644 php/tests/009b.phpt create mode 100644 php/tests/024b.phpt create mode 100644 php/tests/026b.phpt create mode 100644 php/tests/028b.phpt create mode 100644 php/tests/060b.phpt create mode 100644 php/tests/061b.phpt create mode 100644 php/tests/070b.phpt create mode 100644 php/tests/071b.phpt create mode 100644 php/tests/072b.phpt create mode 100644 php/tests/073.phpt create mode 100644 php/tests/073b.phpt create mode 100644 php/tests/080.phpt create mode 100644 php/tests/081.phpt create mode 100644 php/tests/082.phpt create mode 100644 php/tests/083.phpt create mode 100644 php/tests/084.phpt create mode 100644 php/tests/085.phpt create mode 100644 php/tests/086.phpt create mode 100644 php/tests/087.phpt create mode 100644 php/tests/088.phpt create mode 100644 php/tests/089.phpt diff --git a/php/ChangeLog b/php/ChangeLog index 5481c1fc..3cee3b60 100644 --- a/php/ChangeLog +++ b/php/ChangeLog @@ -1,14 +1,21 @@ msgpack extension changelog +Version 0.3.0 +------------- + * Change msgpack_unpack.c (used template) + * Add php_only ini option (true / false) + * Change class MessagePack and MessagePackUnpacker __construct option. + * Add class MessagePack and MessagePackUnpacker setOption method. + Version 0.2.1 ------------- - * Fix stream deserializer + * Fix stream deserializer. Version 0.2.0 ------------- - * Add stream deserializer / class MessagePackUnpacker interface - * Add alias functions - * Add class MessagePack interface + * Add stream deserializer / class MessagePackUnpacker interface. + * Add alias functions. + * Add class MessagePack interface. Version 0.1.5 ------------- diff --git a/php/config.m4 b/php/config.m4 index d319684f..a78e1f32 100644 --- a/php/config.m4 +++ b/php/config.m4 @@ -21,52 +21,7 @@ PHP_ARG_WITH(msgpack, for msgpack support, Make sure that the comment is aligned: [ --with-msgpack Include msgpack support]) -dnl PHP_ARG_ENABLE(msgpack, whether to enable msgpack support, -dnl Make sure that the comment is aligned: -dnl [ --enable-msgpack Enable msgpack support]) - if test "$PHP_MSGPACK" != "no"; then - dnl Write more examples of tests here... - - dnl --with-msgpack -> check with-path - SEARCH_PATH="/usr/local /usr" # you might want to change this - SEARCH_FOR="/include/msgpack.h" # you most likely want to change this - if test -r $PHP_MSGPACK/$SEARCH_FOR; then # path given as parameter - MSGPACK_DIR=$PHP_MSGPACK - else # search default path list - AC_MSG_CHECKING([for msgpack files in default path]) - for i in $SEARCH_PATH ; do - if test -r $i/$SEARCH_FOR; then - MSGPACK_DIR=$i - AC_MSG_RESULT(found in $i) - fi - done - fi - - if test -z "$MSGPACK_DIR"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please reinstall the msgpack distribution]) - fi - - dnl --with-msgpack -> add include path - PHP_ADD_INCLUDE($MSGPACK_DIR/include) - - dnl --with-msgpack -> check for lib and symbol presence - LIBNAME=msgpack # you may want to change this - LIBSYMBOL=msgpack_pack_object # you most likely want to change this - - PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - [ - PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MSGPACK_DIR/lib, MSGPACK_SHARED_LIBADD) - AC_DEFINE(HAVE_MSGPACKLIB,1,[ ]) - ],[ - AC_MSG_ERROR([wrong msgpack lib version or lib not found]) - ],[ - -L$MSGPACK_DIR/lib -lm - ]) - - PHP_SUBST(MSGPACK_SHARED_LIBADD) - PHP_NEW_EXTENSION(msgpack, msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c, $ext_shared) PHP_INSTALL_HEADERS([ext/msgpack], [php_msgpack.h]) diff --git a/php/config.w32 b/php/config.w32 index f2153e6b..726b75f2 100644 --- a/php/config.w32 +++ b/php/config.w32 @@ -4,9 +4,6 @@ // If your extension references something external, use ARG_WITH // ARG_WITH("msgpack", "for msgpack support", "no"); -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("msgpack", "enable msgpack support", "no"); - if (PHP_MSGPACK != "no") { EXTENSION("msgpack", "msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c"); } diff --git a/php/msgpack.c b/php/msgpack.c index 62fb68d7..5d4f9264 100644 --- a/php/msgpack.c +++ b/php/msgpack.c @@ -15,6 +15,7 @@ #include "msgpack_pack.h" #include "msgpack_unpack.h" #include "msgpack_class.h" +#include "msgpack/version.h" static ZEND_FUNCTION(msgpack_serialize); static ZEND_FUNCTION(msgpack_unserialize); @@ -27,20 +28,46 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unserialize, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_END_ARG_INFO() +PHP_INI_BEGIN() +STD_PHP_INI_BOOLEAN( + "msgpack.error_display", "1", PHP_INI_ALL, OnUpdateBool, + error_display, zend_msgpack_globals, msgpack_globals) +STD_PHP_INI_BOOLEAN( + "msgpack.php_only", "1", PHP_INI_ALL, OnUpdateBool, + php_only, zend_msgpack_globals, msgpack_globals) +PHP_INI_END() + PS_SERIALIZER_FUNCS(msgpack); static const zend_function_entry msgpack_functions[] = { ZEND_FE(msgpack_serialize, arginfo_msgpack_serialize) ZEND_FE(msgpack_unserialize, arginfo_msgpack_unserialize) ZEND_FALIAS(msgpack_pack, msgpack_serialize, arginfo_msgpack_serialize) - ZEND_FALIAS(msgpack_unpack, msgpack_unserialize, - arginfo_msgpack_unserialize) + ZEND_FALIAS(msgpack_unpack, msgpack_unserialize, arginfo_msgpack_unserialize) {NULL, NULL, NULL} }; +static void msgpack_init_globals(zend_msgpack_globals *msgpack_globals) +{ + TSRMLS_FETCH(); + + if (PG(display_errors)) + { + msgpack_globals->error_display = 1; + } + else + { + msgpack_globals->error_display = 0; + } + + msgpack_globals->php_only = 1; +} + static ZEND_MINIT_FUNCTION(msgpack) { - MSGPACK_G(error_display) = 1; + ZEND_INIT_MODULE_GLOBALS(msgpack, msgpack_init_globals, NULL); + + REGISTER_INI_ENTRIES(); #if HAVE_PHP_SESSION php_session_register_serializer("msgpack", @@ -48,7 +75,14 @@ static ZEND_MINIT_FUNCTION(msgpack) PS_SERIALIZER_DECODE_NAME(msgpack)); #endif - msgpack_init_class(TSRMLS_CC); + msgpack_init_class(); + + return SUCCESS; +} + +static ZEND_MSHUTDOWN_FUNCTION(msgpack) +{ + UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -56,12 +90,15 @@ static ZEND_MINIT_FUNCTION(msgpack) static ZEND_MINFO_FUNCTION(msgpack) { php_info_print_table_start(); - php_info_print_table_row(2, "msgpack support", "enabled"); - php_info_print_table_row(2, "msgpack version", MSGPACK_VERSION); + php_info_print_table_row(2, "MessagePack Support", "enabled"); #if HAVE_PHP_SESSION - php_info_print_table_row(2, "msgpack Session Support", "enabled" ); + php_info_print_table_row(2, "Session Support", "enabled" ); #endif + php_info_print_table_row(2, "extension Version", MSGPACK_EXTENSION_VERSION); + php_info_print_table_row(2, "header Version", MSGPACK_VERSION); php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); } zend_module_entry msgpack_module_entry = { @@ -71,7 +108,7 @@ zend_module_entry msgpack_module_entry = { "msgpack", msgpack_functions, ZEND_MINIT(msgpack), - NULL, + ZEND_MSHUTDOWN(msgpack), NULL, NULL, ZEND_MINFO(msgpack), @@ -109,7 +146,6 @@ PS_SERIALIZER_ENCODE_FUNC(msgpack) PS_SERIALIZER_DECODE_FUNC(msgpack) { - php_unserialize_data_t var_hash; int ret; HashTable *tmp_hash; HashPosition tmp_hash_pos; @@ -117,38 +153,29 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) ulong key_long; uint key_len; zval *tmp; - zval **data; - msgpack_unserialize_data mpsd; + zval **value; + size_t off = 0; + msgpack_unpack_t mp; + php_unserialize_data_t var_hash; - PHP_VAR_UNSERIALIZE_INIT(var_hash); + ALLOC_INIT_ZVAL(tmp); - MAKE_STD_ZVAL(tmp); + template_init(&mp); - mpsd.data = (unsigned char *)val;; - mpsd.length = vallen; - mpsd.offset = 0; + msgpack_unserialize_var_init(&var_hash); - ret = msgpack_unserialize_zval(&tmp, &mpsd, &var_hash TSRMLS_CC); + (&mp)->user.retval = (zval *)tmp; + (&mp)->user.var_hash = (php_unserialize_data_t *)&var_hash; - switch (ret) - { - case MSGPACK_UNPACK_EXTRA_BYTES: - case MSGPACK_UNPACK_SUCCESS: - break; - case MSGPACK_UNPACK_PARSE_ERROR: - case MSGPACK_UNPACK_CONTINUE: - default: - zval_ptr_dtor(&tmp); - return FAILURE; - } + ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + msgpack_unserialize_var_destroy(&var_hash); tmp_hash = HASH_OF(tmp); zend_hash_internal_pointer_reset_ex(tmp_hash, &tmp_hash_pos); while (zend_hash_get_current_data_ex( - tmp_hash, (void *)&data, &tmp_hash_pos) == SUCCESS) + tmp_hash, (void *)&value, &tmp_hash_pos) == SUCCESS) { ret = zend_hash_get_current_key_ex( tmp_hash, &key_str, &key_len, &key_long, 0, &tmp_hash_pos); @@ -158,7 +185,8 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) /* ??? */ break; case HASH_KEY_IS_STRING: - php_set_session_var(key_str, key_len - 1, *data, NULL TSRMLS_CC); + php_set_session_var( + key_str, key_len - 1, *value, NULL TSRMLS_CC); php_add_session_var(key_str, key_len - 1 TSRMLS_CC); break; } @@ -185,46 +213,59 @@ PHP_MSGPACK_API void php_msgpack_unserialize( zval *return_value, char *str, size_t str_len TSRMLS_DC) { int ret; + size_t off = 0; + msgpack_unpack_t mp; php_unserialize_data_t var_hash; - msgpack_unserialize_data mpsd; if (str_len <= 0) { RETURN_NULL(); } - PHP_VAR_UNSERIALIZE_INIT(var_hash); + template_init(&mp); - mpsd.data = (unsigned char *)str; - mpsd.length = str_len; - mpsd.offset = 0; + msgpack_unserialize_var_init(&var_hash); - ret = msgpack_unserialize_zval(&return_value, &mpsd, &var_hash TSRMLS_CC); + (&mp)->user.retval = (zval *)return_value; + (&mp)->user.var_hash = (php_unserialize_data_t *)&var_hash; + + ret = template_execute(&mp, str, (size_t)str_len, &off); + + msgpack_unserialize_var_destroy(&var_hash); switch (ret) { case MSGPACK_UNPACK_PARSE_ERROR: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Parse error"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Parse error"); + } break; case MSGPACK_UNPACK_CONTINUE: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) " - "Insufficient data for unserializeng"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) " + "Insufficient data for unserializing"); + } break; case MSGPACK_UNPACK_EXTRA_BYTES: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Extra bytes"); - break; case MSGPACK_UNPACK_SUCCESS: + if (off < (size_t)str_len && MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Extra bytes"); + } break; default: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Unknown result"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Unknown result"); + } break; } - - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } static ZEND_FUNCTION(msgpack_serialize) diff --git a/php/msgpack/pack_define.h b/php/msgpack/pack_define.h new file mode 100644 index 00000000..4845d52e --- /dev/null +++ b/php/msgpack/pack_define.h @@ -0,0 +1,26 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_PACK_DEFINE_H__ +#define MSGPACK_PACK_DEFINE_H__ + +#include "msgpack/sysdep.h" +#include +#include + +#endif /* msgpack/pack_define.h */ + diff --git a/php/msgpack/pack_template.h b/php/msgpack/pack_template.h new file mode 100644 index 00000000..b636967f --- /dev/null +++ b/php/msgpack/pack_template.h @@ -0,0 +1,766 @@ +/* + * MessagePack packing routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__LITTLE_ENDIAN__) +#define TAKE8_8(d) ((uint8_t*)&d)[0] +#define TAKE8_16(d) ((uint8_t*)&d)[0] +#define TAKE8_32(d) ((uint8_t*)&d)[0] +#define TAKE8_64(d) ((uint8_t*)&d)[0] +#elif defined(__BIG_ENDIAN__) +#define TAKE8_8(d) ((uint8_t*)&d)[0] +#define TAKE8_16(d) ((uint8_t*)&d)[1] +#define TAKE8_32(d) ((uint8_t*)&d)[3] +#define TAKE8_64(d) ((uint8_t*)&d)[7] +#endif + +#ifndef msgpack_pack_inline_func +#error msgpack_pack_inline_func template is not defined +#endif + +#ifndef msgpack_pack_user +#error msgpack_pack_user type is not defined +#endif + +#ifndef msgpack_pack_append_buffer +#error msgpack_pack_append_buffer callback is not defined +#endif + + +/* + * Integer + */ + +#define msgpack_pack_real_uint8(x, d) \ +do { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_8(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ +} while(0) + +#define msgpack_pack_real_uint16(x, d) \ +do { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \ + } else if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ +} while(0) + +#define msgpack_pack_real_uint32(x, d) \ +do { \ + if(d < (1<<8)) { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else { \ + if(d < (1<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_uint64(x, d) \ +do { \ + if(d < (1ULL<<8)) { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else { \ + if(d < (1ULL<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else if(d < (1ULL<<32)) { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else { \ + /* unsigned 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int8(x, d) \ +do { \ + if(d < -(1<<5)) { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_8(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \ + } \ +} while(0) + +#define msgpack_pack_real_int16(x, d) \ +do { \ + if(d < -(1<<5)) { \ + if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \ + } else { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int32(x, d) \ +do { \ + if(d < -(1<<5)) { \ + if(d < -(1<<15)) { \ + /* signed 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \ + } else { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else if(d < (1<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int64(x, d) \ +do { \ + if(d < -(1LL<<5)) { \ + if(d < -(1LL<<15)) { \ + if(d < -(1LL<<31)) { \ + /* signed 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xd3; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } else { \ + /* signed 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } else { \ + if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \ + } else { \ + if(d < (1LL<<16)) { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ + } else { \ + if(d < (1LL<<32)) { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else { \ + /* unsigned 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } \ + } \ + } \ +} while(0) + + +#ifdef msgpack_pack_inline_func_fixint + +msgpack_pack_inline_func_fixint(_uint8)(msgpack_pack_user x, uint8_t d) +{ + unsigned char buf[2] = {0xcc, TAKE8_8(d)}; + msgpack_pack_append_buffer(x, buf, 2); +} + +msgpack_pack_inline_func_fixint(_uint16)(msgpack_pack_user x, uint16_t d) +{ + unsigned char buf[3]; + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 3); +} + +msgpack_pack_inline_func_fixint(_uint32)(msgpack_pack_user x, uint32_t d) +{ + unsigned char buf[5]; + buf[0] = 0xce; _msgpack_store32(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func_fixint(_uint64)(msgpack_pack_user x, uint64_t d) +{ + unsigned char buf[9]; + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 9); +} + +msgpack_pack_inline_func_fixint(_int8)(msgpack_pack_user x, int8_t d) +{ + unsigned char buf[2] = {0xd0, TAKE8_8(d)}; + msgpack_pack_append_buffer(x, buf, 2); +} + +msgpack_pack_inline_func_fixint(_int16)(msgpack_pack_user x, int16_t d) +{ + unsigned char buf[3]; + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 3); +} + +msgpack_pack_inline_func_fixint(_int32)(msgpack_pack_user x, int32_t d) +{ + unsigned char buf[5]; + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func_fixint(_int64)(msgpack_pack_user x, int64_t d) +{ + unsigned char buf[9]; + buf[0] = 0xd3; _msgpack_store64(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 9); +} + +#undef msgpack_pack_inline_func_fixint +#endif + + +msgpack_pack_inline_func(_uint8)(msgpack_pack_user x, uint8_t d) +{ + msgpack_pack_real_uint8(x, d); +} + +msgpack_pack_inline_func(_uint16)(msgpack_pack_user x, uint16_t d) +{ + msgpack_pack_real_uint16(x, d); +} + +msgpack_pack_inline_func(_uint32)(msgpack_pack_user x, uint32_t d) +{ + msgpack_pack_real_uint32(x, d); +} + +msgpack_pack_inline_func(_uint64)(msgpack_pack_user x, uint64_t d) +{ + msgpack_pack_real_uint64(x, d); +} + +msgpack_pack_inline_func(_int8)(msgpack_pack_user x, int8_t d) +{ + msgpack_pack_real_int8(x, d); +} + +msgpack_pack_inline_func(_int16)(msgpack_pack_user x, int16_t d) +{ + msgpack_pack_real_int16(x, d); +} + +msgpack_pack_inline_func(_int32)(msgpack_pack_user x, int32_t d) +{ + msgpack_pack_real_int32(x, d); +} + +msgpack_pack_inline_func(_int64)(msgpack_pack_user x, int64_t d) +{ + msgpack_pack_real_int64(x, d); +} + + +#ifdef msgpack_pack_inline_func_cint + +msgpack_pack_inline_func_cint(_short)(msgpack_pack_user x, short d) +{ +#if defined(SIZEOF_SHORT) +#if SIZEOF_SHORT == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_SHORT == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(SHRT_MAX) +#if SHRT_MAX == 0x7fff + msgpack_pack_real_int16(x, d); +#elif SHRT_MAX == 0x7fffffff + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(short) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(short) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_int)(msgpack_pack_user x, int d) +{ +#if defined(SIZEOF_INT) +#if SIZEOF_INT == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_INT == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(INT_MAX) +#if INT_MAX == 0x7fff + msgpack_pack_real_int16(x, d); +#elif INT_MAX == 0x7fffffff + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(int) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(int) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_long)(msgpack_pack_user x, long d) +{ +#if defined(SIZEOF_LONG) +#if SIZEOF_LONG == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_LONG == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(LONG_MAX) +#if LONG_MAX == 0x7fffL + msgpack_pack_real_int16(x, d); +#elif LONG_MAX == 0x7fffffffL + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(long) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(long) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_long_long)(msgpack_pack_user x, long long d) +{ +#if defined(SIZEOF_LONG_LONG) +#if SIZEOF_LONG_LONG == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_LONG_LONG == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(LLONG_MAX) +#if LLONG_MAX == 0x7fffL + msgpack_pack_real_int16(x, d); +#elif LLONG_MAX == 0x7fffffffL + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(long long) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(long long) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_short)(msgpack_pack_user x, unsigned short d) +{ +#if defined(SIZEOF_SHORT) +#if SIZEOF_SHORT == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_SHORT == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(USHRT_MAX) +#if USHRT_MAX == 0xffffU + msgpack_pack_real_uint16(x, d); +#elif USHRT_MAX == 0xffffffffU + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned short) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned short) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_int)(msgpack_pack_user x, unsigned int d) +{ +#if defined(SIZEOF_INT) +#if SIZEOF_INT == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_INT == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(UINT_MAX) +#if UINT_MAX == 0xffffU + msgpack_pack_real_uint16(x, d); +#elif UINT_MAX == 0xffffffffU + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned int) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned int) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_long)(msgpack_pack_user x, unsigned long d) +{ +#if defined(SIZEOF_LONG) +#if SIZEOF_LONG == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_LONG == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(ULONG_MAX) +#if ULONG_MAX == 0xffffUL + msgpack_pack_real_uint16(x, d); +#elif ULONG_MAX == 0xffffffffUL + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned long) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned long) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_long_long)(msgpack_pack_user x, unsigned long long d) +{ +#if defined(SIZEOF_LONG_LONG) +#if SIZEOF_LONG_LONG == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_LONG_LONG == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(ULLONG_MAX) +#if ULLONG_MAX == 0xffffUL + msgpack_pack_real_uint16(x, d); +#elif ULLONG_MAX == 0xffffffffUL + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned long long) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned long long) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +#undef msgpack_pack_inline_func_cint +#endif + + + +/* + * Float + */ + +msgpack_pack_inline_func(_float)(msgpack_pack_user x, float d) +{ + union { float f; uint32_t i; } mem; + mem.f = d; + unsigned char buf[5]; + buf[0] = 0xca; _msgpack_store32(&buf[1], mem.i); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func(_double)(msgpack_pack_user x, double d) +{ + union { double f; uint64_t i; } mem; + mem.f = d; + unsigned char buf[9]; + buf[0] = 0xcb; _msgpack_store64(&buf[1], mem.i); + msgpack_pack_append_buffer(x, buf, 9); +} + + +/* + * Nil + */ + +msgpack_pack_inline_func(_nil)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc0; + msgpack_pack_append_buffer(x, &d, 1); +} + + +/* + * Boolean + */ + +msgpack_pack_inline_func(_true)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc3; + msgpack_pack_append_buffer(x, &d, 1); +} + +msgpack_pack_inline_func(_false)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc2; + msgpack_pack_append_buffer(x, &d, 1); +} + + +/* + * Array + */ + +msgpack_pack_inline_func(_array)(msgpack_pack_user x, unsigned int n) +{ + if(n < 16) { + unsigned char d = 0x90 | n; + msgpack_pack_append_buffer(x, &d, 1); + } else if(n < 65536) { + unsigned char buf[3]; + buf[0] = 0xdc; _msgpack_store16(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdd; _msgpack_store32(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 5); + } +} + + +/* + * Map + */ + +msgpack_pack_inline_func(_map)(msgpack_pack_user x, unsigned int n) +{ + if(n < 16) { + unsigned char d = 0x80 | n; + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); + } else if(n < 65536) { + unsigned char buf[3]; + buf[0] = 0xde; _msgpack_store16(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdf; _msgpack_store32(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 5); + } +} + + +/* + * Raw + */ + +msgpack_pack_inline_func(_raw)(msgpack_pack_user x, size_t l) +{ + if(l < 32) { + unsigned char d = 0xa0 | l; + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); + } else if(l < 65536) { + unsigned char buf[3]; + buf[0] = 0xda; _msgpack_store16(&buf[1], l); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdb; _msgpack_store32(&buf[1], l); + msgpack_pack_append_buffer(x, buf, 5); + } +} + +msgpack_pack_inline_func(_raw_body)(msgpack_pack_user x, const void* b, size_t l) +{ + msgpack_pack_append_buffer(x, (const unsigned char*)b, l); +} + +#undef msgpack_pack_inline_func +#undef msgpack_pack_user +#undef msgpack_pack_append_buffer + +#undef TAKE8_8 +#undef TAKE8_16 +#undef TAKE8_32 +#undef TAKE8_64 + +#undef msgpack_pack_real_uint8 +#undef msgpack_pack_real_uint16 +#undef msgpack_pack_real_uint32 +#undef msgpack_pack_real_uint64 +#undef msgpack_pack_real_int8 +#undef msgpack_pack_real_int16 +#undef msgpack_pack_real_int32 +#undef msgpack_pack_real_int64 + diff --git a/php/msgpack/sysdep.h b/php/msgpack/sysdep.h new file mode 100644 index 00000000..2bc01c9f --- /dev/null +++ b/php/msgpack/sysdep.h @@ -0,0 +1,118 @@ +/* + * MessagePack system dependencies + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_SYSDEP_H__ +#define MSGPACK_SYSDEP_H__ + + +#ifdef _MSC_VER +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#include +#include +#endif + + +#ifdef _WIN32 +typedef long _msgpack_atomic_counter_t; +#define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr) +#define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr) +#else +typedef unsigned int _msgpack_atomic_counter_t; +#define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1) +#define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1) +#endif + + +#ifdef _WIN32 +#include + +#ifdef __cplusplus +/* numeric_limits::min,max */ +#ifdef max +#undef max +#endif +#ifdef min +#undef min +#endif +#endif + +#else +#include /* __BYTE_ORDER */ +#endif + +#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define __LITTLE_ENDIAN__ +#elif __BYTE_ORDER == __BIG_ENDIAN +#define __BIG_ENDIAN__ +#endif +#endif + +#ifdef __LITTLE_ENDIAN__ + +#define _msgpack_be16(x) ntohs(x) +#define _msgpack_be32(x) ntohl(x) + +#if defined(_byteswap_uint64) +# define _msgpack_be64(x) (_byteswap_uint64(x)) +#elif defined(bswap_64) +# define _msgpack_be64(x) bswap_64(x) +#elif defined(__DARWIN_OSSwapInt64) +# define _msgpack_be64(x) __DARWIN_OSSwapInt64(x) +#else +#define _msgpack_be64(x) \ + ( ((((uint64_t)x) << 56) & 0xff00000000000000ULL ) | \ + ((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \ + ((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \ + ((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \ + ((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \ + ((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \ + ((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \ + ((((uint64_t)x) >> 56) & 0x00000000000000ffULL ) ) +#endif + +#else +#define _msgpack_be16(x) (x) +#define _msgpack_be32(x) (x) +#define _msgpack_be64(x) (x) +#endif + + +#define _msgpack_store16(to, num) \ + do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0); +#define _msgpack_store32(to, num) \ + do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0); +#define _msgpack_store64(to, num) \ + do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0); + + +#define _msgpack_load16(cast, from) ((cast)_msgpack_be16(*(uint16_t*)from)) +#define _msgpack_load32(cast, from) ((cast)_msgpack_be32(*(uint32_t*)from)) +#define _msgpack_load64(cast, from) ((cast)_msgpack_be64(*(uint64_t*)from)) + + +#endif /* msgpack/sysdep.h */ + diff --git a/php/msgpack/unpack_define.h b/php/msgpack/unpack_define.h new file mode 100644 index 00000000..959d3519 --- /dev/null +++ b/php/msgpack/unpack_define.h @@ -0,0 +1,93 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_UNPACK_DEFINE_H__ +#define MSGPACK_UNPACK_DEFINE_H__ + +#include "msgpack/sysdep.h" +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef MSGPACK_EMBED_STACK_SIZE +#define MSGPACK_EMBED_STACK_SIZE 32 +#endif + + +typedef enum { + CS_HEADER = 0x00, // nil + + //CS_ = 0x01, + //CS_ = 0x02, // false + //CS_ = 0x03, // true + + //CS_ = 0x04, + //CS_ = 0x05, + //CS_ = 0x06, + //CS_ = 0x07, + + //CS_ = 0x08, + //CS_ = 0x09, + CS_FLOAT = 0x0a, + CS_DOUBLE = 0x0b, + CS_UINT_8 = 0x0c, + CS_UINT_16 = 0x0d, + CS_UINT_32 = 0x0e, + CS_UINT_64 = 0x0f, + CS_INT_8 = 0x10, + CS_INT_16 = 0x11, + CS_INT_32 = 0x12, + CS_INT_64 = 0x13, + + //CS_ = 0x14, + //CS_ = 0x15, + //CS_BIG_INT_16 = 0x16, + //CS_BIG_INT_32 = 0x17, + //CS_BIG_FLOAT_16 = 0x18, + //CS_BIG_FLOAT_32 = 0x19, + CS_RAW_16 = 0x1a, + CS_RAW_32 = 0x1b, + CS_ARRAY_16 = 0x1c, + CS_ARRAY_32 = 0x1d, + CS_MAP_16 = 0x1e, + CS_MAP_32 = 0x1f, + + //ACS_BIG_INT_VALUE, + //ACS_BIG_FLOAT_VALUE, + ACS_RAW_VALUE, +} msgpack_unpack_state; + + +typedef enum { + CT_ARRAY_ITEM, + CT_MAP_KEY, + CT_MAP_VALUE, +} msgpack_container_type; + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/unpack_define.h */ + diff --git a/php/msgpack/unpack_template.h b/php/msgpack/unpack_template.h new file mode 100644 index 00000000..0fbfbb78 --- /dev/null +++ b/php/msgpack/unpack_template.h @@ -0,0 +1,409 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef msgpack_unpack_func +#error msgpack_unpack_func template is not defined +#endif + +#ifndef msgpack_unpack_callback +#error msgpack_unpack_callback template is not defined +#endif + +#ifndef msgpack_unpack_struct +#error msgpack_unpack_struct template is not defined +#endif + +#ifndef msgpack_unpack_struct_decl +#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name) +#endif + +#ifndef msgpack_unpack_object +#error msgpack_unpack_object type is not defined +#endif + +#ifndef msgpack_unpack_user +#error msgpack_unpack_user type is not defined +#endif + +#ifndef USE_CASE_RANGE +#if !defined(_MSC_VER) +#define USE_CASE_RANGE +#endif +#endif + +msgpack_unpack_struct_decl(_stack) { + msgpack_unpack_object obj; + size_t count; + unsigned int ct; + msgpack_unpack_object map_key; +}; + +msgpack_unpack_struct_decl(_context) { + msgpack_unpack_user user; + unsigned int cs; + unsigned int trail; + unsigned int top; + /* + msgpack_unpack_struct(_stack)* stack; + unsigned int stack_size; + msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE]; + */ + msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE]; +}; + + +msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) +{ + ctx->cs = CS_HEADER; + ctx->trail = 0; + ctx->top = 0; + /* + ctx->stack = ctx->embed_stack; + ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; + */ + ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); +} + +/* +msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx) +{ + if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { + free(ctx->stack); + } +} +*/ + +msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) +{ + return (ctx)->stack[0].obj; +} + + +msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off) +{ + assert(len >= *off); + + const unsigned char* p = (unsigned char*)data + *off; + const unsigned char* const pe = (unsigned char*)data + len; + const void* n = NULL; + + unsigned int trail = ctx->trail; + unsigned int cs = ctx->cs; + unsigned int top = ctx->top; + msgpack_unpack_struct(_stack)* stack = ctx->stack; + /* + unsigned int stack_size = ctx->stack_size; + */ + msgpack_unpack_user* user = &ctx->user; + + msgpack_unpack_object obj; + msgpack_unpack_struct(_stack)* c = NULL; + + int ret; + +#define push_simple_value(func) \ + if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \ + goto _push +#define push_fixed_value(func, arg) \ + if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \ + goto _push +#define push_variable_value(func, base, pos, len) \ + if(msgpack_unpack_callback(func)(user, \ + (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ + goto _push + +#define again_fixed_trail(_cs, trail_len) \ + trail = trail_len; \ + cs = _cs; \ + goto _fixed_trail_again +#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ + trail = trail_len; \ + if(trail == 0) { goto ifzero; } \ + cs = _cs; \ + goto _fixed_trail_again + +#define start_container(func, count_, ct_) \ + if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \ + if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ + if((count_) == 0) { obj = stack[top].obj; goto _push; } \ + stack[top].ct = ct_; \ + stack[top].count = count_; \ + ++top; \ + /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ + /*printf("stack push %d\n", top);*/ \ + /* FIXME \ + if(top >= stack_size) { \ + if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \ + size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \ + size_t nsize = csize * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \ + if(tmp == NULL) { goto _failed; } \ + memcpy(tmp, ctx->stack, csize); \ + ctx->stack = stack = tmp; \ + ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ + } else { \ + size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \ + if(tmp == NULL) { goto _failed; } \ + ctx->stack = stack = tmp; \ + ctx->stack_size = stack_size = stack_size * 2; \ + } \ + } \ + */ \ + goto _header_again + +#define NEXT_CS(p) \ + ((unsigned int)*p & 0x1f) + +#ifdef USE_CASE_RANGE +#define SWITCH_RANGE_BEGIN switch(*p) { +#define SWITCH_RANGE(FROM, TO) case FROM ... TO: +#define SWITCH_RANGE_DEFAULT default: +#define SWITCH_RANGE_END } +#else +#define SWITCH_RANGE_BEGIN { if(0) { +#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) { +#define SWITCH_RANGE_DEFAULT } else { +#define SWITCH_RANGE_END } } +#endif + + if(p == pe) { goto _out; } + do { + switch(cs) { + case CS_HEADER: + SWITCH_RANGE_BEGIN + SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum + push_fixed_value(_uint8, *(uint8_t*)p); + SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum + push_fixed_value(_int8, *(int8_t*)p); + SWITCH_RANGE(0xc0, 0xdf) // Variable + switch(*p) { + case 0xc0: // nil + push_simple_value(_nil); + //case 0xc1: // string + // again_terminal_trail(NEXT_CS(p), p+1); + case 0xc2: // false + push_simple_value(_false); + case 0xc3: // true + push_simple_value(_true); + //case 0xc4: + //case 0xc5: + //case 0xc6: + //case 0xc7: + //case 0xc8: + //case 0xc9: + case 0xca: // float + case 0xcb: // double + case 0xcc: // unsigned int 8 + case 0xcd: // unsigned int 16 + case 0xce: // unsigned int 32 + case 0xcf: // unsigned int 64 + case 0xd0: // signed int 8 + case 0xd1: // signed int 16 + case 0xd2: // signed int 32 + case 0xd3: // signed int 64 + again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); + //case 0xd4: + //case 0xd5: + //case 0xd6: // big integer 16 + //case 0xd7: // big integer 32 + //case 0xd8: // big float 16 + //case 0xd9: // big float 32 + case 0xda: // raw 16 + case 0xdb: // raw 32 + case 0xdc: // array 16 + case 0xdd: // array 32 + case 0xde: // map 16 + case 0xdf: // map 32 + again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01)); + default: + goto _failed; + } + SWITCH_RANGE(0xa0, 0xbf) // FixRaw + again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero); + SWITCH_RANGE(0x90, 0x9f) // FixArray + start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM); + SWITCH_RANGE(0x80, 0x8f) // FixMap + start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY); + + SWITCH_RANGE_DEFAULT + goto _failed; + SWITCH_RANGE_END + // end CS_HEADER + + + _fixed_trail_again: + ++p; + + default: + if((size_t)(pe - p) < trail) { goto _out; } + n = p; p += trail - 1; + switch(cs) { + //case CS_ + //case CS_ + case CS_FLOAT: { + union { uint32_t i; float f; } mem; + mem.i = _msgpack_load32(uint32_t,n); + push_fixed_value(_float, mem.f); } + case CS_DOUBLE: { + union { uint64_t i; double f; } mem; + mem.i = _msgpack_load64(uint64_t,n); + push_fixed_value(_double, mem.f); } + case CS_UINT_8: + push_fixed_value(_uint8, *(uint8_t*)n); + case CS_UINT_16: + push_fixed_value(_uint16, _msgpack_load16(uint16_t,n)); + case CS_UINT_32: + push_fixed_value(_uint32, _msgpack_load32(uint32_t,n)); + case CS_UINT_64: + push_fixed_value(_uint64, _msgpack_load64(uint64_t,n)); + + case CS_INT_8: + push_fixed_value(_int8, *(int8_t*)n); + case CS_INT_16: + push_fixed_value(_int16, _msgpack_load16(int16_t,n)); + case CS_INT_32: + push_fixed_value(_int32, _msgpack_load32(int32_t,n)); + case CS_INT_64: + push_fixed_value(_int64, _msgpack_load64(int64_t,n)); + + //case CS_ + //case CS_ + //case CS_BIG_INT_16: + // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load16(uint16_t,n), _big_int_zero); + //case CS_BIG_INT_32: + // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load32(uint32_t,n), _big_int_zero); + //case ACS_BIG_INT_VALUE: + //_big_int_zero: + // // FIXME + // push_variable_value(_big_int, data, n, trail); + + //case CS_BIG_FLOAT_16: + // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load16(uint16_t,n), _big_float_zero); + //case CS_BIG_FLOAT_32: + // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load32(uint32_t,n), _big_float_zero); + //case ACS_BIG_FLOAT_VALUE: + //_big_float_zero: + // // FIXME + // push_variable_value(_big_float, data, n, trail); + + case CS_RAW_16: + again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero); + case CS_RAW_32: + again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero); + case ACS_RAW_VALUE: + _raw_zero: + push_variable_value(_raw, data, n, trail); + + case CS_ARRAY_16: + start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM); + case CS_ARRAY_32: + /* FIXME security guard */ + start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM); + + case CS_MAP_16: + start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY); + case CS_MAP_32: + /* FIXME security guard */ + start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY); + + default: + goto _failed; + } + } + +_push: + if(top == 0) { goto _finish; } + c = &stack[top-1]; + switch(c->ct) { + case CT_ARRAY_ITEM: + if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; } + if(--c->count == 0) { + obj = c->obj; + --top; + /*printf("stack pop %d\n", top);*/ + goto _push; + } + goto _header_again; + case CT_MAP_KEY: + c->map_key = obj; + c->ct = CT_MAP_VALUE; + goto _header_again; + case CT_MAP_VALUE: + if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; } + if(--c->count == 0) { + obj = c->obj; + --top; + /*printf("stack pop %d\n", top);*/ + goto _push; + } + c->ct = CT_MAP_KEY; + goto _header_again; + + default: + goto _failed; + } + +_header_again: + cs = CS_HEADER; + ++p; + } while(p != pe); + goto _out; + + +_finish: + stack[0].obj = obj; + ++p; + ret = 1; + /*printf("-- finish --\n"); */ + goto _end; + +_failed: + /*printf("** FAILED **\n"); */ + ret = -1; + goto _end; + +_out: + ret = 0; + goto _end; + +_end: + ctx->cs = cs; + ctx->trail = trail; + ctx->top = top; + *off = p - (const unsigned char*)data; + + return ret; +} + + +#undef msgpack_unpack_func +#undef msgpack_unpack_callback +#undef msgpack_unpack_struct +#undef msgpack_unpack_object +#undef msgpack_unpack_user + +#undef push_simple_value +#undef push_fixed_value +#undef push_variable_value +#undef again_fixed_trail +#undef again_fixed_trail_if_zero +#undef start_container + +#undef NEXT_CS + diff --git a/php/msgpack/version.h b/php/msgpack/version.h new file mode 100644 index 00000000..13671d1a --- /dev/null +++ b/php/msgpack/version.h @@ -0,0 +1,40 @@ +/* + * MessagePack for C version information + * + * Copyright (C) 2008-2009 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_VERSION_H__ +#define MSGPACK_VERSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +const char* msgpack_version(void); +int msgpack_version_major(void); +int msgpack_version_minor(void); + +#define MSGPACK_VERSION "0.5.4" +#define MSGPACK_VERSION_MAJOR 0 +#define MSGPACK_VERSION_MINOR 5 + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/version.h */ + diff --git a/php/msgpack_class.c b/php/msgpack_class.c index b728cb56..5cfff8d8 100644 --- a/php/msgpack_class.c +++ b/php/msgpack_class.c @@ -6,33 +6,81 @@ #include "msgpack_unpack.h" #include "msgpack_class.h" +typedef struct { + zend_object object; + long php_only; +} php_msgpack_base_t; + typedef struct { zend_object object; smart_str buffer; zval *retval; long offset; + msgpack_unpack_t mp; + php_unserialize_data_t var_hash; + long php_only; } php_msgpack_unpacker_t; #if ZEND_MODULE_API_NO >= 20060613 -#define MAGPACK_METHOD_BASE(classname, name) zim_##classname##_##name +# define MSGPACK_METHOD_BASE(classname, name) zim_##classname##_##name #else -#define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name +# define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name #endif +#if ZEND_MODULE_API_NO >= 20090115 +# define PUSH_PARAM(arg) zend_vm_stack_push(arg TSRMLS_CC) +# define POP_PARAM() (void)zend_vm_stack_pop(TSRMLS_C) +# define PUSH_EO_PARAM() +# define POP_EO_PARAM() +#else +# define PUSH_PARAM(arg) zend_ptr_stack_push(&EG(argument_stack), arg) +# define POP_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) +# define PUSH_EO_PARAM() zend_ptr_stack_push(&EG(argument_stack), NULL) +# define POP_EO_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) +#endif + +#define MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, num, param) \ + PUSH_PARAM(param); PUSH_PARAM((void*)num); \ + PUSH_EO_PARAM(); \ + MSGPACK_METHOD_BASE(classname, name)(num, retval, NULL, thisptr, 0 TSRMLS_CC); \ + POP_EO_PARAM(); \ + POP_PARAM(); \ + POP_PARAM(); + #define MSGPACK_METHOD(classname, name, retval, thisptr) \ - MAGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) + MSGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) + +#define MSGPACK_METHOD1(classname, name, retval, thisptr, param1) \ + MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, 1, param1); + +#define MSGPACK_BASE_OBJECT \ + php_msgpack_base_t *base; \ + base = (php_msgpack_base_t *)zend_object_store_get_object(getThis() TSRMLS_CC); #define MSGPACK_UNPACKER_OBJECT \ php_msgpack_unpacker_t *unpacker; \ - unpacker =(php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); + unpacker = (php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); + +#define MSGPACK_CLASS_OPT_PHPONLY -1001 /* MessagePack */ static zend_class_entry *msgpack_ce = NULL; +static ZEND_METHOD(msgpack, __construct); +static ZEND_METHOD(msgpack, setOption); static ZEND_METHOD(msgpack, pack); static ZEND_METHOD(msgpack, unpack); static ZEND_METHOD(msgpack, unpacker); +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base___construct, 0, 0, 0) + ZEND_ARG_INFO(0, opt) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_setOption, 0, 0, 2) + ZEND_ARG_INFO(0, option) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_pack, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() @@ -45,6 +93,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_unpacker, 0, 0, 0) ZEND_END_ARG_INFO() static const zend_function_entry msgpack_base_methods[] = { + ZEND_ME(msgpack, __construct, + arginfo_msgpack_base___construct, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, setOption, arginfo_msgpack_base_setOption, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, pack, arginfo_msgpack_base_pack, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, unpack, arginfo_msgpack_base_unpack, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, unpacker, arginfo_msgpack_base_unpacker, ZEND_ACC_PUBLIC) @@ -54,19 +105,26 @@ static const zend_function_entry msgpack_base_methods[] = { /* MessagePackUnpacker */ static zend_class_entry *msgpack_unpacker_ce = NULL; -static ZEND_METHOD(msgpack, __construct); -static ZEND_METHOD(msgpack, __destruct); -static ZEND_METHOD(msgpack, feed); -static ZEND_METHOD(msgpack, execute); -static ZEND_METHOD(msgpack, data); -static ZEND_METHOD(msgpack, reset); +static ZEND_METHOD(msgpack_unpacker, __construct); +static ZEND_METHOD(msgpack_unpacker, __destruct); +static ZEND_METHOD(msgpack_unpacker, setOption); +static ZEND_METHOD(msgpack_unpacker, feed); +static ZEND_METHOD(msgpack_unpacker, execute); +static ZEND_METHOD(msgpack_unpacker, data); +static ZEND_METHOD(msgpack_unpacker, reset); ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___construct, 0, 0, 0) + ZEND_ARG_INFO(0, opt) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___destruct, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_setOption, 0, 0, 2) + ZEND_ARG_INFO(0, option) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_feed, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_END_ARG_INFO() @@ -83,17 +141,52 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_reset, 0, 0, 0) ZEND_END_ARG_INFO() static const zend_function_entry msgpack_unpacker_methods[] = { - ZEND_ME(msgpack, __construct, + ZEND_ME(msgpack_unpacker, __construct, arginfo_msgpack_unpacker___construct, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, __destruct, + ZEND_ME(msgpack_unpacker, __destruct, arginfo_msgpack_unpacker___destruct, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, feed, arginfo_msgpack_unpacker_feed, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, execute, arginfo_msgpack_unpacker_execute, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, data, arginfo_msgpack_unpacker_data, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, reset, arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, setOption, + arginfo_msgpack_unpacker_setOption, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, feed, + arginfo_msgpack_unpacker_feed, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, execute, + arginfo_msgpack_unpacker_execute, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, data, + arginfo_msgpack_unpacker_data, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, reset, + arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; +static void php_msgpack_base_free(php_msgpack_base_t *base TSRMLS_DC) +{ + zend_object_std_dtor(&base->object TSRMLS_CC); + efree(base); +} + +static zend_object_value php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + zval *tmp; + php_msgpack_base_t *base; + + base = emalloc(sizeof(php_msgpack_base_t)); + + zend_object_std_init(&base->object, ce TSRMLS_CC); + + zend_hash_copy( + base->object.properties, &ce->default_properties, + (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); + + retval.handle = zend_objects_store_put( + base, (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)php_msgpack_base_free, + NULL TSRMLS_CC); + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} + static void php_msgpack_unpacker_free( php_msgpack_unpacker_t *unpacker TSRMLS_DC) { @@ -126,10 +219,58 @@ static zend_object_value php_msgpack_unpacker_new( } /* MessagePack */ +static ZEND_METHOD(msgpack, __construct) +{ + bool php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) + { + return; + } + + base->php_only = php_only; +} + +static ZEND_METHOD(msgpack, setOption) +{ + long option; + zval *value; + MSGPACK_BASE_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) + { + return; + } + + switch (option) + { + case MSGPACK_CLASS_OPT_PHPONLY: + convert_to_boolean(value); + base->php_only = Z_BVAL_P(value); + break; + default: + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (MessagePack::setOption) " + "error setting msgpack option"); + } + RETURN_FALSE; + break; + } + + RETURN_TRUE; +} + static ZEND_METHOD(msgpack, pack) { zval *parameter; smart_str buf = {0}; + int php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) @@ -137,8 +278,12 @@ static ZEND_METHOD(msgpack, pack) return; } + MSGPACK_G(php_only) = base->php_only; + php_msgpack_serialize(&buf, parameter TSRMLS_CC); + MSGPACK_G(php_only) = php_only; + ZVAL_STRINGL(return_value, buf.c, buf.len, 1); smart_str_free(&buf); @@ -148,6 +293,8 @@ static ZEND_METHOD(msgpack, unpack) { char *str; int str_len; + int php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) @@ -160,31 +307,57 @@ static ZEND_METHOD(msgpack, unpack) RETURN_NULL(); } + MSGPACK_G(php_only) = base->php_only; + php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); + + MSGPACK_G(php_only) = php_only; } static ZEND_METHOD(msgpack, unpacker) { - zval temp; + zval temp, *opt; + MSGPACK_BASE_OBJECT; + + ALLOC_INIT_ZVAL(opt); + ZVAL_BOOL(opt, base->php_only); object_init_ex(return_value, msgpack_unpacker_ce); - MSGPACK_METHOD(msgpack, __construct, &temp, return_value); + MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); + + zval_ptr_dtor(&opt); } /* MessagePackUnpacker */ -static ZEND_METHOD(msgpack, __construct) +static ZEND_METHOD(msgpack_unpacker, __construct) { + bool php_only = MSGPACK_G(php_only); MSGPACK_UNPACKER_OBJECT; + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) + { + return; + } + + unpacker->php_only = php_only; + unpacker->buffer.c = NULL; unpacker->buffer.len = 0; unpacker->buffer.a = 0; unpacker->retval = NULL; unpacker->offset = 0; + + template_init(&unpacker->mp); + + msgpack_unserialize_var_init(&unpacker->var_hash); + + (&unpacker->mp)->user.var_hash = + (php_unserialize_data_t *)&unpacker->var_hash; } -static ZEND_METHOD(msgpack, __destruct) +static ZEND_METHOD(msgpack_unpacker, __destruct) { MSGPACK_UNPACKER_OBJECT; @@ -194,9 +367,43 @@ static ZEND_METHOD(msgpack, __destruct) { zval_ptr_dtor(&unpacker->retval); } + + msgpack_unserialize_var_destroy(&unpacker->var_hash); } -static ZEND_METHOD(msgpack, feed) +static ZEND_METHOD(msgpack_unpacker, setOption) +{ + long option; + zval *value; + MSGPACK_UNPACKER_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) + { + return; + } + + switch (option) + { + case MSGPACK_CLASS_OPT_PHPONLY: + convert_to_boolean(value); + unpacker->php_only = Z_BVAL_P(value); + break; + default: + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (MessagePackUnpacker::setOption) " + "error setting msgpack option"); + } + RETURN_FALSE; + break; + } + + RETURN_TRUE; +} + +static ZEND_METHOD(msgpack_unpacker, feed) { char *str; int str_len; @@ -218,14 +425,15 @@ static ZEND_METHOD(msgpack, feed) RETURN_TRUE; } -static ZEND_METHOD(msgpack, execute) +static ZEND_METHOD(msgpack_unpacker, execute) { - char *str = NULL; + char *str = NULL, *data; long str_len = 0; zval *offset; int ret; - php_unserialize_data_t var_hash; - msgpack_unserialize_data mpsd; + size_t len, off; + int error_display = MSGPACK_G(error_display); + int php_only = MSGPACK_G(php_only); MSGPACK_UNPACKER_OBJECT; if (zend_parse_parameters( @@ -237,45 +445,38 @@ static ZEND_METHOD(msgpack, execute) if (str != NULL) { - mpsd.data = (unsigned char *)str; - mpsd.length = str_len; - mpsd.offset = Z_LVAL_P(offset); + data = (char *)str; + len = (size_t)str_len; + off = Z_LVAL_P(offset); } else { - mpsd.data = (unsigned char *)unpacker->buffer.c; - mpsd.length = unpacker->buffer.len; - mpsd.offset = unpacker->offset; + data = (char *)unpacker->buffer.c; + len = unpacker->buffer.len; + off = unpacker->offset; } - if (mpsd.length <= 0 || mpsd.length == mpsd.offset) - { - RETURN_FALSE; - } - - PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (unpacker->retval == NULL) { ALLOC_INIT_ZVAL(unpacker->retval); } + (&unpacker->mp)->user.retval = (zval *)unpacker->retval; MSGPACK_G(error_display) = 0; + MSGPACK_G(php_only) = unpacker->php_only; - ret = msgpack_unserialize_zval( - &unpacker->retval, &mpsd, &var_hash TSRMLS_CC); + ret = template_execute(&unpacker->mp, data, len, &off); - MSGPACK_G(error_display) = 1; - - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + MSGPACK_G(error_display) = error_display; + MSGPACK_G(php_only) = php_only; if (str != NULL) { - ZVAL_LONG(offset, mpsd.offset); + ZVAL_LONG(offset, off); } else { - unpacker->offset = mpsd.offset; + unpacker->offset = off; } switch (ret) @@ -288,14 +489,14 @@ static ZEND_METHOD(msgpack, execute) } } -static ZEND_METHOD(msgpack, data) +static ZEND_METHOD(msgpack_unpacker, data) { MSGPACK_UNPACKER_OBJECT; RETURN_ZVAL(unpacker->retval, 1, 1); } -static ZEND_METHOD(msgpack, reset) +static ZEND_METHOD(msgpack_unpacker, reset) { smart_str buffer = {0}; MSGPACK_UNPACKER_OBJECT; @@ -325,15 +526,33 @@ static ZEND_METHOD(msgpack, reset) zval_ptr_dtor(&unpacker->retval); unpacker->retval = NULL; } + + msgpack_unserialize_var_destroy(&unpacker->var_hash); + + + msgpack_unserialize_var_init(&unpacker->var_hash); + + (&unpacker->mp)->user.var_hash = + (php_unserialize_data_t *)&unpacker->var_hash; + + msgpack_unserialize_init(&((&unpacker->mp)->user)); } -void msgpack_init_class(TSRMLS_DC) +void msgpack_init_class() { zend_class_entry ce; + TSRMLS_FETCH(); + /* base */ INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_base_methods); msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC); + msgpack_ce->create_object = php_msgpack_base_new; + zend_declare_class_constant_long( + msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, + MSGPACK_CLASS_OPT_PHPONLY TSRMLS_CC); + + /* unpacker */ INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods); msgpack_unpacker_ce = zend_register_internal_class(&ce TSRMLS_CC); msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new; diff --git a/php/msgpack_class.h b/php/msgpack_class.h index 00ac9e7b..fbebaf4d 100644 --- a/php/msgpack_class.h +++ b/php/msgpack_class.h @@ -1,7 +1,7 @@ -#ifndef MSGPACL_CLASS_H -#define MSGPACL_CLASS_H +#ifndef MSGPACK_CLASS_H +#define MSGPACK_CLASS_H -void msgpack_init_class(TSRMLS_DC); +void msgpack_init_class(); #endif diff --git a/php/msgpack_pack.c b/php/msgpack_pack.c index 91a3d396..d2d4ba3b 100644 --- a/php/msgpack_pack.c +++ b/php/msgpack_pack.c @@ -119,13 +119,14 @@ inline static void msgpack_serialize_class( if (Z_TYPE_PP(name) != IS_STRING) { - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_class) " - "__sleep should return an array only " - "containing the names of " - "instance-variables to serialize."); - - msgpack_pack_nil(buf); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "__sleep should return an array only " + "containing the names of " + "instance-variables to serialize."); + } continue; } @@ -195,11 +196,14 @@ inline static void msgpack_serialize_class( pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_class) " - "\"%s\" returned as member variable from " - "__sleep() but does not exist", - Z_STRVAL_PP(name)); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "\"%s\" returned as member variable from " + "__sleep() but does not exist", + Z_STRVAL_PP(name)); + } msgpack_serialize_string( buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); @@ -227,6 +231,7 @@ inline static void msgpack_serialize_array( { HashTable *ht; size_t n; + bool hash = true; if (object) { @@ -253,19 +258,46 @@ inline static void msgpack_serialize_array( if (object) { - msgpack_pack_map(buf, n + 1); + if (MSGPACK_G(php_only)) + { + if (Z_ISREF_P(val)) + { + msgpack_pack_map(buf, n + 2); + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + } + else + { + msgpack_pack_map(buf, n + 1); + } - msgpack_pack_nil(buf); + msgpack_pack_nil(buf); - msgpack_serialize_string(buf, class_name, name_len); + msgpack_serialize_string(buf, class_name, name_len); + } + else + { + msgpack_pack_array(buf, n); + hash = false; + } } else if (n == 0) { + hash = false; msgpack_pack_array(buf, n); } else { - msgpack_pack_map(buf, n); + if (Z_ISREF_P(val) && MSGPACK_G(php_only)) + { + msgpack_pack_map(buf, n + 1); + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + } + else + { + msgpack_pack_map(buf, n); + } } if (n > 0) @@ -292,20 +324,26 @@ inline static void msgpack_serialize_array( continue; } - switch (key_type) + if (hash) { - case HASH_KEY_IS_LONG: - msgpack_pack_long(buf, key_index); - break; - case HASH_KEY_IS_STRING: - msgpack_serialize_string(buf, key, key_len - 1); - break; - default: - msgpack_serialize_string(buf, "", sizeof("")); - - zend_error(E_WARNING, "[msgpack] (msgpack_serialize_array) " - "key is not string nor array"); - break; + switch (key_type) + { + case HASH_KEY_IS_LONG: + msgpack_pack_long(buf, key_index); + break; + case HASH_KEY_IS_STRING: + msgpack_serialize_string(buf, key, key_len - 1); + break; + default: + msgpack_serialize_string(buf, "", sizeof("")); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_serialize_array) " + "key is not string nor array"); + } + break; + } } if (zend_hash_get_current_data_ex( @@ -365,7 +403,6 @@ inline static void msgpack_serialize_object( msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT); msgpack_serialize_string(buf, ce->name, ce->name_length); - msgpack_pack_raw(buf, serialized_length); msgpack_pack_raw_body(buf, serialized_data, serialized_length); } @@ -401,11 +438,14 @@ inline static void msgpack_serialize_object( } else { - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_object) " - "__sleep should return an array only " - "containing the names of instance-variables " - "to serialize"); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_object) " + "__sleep should return an array only " + "containing the names of instance-variables " + "to serialize"); + } msgpack_pack_nil(buf); } zval_ptr_dtor(&retval_ptr); @@ -429,18 +469,19 @@ void msgpack_serialize_zval( { ulong *var_already; - if (var_hash && + if (MSGPACK_G(php_only) && + var_hash && msgpack_var_add( var_hash, val, (void *)&var_already TSRMLS_CC) == FAILURE) { - if (Z_ISREF_P(val)) + if (Z_ISREF_P(val) && Z_TYPE_P(val) == IS_ARRAY) { msgpack_pack_map(buf, 2); msgpack_pack_nil(buf); - msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_RECURSIVE); - msgpack_pack_nil(buf); + msgpack_pack_long(buf, 0); msgpack_pack_long(buf, *var_already); return; @@ -450,9 +491,9 @@ void msgpack_serialize_zval( msgpack_pack_map(buf, 2); msgpack_pack_nil(buf); - msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_OBJECT); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_RECURSIVE); - msgpack_pack_nil(buf); + msgpack_pack_long(buf, 0); msgpack_pack_long(buf, *var_already); return; @@ -504,9 +545,12 @@ void msgpack_serialize_zval( } break; default: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_serialize) " - "type is unsupported, encoded as null"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_serialize) " + "type is unsupported, encoded as null"); + } msgpack_pack_nil(buf); break; } diff --git a/php/msgpack_pack.h b/php/msgpack_pack.h index 96cfd4e8..16f3e7bc 100644 --- a/php/msgpack_pack.h +++ b/php/msgpack_pack.h @@ -1,13 +1,14 @@ -#ifndef MSGPACL_PACK_H -#define MSGPACL_PACK_H +#ifndef MSGPACK_PACK_H +#define MSGPACK_PACK_H #include "ext/standard/php_smart_str.h" enum msgpack_serialize_type { + MSGPACK_SERIALIZE_TYPE_NONE = 0, MSGPACK_SERIALIZE_TYPE_REFERENCE = 1, - MSGPACK_SERIALIZE_TYPE_OBJECT, + MSGPACK_SERIALIZE_TYPE_RECURSIVE, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT, }; diff --git a/php/msgpack_unpack.c b/php/msgpack_unpack.c index c6b9b3f9..f3b610d2 100644 --- a/php/msgpack_unpack.c +++ b/php/msgpack_unpack.c @@ -2,31 +2,69 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/php_incomplete_class.h" -#include "ext/standard/php_var.h" #include "php_msgpack.h" #include "msgpack_pack.h" #include "msgpack_unpack.h" -#include "msgpack/unpack_define.h" - -#define VAR_ENTRIES_MAX 1024 - #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) # define Z_ADDREF_PP(ppz) ZVAL_ADDREF(*(ppz)) # define Z_SET_ISREF_PP(ppz) (*(ppz))->is_ref = 1 # define Z_UNSET_ISREF_PP(ppz) (*(ppz))->is_ref = 0 #endif +#define VAR_ENTRIES_MAX 1024 + typedef struct { zval *data[VAR_ENTRIES_MAX]; long used_slots; + long value_slots; + long access_slots[VAR_ENTRIES_MAX]; + bool alloc_slots[VAR_ENTRIES_MAX]; void *next; } var_entries; +#define MSGPACK_UNSERIALIZE_ALLOC(_unpack) \ + if (_unpack->deps <= 0) { \ + *obj = _unpack->retval; \ + msgpack_var_push(_unpack->var_hash, obj, true, false); \ + } else { \ + ALLOC_INIT_ZVAL(*obj); \ + msgpack_var_push(_unpack->var_hash, obj, false, true); \ + } + +#define MSGPACK_UNSERIALIZE_ALLOC_VALUE(_unpack) \ + if (_unpack->deps <= 0) { \ + *obj = _unpack->retval; \ + msgpack_var_push(_unpack->var_hash, obj, true, false); \ + } else { \ + ALLOC_INIT_ZVAL(*obj); \ + msgpack_var_push(_unpack->var_hash, obj, true, true); \ + } + +#define MSGPACK_UNSERIALIZE_PUSH_ITEM(_unpack, _count, _val) \ + msgpack_var_alloc(_unpack->var_hash, _count); \ + if (Z_TYPE_P(_val) != IS_ARRAY && Z_TYPE_P(_val) != IS_OBJECT) { \ + msgpack_var_push(_unpack->var_hash, &_val, true, false); \ + } + +#define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack) \ + long deps = _unpack->deps - 1; \ + _unpack->stack[deps]--; \ + if (_unpack->stack[deps] == 0) { \ + _unpack->deps--; \ + } + +#define MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(_unpack, _key, _val) \ + zval_ptr_dtor(&_key); \ + zval_ptr_dtor(&_val); \ + msgpack_var_alloc(_unpack->var_hash, 2); \ + MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack); + + inline static void msgpack_var_push( - php_unserialize_data_t *var_hashx, zval **rval) + php_unserialize_data_t *var_hashx, zval **rval, bool value, bool alloc) { var_entries *var_hash, *prev = NULL; @@ -47,6 +85,7 @@ inline static void msgpack_var_push( { var_hash = emalloc(sizeof(var_entries)); var_hash->used_slots = 0; + var_hash->value_slots = 0; var_hash->next = 0; if (!var_hashx->first) @@ -59,9 +98,45 @@ inline static void msgpack_var_push( } } + var_hash->alloc_slots[var_hash->used_slots] = alloc; + + if (value) + { + var_hash->access_slots[var_hash->value_slots++] = var_hash->used_slots; + } + var_hash->data[var_hash->used_slots++] = *rval; } +inline static void msgpack_var_alloc( + php_unserialize_data_t *var_hashx, long count) +{ + long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) + { + var_hash = var_hash->next; + } + + if (!var_hash || count <= 0) + { + return; + } + + for (i = var_hash->used_slots - 1; i >= 0; i--) + { + if (var_hash->alloc_slots[i]) + { + var_hash->alloc_slots[i] = false; + if (--count <= 0) + { + break; + } + } + } +} + inline static int msgpack_var_access( php_unserialize_data_t *var_hashx, long id, zval ***store) { @@ -79,6 +154,13 @@ inline static int msgpack_var_access( return !SUCCESS; } + if (id < 0 || id >= var_hash->value_slots) + { + return !SUCCESS; + } + + id = var_hash->access_slots[id]; + if (id < 0 || id >= var_hash->used_slots) { return !SUCCESS; @@ -89,741 +171,533 @@ inline static int msgpack_var_access( return SUCCESS; } -inline static int msgpack_unserialize_array( - zval **return_value, msgpack_unserialize_data *mpsd, - ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) +inline static zend_class_entry* msgpack_unserialize_class( + zval **container, char *class_name, size_t name_len) { - ulong i; - HashTable *ht; - - msgpack_var_push(var_hash, return_value); - - if (Z_TYPE_PP(return_value) != IS_ARRAY) - { - array_init(*return_value); - } - - ht = HASH_OF(*return_value); - - for (i = 0; i < ct; i++) - { - zval *val; - - /* value */ - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_array) " - "Invalid value"); - } - zval_ptr_dtor(&val); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* update */ - zend_hash_index_update(ht, i, &val, sizeof(zval *), NULL); - } - - return MSGPACK_UNPACK_SUCCESS; -} - -inline static int msgpack_unserialize_object_type( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash, zend_bool is_ref TSRMLS_DC) -{ - int ret = MSGPACK_UNPACK_SUCCESS; - zval *key, *val, **rval; - - ALLOC_INIT_ZVAL(key); - - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - ALLOC_INIT_ZVAL(val); - - if (is_ref) - { - ret = msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC); - } - else - { - ret = msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC); - } - - if (ret <= 0) - { - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - if (!var_hash || - msgpack_var_access(var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object_key) " - "Invalid references value: %ld", - Z_LVAL_P(val) - 1); - } - ret = MSGPACK_UNPACK_CONTINUE; - } - else - { - if (*return_value != NULL) - { - zval_ptr_dtor(return_value); - } - - *return_value = *rval; - - Z_ADDREF_PP(return_value); - - if (is_ref) - { - Z_SET_ISREF_PP(return_value); - } - else - { - Z_UNSET_ISREF_PP(return_value); - } - } - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; -} - -inline static int msgpack_unserialize_object( - zval **return_value, msgpack_unserialize_data *mpsd, - ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) -{ - int ret = MSGPACK_UNPACK_SUCCESS; - zend_class_entry *ce, **pce; bool incomplete_class = false; zval *user_func, *retval_ptr, **args[1], *arg_func_name; - HashTable *ht; + TSRMLS_FETCH(); - zval *key, *val; + do + { + /* Try to find class directly */ + if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + break; + } - int object = 1; - int custom_object = 0; + /* Check for unserialize callback */ + if ((PG(unserialize_callback_func) == NULL) || + (PG(unserialize_callback_func)[0] == '\0')) + { + incomplete_class = 1; + ce = PHP_IC_ENTRY; + break; + } - /* Get class */ - ALLOC_INIT_ZVAL(key); + /* Call unserialize callback */ + ALLOC_INIT_ZVAL(user_func); + ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); + args[0] = &arg_func_name; + ALLOC_INIT_ZVAL(arg_func_name); + ZVAL_STRING(arg_func_name, class_name, 1); + if (call_user_function_ex( + CG(function_table), NULL, user_func, &retval_ptr, + 1, args, 0, NULL TSRMLS_CC) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_class) " + "defined (%s) but not found", class_name); + } - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) + incomplete_class = 1; + ce = PHP_IC_ENTRY; + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + break; + } + if (retval_ptr) + { + zval_ptr_dtor(&retval_ptr); + } + + /* The callback function may have defined the class */ + if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + } + else + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_class) " + "Function %s() hasn't defined the class " + "it was called for", class_name); + } + + incomplete_class = true; + ce = PHP_IC_ENTRY; + } + + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + } + while(0); + + if (EG(exception)) { if (MSGPACK_G(error_display)) { zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign key"); + "[msgpack] (msgpack_unserialize_class) " + "Exception error"); } - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; + return NULL; } - ct--; + object_init_ex(*container, ce); - if (Z_TYPE_P(key) == IS_NULL) + /* store incomplete class name */ + if (incomplete_class) { - ALLOC_INIT_ZVAL(val); + php_store_class_name(*container, class_name, name_len); + } - if (msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC) <= 0) + return ce; +} + +void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx) +{ + var_hashx->first = 0; + var_hashx->first_dtor = 0; +} + +void msgpack_unserialize_var_destroy(php_unserialize_data_t *var_hashx) +{ + void *next; + long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) + { + for (i = 0; i < var_hash->used_slots; i++) { - if (MSGPACK_G(error_display)) + if (var_hash->alloc_slots[i] && var_hash->data[i]) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign value"); - } - - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - if (Z_TYPE_P(val) == IS_LONG) - { - switch (Z_LVAL_P(val)) - { - case MSGPACK_SERIALIZE_TYPE_REFERENCE: - ret = msgpack_unserialize_object_type( - return_value, mpsd, var_hash, 1 TSRMLS_CC); - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; - case MSGPACK_SERIALIZE_TYPE_OBJECT: - ret = msgpack_unserialize_object_type( - return_value, mpsd, var_hash, 0 TSRMLS_CC); - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; - case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: - custom_object = 1; - - zval_ptr_dtor(&val); - - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval( - &val, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; + zval_ptr_dtor(&var_hash->data[i]); } } + + next = var_hash->next; + efree(var_hash); + var_hash = next; + } + + /* + var_hash = var_hashx->first_dtor; + + while (var_hash) + { + for (i = 0; i < var_hash->used_slots; i++) + { + zval_ptr_dtor(&var_hash->data[i]); + } + next = var_hash->next; + efree(var_hash); + var_hash = next; + } + */ +} + +void msgpack_unserialize_init(msgpack_unserialize_data *unpack) +{ + unpack->deps = 0; + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; +} + +int msgpack_unserialize_uint8( + msgpack_unserialize_data *unpack, uint8_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint16( + msgpack_unserialize_data *unpack, uint16_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint32( + msgpack_unserialize_data *unpack, uint32_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint64( + msgpack_unserialize_data *unpack, uint64_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int8( + msgpack_unserialize_data *unpack, int8_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int16( + msgpack_unserialize_data *unpack, int16_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int32( + msgpack_unserialize_data *unpack, int32_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int64( + msgpack_unserialize_data *unpack, int64_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_float( + msgpack_unserialize_data *unpack, float data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_DOUBLE(*obj, data); + + return 0; +} + +int msgpack_unserialize_double( + msgpack_unserialize_data *unpack, double data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_DOUBLE(*obj, data); + + return 0; +} + +int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_NULL(*obj); + + return 0; +} + +int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_BOOL(*obj, 1); + + return 0; +} + +int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_BOOL(*obj, 0); + + return 0; +} + +int msgpack_unserialize_raw( + msgpack_unserialize_data *unpack, const char* base, + const char* data, unsigned int len, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + if (len == 0) + { + ZVAL_STRINGL(*obj, "", 0, 1); } else { - object = 0; - - msgpack_var_push(var_hash, return_value); - - if (Z_TYPE_PP(return_value) != IS_ARRAY) - { - array_init(*return_value); - } - - ht = HASH_OF(*return_value); - - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign value"); - } - - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* update */ - switch (Z_TYPE_P(key)) - { - case IS_LONG: - zend_hash_index_update( - ht, Z_LVAL_P(key), &val, sizeof(zval *), NULL); - break; - case IS_STRING: - zend_symtable_update( - ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, - &val, sizeof(zval *), NULL); - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return MSGPACK_UNPACK_PARSE_ERROR; - } + ZVAL_STRINGL(*obj, data, len, 1); } - zval_ptr_dtor(&key); + return 0; +} - if (object) +int msgpack_unserialize_array( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); + + array_init(*obj); + + unpack->stack[unpack->deps++] = count; + + return 0; +} + +int msgpack_unserialize_array_item( + msgpack_unserialize_data *unpack, zval **container, zval *obj) +{ + MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 1, obj); + + add_next_index_zval(*container, obj); + + MSGPACK_UNSERIALIZE_FINISH_ITEM(unpack); + + return 0; +} + +int msgpack_unserialize_map( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); + + unpack->stack[unpack->deps++] = count; + + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + return 0; +} + +int msgpack_unserialize_map_item( + msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val) +{ + TSRMLS_FETCH(); + + if (MSGPACK_G(php_only)) { - convert_to_string(val); + if (Z_TYPE_P(key) == IS_NULL) + { + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - do { - /* Try to find class directly */ - if (zend_lookup_class( - Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) + if (Z_TYPE_P(val) == IS_LONG) { - ce = *pce; - break; - } - - /* Check for unserialize callback */ - if ((PG(unserialize_callback_func) == NULL) || - (PG(unserialize_callback_func)[0] == '\0')) - { - incomplete_class = 1; - ce = PHP_IC_ENTRY; - break; - } - - /* Call unserialize callback */ - ALLOC_INIT_ZVAL(user_func); - ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); - args[0] = &arg_func_name; - ALLOC_INIT_ZVAL(arg_func_name); - ZVAL_STRING(arg_func_name, Z_STRVAL_P(val), 1); - if (call_user_function_ex( - CG(function_table), NULL, user_func, &retval_ptr, - 1, args, 0, NULL TSRMLS_CC) != SUCCESS) - { - if (MSGPACK_G(error_display)) + switch (Z_LVAL_P(val)) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "defined (%s) but not found", Z_STRVAL_P(val)); + case MSGPACK_SERIALIZE_TYPE_REFERENCE: + Z_SET_ISREF_PP(container); + break; + case MSGPACK_SERIALIZE_TYPE_RECURSIVE: + unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE; + break; + case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: + unpack->type = MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT; + break; + default: + break; } + } + else if (Z_TYPE_P(val) == IS_STRING) + { + zend_class_entry *ce = msgpack_unserialize_class( + container, Z_STRVAL_P(val), Z_STRLEN_P(val)); - incomplete_class = 1; - ce = PHP_IC_ENTRY; - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); - break; - } - if (retval_ptr) - { - zval_ptr_dtor(&retval_ptr); - } - - /* The callback function may have defined the class */ - if (zend_lookup_class( - Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) - { - ce = *pce; - } - else - { - if (MSGPACK_G(error_display)) + if (ce == NULL) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Function %s() hasn't defined the class" - "it was called for", Z_STRVAL_P(val)); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; } - - incomplete_class = true; - ce = PHP_IC_ENTRY; } - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); - } while(0); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - if (EG(exception)) + return 0; + } + else if (unpack->type == MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT) { - if (MSGPACK_G(error_display)) + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + zend_class_entry *ce = msgpack_unserialize_class( + container, Z_STRVAL_P(key), Z_STRLEN_P(key)); + + if (ce == NULL) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Exception error"); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; } - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - msgpack_var_push(var_hash, return_value); - - object_init_ex(*return_value, ce); - - /* store incomplete class name */ - if (incomplete_class) - { - php_store_class_name( - *return_value, Z_STRVAL_P(val), Z_STRLEN_P(val)); - } - - zval_ptr_dtor(&val); - - /* implementing Serializable */ - if (custom_object) - { - zval *rval; - + /* implementing Serializable */ if (ce->unserialize == NULL) { if (MSGPACK_G(error_display)) { zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " + "[msgpack] (msgpack_unserialize_map_item) " "Class %s has no unserializer", ce->name); } - return MSGPACK_UNPACK_PARSE_ERROR; - } + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - /* value */ - ALLOC_INIT_ZVAL(rval); - - if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&rval); - - return MSGPACK_UNPACK_PARSE_ERROR; + return 0; } ce->unserialize( - return_value, ce, - (const unsigned char *)Z_STRVAL_P(rval), Z_STRLEN_P(rval) + 1, - (zend_unserialize_data *)var_hash TSRMLS_CC); + container, ce, + (const unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val) + 1, + NULL TSRMLS_CC); - zval_ptr_dtor(&key); - zval_ptr_dtor(&rval); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - return ret; + return 0; } + else if (unpack->type == MSGPACK_SERIALIZE_TYPE_RECURSIVE) + { + zval **rval; - ht = HASH_OF(*return_value); + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + if (msgpack_var_access( + unpack->var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "Invalid references value: %ld", + Z_LVAL_P(val) - 1); + } + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; + } + + if (container != NULL) + { + zval_ptr_dtor(container); + } + + *container = *rval; + + Z_ADDREF_PP(container); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; + } } - /* object property */ - while (ct-- > 0) + MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 2, val); + + if (Z_TYPE_PP(container) != IS_ARRAY && Z_TYPE_PP(container) != IS_OBJECT) { - zval *rval; - - /* key */ - ALLOC_INIT_ZVAL(key); - - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* value */ - ALLOC_INIT_ZVAL(rval); - - if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&rval); - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - - } - - /* update */ - switch (Z_TYPE_P(key)) - { - case IS_LONG: - zend_hash_index_update( - ht, Z_LVAL_P(key), &rval, sizeof(zval *), NULL); - break; - case IS_STRING: - zend_symtable_update( - ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, - &rval, sizeof(zval *), NULL); - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&rval); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - zval_ptr_dtor(&key); + array_init(*container); } - /* wakeup */ - if (object && Z_OBJCE_PP(return_value) != PHP_IC_ENTRY && - zend_hash_exists(&Z_OBJCE_PP(return_value)->function_table, - "__wakeup", sizeof("__wakeup"))) + switch (Z_TYPE_P(key)) { - zval f, *h = NULL; + case IS_LONG: + if (zend_hash_index_update( + HASH_OF(*container), Z_LVAL_P(key), &val, + sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + } + break; + case IS_STRING: + if (zend_symtable_update( + HASH_OF(*container), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, + &val, sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + } + break; + default: + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + break; + } - INIT_PZVAL(&f); - ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0); - call_user_function_ex( - CG(function_table), return_value, &f, &h, 0, 0, 1, NULL TSRMLS_CC); - if (h) - { - zval_ptr_dtor(&h); - } + zval_ptr_dtor(&key); - if (EG(exception)) + long deps = unpack->deps - 1; + unpack->stack[deps]--; + if (unpack->stack[deps] == 0) + { + unpack->deps--; + + /* wakeup */ + if (MSGPACK_G(php_only) && + Z_TYPE_PP(container) == IS_OBJECT && + Z_OBJCE_PP(container) != PHP_IC_ENTRY && + zend_hash_exists( + &Z_OBJCE_PP(container)->function_table, + "__wakeup", sizeof("__wakeup"))) { - ret = MSGPACK_UNPACK_PARSE_ERROR; + zval f, *h = NULL; + + INIT_PZVAL(&f); + ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0); + call_user_function_ex( + CG(function_table), container, &f, &h, 0, 0, 1, NULL TSRMLS_CC); + if (h) + { + zval_ptr_dtor(&h); + } } } - return ret; + return 0; } - -int msgpack_unserialize_zval( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash TSRMLS_DC) -{ - const unsigned char* data = mpsd->data; - const unsigned char* const pe = mpsd->data + mpsd->length; - const void* n = NULL; - - unsigned int trail = 0; - unsigned int cs = CS_HEADER; - - int ret; - unsigned int ct; - -#define next_cs(p) ((unsigned int)*p & 0x1f) - -#define finish_zval_long(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_LONG(*return_value, val_); \ - goto _finish - -#define finish_zval_null() \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_NULL(*return_value); \ - goto _finish - -#define finish_zval_bool(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_BOOL(*return_value, val_); \ - goto _finish - -#define finish_zval_double(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_DOUBLE(*return_value, val_); \ - goto _finish - -#define finish_zval_string(val_, len_) \ - msgpack_var_push(var_hash, return_value); \ - if (len_ == 0) { ZVAL_STRINGL(*return_value, "", 0, 1); } \ - else { ZVAL_STRINGL(*return_value, val_, len_, 1); } \ - goto _finish - -#define finish_zval_array(count_) \ - ct = count_; \ - cs = CS_HEADER; \ - ++(mpsd->data); \ - mpsd->length = (pe - mpsd->data); \ - if (msgpack_unserialize_array(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ - goto _finish_end - -#define finish_zval_object(count_) \ - ct = count_; \ - cs = CS_HEADER; \ - ++(mpsd->data); \ - mpsd->length = (pe - mpsd->data); \ - if (msgpack_unserialize_object(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ - goto _finish_end - -#define again_fixed_trail(_cs, trail_len) \ - trail = trail_len; \ - cs = _cs; \ - goto _fixed_trail_again - -#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ - trail = trail_len; \ - if(trail == 0) { goto ifzero; } \ - cs = _cs; \ - goto _fixed_trail_again - - if (mpsd->length <= 0) - { - goto _failed; - } - - if (mpsd->data == pe) - { - goto _out; - } - do - { - switch (cs) - { - case CS_HEADER: - switch (*(mpsd->data)) - { - case 0x00 ... 0x7f: /* Positive Fixnum */ - finish_zval_long(*(uint8_t*)mpsd->data); - case 0xe0 ... 0xff: /* Negative Fixnum */ - finish_zval_long(*(int8_t*)mpsd->data); - case 0xc0 ... 0xdf: /* Variable */ - switch (*(mpsd->data)) - { - case 0xc0: /* nil */ - finish_zval_null(); - case 0xc2: /* false */ - finish_zval_bool(0); - case 0xc3: /* true */ - finish_zval_bool(1); - case 0xca: /* float */ - case 0xcb: /* double */ - case 0xcc: /* unsigned int 8 */ - case 0xcd: /* unsigned int 16 */ - case 0xce: /* unsigned int 32 */ - case 0xcf: /* unsigned int 64 */ - case 0xd0: /* signed int 8 */ - case 0xd1: /* signed int 16 */ - case 0xd2: /* signed int 32 */ - case 0xd3: /* signed int 64 */ - again_fixed_trail( - next_cs(mpsd->data), - 1 << (((unsigned int)*(mpsd->data)) & 0x03)); - case 0xda: /* raw 16 */ - case 0xdb: /* raw 32 */ - case 0xdc: /* array 16 */ - case 0xdd: /* array 32 */ - case 0xde: /* map 16 */ - case 0xdf: /* map 32 */ - again_fixed_trail( - next_cs(mpsd->data), - 2 << (((unsigned int)*(mpsd->data)) & 0x01)); - default: - goto _failed; - } - case 0xa0 ... 0xbf: /* FixRaw */ - again_fixed_trail_if_zero( - ACS_RAW_VALUE, (unsigned int)*(mpsd->data) & 0x1f, - _raw_zero); - case 0x90 ... 0x9f: /* FixArray */ - finish_zval_array(((unsigned int)*(mpsd->data)) & 0x0f); - case 0x80 ... 0x8f: /* FixMap */ - finish_zval_object(((unsigned int)*(mpsd->data)) & 0x0f); - default: - goto _failed; - } -_fixed_trail_again: - ++(mpsd->data); - default: - if ((size_t)(pe - (mpsd->data)) < trail) - { - goto _out; - } - n = (mpsd->data); - mpsd->data += trail - 1; - switch (cs) - { - case CS_FLOAT: - { - union { uint32_t i; float f; } mem; - mem.i = _msgpack_load32(uint32_t, n); - finish_zval_double(mem.f); - } - case CS_DOUBLE: - { - union { uint64_t i; double f; } mem; - mem.i = _msgpack_load64(uint64_t, n); - finish_zval_double(mem.f); - } - case CS_UINT_8: - finish_zval_long(*(uint8_t*)n); - case CS_UINT_16: - finish_zval_long(_msgpack_load16(uint16_t, n)); - case CS_UINT_32: - finish_zval_long(_msgpack_load32(uint32_t, n)); - case CS_UINT_64: - finish_zval_long(_msgpack_load64(uint64_t, n)); - case CS_INT_8: - finish_zval_long(*(int8_t*)n); - case CS_INT_16: - finish_zval_long(_msgpack_load16(int16_t, n)); - case CS_INT_32: - finish_zval_long(_msgpack_load32(int32_t, n)); - case CS_INT_64: - finish_zval_long(_msgpack_load64(int64_t, n)); - case CS_RAW_16: - again_fixed_trail_if_zero( - ACS_RAW_VALUE, _msgpack_load16(uint16_t, n), - _raw_zero); - case CS_RAW_32: - again_fixed_trail_if_zero( - ACS_RAW_VALUE, _msgpack_load32(uint32_t, n), - _raw_zero); - case ACS_RAW_VALUE: -_raw_zero: - finish_zval_string(n, trail); - case CS_ARRAY_16: - finish_zval_array(_msgpack_load16(uint16_t, n)); - case CS_ARRAY_32: - finish_zval_array(_msgpack_load32(uint32_t, n)); - /* FIXME security guard */ - case CS_MAP_16: - finish_zval_object(_msgpack_load16(uint16_t, n)); - case CS_MAP_32: - finish_zval_object(_msgpack_load32(uint32_t, n)); - /* FIXME security guard */ - default: - goto _failed; - } - } - cs = CS_HEADER; - ++(mpsd->data); - } - while (mpsd->data != pe); - goto _out; - -_finish: - ++(mpsd->data); -_finish_end: - ret = MSGPACK_UNPACK_EXTRA_BYTES; - goto _end; - -_failed: - ret = MSGPACK_UNPACK_PARSE_ERROR; - goto _end; - -_out: - ret = MSGPACK_UNPACK_CONTINUE; - goto _end; - -_end: - mpsd->offset = mpsd->data - data; - mpsd->length = pe - mpsd->data; - - if (ret == MSGPACK_UNPACK_EXTRA_BYTES && mpsd->length == 0) - { - ret = MSGPACK_UNPACK_SUCCESS; - } - - return ret; -} - -#undef finish_zval_long -#undef finish_zval_null -#undef finish_zval_bool -#undef finish_zval_double -#undef finish_zval_string -#undef finish_zval_array -#undef finish_zval_object -#undef again_fixed_trail -#undef again_fixed_trail_if_zero - -#undef next_cs diff --git a/php/msgpack_unpack.h b/php/msgpack_unpack.h index 6c85d73f..da963ebf 100644 --- a/php/msgpack_unpack.h +++ b/php/msgpack_unpack.h @@ -1,9 +1,13 @@ -#ifndef MSGPACL_UNPACK_H -#define MSGPACL_UNPACK_H +#ifndef MSGPACK_UNPACK_H +#define MSGPACK_UNPACK_H #include "ext/standard/php_var.h" +#define MSGPACK_EMBED_STACK_SIZE 1024 + +#include "msgpack/unpack_define.h" + typedef enum { MSGPACK_UNPACK_SUCCESS = 2, @@ -12,15 +16,114 @@ typedef enum MSGPACK_UNPACK_PARSE_ERROR = -1, } msgpack_unpack_return; -typedef struct -{ - unsigned char *data; - size_t length; - size_t offset; +typedef struct { + zval *retval; + long deps; + php_unserialize_data_t *var_hash; + long stack[MSGPACK_EMBED_STACK_SIZE]; + int type; } msgpack_unserialize_data; -int msgpack_unserialize_zval( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash TSRMLS_DC); +void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx); +void msgpack_unserialize_var_destroy(php_unserialize_data_t *var_hashx); + +void msgpack_unserialize_init(msgpack_unserialize_data *unpack); + +int msgpack_unserialize_uint8( + msgpack_unserialize_data *unpack, uint8_t data, zval **obj); +int msgpack_unserialize_uint16( + msgpack_unserialize_data *unpack, uint16_t data, zval **obj); +int msgpack_unserialize_uint32( + msgpack_unserialize_data *unpack, uint32_t data, zval **obj); +int msgpack_unserialize_uint64( + msgpack_unserialize_data *unpack, uint64_t data, zval **obj); +int msgpack_unserialize_int8( + msgpack_unserialize_data *unpack, int8_t data, zval **obj); +int msgpack_unserialize_int16( + msgpack_unserialize_data *unpack, int16_t data, zval **obj); +int msgpack_unserialize_int32( + msgpack_unserialize_data *unpack, int32_t data, zval **obj); +int msgpack_unserialize_int64( + msgpack_unserialize_data *unpack, int64_t data, zval **obj); +int msgpack_unserialize_float( + msgpack_unserialize_data *unpack, float data, zval **obj); +int msgpack_unserialize_double( + msgpack_unserialize_data *unpack, double data, zval **obj); +int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_raw( + msgpack_unserialize_data *unpack, const char* base, const char* data, + unsigned int len, zval **obj); +int msgpack_unserialize_array( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj); +int msgpack_unserialize_array_item( + msgpack_unserialize_data *unpack, zval **container, zval *obj); +int msgpack_unserialize_map( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj); +int msgpack_unserialize_map_item( + msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val); + +/* template functions */ +#define msgpack_unpack_struct(name) struct template ## name +#define msgpack_unpack_func(ret, name) ret template ## name +#define msgpack_unpack_callback(name) template_callback ## name + +#define msgpack_unpack_object zval* +#define unpack_user msgpack_unserialize_data +#define msgpack_unpack_user msgpack_unserialize_data + +struct template_context; +typedef struct template_context msgpack_unpack_t; + +static void template_init(msgpack_unpack_t* unpack); +static msgpack_unpack_object template_data(msgpack_unpack_t* unpack); +static int template_execute( + msgpack_unpack_t* unpack, const char* data, size_t len, size_t* off); + +static inline msgpack_unpack_object template_callback_root(unpack_user* user) +{ + msgpack_unserialize_init(user); + return NULL; +} + +#define template_callback_uint8(user, data, obj) \ + msgpack_unserialize_uint8(user, data, obj) +#define template_callback_uint16(user, data, obj) \ + msgpack_unserialize_uint16(user, data, obj) +#define template_callback_uint32(user, data, obj) \ + msgpack_unserialize_uint32(user, data, obj) +#define template_callback_uint64(user, data, obj) \ + msgpack_unserialize_uint64(user, data, obj) +#define template_callback_int8(user, data, obj) \ + msgpack_unserialize_int8(user, data, obj) +#define template_callback_int16(user, data, obj) \ + msgpack_unserialize_int16(user, data, obj) +#define template_callback_int32(user, data, obj) \ + msgpack_unserialize_int32(user, data, obj) +#define template_callback_int64(user, data, obj) \ + msgpack_unserialize_int64(user, data, obj) +#define template_callback_float(user, data, obj) \ + msgpack_unserialize_float(user, data, obj) +#define template_callback_double(user, data, obj) \ + msgpack_unserialize_double(user, data, obj) +#define template_callback_nil(user, obj) \ + msgpack_unserialize_nil(user, obj) +#define template_callback_true(user, obj) \ + msgpack_unserialize_true(user, obj) +#define template_callback_false(user, obj) \ + msgpack_unserialize_false(user, obj) +#define template_callback_raw(user, base, data, len, obj) \ + msgpack_unserialize_raw(user, base, data, len, obj) +#define template_callback_array(user, count, obj) \ + msgpack_unserialize_array(user, count, obj) +#define template_callback_array_item(user, container, obj) \ + msgpack_unserialize_array_item(user, container, obj) +#define template_callback_map(user, count, obj) \ + msgpack_unserialize_map(user, count, obj) +#define template_callback_map_item(user, container, key, val) \ + msgpack_unserialize_map_item(user, container, key, val) + +#include "msgpack/unpack_template.h" #endif diff --git a/php/package.xml b/php/package.xml index 48697704..6172a4c5 100644 --- a/php/package.xml +++ b/php/package.xml @@ -10,11 +10,11 @@ advect@gmail.com yes - 2010-07-17 - + 2010-09-28 + - 0.2.1 - 0.2.1 + 0.3.0 + 0.3.0 beta @@ -26,15 +26,21 @@ - - - - - - - - - + + + + + + + + + + + + + + + @@ -43,28 +49,32 @@ - + + - - - + + + - + - + + - - - - - + + + + + + + @@ -74,13 +84,30 @@ - - + + + + - - - + + + + + + + + + + + + + + + + + + diff --git a/php/php-msgpack.spec b/php/php-msgpack.spec index 5726c434..6a98288b 100644 --- a/php/php-msgpack.spec +++ b/php/php-msgpack.spec @@ -3,7 +3,7 @@ Summary: PHP extension for interfacing with MessagePack Name: php-msgpack -Version: 0.2.1 +Version: 0.3.0 Release: 1%{?dist} Source: php-msgpack-%{version}.tar.gz License: New BSD License @@ -11,7 +11,7 @@ Group: Development/Libraries Packager: advect Provides: php-pecl-msgpack BuildRoot: %{_tmppath}/%{name}-%{version}-root -BuildRequires: php-devel, msgpack-devel +BuildRequires: php-devel Requires: msgpack %if 0%{?php_zend_api} Requires: php(zend-abi) = %{php_zend_api} diff --git a/php/php_msgpack.h b/php/php_msgpack.h index 91b2d30f..61badea7 100644 --- a/php/php_msgpack.h +++ b/php/php_msgpack.h @@ -2,7 +2,7 @@ #ifndef PHP_MSGPACK_H #define PHP_MSGPACK_H -#define MSGPACK_VERSION "0.2.1" +#define MSGPACK_EXTENSION_VERSION "0.3.0" #include "ext/standard/php_smart_str.h" @@ -23,6 +23,7 @@ extern zend_module_entry msgpack_module_entry; ZEND_BEGIN_MODULE_GLOBALS(msgpack) zend_bool error_display; + zend_bool php_only; ZEND_END_MODULE_GLOBALS(msgpack) ZEND_DECLARE_MODULE_GLOBALS(msgpack) diff --git a/php/tests/009.phpt b/php/tests/009.phpt index 6baad5ee..9992988a 100644 --- a/php/tests/009.phpt +++ b/php/tests/009.phpt @@ -1,6 +1,10 @@ --TEST-- -Check for reference serialisation +Check for reference serialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { @@ -63,16 +67,16 @@ array(2) { } OK cyclic -81008100810082c001c002 +810082c0010082c0010082c0020002 array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } @@ -101,11 +105,11 @@ array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/009b.phpt b/php/tests/009b.phpt new file mode 100644 index 00000000..7765d62a --- /dev/null +++ b/php/tests/009b.phpt @@ -0,0 +1,101 @@ +--TEST-- +Check for reference serialization +--SKIPIF-- + + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(&$a, &$a) +820082c00100a3666f6f0182c0020002 +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +cyclic +810082c0010082c0010082c0020002 +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} diff --git a/php/tests/014.phpt b/php/tests/014.phpt index c663579d..b9c7c671 100644 --- a/php/tests/014.phpt +++ b/php/tests/014.phpt @@ -34,7 +34,7 @@ test('object', $a, false); ?> --EXPECTF-- object -820083c0a34f626aa16101a162020182c001c002 +820084c001c0a34f626aa16101a162020182c0020002 array(2) { [0]=> &object(Obj)#%d (2) { diff --git a/php/tests/015.phpt b/php/tests/015.phpt index 828800a2..634a8b1a 100644 --- a/php/tests/015.phpt +++ b/php/tests/015.phpt @@ -51,7 +51,7 @@ var_dump($_SESSION); ?> --EXPECT-- 2 -81a3666f6f02 +82c001a3666f6f02 array(1) { ["foo"]=> int(2) diff --git a/php/tests/015b.phpt b/php/tests/015b.phpt index 829584b7..7ced3126 100644 --- a/php/tests/015b.phpt +++ b/php/tests/015b.phpt @@ -51,7 +51,7 @@ var_dump($_SESSION); ?> --EXPECT-- 2 -81a3666f6f02 +82c001a3666f6f02 array(1) { ["foo"]=> int(2) diff --git a/php/tests/018.phpt b/php/tests/018.phpt index 84ccafa2..f5ff4b72 100644 --- a/php/tests/018.phpt +++ b/php/tests/018.phpt @@ -74,7 +74,7 @@ object(Obj)#%d (3) { } OK wrong -82c0a34f706ac0 +82c0a34f706a object(Opj)#%d (2) { ["a"]=> NULL diff --git a/php/tests/024.phpt b/php/tests/024.phpt index 30fab759..9b185f7c 100644 --- a/php/tests/024.phpt +++ b/php/tests/024.phpt @@ -1,6 +1,10 @@ --TEST-- Recursive objects --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- int(100) diff --git a/php/tests/024b.phpt b/php/tests/024b.phpt new file mode 100644 index 00000000..7c691bec --- /dev/null +++ b/php/tests/024b.phpt @@ -0,0 +1,165 @@ +--TEST-- +Recursive objects +--SKIPIF-- +a = $a; + $this->b = $b; + $this->c = $c; + } +} + +class Obj2 { + public $aa; + protected $bb; + private $cc; + private $obj; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + + $this->obj = new Obj($a, $b, $c); + } +} + +class Obj3 { + private $objs; + + function __construct($a, $b, $c) { + $this->objs = array(); + + for ($i = $a; $i < $c; $i += $b) { + $this->objs[] = new Obj($a, $i, $c); + } + } +} + +class Obj4 { + private $a; + private $obj; + + function __construct($a) { + $this->a = $a; + } + + public function set($obj) { + $this->obj = $obj; + } +} + +$o2 = new Obj2(1, 2, 3); +test('objectrec', $o2, false); + +$o3 = new Obj3(0, 1, 4); +test('objectrecarr', $o3, false); + +$o4 = new Obj4(100); +$o4->set($o4); +test('objectselfrec', $o4, true); +?> +--EXPECTF-- +objectrec +88c0a44f626a32a26161c0a5002a006262c0a8004f626a32006363c0a9004f626a32006f626a84c0a34f626aa16101a4002a006202a6004f626a006303a16101a16202a16303 +object(Obj2)#%d (7) { + ["aa"]=> + NULL + [%r"?bb"?:protected"?%r]=> + NULL + [%r"?cc"?:("Obj2":)?private"?%r]=> + NULL + [%r"?obj"?:("Obj2":)?private"?%r]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} +OK +objectrecarr +82c0a44f626a33aa004f626a33006f626a73840084c0a34f626aa16100a4002a006200a6004f626a0063040184c0a34f626aa16100a4002a006201a6004f626a0063040284c0a34f626aa16100a4002a006202a6004f626a0063040384c0a34f626aa16100a4002a006203a6004f626a006304 +object(Obj3)#%d (1) { + [%r"?objs"?:("Obj3":)?private"?%r]=> + array(4) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(0) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(1) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [2]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [3]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(3) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + } +} +OK +objectselfrec +83c0a44f626a34a7004f626a34006164a9004f626a34006f626a82c0020001 +object(Obj4)#%d (2) { + [%r"?a"?:("Obj4":)?private"?%r]=> + int(100) + [%r"?obj"?:("Obj4":)?private"?%r]=> + *RECURSION* +} +OK diff --git a/php/tests/026.phpt b/php/tests/026.phpt index 2d3bb734..c243ef51 100644 --- a/php/tests/026.phpt +++ b/php/tests/026.phpt @@ -2,6 +2,10 @@ Cyclic array test --INI-- --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- --EXPECT-- array -82a16182a162a163a164a165a16682a16182a162a163a164a165a16682c001c005 +82a16182a162a163a164a165a16683c001a16182a162a163a164a165a16682c0020005 array(2) { ["a"]=> array(2) { diff --git a/php/tests/026b.phpt b/php/tests/026b.phpt new file mode 100644 index 00000000..f7a3381f --- /dev/null +++ b/php/tests/026b.phpt @@ -0,0 +1,107 @@ +--TEST-- +Cyclic array test +--INI-- +--SKIPIF-- + array( + 'b' => 'c', + 'd' => 'e' + ), +); + +$a['f'] = &$a; + +test('array', $a, true); + +$a = array("foo" => &$b); +$b = array(1, 2, $a); +var_dump($a); +var_dump($k = msgpack_unserialize(msgpack_serialize($a))); + +$k["foo"][1] = "b"; +var_dump($k); +?> +--EXPECT-- +array +82a16182a162a163a164a165a16683c001a16182a162a163a164a165a16682c0020005 +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + &array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + *RECURSION* + } +} +OK +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + *RECURSION* + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + string(1) "b" + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } +} diff --git a/php/tests/027.phpt b/php/tests/027.phpt index ecb87841..c9c7cbd5 100644 --- a/php/tests/027.phpt +++ b/php/tests/027.phpt @@ -64,7 +64,7 @@ var_dump($_SESSION); --EXPECT-- bool(true) read -wrote: 82a3666f6f01a474657374a6666f6f626172 +wrote: 83c001a3666f6f01a474657374a6666f6f626172 array(2) { ["foo"]=> int(1) diff --git a/php/tests/028.phpt b/php/tests/028.phpt index 56805f9e..00db6751 100644 --- a/php/tests/028.phpt +++ b/php/tests/028.phpt @@ -1,6 +1,10 @@ --TEST-- Serialize object into session, full set --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- --EXPECTF-- read -write: 83a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c002c002a70042617200643282c002c002a5002a00643382c002c002a5002a00643282c002c003a2643382c002c003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002c00aa5002a00643282c002c00aa2643382c002c00aa70042617200643282c002c00ba5002a00643382c002c00b +write: 84c001a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c0020002a70042617200643282c0020002a5002a00643382c0020002a5002a00643282c0020003a2643382c0020003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002000aa5002a00643282c002000aa2643382c002000aa70042617200643282c002000ba5002a00643382c002000b array(3) { ["old"]=> object(Foo)#3 (3) { diff --git a/php/tests/028b.phpt b/php/tests/028b.phpt new file mode 100644 index 00000000..7331a576 --- /dev/null +++ b/php/tests/028b.phpt @@ -0,0 +1,167 @@ +--TEST-- +Serialize object into session, full set +--SKIPIF-- +d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +class Bar { + private static $s1 = array(); + protected static $s2 = array(); + public static $s3 = array(); + + public $d1; + private $d2; + protected $d3; + + public function __construct() { + } + + public function set($foo) { + $this->d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +$output = ''; + +function open($path, $name) { + return true; +} + +function close() { + return true; +} + +function read($id) { + global $output; + $output .= "read" . PHP_EOL; + $a = new Bar(); + $b = new Foo($a); + $a->set($b); + $session = array('old' => $b); + return msgpack_serialize($session); +} + +function write($id, $data) { + global $output; + $output .= "write: "; + $output .= bin2hex($data) . PHP_EOL; + return true; +} + +function destroy($id) { + return true; +} + +function gc($time) { + return true; +} + +ini_set('session.serialize_handler', 'msgpack'); + +session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc'); + +session_start(); + +$_SESSION['test'] = "foobar"; +$a = new Bar(); +$b = new Foo($a); +$a->set($b); +$_SESSION['new'] = $a; + +session_write_close(); + +echo $output; +var_dump($_SESSION); +?> +--EXPECTF-- +read +write: 84c001a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c0020002a70042617200643282c0020002a5002a00643382c0020002a5002a00643282c0020003a2643382c0020003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002000aa5002a00643282c002000aa2643382c002000aa70042617200643282c002000ba5002a00643382c002000b +array(3) { + ["old"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + ["test"]=> + string(6) "foobar" + ["new"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } +} diff --git a/php/tests/029.phpt b/php/tests/029.phpt index 3bd1e9dc..686abb92 100644 --- a/php/tests/029.phpt +++ b/php/tests/029.phpt @@ -9,12 +9,39 @@ phpinfo(INFO_MODULES); $str = ob_get_clean(); $array = explode("\n", $str); -$array = preg_grep('/^msgpack/', $array); -echo implode("\n", $array), PHP_EOL; +$section = false; +$blank = 0; +foreach ($array as $key => $val) +{ + if (strcmp($val, 'msgpack') == 0 || $section) + { + $section = true; + } + else + { + continue; + } + if (empty($val)) + { + $blank++; + if ($blank == 3) + { + $section = false; + } + } + + echo $val, PHP_EOL; +} --EXPECTF-- msgpack -msgpack support => enabled -msgpack version => %s -msgpack Session Support => enabled + +MessagePack Support => enabled +Session Support => enabled +extension Version => %s +header Version => %s + +Directive => Local Value => Master Value +msgpack.error_display => On => On +msgpack.php_only => On => On diff --git a/php/tests/030.phpt b/php/tests/030.phpt index ec8622dc..3b8d986e 100644 --- a/php/tests/030.phpt +++ b/php/tests/030.phpt @@ -56,9 +56,6 @@ foreach ($datas as $data) { } ?> --EXPECTF-- -output at 2: -array(0) { -} output at 3: array(1) { [0]=> diff --git a/php/tests/060.phpt b/php/tests/060.phpt index c0fda4c2..649d7886 100644 --- a/php/tests/060.phpt +++ b/php/tests/060.phpt @@ -1,6 +1,10 @@ --TEST-- Check for buffered streaming unserialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- 1, "two" => 2))', array("one" => 1, "two" => 2), false); @@ -234,11 +238,11 @@ array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/060b.phpt b/php/tests/060b.phpt new file mode 100644 index 00000000..0b947c8e --- /dev/null +++ b/php/tests/060b.phpt @@ -0,0 +1,313 @@ +--TEST-- +Check for buffered streaming unserialization +--SKIPIF-- +feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('bool: true', true); +test('bool: false', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('array', array(), false); +test('array(1, 2, 3)', array(1, 2, 3), false); +test('array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/061.phpt b/php/tests/061.phpt index ded494e0..7ecc0c9f 100644 --- a/php/tests/061.phpt +++ b/php/tests/061.phpt @@ -1,6 +1,10 @@ --TEST-- Check for unbuffered streaming unserialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/061b.phpt b/php/tests/061b.phpt new file mode 100644 index 00000000..efb3a9bf --- /dev/null +++ b/php/tests/061b.phpt @@ -0,0 +1,318 @@ +--TEST-- +Check for unbuffered streaming unserialization +--SKIPIF-- +execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/070.phpt b/php/tests/070.phpt index 4a00ddf5..893023b5 100644 --- a/php/tests/070.phpt +++ b/php/tests/070.phpt @@ -1,6 +1,10 @@ --TEST-- Check for alias functions --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/070b.phpt b/php/tests/070b.phpt new file mode 100644 index 00000000..109ddc1a --- /dev/null +++ b/php/tests/070b.phpt @@ -0,0 +1,297 @@ +--TEST-- +Check for alias functions +--SKIPIF-- + 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/071.phpt b/php/tests/071.phpt index cca351aa..431303b6 100644 --- a/php/tests/071.phpt +++ b/php/tests/071.phpt @@ -1,6 +1,10 @@ --TEST-- Check for class methods --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/071b.phpt b/php/tests/071b.phpt new file mode 100644 index 00000000..770d06ee --- /dev/null +++ b/php/tests/071b.phpt @@ -0,0 +1,299 @@ +--TEST-- +Check for class methods +--SKIPIF-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/072.phpt b/php/tests/072.phpt index d8cb1b99..ea79a56d 100644 --- a/php/tests/072.phpt +++ b/php/tests/072.phpt @@ -1,6 +1,10 @@ --TEST-- Check for class methods unpacker --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/072b.phpt b/php/tests/072b.phpt new file mode 100644 index 00000000..c7b0c3ce --- /dev/null +++ b/php/tests/072b.phpt @@ -0,0 +1,339 @@ +--TEST-- +Check for class methods unpacker +--SKIPIF-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/073.phpt b/php/tests/073.phpt new file mode 100644 index 00000000..d3a76379 --- /dev/null +++ b/php/tests/073.phpt @@ -0,0 +1,346 @@ +--TEST-- +Check for class unpacker +--SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/073b.phpt b/php/tests/073b.phpt new file mode 100644 index 00000000..131a5346 --- /dev/null +++ b/php/tests/073b.phpt @@ -0,0 +1,340 @@ +--TEST-- +Check for class unpacker +--SKIPIF-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/080.phpt b/php/tests/080.phpt new file mode 100644 index 00000000..aba1cb63 --- /dev/null +++ b/php/tests/080.phpt @@ -0,0 +1,301 @@ +--TEST-- +disabled php only (ini_set) +--SKIPIF-- +--FILE-- + 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/081.phpt b/php/tests/081.phpt new file mode 100644 index 00000000..d22daaa0 --- /dev/null +++ b/php/tests/081.phpt @@ -0,0 +1,303 @@ +--TEST-- +disabled php only for class methods (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/082.phpt b/php/tests/082.phpt new file mode 100644 index 00000000..45a9d938 --- /dev/null +++ b/php/tests/082.phpt @@ -0,0 +1,346 @@ +--TEST-- +disabled php only for class methods unpacker (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/083.phpt b/php/tests/083.phpt new file mode 100644 index 00000000..203d8299 --- /dev/null +++ b/php/tests/083.phpt @@ -0,0 +1,347 @@ +--TEST-- +disabled php only for class unpacker (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/084.phpt b/php/tests/084.phpt new file mode 100644 index 00000000..74d061b5 --- /dev/null +++ b/php/tests/084.phpt @@ -0,0 +1,301 @@ +--TEST-- +disabled php only for class methods (constract) +--SKIPIF-- +--FILE-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/085.phpt b/php/tests/085.phpt new file mode 100644 index 00000000..72aacc8b --- /dev/null +++ b/php/tests/085.phpt @@ -0,0 +1,344 @@ +--TEST-- +disabled php only for class methods unpacker (constract) +--SKIPIF-- +--FILE-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/086.phpt b/php/tests/086.phpt new file mode 100644 index 00000000..aeaa3328 --- /dev/null +++ b/php/tests/086.phpt @@ -0,0 +1,345 @@ +--TEST-- +disabled php only for class unpacker (constract) +--SKIPIF-- +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(false); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/087.phpt b/php/tests/087.phpt new file mode 100644 index 00000000..9bb4e49a --- /dev/null +++ b/php/tests/087.phpt @@ -0,0 +1,302 @@ +--TEST-- +disabled php only for class methods (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/088.phpt b/php/tests/088.phpt new file mode 100644 index 00000000..7cbabb91 --- /dev/null +++ b/php/tests/088.phpt @@ -0,0 +1,345 @@ +--TEST-- +disabled php only for class methods unpacker (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/089.phpt b/php/tests/089.phpt new file mode 100644 index 00000000..f3a05378 --- /dev/null +++ b/php/tests/089.phpt @@ -0,0 +1,347 @@ +--TEST-- +disabled php only for class unpacker (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + + $unpacker = new MessagePackUnpacker(); + $unpacker->setOption(MessagePack::OPT_PHPONLY, false); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK