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===