diff --git a/php/ChangeLog b/php/ChangeLog index 5481c1fc..3cee3b60 100644 --- a/php/ChangeLog +++ b/php/ChangeLog @@ -1,14 +1,21 @@ msgpack extension changelog +Version 0.3.0 +------------- + * Change msgpack_unpack.c (used template) + * Add php_only ini option (true / false) + * Change class MessagePack and MessagePackUnpacker __construct option. + * Add class MessagePack and MessagePackUnpacker setOption method. + Version 0.2.1 ------------- - * Fix stream deserializer + * Fix stream deserializer. Version 0.2.0 ------------- - * Add stream deserializer / class MessagePackUnpacker interface - * Add alias functions - * Add class MessagePack interface + * Add stream deserializer / class MessagePackUnpacker interface. + * Add alias functions. + * Add class MessagePack interface. Version 0.1.5 ------------- diff --git a/php/config.m4 b/php/config.m4 index d319684f..a78e1f32 100644 --- a/php/config.m4 +++ b/php/config.m4 @@ -21,52 +21,7 @@ PHP_ARG_WITH(msgpack, for msgpack support, Make sure that the comment is aligned: [ --with-msgpack Include msgpack support]) -dnl PHP_ARG_ENABLE(msgpack, whether to enable msgpack support, -dnl Make sure that the comment is aligned: -dnl [ --enable-msgpack Enable msgpack support]) - if test "$PHP_MSGPACK" != "no"; then - dnl Write more examples of tests here... - - dnl --with-msgpack -> check with-path - SEARCH_PATH="/usr/local /usr" # you might want to change this - SEARCH_FOR="/include/msgpack.h" # you most likely want to change this - if test -r $PHP_MSGPACK/$SEARCH_FOR; then # path given as parameter - MSGPACK_DIR=$PHP_MSGPACK - else # search default path list - AC_MSG_CHECKING([for msgpack files in default path]) - for i in $SEARCH_PATH ; do - if test -r $i/$SEARCH_FOR; then - MSGPACK_DIR=$i - AC_MSG_RESULT(found in $i) - fi - done - fi - - if test -z "$MSGPACK_DIR"; then - AC_MSG_RESULT([not found]) - AC_MSG_ERROR([Please reinstall the msgpack distribution]) - fi - - dnl --with-msgpack -> add include path - PHP_ADD_INCLUDE($MSGPACK_DIR/include) - - dnl --with-msgpack -> check for lib and symbol presence - LIBNAME=msgpack # you may want to change this - LIBSYMBOL=msgpack_pack_object # you most likely want to change this - - PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - [ - PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MSGPACK_DIR/lib, MSGPACK_SHARED_LIBADD) - AC_DEFINE(HAVE_MSGPACKLIB,1,[ ]) - ],[ - AC_MSG_ERROR([wrong msgpack lib version or lib not found]) - ],[ - -L$MSGPACK_DIR/lib -lm - ]) - - PHP_SUBST(MSGPACK_SHARED_LIBADD) - PHP_NEW_EXTENSION(msgpack, msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c, $ext_shared) PHP_INSTALL_HEADERS([ext/msgpack], [php_msgpack.h]) diff --git a/php/config.w32 b/php/config.w32 index f2153e6b..726b75f2 100644 --- a/php/config.w32 +++ b/php/config.w32 @@ -4,9 +4,6 @@ // If your extension references something external, use ARG_WITH // ARG_WITH("msgpack", "for msgpack support", "no"); -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("msgpack", "enable msgpack support", "no"); - if (PHP_MSGPACK != "no") { EXTENSION("msgpack", "msgpack.c msgpack_pack.c msgpack_unpack.c msgpack_class.c"); } diff --git a/php/msgpack.c b/php/msgpack.c index 62fb68d7..5d4f9264 100644 --- a/php/msgpack.c +++ b/php/msgpack.c @@ -15,6 +15,7 @@ #include "msgpack_pack.h" #include "msgpack_unpack.h" #include "msgpack_class.h" +#include "msgpack/version.h" static ZEND_FUNCTION(msgpack_serialize); static ZEND_FUNCTION(msgpack_unserialize); @@ -27,20 +28,46 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unserialize, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_END_ARG_INFO() +PHP_INI_BEGIN() +STD_PHP_INI_BOOLEAN( + "msgpack.error_display", "1", PHP_INI_ALL, OnUpdateBool, + error_display, zend_msgpack_globals, msgpack_globals) +STD_PHP_INI_BOOLEAN( + "msgpack.php_only", "1", PHP_INI_ALL, OnUpdateBool, + php_only, zend_msgpack_globals, msgpack_globals) +PHP_INI_END() + PS_SERIALIZER_FUNCS(msgpack); static const zend_function_entry msgpack_functions[] = { ZEND_FE(msgpack_serialize, arginfo_msgpack_serialize) ZEND_FE(msgpack_unserialize, arginfo_msgpack_unserialize) ZEND_FALIAS(msgpack_pack, msgpack_serialize, arginfo_msgpack_serialize) - ZEND_FALIAS(msgpack_unpack, msgpack_unserialize, - arginfo_msgpack_unserialize) + ZEND_FALIAS(msgpack_unpack, msgpack_unserialize, arginfo_msgpack_unserialize) {NULL, NULL, NULL} }; +static void msgpack_init_globals(zend_msgpack_globals *msgpack_globals) +{ + TSRMLS_FETCH(); + + if (PG(display_errors)) + { + msgpack_globals->error_display = 1; + } + else + { + msgpack_globals->error_display = 0; + } + + msgpack_globals->php_only = 1; +} + static ZEND_MINIT_FUNCTION(msgpack) { - MSGPACK_G(error_display) = 1; + ZEND_INIT_MODULE_GLOBALS(msgpack, msgpack_init_globals, NULL); + + REGISTER_INI_ENTRIES(); #if HAVE_PHP_SESSION php_session_register_serializer("msgpack", @@ -48,7 +75,14 @@ static ZEND_MINIT_FUNCTION(msgpack) PS_SERIALIZER_DECODE_NAME(msgpack)); #endif - msgpack_init_class(TSRMLS_CC); + msgpack_init_class(); + + return SUCCESS; +} + +static ZEND_MSHUTDOWN_FUNCTION(msgpack) +{ + UNREGISTER_INI_ENTRIES(); return SUCCESS; } @@ -56,12 +90,15 @@ static ZEND_MINIT_FUNCTION(msgpack) static ZEND_MINFO_FUNCTION(msgpack) { php_info_print_table_start(); - php_info_print_table_row(2, "msgpack support", "enabled"); - php_info_print_table_row(2, "msgpack version", MSGPACK_VERSION); + php_info_print_table_row(2, "MessagePack Support", "enabled"); #if HAVE_PHP_SESSION - php_info_print_table_row(2, "msgpack Session Support", "enabled" ); + php_info_print_table_row(2, "Session Support", "enabled" ); #endif + php_info_print_table_row(2, "extension Version", MSGPACK_EXTENSION_VERSION); + php_info_print_table_row(2, "header Version", MSGPACK_VERSION); php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); } zend_module_entry msgpack_module_entry = { @@ -71,7 +108,7 @@ zend_module_entry msgpack_module_entry = { "msgpack", msgpack_functions, ZEND_MINIT(msgpack), - NULL, + ZEND_MSHUTDOWN(msgpack), NULL, NULL, ZEND_MINFO(msgpack), @@ -109,7 +146,6 @@ PS_SERIALIZER_ENCODE_FUNC(msgpack) PS_SERIALIZER_DECODE_FUNC(msgpack) { - php_unserialize_data_t var_hash; int ret; HashTable *tmp_hash; HashPosition tmp_hash_pos; @@ -117,38 +153,29 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) ulong key_long; uint key_len; zval *tmp; - zval **data; - msgpack_unserialize_data mpsd; + zval **value; + size_t off = 0; + msgpack_unpack_t mp; + php_unserialize_data_t var_hash; - PHP_VAR_UNSERIALIZE_INIT(var_hash); + ALLOC_INIT_ZVAL(tmp); - MAKE_STD_ZVAL(tmp); + template_init(&mp); - mpsd.data = (unsigned char *)val;; - mpsd.length = vallen; - mpsd.offset = 0; + msgpack_unserialize_var_init(&var_hash); - ret = msgpack_unserialize_zval(&tmp, &mpsd, &var_hash TSRMLS_CC); + (&mp)->user.retval = (zval *)tmp; + (&mp)->user.var_hash = (php_unserialize_data_t *)&var_hash; - switch (ret) - { - case MSGPACK_UNPACK_EXTRA_BYTES: - case MSGPACK_UNPACK_SUCCESS: - break; - case MSGPACK_UNPACK_PARSE_ERROR: - case MSGPACK_UNPACK_CONTINUE: - default: - zval_ptr_dtor(&tmp); - return FAILURE; - } + ret = template_execute(&mp, (char *)val, (size_t)vallen, &off); - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + msgpack_unserialize_var_destroy(&var_hash); tmp_hash = HASH_OF(tmp); zend_hash_internal_pointer_reset_ex(tmp_hash, &tmp_hash_pos); while (zend_hash_get_current_data_ex( - tmp_hash, (void *)&data, &tmp_hash_pos) == SUCCESS) + tmp_hash, (void *)&value, &tmp_hash_pos) == SUCCESS) { ret = zend_hash_get_current_key_ex( tmp_hash, &key_str, &key_len, &key_long, 0, &tmp_hash_pos); @@ -158,7 +185,8 @@ PS_SERIALIZER_DECODE_FUNC(msgpack) /* ??? */ break; case HASH_KEY_IS_STRING: - php_set_session_var(key_str, key_len - 1, *data, NULL TSRMLS_CC); + php_set_session_var( + key_str, key_len - 1, *value, NULL TSRMLS_CC); php_add_session_var(key_str, key_len - 1 TSRMLS_CC); break; } @@ -185,46 +213,59 @@ PHP_MSGPACK_API void php_msgpack_unserialize( zval *return_value, char *str, size_t str_len TSRMLS_DC) { int ret; + size_t off = 0; + msgpack_unpack_t mp; php_unserialize_data_t var_hash; - msgpack_unserialize_data mpsd; if (str_len <= 0) { RETURN_NULL(); } - PHP_VAR_UNSERIALIZE_INIT(var_hash); + template_init(&mp); - mpsd.data = (unsigned char *)str; - mpsd.length = str_len; - mpsd.offset = 0; + msgpack_unserialize_var_init(&var_hash); - ret = msgpack_unserialize_zval(&return_value, &mpsd, &var_hash TSRMLS_CC); + (&mp)->user.retval = (zval *)return_value; + (&mp)->user.var_hash = (php_unserialize_data_t *)&var_hash; + + ret = template_execute(&mp, str, (size_t)str_len, &off); + + msgpack_unserialize_var_destroy(&var_hash); switch (ret) { case MSGPACK_UNPACK_PARSE_ERROR: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Parse error"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Parse error"); + } break; case MSGPACK_UNPACK_CONTINUE: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) " - "Insufficient data for unserializeng"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) " + "Insufficient data for unserializing"); + } break; case MSGPACK_UNPACK_EXTRA_BYTES: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Extra bytes"); - break; case MSGPACK_UNPACK_SUCCESS: + if (off < (size_t)str_len && MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Extra bytes"); + } break; default: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_unserialize) Unknown result"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_unserialize) Unknown result"); + } break; } - - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); } static ZEND_FUNCTION(msgpack_serialize) diff --git a/php/msgpack/pack_define.h b/php/msgpack/pack_define.h new file mode 100644 index 00000000..4845d52e --- /dev/null +++ b/php/msgpack/pack_define.h @@ -0,0 +1,26 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_PACK_DEFINE_H__ +#define MSGPACK_PACK_DEFINE_H__ + +#include "msgpack/sysdep.h" +#include +#include + +#endif /* msgpack/pack_define.h */ + diff --git a/php/msgpack/pack_template.h b/php/msgpack/pack_template.h new file mode 100644 index 00000000..b636967f --- /dev/null +++ b/php/msgpack/pack_template.h @@ -0,0 +1,766 @@ +/* + * MessagePack packing routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(__LITTLE_ENDIAN__) +#define TAKE8_8(d) ((uint8_t*)&d)[0] +#define TAKE8_16(d) ((uint8_t*)&d)[0] +#define TAKE8_32(d) ((uint8_t*)&d)[0] +#define TAKE8_64(d) ((uint8_t*)&d)[0] +#elif defined(__BIG_ENDIAN__) +#define TAKE8_8(d) ((uint8_t*)&d)[0] +#define TAKE8_16(d) ((uint8_t*)&d)[1] +#define TAKE8_32(d) ((uint8_t*)&d)[3] +#define TAKE8_64(d) ((uint8_t*)&d)[7] +#endif + +#ifndef msgpack_pack_inline_func +#error msgpack_pack_inline_func template is not defined +#endif + +#ifndef msgpack_pack_user +#error msgpack_pack_user type is not defined +#endif + +#ifndef msgpack_pack_append_buffer +#error msgpack_pack_append_buffer callback is not defined +#endif + + +/* + * Integer + */ + +#define msgpack_pack_real_uint8(x, d) \ +do { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_8(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ +} while(0) + +#define msgpack_pack_real_uint16(x, d) \ +do { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \ + } else if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ +} while(0) + +#define msgpack_pack_real_uint32(x, d) \ +do { \ + if(d < (1<<8)) { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else { \ + if(d < (1<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_uint64(x, d) \ +do { \ + if(d < (1ULL<<8)) { \ + if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \ + } else { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else { \ + if(d < (1ULL<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else if(d < (1ULL<<32)) { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else { \ + /* unsigned 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int8(x, d) \ +do { \ + if(d < -(1<<5)) { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_8(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); \ + } \ +} while(0) + +#define msgpack_pack_real_int16(x, d) \ +do { \ + if(d < -(1<<5)) { \ + if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_16(d), 1); \ + } else { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_16(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int32(x, d) \ +do { \ + if(d < -(1<<5)) { \ + if(d < -(1<<15)) { \ + /* signed 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_32(d), 1); \ + } else { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_32(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else if(d < (1<<16)) { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } \ +} while(0) + +#define msgpack_pack_real_int64(x, d) \ +do { \ + if(d < -(1LL<<5)) { \ + if(d < -(1LL<<15)) { \ + if(d < -(1LL<<31)) { \ + /* signed 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xd3; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } else { \ + /* signed 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } \ + } else { \ + if(d < -(1<<7)) { \ + /* signed 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } else { \ + /* signed 8 */ \ + unsigned char buf[2] = {0xd0, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } \ + } \ + } else if(d < (1<<7)) { \ + /* fixnum */ \ + msgpack_pack_append_buffer(x, &TAKE8_64(d), 1); \ + } else { \ + if(d < (1LL<<16)) { \ + if(d < (1<<8)) { \ + /* unsigned 8 */ \ + unsigned char buf[2] = {0xcc, TAKE8_64(d)}; \ + msgpack_pack_append_buffer(x, buf, 2); \ + } else { \ + /* unsigned 16 */ \ + unsigned char buf[3]; \ + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 3); \ + } \ + } else { \ + if(d < (1LL<<32)) { \ + /* unsigned 32 */ \ + unsigned char buf[5]; \ + buf[0] = 0xce; _msgpack_store32(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 5); \ + } else { \ + /* unsigned 64 */ \ + unsigned char buf[9]; \ + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); \ + msgpack_pack_append_buffer(x, buf, 9); \ + } \ + } \ + } \ +} while(0) + + +#ifdef msgpack_pack_inline_func_fixint + +msgpack_pack_inline_func_fixint(_uint8)(msgpack_pack_user x, uint8_t d) +{ + unsigned char buf[2] = {0xcc, TAKE8_8(d)}; + msgpack_pack_append_buffer(x, buf, 2); +} + +msgpack_pack_inline_func_fixint(_uint16)(msgpack_pack_user x, uint16_t d) +{ + unsigned char buf[3]; + buf[0] = 0xcd; _msgpack_store16(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 3); +} + +msgpack_pack_inline_func_fixint(_uint32)(msgpack_pack_user x, uint32_t d) +{ + unsigned char buf[5]; + buf[0] = 0xce; _msgpack_store32(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func_fixint(_uint64)(msgpack_pack_user x, uint64_t d) +{ + unsigned char buf[9]; + buf[0] = 0xcf; _msgpack_store64(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 9); +} + +msgpack_pack_inline_func_fixint(_int8)(msgpack_pack_user x, int8_t d) +{ + unsigned char buf[2] = {0xd0, TAKE8_8(d)}; + msgpack_pack_append_buffer(x, buf, 2); +} + +msgpack_pack_inline_func_fixint(_int16)(msgpack_pack_user x, int16_t d) +{ + unsigned char buf[3]; + buf[0] = 0xd1; _msgpack_store16(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 3); +} + +msgpack_pack_inline_func_fixint(_int32)(msgpack_pack_user x, int32_t d) +{ + unsigned char buf[5]; + buf[0] = 0xd2; _msgpack_store32(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func_fixint(_int64)(msgpack_pack_user x, int64_t d) +{ + unsigned char buf[9]; + buf[0] = 0xd3; _msgpack_store64(&buf[1], d); + msgpack_pack_append_buffer(x, buf, 9); +} + +#undef msgpack_pack_inline_func_fixint +#endif + + +msgpack_pack_inline_func(_uint8)(msgpack_pack_user x, uint8_t d) +{ + msgpack_pack_real_uint8(x, d); +} + +msgpack_pack_inline_func(_uint16)(msgpack_pack_user x, uint16_t d) +{ + msgpack_pack_real_uint16(x, d); +} + +msgpack_pack_inline_func(_uint32)(msgpack_pack_user x, uint32_t d) +{ + msgpack_pack_real_uint32(x, d); +} + +msgpack_pack_inline_func(_uint64)(msgpack_pack_user x, uint64_t d) +{ + msgpack_pack_real_uint64(x, d); +} + +msgpack_pack_inline_func(_int8)(msgpack_pack_user x, int8_t d) +{ + msgpack_pack_real_int8(x, d); +} + +msgpack_pack_inline_func(_int16)(msgpack_pack_user x, int16_t d) +{ + msgpack_pack_real_int16(x, d); +} + +msgpack_pack_inline_func(_int32)(msgpack_pack_user x, int32_t d) +{ + msgpack_pack_real_int32(x, d); +} + +msgpack_pack_inline_func(_int64)(msgpack_pack_user x, int64_t d) +{ + msgpack_pack_real_int64(x, d); +} + + +#ifdef msgpack_pack_inline_func_cint + +msgpack_pack_inline_func_cint(_short)(msgpack_pack_user x, short d) +{ +#if defined(SIZEOF_SHORT) +#if SIZEOF_SHORT == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_SHORT == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(SHRT_MAX) +#if SHRT_MAX == 0x7fff + msgpack_pack_real_int16(x, d); +#elif SHRT_MAX == 0x7fffffff + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(short) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(short) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_int)(msgpack_pack_user x, int d) +{ +#if defined(SIZEOF_INT) +#if SIZEOF_INT == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_INT == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(INT_MAX) +#if INT_MAX == 0x7fff + msgpack_pack_real_int16(x, d); +#elif INT_MAX == 0x7fffffff + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(int) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(int) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_long)(msgpack_pack_user x, long d) +{ +#if defined(SIZEOF_LONG) +#if SIZEOF_LONG == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_LONG == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(LONG_MAX) +#if LONG_MAX == 0x7fffL + msgpack_pack_real_int16(x, d); +#elif LONG_MAX == 0x7fffffffL + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(long) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(long) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_long_long)(msgpack_pack_user x, long long d) +{ +#if defined(SIZEOF_LONG_LONG) +#if SIZEOF_LONG_LONG == 2 + msgpack_pack_real_int16(x, d); +#elif SIZEOF_LONG_LONG == 4 + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#elif defined(LLONG_MAX) +#if LLONG_MAX == 0x7fffL + msgpack_pack_real_int16(x, d); +#elif LLONG_MAX == 0x7fffffffL + msgpack_pack_real_int32(x, d); +#else + msgpack_pack_real_int64(x, d); +#endif + +#else +if(sizeof(long long) == 2) { + msgpack_pack_real_int16(x, d); +} else if(sizeof(long long) == 4) { + msgpack_pack_real_int32(x, d); +} else { + msgpack_pack_real_int64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_short)(msgpack_pack_user x, unsigned short d) +{ +#if defined(SIZEOF_SHORT) +#if SIZEOF_SHORT == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_SHORT == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(USHRT_MAX) +#if USHRT_MAX == 0xffffU + msgpack_pack_real_uint16(x, d); +#elif USHRT_MAX == 0xffffffffU + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned short) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned short) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_int)(msgpack_pack_user x, unsigned int d) +{ +#if defined(SIZEOF_INT) +#if SIZEOF_INT == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_INT == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(UINT_MAX) +#if UINT_MAX == 0xffffU + msgpack_pack_real_uint16(x, d); +#elif UINT_MAX == 0xffffffffU + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned int) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned int) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_long)(msgpack_pack_user x, unsigned long d) +{ +#if defined(SIZEOF_LONG) +#if SIZEOF_LONG == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_LONG == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(ULONG_MAX) +#if ULONG_MAX == 0xffffUL + msgpack_pack_real_uint16(x, d); +#elif ULONG_MAX == 0xffffffffUL + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned long) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned long) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +msgpack_pack_inline_func_cint(_unsigned_long_long)(msgpack_pack_user x, unsigned long long d) +{ +#if defined(SIZEOF_LONG_LONG) +#if SIZEOF_LONG_LONG == 2 + msgpack_pack_real_uint16(x, d); +#elif SIZEOF_LONG_LONG == 4 + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#elif defined(ULLONG_MAX) +#if ULLONG_MAX == 0xffffUL + msgpack_pack_real_uint16(x, d); +#elif ULLONG_MAX == 0xffffffffUL + msgpack_pack_real_uint32(x, d); +#else + msgpack_pack_real_uint64(x, d); +#endif + +#else +if(sizeof(unsigned long long) == 2) { + msgpack_pack_real_uint16(x, d); +} else if(sizeof(unsigned long long) == 4) { + msgpack_pack_real_uint32(x, d); +} else { + msgpack_pack_real_uint64(x, d); +} +#endif +} + +#undef msgpack_pack_inline_func_cint +#endif + + + +/* + * Float + */ + +msgpack_pack_inline_func(_float)(msgpack_pack_user x, float d) +{ + union { float f; uint32_t i; } mem; + mem.f = d; + unsigned char buf[5]; + buf[0] = 0xca; _msgpack_store32(&buf[1], mem.i); + msgpack_pack_append_buffer(x, buf, 5); +} + +msgpack_pack_inline_func(_double)(msgpack_pack_user x, double d) +{ + union { double f; uint64_t i; } mem; + mem.f = d; + unsigned char buf[9]; + buf[0] = 0xcb; _msgpack_store64(&buf[1], mem.i); + msgpack_pack_append_buffer(x, buf, 9); +} + + +/* + * Nil + */ + +msgpack_pack_inline_func(_nil)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc0; + msgpack_pack_append_buffer(x, &d, 1); +} + + +/* + * Boolean + */ + +msgpack_pack_inline_func(_true)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc3; + msgpack_pack_append_buffer(x, &d, 1); +} + +msgpack_pack_inline_func(_false)(msgpack_pack_user x) +{ + static const unsigned char d = 0xc2; + msgpack_pack_append_buffer(x, &d, 1); +} + + +/* + * Array + */ + +msgpack_pack_inline_func(_array)(msgpack_pack_user x, unsigned int n) +{ + if(n < 16) { + unsigned char d = 0x90 | n; + msgpack_pack_append_buffer(x, &d, 1); + } else if(n < 65536) { + unsigned char buf[3]; + buf[0] = 0xdc; _msgpack_store16(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdd; _msgpack_store32(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 5); + } +} + + +/* + * Map + */ + +msgpack_pack_inline_func(_map)(msgpack_pack_user x, unsigned int n) +{ + if(n < 16) { + unsigned char d = 0x80 | n; + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); + } else if(n < 65536) { + unsigned char buf[3]; + buf[0] = 0xde; _msgpack_store16(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdf; _msgpack_store32(&buf[1], n); + msgpack_pack_append_buffer(x, buf, 5); + } +} + + +/* + * Raw + */ + +msgpack_pack_inline_func(_raw)(msgpack_pack_user x, size_t l) +{ + if(l < 32) { + unsigned char d = 0xa0 | l; + msgpack_pack_append_buffer(x, &TAKE8_8(d), 1); + } else if(l < 65536) { + unsigned char buf[3]; + buf[0] = 0xda; _msgpack_store16(&buf[1], l); + msgpack_pack_append_buffer(x, buf, 3); + } else { + unsigned char buf[5]; + buf[0] = 0xdb; _msgpack_store32(&buf[1], l); + msgpack_pack_append_buffer(x, buf, 5); + } +} + +msgpack_pack_inline_func(_raw_body)(msgpack_pack_user x, const void* b, size_t l) +{ + msgpack_pack_append_buffer(x, (const unsigned char*)b, l); +} + +#undef msgpack_pack_inline_func +#undef msgpack_pack_user +#undef msgpack_pack_append_buffer + +#undef TAKE8_8 +#undef TAKE8_16 +#undef TAKE8_32 +#undef TAKE8_64 + +#undef msgpack_pack_real_uint8 +#undef msgpack_pack_real_uint16 +#undef msgpack_pack_real_uint32 +#undef msgpack_pack_real_uint64 +#undef msgpack_pack_real_int8 +#undef msgpack_pack_real_int16 +#undef msgpack_pack_real_int32 +#undef msgpack_pack_real_int64 + diff --git a/php/msgpack/sysdep.h b/php/msgpack/sysdep.h new file mode 100644 index 00000000..2bc01c9f --- /dev/null +++ b/php/msgpack/sysdep.h @@ -0,0 +1,118 @@ +/* + * MessagePack system dependencies + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_SYSDEP_H__ +#define MSGPACK_SYSDEP_H__ + + +#ifdef _MSC_VER +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#include +#include +#endif + + +#ifdef _WIN32 +typedef long _msgpack_atomic_counter_t; +#define _msgpack_sync_decr_and_fetch(ptr) InterlockedDecrement(ptr) +#define _msgpack_sync_incr_and_fetch(ptr) InterlockedIncrement(ptr) +#else +typedef unsigned int _msgpack_atomic_counter_t; +#define _msgpack_sync_decr_and_fetch(ptr) __sync_sub_and_fetch(ptr, 1) +#define _msgpack_sync_incr_and_fetch(ptr) __sync_add_and_fetch(ptr, 1) +#endif + + +#ifdef _WIN32 +#include + +#ifdef __cplusplus +/* numeric_limits::min,max */ +#ifdef max +#undef max +#endif +#ifdef min +#undef min +#endif +#endif + +#else +#include /* __BYTE_ORDER */ +#endif + +#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define __LITTLE_ENDIAN__ +#elif __BYTE_ORDER == __BIG_ENDIAN +#define __BIG_ENDIAN__ +#endif +#endif + +#ifdef __LITTLE_ENDIAN__ + +#define _msgpack_be16(x) ntohs(x) +#define _msgpack_be32(x) ntohl(x) + +#if defined(_byteswap_uint64) +# define _msgpack_be64(x) (_byteswap_uint64(x)) +#elif defined(bswap_64) +# define _msgpack_be64(x) bswap_64(x) +#elif defined(__DARWIN_OSSwapInt64) +# define _msgpack_be64(x) __DARWIN_OSSwapInt64(x) +#else +#define _msgpack_be64(x) \ + ( ((((uint64_t)x) << 56) & 0xff00000000000000ULL ) | \ + ((((uint64_t)x) << 40) & 0x00ff000000000000ULL ) | \ + ((((uint64_t)x) << 24) & 0x0000ff0000000000ULL ) | \ + ((((uint64_t)x) << 8) & 0x000000ff00000000ULL ) | \ + ((((uint64_t)x) >> 8) & 0x00000000ff000000ULL ) | \ + ((((uint64_t)x) >> 24) & 0x0000000000ff0000ULL ) | \ + ((((uint64_t)x) >> 40) & 0x000000000000ff00ULL ) | \ + ((((uint64_t)x) >> 56) & 0x00000000000000ffULL ) ) +#endif + +#else +#define _msgpack_be16(x) (x) +#define _msgpack_be32(x) (x) +#define _msgpack_be64(x) (x) +#endif + + +#define _msgpack_store16(to, num) \ + do { uint16_t val = _msgpack_be16(num); memcpy(to, &val, 2); } while(0); +#define _msgpack_store32(to, num) \ + do { uint32_t val = _msgpack_be32(num); memcpy(to, &val, 4); } while(0); +#define _msgpack_store64(to, num) \ + do { uint64_t val = _msgpack_be64(num); memcpy(to, &val, 8); } while(0); + + +#define _msgpack_load16(cast, from) ((cast)_msgpack_be16(*(uint16_t*)from)) +#define _msgpack_load32(cast, from) ((cast)_msgpack_be32(*(uint32_t*)from)) +#define _msgpack_load64(cast, from) ((cast)_msgpack_be64(*(uint64_t*)from)) + + +#endif /* msgpack/sysdep.h */ + diff --git a/php/msgpack/unpack_define.h b/php/msgpack/unpack_define.h new file mode 100644 index 00000000..959d3519 --- /dev/null +++ b/php/msgpack/unpack_define.h @@ -0,0 +1,93 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_UNPACK_DEFINE_H__ +#define MSGPACK_UNPACK_DEFINE_H__ + +#include "msgpack/sysdep.h" +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifndef MSGPACK_EMBED_STACK_SIZE +#define MSGPACK_EMBED_STACK_SIZE 32 +#endif + + +typedef enum { + CS_HEADER = 0x00, // nil + + //CS_ = 0x01, + //CS_ = 0x02, // false + //CS_ = 0x03, // true + + //CS_ = 0x04, + //CS_ = 0x05, + //CS_ = 0x06, + //CS_ = 0x07, + + //CS_ = 0x08, + //CS_ = 0x09, + CS_FLOAT = 0x0a, + CS_DOUBLE = 0x0b, + CS_UINT_8 = 0x0c, + CS_UINT_16 = 0x0d, + CS_UINT_32 = 0x0e, + CS_UINT_64 = 0x0f, + CS_INT_8 = 0x10, + CS_INT_16 = 0x11, + CS_INT_32 = 0x12, + CS_INT_64 = 0x13, + + //CS_ = 0x14, + //CS_ = 0x15, + //CS_BIG_INT_16 = 0x16, + //CS_BIG_INT_32 = 0x17, + //CS_BIG_FLOAT_16 = 0x18, + //CS_BIG_FLOAT_32 = 0x19, + CS_RAW_16 = 0x1a, + CS_RAW_32 = 0x1b, + CS_ARRAY_16 = 0x1c, + CS_ARRAY_32 = 0x1d, + CS_MAP_16 = 0x1e, + CS_MAP_32 = 0x1f, + + //ACS_BIG_INT_VALUE, + //ACS_BIG_FLOAT_VALUE, + ACS_RAW_VALUE, +} msgpack_unpack_state; + + +typedef enum { + CT_ARRAY_ITEM, + CT_MAP_KEY, + CT_MAP_VALUE, +} msgpack_container_type; + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/unpack_define.h */ + diff --git a/php/msgpack/unpack_template.h b/php/msgpack/unpack_template.h new file mode 100644 index 00000000..0fbfbb78 --- /dev/null +++ b/php/msgpack/unpack_template.h @@ -0,0 +1,409 @@ +/* + * MessagePack unpacking routine template + * + * Copyright (C) 2008-2010 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef msgpack_unpack_func +#error msgpack_unpack_func template is not defined +#endif + +#ifndef msgpack_unpack_callback +#error msgpack_unpack_callback template is not defined +#endif + +#ifndef msgpack_unpack_struct +#error msgpack_unpack_struct template is not defined +#endif + +#ifndef msgpack_unpack_struct_decl +#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name) +#endif + +#ifndef msgpack_unpack_object +#error msgpack_unpack_object type is not defined +#endif + +#ifndef msgpack_unpack_user +#error msgpack_unpack_user type is not defined +#endif + +#ifndef USE_CASE_RANGE +#if !defined(_MSC_VER) +#define USE_CASE_RANGE +#endif +#endif + +msgpack_unpack_struct_decl(_stack) { + msgpack_unpack_object obj; + size_t count; + unsigned int ct; + msgpack_unpack_object map_key; +}; + +msgpack_unpack_struct_decl(_context) { + msgpack_unpack_user user; + unsigned int cs; + unsigned int trail; + unsigned int top; + /* + msgpack_unpack_struct(_stack)* stack; + unsigned int stack_size; + msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE]; + */ + msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE]; +}; + + +msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) +{ + ctx->cs = CS_HEADER; + ctx->trail = 0; + ctx->top = 0; + /* + ctx->stack = ctx->embed_stack; + ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; + */ + ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); +} + +/* +msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx) +{ + if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { + free(ctx->stack); + } +} +*/ + +msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) +{ + return (ctx)->stack[0].obj; +} + + +msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off) +{ + assert(len >= *off); + + const unsigned char* p = (unsigned char*)data + *off; + const unsigned char* const pe = (unsigned char*)data + len; + const void* n = NULL; + + unsigned int trail = ctx->trail; + unsigned int cs = ctx->cs; + unsigned int top = ctx->top; + msgpack_unpack_struct(_stack)* stack = ctx->stack; + /* + unsigned int stack_size = ctx->stack_size; + */ + msgpack_unpack_user* user = &ctx->user; + + msgpack_unpack_object obj; + msgpack_unpack_struct(_stack)* c = NULL; + + int ret; + +#define push_simple_value(func) \ + if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \ + goto _push +#define push_fixed_value(func, arg) \ + if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \ + goto _push +#define push_variable_value(func, base, pos, len) \ + if(msgpack_unpack_callback(func)(user, \ + (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ + goto _push + +#define again_fixed_trail(_cs, trail_len) \ + trail = trail_len; \ + cs = _cs; \ + goto _fixed_trail_again +#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ + trail = trail_len; \ + if(trail == 0) { goto ifzero; } \ + cs = _cs; \ + goto _fixed_trail_again + +#define start_container(func, count_, ct_) \ + if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \ + if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ + if((count_) == 0) { obj = stack[top].obj; goto _push; } \ + stack[top].ct = ct_; \ + stack[top].count = count_; \ + ++top; \ + /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ + /*printf("stack push %d\n", top);*/ \ + /* FIXME \ + if(top >= stack_size) { \ + if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \ + size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \ + size_t nsize = csize * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \ + if(tmp == NULL) { goto _failed; } \ + memcpy(tmp, ctx->stack, csize); \ + ctx->stack = stack = tmp; \ + ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ + } else { \ + size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \ + if(tmp == NULL) { goto _failed; } \ + ctx->stack = stack = tmp; \ + ctx->stack_size = stack_size = stack_size * 2; \ + } \ + } \ + */ \ + goto _header_again + +#define NEXT_CS(p) \ + ((unsigned int)*p & 0x1f) + +#ifdef USE_CASE_RANGE +#define SWITCH_RANGE_BEGIN switch(*p) { +#define SWITCH_RANGE(FROM, TO) case FROM ... TO: +#define SWITCH_RANGE_DEFAULT default: +#define SWITCH_RANGE_END } +#else +#define SWITCH_RANGE_BEGIN { if(0) { +#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) { +#define SWITCH_RANGE_DEFAULT } else { +#define SWITCH_RANGE_END } } +#endif + + if(p == pe) { goto _out; } + do { + switch(cs) { + case CS_HEADER: + SWITCH_RANGE_BEGIN + SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum + push_fixed_value(_uint8, *(uint8_t*)p); + SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum + push_fixed_value(_int8, *(int8_t*)p); + SWITCH_RANGE(0xc0, 0xdf) // Variable + switch(*p) { + case 0xc0: // nil + push_simple_value(_nil); + //case 0xc1: // string + // again_terminal_trail(NEXT_CS(p), p+1); + case 0xc2: // false + push_simple_value(_false); + case 0xc3: // true + push_simple_value(_true); + //case 0xc4: + //case 0xc5: + //case 0xc6: + //case 0xc7: + //case 0xc8: + //case 0xc9: + case 0xca: // float + case 0xcb: // double + case 0xcc: // unsigned int 8 + case 0xcd: // unsigned int 16 + case 0xce: // unsigned int 32 + case 0xcf: // unsigned int 64 + case 0xd0: // signed int 8 + case 0xd1: // signed int 16 + case 0xd2: // signed int 32 + case 0xd3: // signed int 64 + again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); + //case 0xd4: + //case 0xd5: + //case 0xd6: // big integer 16 + //case 0xd7: // big integer 32 + //case 0xd8: // big float 16 + //case 0xd9: // big float 32 + case 0xda: // raw 16 + case 0xdb: // raw 32 + case 0xdc: // array 16 + case 0xdd: // array 32 + case 0xde: // map 16 + case 0xdf: // map 32 + again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01)); + default: + goto _failed; + } + SWITCH_RANGE(0xa0, 0xbf) // FixRaw + again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero); + SWITCH_RANGE(0x90, 0x9f) // FixArray + start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM); + SWITCH_RANGE(0x80, 0x8f) // FixMap + start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY); + + SWITCH_RANGE_DEFAULT + goto _failed; + SWITCH_RANGE_END + // end CS_HEADER + + + _fixed_trail_again: + ++p; + + default: + if((size_t)(pe - p) < trail) { goto _out; } + n = p; p += trail - 1; + switch(cs) { + //case CS_ + //case CS_ + case CS_FLOAT: { + union { uint32_t i; float f; } mem; + mem.i = _msgpack_load32(uint32_t,n); + push_fixed_value(_float, mem.f); } + case CS_DOUBLE: { + union { uint64_t i; double f; } mem; + mem.i = _msgpack_load64(uint64_t,n); + push_fixed_value(_double, mem.f); } + case CS_UINT_8: + push_fixed_value(_uint8, *(uint8_t*)n); + case CS_UINT_16: + push_fixed_value(_uint16, _msgpack_load16(uint16_t,n)); + case CS_UINT_32: + push_fixed_value(_uint32, _msgpack_load32(uint32_t,n)); + case CS_UINT_64: + push_fixed_value(_uint64, _msgpack_load64(uint64_t,n)); + + case CS_INT_8: + push_fixed_value(_int8, *(int8_t*)n); + case CS_INT_16: + push_fixed_value(_int16, _msgpack_load16(int16_t,n)); + case CS_INT_32: + push_fixed_value(_int32, _msgpack_load32(int32_t,n)); + case CS_INT_64: + push_fixed_value(_int64, _msgpack_load64(int64_t,n)); + + //case CS_ + //case CS_ + //case CS_BIG_INT_16: + // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load16(uint16_t,n), _big_int_zero); + //case CS_BIG_INT_32: + // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load32(uint32_t,n), _big_int_zero); + //case ACS_BIG_INT_VALUE: + //_big_int_zero: + // // FIXME + // push_variable_value(_big_int, data, n, trail); + + //case CS_BIG_FLOAT_16: + // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load16(uint16_t,n), _big_float_zero); + //case CS_BIG_FLOAT_32: + // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load32(uint32_t,n), _big_float_zero); + //case ACS_BIG_FLOAT_VALUE: + //_big_float_zero: + // // FIXME + // push_variable_value(_big_float, data, n, trail); + + case CS_RAW_16: + again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero); + case CS_RAW_32: + again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero); + case ACS_RAW_VALUE: + _raw_zero: + push_variable_value(_raw, data, n, trail); + + case CS_ARRAY_16: + start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM); + case CS_ARRAY_32: + /* FIXME security guard */ + start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM); + + case CS_MAP_16: + start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY); + case CS_MAP_32: + /* FIXME security guard */ + start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY); + + default: + goto _failed; + } + } + +_push: + if(top == 0) { goto _finish; } + c = &stack[top-1]; + switch(c->ct) { + case CT_ARRAY_ITEM: + if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; } + if(--c->count == 0) { + obj = c->obj; + --top; + /*printf("stack pop %d\n", top);*/ + goto _push; + } + goto _header_again; + case CT_MAP_KEY: + c->map_key = obj; + c->ct = CT_MAP_VALUE; + goto _header_again; + case CT_MAP_VALUE: + if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; } + if(--c->count == 0) { + obj = c->obj; + --top; + /*printf("stack pop %d\n", top);*/ + goto _push; + } + c->ct = CT_MAP_KEY; + goto _header_again; + + default: + goto _failed; + } + +_header_again: + cs = CS_HEADER; + ++p; + } while(p != pe); + goto _out; + + +_finish: + stack[0].obj = obj; + ++p; + ret = 1; + /*printf("-- finish --\n"); */ + goto _end; + +_failed: + /*printf("** FAILED **\n"); */ + ret = -1; + goto _end; + +_out: + ret = 0; + goto _end; + +_end: + ctx->cs = cs; + ctx->trail = trail; + ctx->top = top; + *off = p - (const unsigned char*)data; + + return ret; +} + + +#undef msgpack_unpack_func +#undef msgpack_unpack_callback +#undef msgpack_unpack_struct +#undef msgpack_unpack_object +#undef msgpack_unpack_user + +#undef push_simple_value +#undef push_fixed_value +#undef push_variable_value +#undef again_fixed_trail +#undef again_fixed_trail_if_zero +#undef start_container + +#undef NEXT_CS + diff --git a/php/msgpack/version.h b/php/msgpack/version.h new file mode 100644 index 00000000..13671d1a --- /dev/null +++ b/php/msgpack/version.h @@ -0,0 +1,40 @@ +/* + * MessagePack for C version information + * + * Copyright (C) 2008-2009 FURUHASHI Sadayuki + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MSGPACK_VERSION_H__ +#define MSGPACK_VERSION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + +const char* msgpack_version(void); +int msgpack_version_major(void); +int msgpack_version_minor(void); + +#define MSGPACK_VERSION "0.5.4" +#define MSGPACK_VERSION_MAJOR 0 +#define MSGPACK_VERSION_MINOR 5 + + +#ifdef __cplusplus +} +#endif + +#endif /* msgpack/version.h */ + diff --git a/php/msgpack_class.c b/php/msgpack_class.c index b728cb56..5cfff8d8 100644 --- a/php/msgpack_class.c +++ b/php/msgpack_class.c @@ -6,33 +6,81 @@ #include "msgpack_unpack.h" #include "msgpack_class.h" +typedef struct { + zend_object object; + long php_only; +} php_msgpack_base_t; + typedef struct { zend_object object; smart_str buffer; zval *retval; long offset; + msgpack_unpack_t mp; + php_unserialize_data_t var_hash; + long php_only; } php_msgpack_unpacker_t; #if ZEND_MODULE_API_NO >= 20060613 -#define MAGPACK_METHOD_BASE(classname, name) zim_##classname##_##name +# define MSGPACK_METHOD_BASE(classname, name) zim_##classname##_##name #else -#define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name +# define MSGPACK_METHOD_BASE(classname, name) zif_##classname##_##name #endif +#if ZEND_MODULE_API_NO >= 20090115 +# define PUSH_PARAM(arg) zend_vm_stack_push(arg TSRMLS_CC) +# define POP_PARAM() (void)zend_vm_stack_pop(TSRMLS_C) +# define PUSH_EO_PARAM() +# define POP_EO_PARAM() +#else +# define PUSH_PARAM(arg) zend_ptr_stack_push(&EG(argument_stack), arg) +# define POP_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) +# define PUSH_EO_PARAM() zend_ptr_stack_push(&EG(argument_stack), NULL) +# define POP_EO_PARAM() (void)zend_ptr_stack_pop(&EG(argument_stack)) +#endif + +#define MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, num, param) \ + PUSH_PARAM(param); PUSH_PARAM((void*)num); \ + PUSH_EO_PARAM(); \ + MSGPACK_METHOD_BASE(classname, name)(num, retval, NULL, thisptr, 0 TSRMLS_CC); \ + POP_EO_PARAM(); \ + POP_PARAM(); \ + POP_PARAM(); + #define MSGPACK_METHOD(classname, name, retval, thisptr) \ - MAGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) + MSGPACK_METHOD_BASE(classname, name)(0, retval, NULL, thisptr, 0 TSRMLS_CC) + +#define MSGPACK_METHOD1(classname, name, retval, thisptr, param1) \ + MSGPACK_METHOD_HELPER(classname, name, retval, thisptr, 1, param1); + +#define MSGPACK_BASE_OBJECT \ + php_msgpack_base_t *base; \ + base = (php_msgpack_base_t *)zend_object_store_get_object(getThis() TSRMLS_CC); #define MSGPACK_UNPACKER_OBJECT \ php_msgpack_unpacker_t *unpacker; \ - unpacker =(php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); + unpacker = (php_msgpack_unpacker_t *)zend_object_store_get_object(getThis() TSRMLS_CC); + +#define MSGPACK_CLASS_OPT_PHPONLY -1001 /* MessagePack */ static zend_class_entry *msgpack_ce = NULL; +static ZEND_METHOD(msgpack, __construct); +static ZEND_METHOD(msgpack, setOption); static ZEND_METHOD(msgpack, pack); static ZEND_METHOD(msgpack, unpack); static ZEND_METHOD(msgpack, unpacker); +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base___construct, 0, 0, 0) + ZEND_ARG_INFO(0, opt) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_setOption, 0, 0, 2) + ZEND_ARG_INFO(0, option) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_pack, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() @@ -45,6 +93,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_base_unpacker, 0, 0, 0) ZEND_END_ARG_INFO() static const zend_function_entry msgpack_base_methods[] = { + ZEND_ME(msgpack, __construct, + arginfo_msgpack_base___construct, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack, setOption, arginfo_msgpack_base_setOption, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, pack, arginfo_msgpack_base_pack, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, unpack, arginfo_msgpack_base_unpack, ZEND_ACC_PUBLIC) ZEND_ME(msgpack, unpacker, arginfo_msgpack_base_unpacker, ZEND_ACC_PUBLIC) @@ -54,19 +105,26 @@ static const zend_function_entry msgpack_base_methods[] = { /* MessagePackUnpacker */ static zend_class_entry *msgpack_unpacker_ce = NULL; -static ZEND_METHOD(msgpack, __construct); -static ZEND_METHOD(msgpack, __destruct); -static ZEND_METHOD(msgpack, feed); -static ZEND_METHOD(msgpack, execute); -static ZEND_METHOD(msgpack, data); -static ZEND_METHOD(msgpack, reset); +static ZEND_METHOD(msgpack_unpacker, __construct); +static ZEND_METHOD(msgpack_unpacker, __destruct); +static ZEND_METHOD(msgpack_unpacker, setOption); +static ZEND_METHOD(msgpack_unpacker, feed); +static ZEND_METHOD(msgpack_unpacker, execute); +static ZEND_METHOD(msgpack_unpacker, data); +static ZEND_METHOD(msgpack_unpacker, reset); ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___construct, 0, 0, 0) + ZEND_ARG_INFO(0, opt) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker___destruct, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_setOption, 0, 0, 2) + ZEND_ARG_INFO(0, option) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_feed, 0, 0, 1) ZEND_ARG_INFO(0, str) ZEND_END_ARG_INFO() @@ -83,17 +141,52 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_msgpack_unpacker_reset, 0, 0, 0) ZEND_END_ARG_INFO() static const zend_function_entry msgpack_unpacker_methods[] = { - ZEND_ME(msgpack, __construct, + ZEND_ME(msgpack_unpacker, __construct, arginfo_msgpack_unpacker___construct, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, __destruct, + ZEND_ME(msgpack_unpacker, __destruct, arginfo_msgpack_unpacker___destruct, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, feed, arginfo_msgpack_unpacker_feed, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, execute, arginfo_msgpack_unpacker_execute, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, data, arginfo_msgpack_unpacker_data, ZEND_ACC_PUBLIC) - ZEND_ME(msgpack, reset, arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, setOption, + arginfo_msgpack_unpacker_setOption, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, feed, + arginfo_msgpack_unpacker_feed, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, execute, + arginfo_msgpack_unpacker_execute, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, data, + arginfo_msgpack_unpacker_data, ZEND_ACC_PUBLIC) + ZEND_ME(msgpack_unpacker, reset, + arginfo_msgpack_unpacker_reset, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; +static void php_msgpack_base_free(php_msgpack_base_t *base TSRMLS_DC) +{ + zend_object_std_dtor(&base->object TSRMLS_CC); + efree(base); +} + +static zend_object_value php_msgpack_base_new(zend_class_entry *ce TSRMLS_DC) +{ + zend_object_value retval; + zval *tmp; + php_msgpack_base_t *base; + + base = emalloc(sizeof(php_msgpack_base_t)); + + zend_object_std_init(&base->object, ce TSRMLS_CC); + + zend_hash_copy( + base->object.properties, &ce->default_properties, + (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *)); + + retval.handle = zend_objects_store_put( + base, (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)php_msgpack_base_free, + NULL TSRMLS_CC); + retval.handlers = zend_get_std_object_handlers(); + + return retval; +} + static void php_msgpack_unpacker_free( php_msgpack_unpacker_t *unpacker TSRMLS_DC) { @@ -126,10 +219,58 @@ static zend_object_value php_msgpack_unpacker_new( } /* MessagePack */ +static ZEND_METHOD(msgpack, __construct) +{ + bool php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) + { + return; + } + + base->php_only = php_only; +} + +static ZEND_METHOD(msgpack, setOption) +{ + long option; + zval *value; + MSGPACK_BASE_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) + { + return; + } + + switch (option) + { + case MSGPACK_CLASS_OPT_PHPONLY: + convert_to_boolean(value); + base->php_only = Z_BVAL_P(value); + break; + default: + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (MessagePack::setOption) " + "error setting msgpack option"); + } + RETURN_FALSE; + break; + } + + RETURN_TRUE; +} + static ZEND_METHOD(msgpack, pack) { zval *parameter; smart_str buf = {0}; + int php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE) @@ -137,8 +278,12 @@ static ZEND_METHOD(msgpack, pack) return; } + MSGPACK_G(php_only) = base->php_only; + php_msgpack_serialize(&buf, parameter TSRMLS_CC); + MSGPACK_G(php_only) = php_only; + ZVAL_STRINGL(return_value, buf.c, buf.len, 1); smart_str_free(&buf); @@ -148,6 +293,8 @@ static ZEND_METHOD(msgpack, unpack) { char *str; int str_len; + int php_only = MSGPACK_G(php_only); + MSGPACK_BASE_OBJECT; if (zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) @@ -160,31 +307,57 @@ static ZEND_METHOD(msgpack, unpack) RETURN_NULL(); } + MSGPACK_G(php_only) = base->php_only; + php_msgpack_unserialize(return_value, str, str_len TSRMLS_CC); + + MSGPACK_G(php_only) = php_only; } static ZEND_METHOD(msgpack, unpacker) { - zval temp; + zval temp, *opt; + MSGPACK_BASE_OBJECT; + + ALLOC_INIT_ZVAL(opt); + ZVAL_BOOL(opt, base->php_only); object_init_ex(return_value, msgpack_unpacker_ce); - MSGPACK_METHOD(msgpack, __construct, &temp, return_value); + MSGPACK_METHOD1(msgpack_unpacker, __construct, &temp, return_value, opt); + + zval_ptr_dtor(&opt); } /* MessagePackUnpacker */ -static ZEND_METHOD(msgpack, __construct) +static ZEND_METHOD(msgpack_unpacker, __construct) { + bool php_only = MSGPACK_G(php_only); MSGPACK_UNPACKER_OBJECT; + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "|b", &php_only) == FAILURE) + { + return; + } + + unpacker->php_only = php_only; + unpacker->buffer.c = NULL; unpacker->buffer.len = 0; unpacker->buffer.a = 0; unpacker->retval = NULL; unpacker->offset = 0; + + template_init(&unpacker->mp); + + msgpack_unserialize_var_init(&unpacker->var_hash); + + (&unpacker->mp)->user.var_hash = + (php_unserialize_data_t *)&unpacker->var_hash; } -static ZEND_METHOD(msgpack, __destruct) +static ZEND_METHOD(msgpack_unpacker, __destruct) { MSGPACK_UNPACKER_OBJECT; @@ -194,9 +367,43 @@ static ZEND_METHOD(msgpack, __destruct) { zval_ptr_dtor(&unpacker->retval); } + + msgpack_unserialize_var_destroy(&unpacker->var_hash); } -static ZEND_METHOD(msgpack, feed) +static ZEND_METHOD(msgpack_unpacker, setOption) +{ + long option; + zval *value; + MSGPACK_UNPACKER_OBJECT; + + if (zend_parse_parameters( + ZEND_NUM_ARGS() TSRMLS_CC, "lz", &option, &value) == FAILURE) + { + return; + } + + switch (option) + { + case MSGPACK_CLASS_OPT_PHPONLY: + convert_to_boolean(value); + unpacker->php_only = Z_BVAL_P(value); + break; + default: + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (MessagePackUnpacker::setOption) " + "error setting msgpack option"); + } + RETURN_FALSE; + break; + } + + RETURN_TRUE; +} + +static ZEND_METHOD(msgpack_unpacker, feed) { char *str; int str_len; @@ -218,14 +425,15 @@ static ZEND_METHOD(msgpack, feed) RETURN_TRUE; } -static ZEND_METHOD(msgpack, execute) +static ZEND_METHOD(msgpack_unpacker, execute) { - char *str = NULL; + char *str = NULL, *data; long str_len = 0; zval *offset; int ret; - php_unserialize_data_t var_hash; - msgpack_unserialize_data mpsd; + size_t len, off; + int error_display = MSGPACK_G(error_display); + int php_only = MSGPACK_G(php_only); MSGPACK_UNPACKER_OBJECT; if (zend_parse_parameters( @@ -237,45 +445,38 @@ static ZEND_METHOD(msgpack, execute) if (str != NULL) { - mpsd.data = (unsigned char *)str; - mpsd.length = str_len; - mpsd.offset = Z_LVAL_P(offset); + data = (char *)str; + len = (size_t)str_len; + off = Z_LVAL_P(offset); } else { - mpsd.data = (unsigned char *)unpacker->buffer.c; - mpsd.length = unpacker->buffer.len; - mpsd.offset = unpacker->offset; + data = (char *)unpacker->buffer.c; + len = unpacker->buffer.len; + off = unpacker->offset; } - if (mpsd.length <= 0 || mpsd.length == mpsd.offset) - { - RETURN_FALSE; - } - - PHP_VAR_UNSERIALIZE_INIT(var_hash); - if (unpacker->retval == NULL) { ALLOC_INIT_ZVAL(unpacker->retval); } + (&unpacker->mp)->user.retval = (zval *)unpacker->retval; MSGPACK_G(error_display) = 0; + MSGPACK_G(php_only) = unpacker->php_only; - ret = msgpack_unserialize_zval( - &unpacker->retval, &mpsd, &var_hash TSRMLS_CC); + ret = template_execute(&unpacker->mp, data, len, &off); - MSGPACK_G(error_display) = 1; - - PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + MSGPACK_G(error_display) = error_display; + MSGPACK_G(php_only) = php_only; if (str != NULL) { - ZVAL_LONG(offset, mpsd.offset); + ZVAL_LONG(offset, off); } else { - unpacker->offset = mpsd.offset; + unpacker->offset = off; } switch (ret) @@ -288,14 +489,14 @@ static ZEND_METHOD(msgpack, execute) } } -static ZEND_METHOD(msgpack, data) +static ZEND_METHOD(msgpack_unpacker, data) { MSGPACK_UNPACKER_OBJECT; RETURN_ZVAL(unpacker->retval, 1, 1); } -static ZEND_METHOD(msgpack, reset) +static ZEND_METHOD(msgpack_unpacker, reset) { smart_str buffer = {0}; MSGPACK_UNPACKER_OBJECT; @@ -325,15 +526,33 @@ static ZEND_METHOD(msgpack, reset) zval_ptr_dtor(&unpacker->retval); unpacker->retval = NULL; } + + msgpack_unserialize_var_destroy(&unpacker->var_hash); + + + msgpack_unserialize_var_init(&unpacker->var_hash); + + (&unpacker->mp)->user.var_hash = + (php_unserialize_data_t *)&unpacker->var_hash; + + msgpack_unserialize_init(&((&unpacker->mp)->user)); } -void msgpack_init_class(TSRMLS_DC) +void msgpack_init_class() { zend_class_entry ce; + TSRMLS_FETCH(); + /* base */ INIT_CLASS_ENTRY(ce, "MessagePack", msgpack_base_methods); msgpack_ce = zend_register_internal_class(&ce TSRMLS_CC); + msgpack_ce->create_object = php_msgpack_base_new; + zend_declare_class_constant_long( + msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, + MSGPACK_CLASS_OPT_PHPONLY TSRMLS_CC); + + /* unpacker */ INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods); msgpack_unpacker_ce = zend_register_internal_class(&ce TSRMLS_CC); msgpack_unpacker_ce->create_object = php_msgpack_unpacker_new; diff --git a/php/msgpack_class.h b/php/msgpack_class.h index 00ac9e7b..fbebaf4d 100644 --- a/php/msgpack_class.h +++ b/php/msgpack_class.h @@ -1,7 +1,7 @@ -#ifndef MSGPACL_CLASS_H -#define MSGPACL_CLASS_H +#ifndef MSGPACK_CLASS_H +#define MSGPACK_CLASS_H -void msgpack_init_class(TSRMLS_DC); +void msgpack_init_class(); #endif diff --git a/php/msgpack_pack.c b/php/msgpack_pack.c index 91a3d396..d2d4ba3b 100644 --- a/php/msgpack_pack.c +++ b/php/msgpack_pack.c @@ -119,13 +119,14 @@ inline static void msgpack_serialize_class( if (Z_TYPE_PP(name) != IS_STRING) { - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_class) " - "__sleep should return an array only " - "containing the names of " - "instance-variables to serialize."); - - msgpack_pack_nil(buf); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "__sleep should return an array only " + "containing the names of " + "instance-variables to serialize."); + } continue; } @@ -195,11 +196,14 @@ inline static void msgpack_serialize_class( pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_class) " - "\"%s\" returned as member variable from " - "__sleep() but does not exist", - Z_STRVAL_PP(name)); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_class) " + "\"%s\" returned as member variable from " + "__sleep() but does not exist", + Z_STRVAL_PP(name)); + } msgpack_serialize_string( buf, Z_STRVAL_PP(name), Z_STRLEN_PP(name)); @@ -227,6 +231,7 @@ inline static void msgpack_serialize_array( { HashTable *ht; size_t n; + bool hash = true; if (object) { @@ -253,19 +258,46 @@ inline static void msgpack_serialize_array( if (object) { - msgpack_pack_map(buf, n + 1); + if (MSGPACK_G(php_only)) + { + if (Z_ISREF_P(val)) + { + msgpack_pack_map(buf, n + 2); + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + } + else + { + msgpack_pack_map(buf, n + 1); + } - msgpack_pack_nil(buf); + msgpack_pack_nil(buf); - msgpack_serialize_string(buf, class_name, name_len); + msgpack_serialize_string(buf, class_name, name_len); + } + else + { + msgpack_pack_array(buf, n); + hash = false; + } } else if (n == 0) { + hash = false; msgpack_pack_array(buf, n); } else { - msgpack_pack_map(buf, n); + if (Z_ISREF_P(val) && MSGPACK_G(php_only)) + { + msgpack_pack_map(buf, n + 1); + msgpack_pack_nil(buf); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + } + else + { + msgpack_pack_map(buf, n); + } } if (n > 0) @@ -292,20 +324,26 @@ inline static void msgpack_serialize_array( continue; } - switch (key_type) + if (hash) { - case HASH_KEY_IS_LONG: - msgpack_pack_long(buf, key_index); - break; - case HASH_KEY_IS_STRING: - msgpack_serialize_string(buf, key, key_len - 1); - break; - default: - msgpack_serialize_string(buf, "", sizeof("")); - - zend_error(E_WARNING, "[msgpack] (msgpack_serialize_array) " - "key is not string nor array"); - break; + switch (key_type) + { + case HASH_KEY_IS_LONG: + msgpack_pack_long(buf, key_index); + break; + case HASH_KEY_IS_STRING: + msgpack_serialize_string(buf, key, key_len - 1); + break; + default: + msgpack_serialize_string(buf, "", sizeof("")); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_serialize_array) " + "key is not string nor array"); + } + break; + } } if (zend_hash_get_current_data_ex( @@ -365,7 +403,6 @@ inline static void msgpack_serialize_object( msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT); msgpack_serialize_string(buf, ce->name, ce->name_length); - msgpack_pack_raw(buf, serialized_length); msgpack_pack_raw_body(buf, serialized_data, serialized_length); } @@ -401,11 +438,14 @@ inline static void msgpack_serialize_object( } else { - zend_error(E_NOTICE, - "[msgpack] (msgpack_serialize_object) " - "__sleep should return an array only " - "containing the names of instance-variables " - "to serialize"); + if (MSGPACK_G(error_display)) + { + zend_error(E_NOTICE, + "[msgpack] (msgpack_serialize_object) " + "__sleep should return an array only " + "containing the names of instance-variables " + "to serialize"); + } msgpack_pack_nil(buf); } zval_ptr_dtor(&retval_ptr); @@ -429,18 +469,19 @@ void msgpack_serialize_zval( { ulong *var_already; - if (var_hash && + if (MSGPACK_G(php_only) && + var_hash && msgpack_var_add( var_hash, val, (void *)&var_already TSRMLS_CC) == FAILURE) { - if (Z_ISREF_P(val)) + if (Z_ISREF_P(val) && Z_TYPE_P(val) == IS_ARRAY) { msgpack_pack_map(buf, 2); msgpack_pack_nil(buf); - msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_REFERENCE); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_RECURSIVE); - msgpack_pack_nil(buf); + msgpack_pack_long(buf, 0); msgpack_pack_long(buf, *var_already); return; @@ -450,9 +491,9 @@ void msgpack_serialize_zval( msgpack_pack_map(buf, 2); msgpack_pack_nil(buf); - msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_OBJECT); + msgpack_pack_long(buf, MSGPACK_SERIALIZE_TYPE_RECURSIVE); - msgpack_pack_nil(buf); + msgpack_pack_long(buf, 0); msgpack_pack_long(buf, *var_already); return; @@ -504,9 +545,12 @@ void msgpack_serialize_zval( } break; default: - zend_error(E_WARNING, - "[msgpack] (php_msgpack_serialize) " - "type is unsupported, encoded as null"); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (php_msgpack_serialize) " + "type is unsupported, encoded as null"); + } msgpack_pack_nil(buf); break; } diff --git a/php/msgpack_pack.h b/php/msgpack_pack.h index 96cfd4e8..16f3e7bc 100644 --- a/php/msgpack_pack.h +++ b/php/msgpack_pack.h @@ -1,13 +1,14 @@ -#ifndef MSGPACL_PACK_H -#define MSGPACL_PACK_H +#ifndef MSGPACK_PACK_H +#define MSGPACK_PACK_H #include "ext/standard/php_smart_str.h" enum msgpack_serialize_type { + MSGPACK_SERIALIZE_TYPE_NONE = 0, MSGPACK_SERIALIZE_TYPE_REFERENCE = 1, - MSGPACK_SERIALIZE_TYPE_OBJECT, + MSGPACK_SERIALIZE_TYPE_RECURSIVE, MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT, }; diff --git a/php/msgpack_unpack.c b/php/msgpack_unpack.c index c6b9b3f9..f3b610d2 100644 --- a/php/msgpack_unpack.c +++ b/php/msgpack_unpack.c @@ -2,31 +2,69 @@ #include "php.h" #include "php_ini.h" #include "ext/standard/php_incomplete_class.h" -#include "ext/standard/php_var.h" #include "php_msgpack.h" #include "msgpack_pack.h" #include "msgpack_unpack.h" -#include "msgpack/unpack_define.h" - -#define VAR_ENTRIES_MAX 1024 - #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) # define Z_ADDREF_PP(ppz) ZVAL_ADDREF(*(ppz)) # define Z_SET_ISREF_PP(ppz) (*(ppz))->is_ref = 1 # define Z_UNSET_ISREF_PP(ppz) (*(ppz))->is_ref = 0 #endif +#define VAR_ENTRIES_MAX 1024 + typedef struct { zval *data[VAR_ENTRIES_MAX]; long used_slots; + long value_slots; + long access_slots[VAR_ENTRIES_MAX]; + bool alloc_slots[VAR_ENTRIES_MAX]; void *next; } var_entries; +#define MSGPACK_UNSERIALIZE_ALLOC(_unpack) \ + if (_unpack->deps <= 0) { \ + *obj = _unpack->retval; \ + msgpack_var_push(_unpack->var_hash, obj, true, false); \ + } else { \ + ALLOC_INIT_ZVAL(*obj); \ + msgpack_var_push(_unpack->var_hash, obj, false, true); \ + } + +#define MSGPACK_UNSERIALIZE_ALLOC_VALUE(_unpack) \ + if (_unpack->deps <= 0) { \ + *obj = _unpack->retval; \ + msgpack_var_push(_unpack->var_hash, obj, true, false); \ + } else { \ + ALLOC_INIT_ZVAL(*obj); \ + msgpack_var_push(_unpack->var_hash, obj, true, true); \ + } + +#define MSGPACK_UNSERIALIZE_PUSH_ITEM(_unpack, _count, _val) \ + msgpack_var_alloc(_unpack->var_hash, _count); \ + if (Z_TYPE_P(_val) != IS_ARRAY && Z_TYPE_P(_val) != IS_OBJECT) { \ + msgpack_var_push(_unpack->var_hash, &_val, true, false); \ + } + +#define MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack) \ + long deps = _unpack->deps - 1; \ + _unpack->stack[deps]--; \ + if (_unpack->stack[deps] == 0) { \ + _unpack->deps--; \ + } + +#define MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(_unpack, _key, _val) \ + zval_ptr_dtor(&_key); \ + zval_ptr_dtor(&_val); \ + msgpack_var_alloc(_unpack->var_hash, 2); \ + MSGPACK_UNSERIALIZE_FINISH_ITEM(_unpack); + + inline static void msgpack_var_push( - php_unserialize_data_t *var_hashx, zval **rval) + php_unserialize_data_t *var_hashx, zval **rval, bool value, bool alloc) { var_entries *var_hash, *prev = NULL; @@ -47,6 +85,7 @@ inline static void msgpack_var_push( { var_hash = emalloc(sizeof(var_entries)); var_hash->used_slots = 0; + var_hash->value_slots = 0; var_hash->next = 0; if (!var_hashx->first) @@ -59,9 +98,45 @@ inline static void msgpack_var_push( } } + var_hash->alloc_slots[var_hash->used_slots] = alloc; + + if (value) + { + var_hash->access_slots[var_hash->value_slots++] = var_hash->used_slots; + } + var_hash->data[var_hash->used_slots++] = *rval; } +inline static void msgpack_var_alloc( + php_unserialize_data_t *var_hashx, long count) +{ + long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash && var_hash->used_slots == VAR_ENTRIES_MAX) + { + var_hash = var_hash->next; + } + + if (!var_hash || count <= 0) + { + return; + } + + for (i = var_hash->used_slots - 1; i >= 0; i--) + { + if (var_hash->alloc_slots[i]) + { + var_hash->alloc_slots[i] = false; + if (--count <= 0) + { + break; + } + } + } +} + inline static int msgpack_var_access( php_unserialize_data_t *var_hashx, long id, zval ***store) { @@ -79,6 +154,13 @@ inline static int msgpack_var_access( return !SUCCESS; } + if (id < 0 || id >= var_hash->value_slots) + { + return !SUCCESS; + } + + id = var_hash->access_slots[id]; + if (id < 0 || id >= var_hash->used_slots) { return !SUCCESS; @@ -89,741 +171,533 @@ inline static int msgpack_var_access( return SUCCESS; } -inline static int msgpack_unserialize_array( - zval **return_value, msgpack_unserialize_data *mpsd, - ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) +inline static zend_class_entry* msgpack_unserialize_class( + zval **container, char *class_name, size_t name_len) { - ulong i; - HashTable *ht; - - msgpack_var_push(var_hash, return_value); - - if (Z_TYPE_PP(return_value) != IS_ARRAY) - { - array_init(*return_value); - } - - ht = HASH_OF(*return_value); - - for (i = 0; i < ct; i++) - { - zval *val; - - /* value */ - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_array) " - "Invalid value"); - } - zval_ptr_dtor(&val); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* update */ - zend_hash_index_update(ht, i, &val, sizeof(zval *), NULL); - } - - return MSGPACK_UNPACK_SUCCESS; -} - -inline static int msgpack_unserialize_object_type( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash, zend_bool is_ref TSRMLS_DC) -{ - int ret = MSGPACK_UNPACK_SUCCESS; - zval *key, *val, **rval; - - ALLOC_INIT_ZVAL(key); - - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - ALLOC_INIT_ZVAL(val); - - if (is_ref) - { - ret = msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC); - } - else - { - ret = msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC); - } - - if (ret <= 0) - { - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - if (!var_hash || - msgpack_var_access(var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object_key) " - "Invalid references value: %ld", - Z_LVAL_P(val) - 1); - } - ret = MSGPACK_UNPACK_CONTINUE; - } - else - { - if (*return_value != NULL) - { - zval_ptr_dtor(return_value); - } - - *return_value = *rval; - - Z_ADDREF_PP(return_value); - - if (is_ref) - { - Z_SET_ISREF_PP(return_value); - } - else - { - Z_UNSET_ISREF_PP(return_value); - } - } - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; -} - -inline static int msgpack_unserialize_object( - zval **return_value, msgpack_unserialize_data *mpsd, - ulong ct, php_unserialize_data_t *var_hash TSRMLS_DC) -{ - int ret = MSGPACK_UNPACK_SUCCESS; - zend_class_entry *ce, **pce; bool incomplete_class = false; zval *user_func, *retval_ptr, **args[1], *arg_func_name; - HashTable *ht; + TSRMLS_FETCH(); - zval *key, *val; + do + { + /* Try to find class directly */ + if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + break; + } - int object = 1; - int custom_object = 0; + /* Check for unserialize callback */ + if ((PG(unserialize_callback_func) == NULL) || + (PG(unserialize_callback_func)[0] == '\0')) + { + incomplete_class = 1; + ce = PHP_IC_ENTRY; + break; + } - /* Get class */ - ALLOC_INIT_ZVAL(key); + /* Call unserialize callback */ + ALLOC_INIT_ZVAL(user_func); + ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); + args[0] = &arg_func_name; + ALLOC_INIT_ZVAL(arg_func_name); + ZVAL_STRING(arg_func_name, class_name, 1); + if (call_user_function_ex( + CG(function_table), NULL, user_func, &retval_ptr, + 1, args, 0, NULL TSRMLS_CC) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_class) " + "defined (%s) but not found", class_name); + } - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) + incomplete_class = 1; + ce = PHP_IC_ENTRY; + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + break; + } + if (retval_ptr) + { + zval_ptr_dtor(&retval_ptr); + } + + /* The callback function may have defined the class */ + if (zend_lookup_class(class_name, name_len, &pce TSRMLS_CC) == SUCCESS) + { + ce = *pce; + } + else + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_class) " + "Function %s() hasn't defined the class " + "it was called for", class_name); + } + + incomplete_class = true; + ce = PHP_IC_ENTRY; + } + + zval_ptr_dtor(&user_func); + zval_ptr_dtor(&arg_func_name); + } + while(0); + + if (EG(exception)) { if (MSGPACK_G(error_display)) { zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign key"); + "[msgpack] (msgpack_unserialize_class) " + "Exception error"); } - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; + return NULL; } - ct--; + object_init_ex(*container, ce); - if (Z_TYPE_P(key) == IS_NULL) + /* store incomplete class name */ + if (incomplete_class) { - ALLOC_INIT_ZVAL(val); + php_store_class_name(*container, class_name, name_len); + } - if (msgpack_unserialize_zval(&val, mpsd, NULL TSRMLS_CC) <= 0) + return ce; +} + +void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx) +{ + var_hashx->first = 0; + var_hashx->first_dtor = 0; +} + +void msgpack_unserialize_var_destroy(php_unserialize_data_t *var_hashx) +{ + void *next; + long i; + var_entries *var_hash = var_hashx->first; + + while (var_hash) + { + for (i = 0; i < var_hash->used_slots; i++) { - if (MSGPACK_G(error_display)) + if (var_hash->alloc_slots[i] && var_hash->data[i]) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign value"); - } - - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - if (Z_TYPE_P(val) == IS_LONG) - { - switch (Z_LVAL_P(val)) - { - case MSGPACK_SERIALIZE_TYPE_REFERENCE: - ret = msgpack_unserialize_object_type( - return_value, mpsd, var_hash, 1 TSRMLS_CC); - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; - case MSGPACK_SERIALIZE_TYPE_OBJECT: - ret = msgpack_unserialize_object_type( - return_value, mpsd, var_hash, 0 TSRMLS_CC); - - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return ret; - case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: - custom_object = 1; - - zval_ptr_dtor(&val); - - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval( - &val, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; + zval_ptr_dtor(&var_hash->data[i]); } } + + next = var_hash->next; + efree(var_hash); + var_hash = next; + } + + /* + var_hash = var_hashx->first_dtor; + + while (var_hash) + { + for (i = 0; i < var_hash->used_slots; i++) + { + zval_ptr_dtor(&var_hash->data[i]); + } + next = var_hash->next; + efree(var_hash); + var_hash = next; + } + */ +} + +void msgpack_unserialize_init(msgpack_unserialize_data *unpack) +{ + unpack->deps = 0; + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; +} + +int msgpack_unserialize_uint8( + msgpack_unserialize_data *unpack, uint8_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint16( + msgpack_unserialize_data *unpack, uint16_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint32( + msgpack_unserialize_data *unpack, uint32_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_uint64( + msgpack_unserialize_data *unpack, uint64_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int8( + msgpack_unserialize_data *unpack, int8_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int16( + msgpack_unserialize_data *unpack, int16_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int32( + msgpack_unserialize_data *unpack, int32_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_int64( + msgpack_unserialize_data *unpack, int64_t data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_LONG(*obj, data); + + return 0; +} + +int msgpack_unserialize_float( + msgpack_unserialize_data *unpack, float data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_DOUBLE(*obj, data); + + return 0; +} + +int msgpack_unserialize_double( + msgpack_unserialize_data *unpack, double data, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_DOUBLE(*obj, data); + + return 0; +} + +int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_NULL(*obj); + + return 0; +} + +int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_BOOL(*obj, 1); + + return 0; +} + +int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + ZVAL_BOOL(*obj, 0); + + return 0; +} + +int msgpack_unserialize_raw( + msgpack_unserialize_data *unpack, const char* base, + const char* data, unsigned int len, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC(unpack); + + if (len == 0) + { + ZVAL_STRINGL(*obj, "", 0, 1); } else { - object = 0; - - msgpack_var_push(var_hash, return_value); - - if (Z_TYPE_PP(return_value) != IS_ARRAY) - { - array_init(*return_value); - } - - ht = HASH_OF(*return_value); - - ALLOC_INIT_ZVAL(val); - - if (msgpack_unserialize_zval(&val, mpsd, var_hash TSRMLS_CC) <= 0) - { - if (MSGPACK_G(error_display)) - { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Invalid sign value"); - } - - zval_ptr_dtor(&val); - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* update */ - switch (Z_TYPE_P(key)) - { - case IS_LONG: - zend_hash_index_update( - ht, Z_LVAL_P(key), &val, sizeof(zval *), NULL); - break; - case IS_STRING: - zend_symtable_update( - ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, - &val, sizeof(zval *), NULL); - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&val); - - return MSGPACK_UNPACK_PARSE_ERROR; - } + ZVAL_STRINGL(*obj, data, len, 1); } - zval_ptr_dtor(&key); + return 0; +} - if (object) +int msgpack_unserialize_array( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); + + array_init(*obj); + + unpack->stack[unpack->deps++] = count; + + return 0; +} + +int msgpack_unserialize_array_item( + msgpack_unserialize_data *unpack, zval **container, zval *obj) +{ + MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 1, obj); + + add_next_index_zval(*container, obj); + + MSGPACK_UNSERIALIZE_FINISH_ITEM(unpack); + + return 0; +} + +int msgpack_unserialize_map( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj) +{ + MSGPACK_UNSERIALIZE_ALLOC_VALUE(unpack); + + unpack->stack[unpack->deps++] = count; + + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + return 0; +} + +int msgpack_unserialize_map_item( + msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val) +{ + TSRMLS_FETCH(); + + if (MSGPACK_G(php_only)) { - convert_to_string(val); + if (Z_TYPE_P(key) == IS_NULL) + { + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; - do { - /* Try to find class directly */ - if (zend_lookup_class( - Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) + if (Z_TYPE_P(val) == IS_LONG) { - ce = *pce; - break; - } - - /* Check for unserialize callback */ - if ((PG(unserialize_callback_func) == NULL) || - (PG(unserialize_callback_func)[0] == '\0')) - { - incomplete_class = 1; - ce = PHP_IC_ENTRY; - break; - } - - /* Call unserialize callback */ - ALLOC_INIT_ZVAL(user_func); - ZVAL_STRING(user_func, PG(unserialize_callback_func), 1); - args[0] = &arg_func_name; - ALLOC_INIT_ZVAL(arg_func_name); - ZVAL_STRING(arg_func_name, Z_STRVAL_P(val), 1); - if (call_user_function_ex( - CG(function_table), NULL, user_func, &retval_ptr, - 1, args, 0, NULL TSRMLS_CC) != SUCCESS) - { - if (MSGPACK_G(error_display)) + switch (Z_LVAL_P(val)) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "defined (%s) but not found", Z_STRVAL_P(val)); + case MSGPACK_SERIALIZE_TYPE_REFERENCE: + Z_SET_ISREF_PP(container); + break; + case MSGPACK_SERIALIZE_TYPE_RECURSIVE: + unpack->type = MSGPACK_SERIALIZE_TYPE_RECURSIVE; + break; + case MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT: + unpack->type = MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT; + break; + default: + break; } + } + else if (Z_TYPE_P(val) == IS_STRING) + { + zend_class_entry *ce = msgpack_unserialize_class( + container, Z_STRVAL_P(val), Z_STRLEN_P(val)); - incomplete_class = 1; - ce = PHP_IC_ENTRY; - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); - break; - } - if (retval_ptr) - { - zval_ptr_dtor(&retval_ptr); - } - - /* The callback function may have defined the class */ - if (zend_lookup_class( - Z_STRVAL_P(val), Z_STRLEN_P(val), &pce TSRMLS_CC) == SUCCESS) - { - ce = *pce; - } - else - { - if (MSGPACK_G(error_display)) + if (ce == NULL) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Function %s() hasn't defined the class" - "it was called for", Z_STRVAL_P(val)); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; } - - incomplete_class = true; - ce = PHP_IC_ENTRY; } - zval_ptr_dtor(&user_func); - zval_ptr_dtor(&arg_func_name); - } while(0); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - if (EG(exception)) + return 0; + } + else if (unpack->type == MSGPACK_SERIALIZE_TYPE_CUSTOM_OBJECT) { - if (MSGPACK_G(error_display)) + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + zend_class_entry *ce = msgpack_unserialize_class( + container, Z_STRVAL_P(key), Z_STRLEN_P(key)); + + if (ce == NULL) { - zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " - "Exception error"); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; } - zval_ptr_dtor(&val); - - ZVAL_BOOL(*return_value, 0); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - msgpack_var_push(var_hash, return_value); - - object_init_ex(*return_value, ce); - - /* store incomplete class name */ - if (incomplete_class) - { - php_store_class_name( - *return_value, Z_STRVAL_P(val), Z_STRLEN_P(val)); - } - - zval_ptr_dtor(&val); - - /* implementing Serializable */ - if (custom_object) - { - zval *rval; - + /* implementing Serializable */ if (ce->unserialize == NULL) { if (MSGPACK_G(error_display)) { zend_error(E_WARNING, - "[msgpack] (msgpack_unserialize_object) " + "[msgpack] (msgpack_unserialize_map_item) " "Class %s has no unserializer", ce->name); } - return MSGPACK_UNPACK_PARSE_ERROR; - } + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - /* value */ - ALLOC_INIT_ZVAL(rval); - - if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&rval); - - return MSGPACK_UNPACK_PARSE_ERROR; + return 0; } ce->unserialize( - return_value, ce, - (const unsigned char *)Z_STRVAL_P(rval), Z_STRLEN_P(rval) + 1, - (zend_unserialize_data *)var_hash TSRMLS_CC); + container, ce, + (const unsigned char *)Z_STRVAL_P(val), Z_STRLEN_P(val) + 1, + NULL TSRMLS_CC); - zval_ptr_dtor(&key); - zval_ptr_dtor(&rval); + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); - return ret; + return 0; } + else if (unpack->type == MSGPACK_SERIALIZE_TYPE_RECURSIVE) + { + zval **rval; - ht = HASH_OF(*return_value); + unpack->type = MSGPACK_SERIALIZE_TYPE_NONE; + + if (msgpack_var_access( + unpack->var_hash, Z_LVAL_P(val) - 1, &rval) != SUCCESS) + { + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "Invalid references value: %ld", + Z_LVAL_P(val) - 1); + } + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; + } + + if (container != NULL) + { + zval_ptr_dtor(container); + } + + *container = *rval; + + Z_ADDREF_PP(container); + + MSGPACK_UNSERIALIZE_FINISH_MAP_ITEM(unpack, key, val); + + return 0; + } } - /* object property */ - while (ct-- > 0) + MSGPACK_UNSERIALIZE_PUSH_ITEM(unpack, 2, val); + + if (Z_TYPE_PP(container) != IS_ARRAY && Z_TYPE_PP(container) != IS_OBJECT) { - zval *rval; - - /* key */ - ALLOC_INIT_ZVAL(key); - - if (msgpack_unserialize_zval(&key, mpsd, NULL TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - /* value */ - ALLOC_INIT_ZVAL(rval); - - if (msgpack_unserialize_zval(&rval, mpsd, var_hash TSRMLS_CC) <= 0) - { - zval_ptr_dtor(&rval); - zval_ptr_dtor(&key); - - return MSGPACK_UNPACK_PARSE_ERROR; - - } - - /* update */ - switch (Z_TYPE_P(key)) - { - case IS_LONG: - zend_hash_index_update( - ht, Z_LVAL_P(key), &rval, sizeof(zval *), NULL); - break; - case IS_STRING: - zend_symtable_update( - ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, - &rval, sizeof(zval *), NULL); - break; - default: - zval_ptr_dtor(&key); - zval_ptr_dtor(&rval); - - return MSGPACK_UNPACK_PARSE_ERROR; - } - - zval_ptr_dtor(&key); + array_init(*container); } - /* wakeup */ - if (object && Z_OBJCE_PP(return_value) != PHP_IC_ENTRY && - zend_hash_exists(&Z_OBJCE_PP(return_value)->function_table, - "__wakeup", sizeof("__wakeup"))) + switch (Z_TYPE_P(key)) { - zval f, *h = NULL; + case IS_LONG: + if (zend_hash_index_update( + HASH_OF(*container), Z_LVAL_P(key), &val, + sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + } + break; + case IS_STRING: + if (zend_symtable_update( + HASH_OF(*container), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, + &val, sizeof(val), NULL) == FAILURE) + { + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + } + break; + default: + zval_ptr_dtor(&val); + if (MSGPACK_G(error_display)) + { + zend_error(E_WARNING, + "[msgpack] (msgpack_unserialize_map_item) " + "illegal offset type, skip this decoding"); + } + break; + } - INIT_PZVAL(&f); - ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0); - call_user_function_ex( - CG(function_table), return_value, &f, &h, 0, 0, 1, NULL TSRMLS_CC); - if (h) - { - zval_ptr_dtor(&h); - } + zval_ptr_dtor(&key); - if (EG(exception)) + long deps = unpack->deps - 1; + unpack->stack[deps]--; + if (unpack->stack[deps] == 0) + { + unpack->deps--; + + /* wakeup */ + if (MSGPACK_G(php_only) && + Z_TYPE_PP(container) == IS_OBJECT && + Z_OBJCE_PP(container) != PHP_IC_ENTRY && + zend_hash_exists( + &Z_OBJCE_PP(container)->function_table, + "__wakeup", sizeof("__wakeup"))) { - ret = MSGPACK_UNPACK_PARSE_ERROR; + zval f, *h = NULL; + + INIT_PZVAL(&f); + ZVAL_STRINGL(&f, "__wakeup", sizeof("__wakeup") - 1, 0); + call_user_function_ex( + CG(function_table), container, &f, &h, 0, 0, 1, NULL TSRMLS_CC); + if (h) + { + zval_ptr_dtor(&h); + } } } - return ret; + return 0; } - -int msgpack_unserialize_zval( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash TSRMLS_DC) -{ - const unsigned char* data = mpsd->data; - const unsigned char* const pe = mpsd->data + mpsd->length; - const void* n = NULL; - - unsigned int trail = 0; - unsigned int cs = CS_HEADER; - - int ret; - unsigned int ct; - -#define next_cs(p) ((unsigned int)*p & 0x1f) - -#define finish_zval_long(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_LONG(*return_value, val_); \ - goto _finish - -#define finish_zval_null() \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_NULL(*return_value); \ - goto _finish - -#define finish_zval_bool(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_BOOL(*return_value, val_); \ - goto _finish - -#define finish_zval_double(val_) \ - msgpack_var_push(var_hash, return_value); \ - ZVAL_DOUBLE(*return_value, val_); \ - goto _finish - -#define finish_zval_string(val_, len_) \ - msgpack_var_push(var_hash, return_value); \ - if (len_ == 0) { ZVAL_STRINGL(*return_value, "", 0, 1); } \ - else { ZVAL_STRINGL(*return_value, val_, len_, 1); } \ - goto _finish - -#define finish_zval_array(count_) \ - ct = count_; \ - cs = CS_HEADER; \ - ++(mpsd->data); \ - mpsd->length = (pe - mpsd->data); \ - if (msgpack_unserialize_array(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ - goto _finish_end - -#define finish_zval_object(count_) \ - ct = count_; \ - cs = CS_HEADER; \ - ++(mpsd->data); \ - mpsd->length = (pe - mpsd->data); \ - if (msgpack_unserialize_object(return_value, mpsd, ct, var_hash TSRMLS_CC) <= 0) { goto _failed; } \ - goto _finish_end - -#define again_fixed_trail(_cs, trail_len) \ - trail = trail_len; \ - cs = _cs; \ - goto _fixed_trail_again - -#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ - trail = trail_len; \ - if(trail == 0) { goto ifzero; } \ - cs = _cs; \ - goto _fixed_trail_again - - if (mpsd->length <= 0) - { - goto _failed; - } - - if (mpsd->data == pe) - { - goto _out; - } - do - { - switch (cs) - { - case CS_HEADER: - switch (*(mpsd->data)) - { - case 0x00 ... 0x7f: /* Positive Fixnum */ - finish_zval_long(*(uint8_t*)mpsd->data); - case 0xe0 ... 0xff: /* Negative Fixnum */ - finish_zval_long(*(int8_t*)mpsd->data); - case 0xc0 ... 0xdf: /* Variable */ - switch (*(mpsd->data)) - { - case 0xc0: /* nil */ - finish_zval_null(); - case 0xc2: /* false */ - finish_zval_bool(0); - case 0xc3: /* true */ - finish_zval_bool(1); - case 0xca: /* float */ - case 0xcb: /* double */ - case 0xcc: /* unsigned int 8 */ - case 0xcd: /* unsigned int 16 */ - case 0xce: /* unsigned int 32 */ - case 0xcf: /* unsigned int 64 */ - case 0xd0: /* signed int 8 */ - case 0xd1: /* signed int 16 */ - case 0xd2: /* signed int 32 */ - case 0xd3: /* signed int 64 */ - again_fixed_trail( - next_cs(mpsd->data), - 1 << (((unsigned int)*(mpsd->data)) & 0x03)); - case 0xda: /* raw 16 */ - case 0xdb: /* raw 32 */ - case 0xdc: /* array 16 */ - case 0xdd: /* array 32 */ - case 0xde: /* map 16 */ - case 0xdf: /* map 32 */ - again_fixed_trail( - next_cs(mpsd->data), - 2 << (((unsigned int)*(mpsd->data)) & 0x01)); - default: - goto _failed; - } - case 0xa0 ... 0xbf: /* FixRaw */ - again_fixed_trail_if_zero( - ACS_RAW_VALUE, (unsigned int)*(mpsd->data) & 0x1f, - _raw_zero); - case 0x90 ... 0x9f: /* FixArray */ - finish_zval_array(((unsigned int)*(mpsd->data)) & 0x0f); - case 0x80 ... 0x8f: /* FixMap */ - finish_zval_object(((unsigned int)*(mpsd->data)) & 0x0f); - default: - goto _failed; - } -_fixed_trail_again: - ++(mpsd->data); - default: - if ((size_t)(pe - (mpsd->data)) < trail) - { - goto _out; - } - n = (mpsd->data); - mpsd->data += trail - 1; - switch (cs) - { - case CS_FLOAT: - { - union { uint32_t i; float f; } mem; - mem.i = _msgpack_load32(uint32_t, n); - finish_zval_double(mem.f); - } - case CS_DOUBLE: - { - union { uint64_t i; double f; } mem; - mem.i = _msgpack_load64(uint64_t, n); - finish_zval_double(mem.f); - } - case CS_UINT_8: - finish_zval_long(*(uint8_t*)n); - case CS_UINT_16: - finish_zval_long(_msgpack_load16(uint16_t, n)); - case CS_UINT_32: - finish_zval_long(_msgpack_load32(uint32_t, n)); - case CS_UINT_64: - finish_zval_long(_msgpack_load64(uint64_t, n)); - case CS_INT_8: - finish_zval_long(*(int8_t*)n); - case CS_INT_16: - finish_zval_long(_msgpack_load16(int16_t, n)); - case CS_INT_32: - finish_zval_long(_msgpack_load32(int32_t, n)); - case CS_INT_64: - finish_zval_long(_msgpack_load64(int64_t, n)); - case CS_RAW_16: - again_fixed_trail_if_zero( - ACS_RAW_VALUE, _msgpack_load16(uint16_t, n), - _raw_zero); - case CS_RAW_32: - again_fixed_trail_if_zero( - ACS_RAW_VALUE, _msgpack_load32(uint32_t, n), - _raw_zero); - case ACS_RAW_VALUE: -_raw_zero: - finish_zval_string(n, trail); - case CS_ARRAY_16: - finish_zval_array(_msgpack_load16(uint16_t, n)); - case CS_ARRAY_32: - finish_zval_array(_msgpack_load32(uint32_t, n)); - /* FIXME security guard */ - case CS_MAP_16: - finish_zval_object(_msgpack_load16(uint16_t, n)); - case CS_MAP_32: - finish_zval_object(_msgpack_load32(uint32_t, n)); - /* FIXME security guard */ - default: - goto _failed; - } - } - cs = CS_HEADER; - ++(mpsd->data); - } - while (mpsd->data != pe); - goto _out; - -_finish: - ++(mpsd->data); -_finish_end: - ret = MSGPACK_UNPACK_EXTRA_BYTES; - goto _end; - -_failed: - ret = MSGPACK_UNPACK_PARSE_ERROR; - goto _end; - -_out: - ret = MSGPACK_UNPACK_CONTINUE; - goto _end; - -_end: - mpsd->offset = mpsd->data - data; - mpsd->length = pe - mpsd->data; - - if (ret == MSGPACK_UNPACK_EXTRA_BYTES && mpsd->length == 0) - { - ret = MSGPACK_UNPACK_SUCCESS; - } - - return ret; -} - -#undef finish_zval_long -#undef finish_zval_null -#undef finish_zval_bool -#undef finish_zval_double -#undef finish_zval_string -#undef finish_zval_array -#undef finish_zval_object -#undef again_fixed_trail -#undef again_fixed_trail_if_zero - -#undef next_cs diff --git a/php/msgpack_unpack.h b/php/msgpack_unpack.h index 6c85d73f..da963ebf 100644 --- a/php/msgpack_unpack.h +++ b/php/msgpack_unpack.h @@ -1,9 +1,13 @@ -#ifndef MSGPACL_UNPACK_H -#define MSGPACL_UNPACK_H +#ifndef MSGPACK_UNPACK_H +#define MSGPACK_UNPACK_H #include "ext/standard/php_var.h" +#define MSGPACK_EMBED_STACK_SIZE 1024 + +#include "msgpack/unpack_define.h" + typedef enum { MSGPACK_UNPACK_SUCCESS = 2, @@ -12,15 +16,114 @@ typedef enum MSGPACK_UNPACK_PARSE_ERROR = -1, } msgpack_unpack_return; -typedef struct -{ - unsigned char *data; - size_t length; - size_t offset; +typedef struct { + zval *retval; + long deps; + php_unserialize_data_t *var_hash; + long stack[MSGPACK_EMBED_STACK_SIZE]; + int type; } msgpack_unserialize_data; -int msgpack_unserialize_zval( - zval **return_value, msgpack_unserialize_data *mpsd, - php_unserialize_data_t *var_hash TSRMLS_DC); +void msgpack_unserialize_var_init(php_unserialize_data_t *var_hashx); +void msgpack_unserialize_var_destroy(php_unserialize_data_t *var_hashx); + +void msgpack_unserialize_init(msgpack_unserialize_data *unpack); + +int msgpack_unserialize_uint8( + msgpack_unserialize_data *unpack, uint8_t data, zval **obj); +int msgpack_unserialize_uint16( + msgpack_unserialize_data *unpack, uint16_t data, zval **obj); +int msgpack_unserialize_uint32( + msgpack_unserialize_data *unpack, uint32_t data, zval **obj); +int msgpack_unserialize_uint64( + msgpack_unserialize_data *unpack, uint64_t data, zval **obj); +int msgpack_unserialize_int8( + msgpack_unserialize_data *unpack, int8_t data, zval **obj); +int msgpack_unserialize_int16( + msgpack_unserialize_data *unpack, int16_t data, zval **obj); +int msgpack_unserialize_int32( + msgpack_unserialize_data *unpack, int32_t data, zval **obj); +int msgpack_unserialize_int64( + msgpack_unserialize_data *unpack, int64_t data, zval **obj); +int msgpack_unserialize_float( + msgpack_unserialize_data *unpack, float data, zval **obj); +int msgpack_unserialize_double( + msgpack_unserialize_data *unpack, double data, zval **obj); +int msgpack_unserialize_nil(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_true(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_false(msgpack_unserialize_data *unpack, zval **obj); +int msgpack_unserialize_raw( + msgpack_unserialize_data *unpack, const char* base, const char* data, + unsigned int len, zval **obj); +int msgpack_unserialize_array( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj); +int msgpack_unserialize_array_item( + msgpack_unserialize_data *unpack, zval **container, zval *obj); +int msgpack_unserialize_map( + msgpack_unserialize_data *unpack, unsigned int count, zval **obj); +int msgpack_unserialize_map_item( + msgpack_unserialize_data *unpack, zval **container, zval *key, zval *val); + +/* template functions */ +#define msgpack_unpack_struct(name) struct template ## name +#define msgpack_unpack_func(ret, name) ret template ## name +#define msgpack_unpack_callback(name) template_callback ## name + +#define msgpack_unpack_object zval* +#define unpack_user msgpack_unserialize_data +#define msgpack_unpack_user msgpack_unserialize_data + +struct template_context; +typedef struct template_context msgpack_unpack_t; + +static void template_init(msgpack_unpack_t* unpack); +static msgpack_unpack_object template_data(msgpack_unpack_t* unpack); +static int template_execute( + msgpack_unpack_t* unpack, const char* data, size_t len, size_t* off); + +static inline msgpack_unpack_object template_callback_root(unpack_user* user) +{ + msgpack_unserialize_init(user); + return NULL; +} + +#define template_callback_uint8(user, data, obj) \ + msgpack_unserialize_uint8(user, data, obj) +#define template_callback_uint16(user, data, obj) \ + msgpack_unserialize_uint16(user, data, obj) +#define template_callback_uint32(user, data, obj) \ + msgpack_unserialize_uint32(user, data, obj) +#define template_callback_uint64(user, data, obj) \ + msgpack_unserialize_uint64(user, data, obj) +#define template_callback_int8(user, data, obj) \ + msgpack_unserialize_int8(user, data, obj) +#define template_callback_int16(user, data, obj) \ + msgpack_unserialize_int16(user, data, obj) +#define template_callback_int32(user, data, obj) \ + msgpack_unserialize_int32(user, data, obj) +#define template_callback_int64(user, data, obj) \ + msgpack_unserialize_int64(user, data, obj) +#define template_callback_float(user, data, obj) \ + msgpack_unserialize_float(user, data, obj) +#define template_callback_double(user, data, obj) \ + msgpack_unserialize_double(user, data, obj) +#define template_callback_nil(user, obj) \ + msgpack_unserialize_nil(user, obj) +#define template_callback_true(user, obj) \ + msgpack_unserialize_true(user, obj) +#define template_callback_false(user, obj) \ + msgpack_unserialize_false(user, obj) +#define template_callback_raw(user, base, data, len, obj) \ + msgpack_unserialize_raw(user, base, data, len, obj) +#define template_callback_array(user, count, obj) \ + msgpack_unserialize_array(user, count, obj) +#define template_callback_array_item(user, container, obj) \ + msgpack_unserialize_array_item(user, container, obj) +#define template_callback_map(user, count, obj) \ + msgpack_unserialize_map(user, count, obj) +#define template_callback_map_item(user, container, key, val) \ + msgpack_unserialize_map_item(user, container, key, val) + +#include "msgpack/unpack_template.h" #endif diff --git a/php/package.xml b/php/package.xml index 48697704..6172a4c5 100644 --- a/php/package.xml +++ b/php/package.xml @@ -10,11 +10,11 @@ advect@gmail.com yes - 2010-07-17 - + 2010-09-28 + - 0.2.1 - 0.2.1 + 0.3.0 + 0.3.0 beta @@ -26,15 +26,21 @@ - - - - - - - - - + + + + + + + + + + + + + + + @@ -43,28 +49,32 @@ - + + - - - + + + - + - + + - - - - - + + + + + + + @@ -74,13 +84,30 @@ - - + + + + - - - + + + + + + + + + + + + + + + + + + diff --git a/php/php-msgpack.spec b/php/php-msgpack.spec index 5726c434..6a98288b 100644 --- a/php/php-msgpack.spec +++ b/php/php-msgpack.spec @@ -3,7 +3,7 @@ Summary: PHP extension for interfacing with MessagePack Name: php-msgpack -Version: 0.2.1 +Version: 0.3.0 Release: 1%{?dist} Source: php-msgpack-%{version}.tar.gz License: New BSD License @@ -11,7 +11,7 @@ Group: Development/Libraries Packager: advect Provides: php-pecl-msgpack BuildRoot: %{_tmppath}/%{name}-%{version}-root -BuildRequires: php-devel, msgpack-devel +BuildRequires: php-devel Requires: msgpack %if 0%{?php_zend_api} Requires: php(zend-abi) = %{php_zend_api} diff --git a/php/php_msgpack.h b/php/php_msgpack.h index 91b2d30f..61badea7 100644 --- a/php/php_msgpack.h +++ b/php/php_msgpack.h @@ -2,7 +2,7 @@ #ifndef PHP_MSGPACK_H #define PHP_MSGPACK_H -#define MSGPACK_VERSION "0.2.1" +#define MSGPACK_EXTENSION_VERSION "0.3.0" #include "ext/standard/php_smart_str.h" @@ -23,6 +23,7 @@ extern zend_module_entry msgpack_module_entry; ZEND_BEGIN_MODULE_GLOBALS(msgpack) zend_bool error_display; + zend_bool php_only; ZEND_END_MODULE_GLOBALS(msgpack) ZEND_DECLARE_MODULE_GLOBALS(msgpack) diff --git a/php/tests/009.phpt b/php/tests/009.phpt index 6baad5ee..9992988a 100644 --- a/php/tests/009.phpt +++ b/php/tests/009.phpt @@ -1,6 +1,10 @@ --TEST-- -Check for reference serialisation +Check for reference serialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { @@ -63,16 +67,16 @@ array(2) { } OK cyclic -81008100810082c001c002 +810082c0010082c0010082c0020002 array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } @@ -101,11 +105,11 @@ array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/009b.phpt b/php/tests/009b.phpt new file mode 100644 index 00000000..7765d62a --- /dev/null +++ b/php/tests/009b.phpt @@ -0,0 +1,101 @@ +--TEST-- +Check for reference serialization +--SKIPIF-- + + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(&$a, &$a) +820082c00100a3666f6f0182c0020002 +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +cyclic +810082c0010082c0010082c0020002 +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} diff --git a/php/tests/014.phpt b/php/tests/014.phpt index c663579d..b9c7c671 100644 --- a/php/tests/014.phpt +++ b/php/tests/014.phpt @@ -34,7 +34,7 @@ test('object', $a, false); ?> --EXPECTF-- object -820083c0a34f626aa16101a162020182c001c002 +820084c001c0a34f626aa16101a162020182c0020002 array(2) { [0]=> &object(Obj)#%d (2) { diff --git a/php/tests/015.phpt b/php/tests/015.phpt index 828800a2..634a8b1a 100644 --- a/php/tests/015.phpt +++ b/php/tests/015.phpt @@ -51,7 +51,7 @@ var_dump($_SESSION); ?> --EXPECT-- 2 -81a3666f6f02 +82c001a3666f6f02 array(1) { ["foo"]=> int(2) diff --git a/php/tests/015b.phpt b/php/tests/015b.phpt index 829584b7..7ced3126 100644 --- a/php/tests/015b.phpt +++ b/php/tests/015b.phpt @@ -51,7 +51,7 @@ var_dump($_SESSION); ?> --EXPECT-- 2 -81a3666f6f02 +82c001a3666f6f02 array(1) { ["foo"]=> int(2) diff --git a/php/tests/018.phpt b/php/tests/018.phpt index 84ccafa2..f5ff4b72 100644 --- a/php/tests/018.phpt +++ b/php/tests/018.phpt @@ -74,7 +74,7 @@ object(Obj)#%d (3) { } OK wrong -82c0a34f706ac0 +82c0a34f706a object(Opj)#%d (2) { ["a"]=> NULL diff --git a/php/tests/024.phpt b/php/tests/024.phpt index 30fab759..9b185f7c 100644 --- a/php/tests/024.phpt +++ b/php/tests/024.phpt @@ -1,6 +1,10 @@ --TEST-- Recursive objects --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- int(100) diff --git a/php/tests/024b.phpt b/php/tests/024b.phpt new file mode 100644 index 00000000..7c691bec --- /dev/null +++ b/php/tests/024b.phpt @@ -0,0 +1,165 @@ +--TEST-- +Recursive objects +--SKIPIF-- +a = $a; + $this->b = $b; + $this->c = $c; + } +} + +class Obj2 { + public $aa; + protected $bb; + private $cc; + private $obj; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + + $this->obj = new Obj($a, $b, $c); + } +} + +class Obj3 { + private $objs; + + function __construct($a, $b, $c) { + $this->objs = array(); + + for ($i = $a; $i < $c; $i += $b) { + $this->objs[] = new Obj($a, $i, $c); + } + } +} + +class Obj4 { + private $a; + private $obj; + + function __construct($a) { + $this->a = $a; + } + + public function set($obj) { + $this->obj = $obj; + } +} + +$o2 = new Obj2(1, 2, 3); +test('objectrec', $o2, false); + +$o3 = new Obj3(0, 1, 4); +test('objectrecarr', $o3, false); + +$o4 = new Obj4(100); +$o4->set($o4); +test('objectselfrec', $o4, true); +?> +--EXPECTF-- +objectrec +88c0a44f626a32a26161c0a5002a006262c0a8004f626a32006363c0a9004f626a32006f626a84c0a34f626aa16101a4002a006202a6004f626a006303a16101a16202a16303 +object(Obj2)#%d (7) { + ["aa"]=> + NULL + [%r"?bb"?:protected"?%r]=> + NULL + [%r"?cc"?:("Obj2":)?private"?%r]=> + NULL + [%r"?obj"?:("Obj2":)?private"?%r]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + ["a"]=> + int(1) + ["b"]=> + int(2) + ["c"]=> + int(3) +} +OK +objectrecarr +82c0a44f626a33aa004f626a33006f626a73840084c0a34f626aa16100a4002a006200a6004f626a0063040184c0a34f626aa16100a4002a006201a6004f626a0063040284c0a34f626aa16100a4002a006202a6004f626a0063040384c0a34f626aa16100a4002a006203a6004f626a006304 +object(Obj3)#%d (1) { + [%r"?objs"?:("Obj3":)?private"?%r]=> + array(4) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(0) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(1) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [2]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + [3]=> + object(Obj)#%d (3) { + ["a"]=> + int(0) + [%r"?b"?:protected"?%r]=> + int(3) + [%r"?c"?:("Obj":)?private"?%r]=> + int(4) + } + } +} +OK +objectselfrec +83c0a44f626a34a7004f626a34006164a9004f626a34006f626a82c0020001 +object(Obj4)#%d (2) { + [%r"?a"?:("Obj4":)?private"?%r]=> + int(100) + [%r"?obj"?:("Obj4":)?private"?%r]=> + *RECURSION* +} +OK diff --git a/php/tests/026.phpt b/php/tests/026.phpt index 2d3bb734..c243ef51 100644 --- a/php/tests/026.phpt +++ b/php/tests/026.phpt @@ -2,6 +2,10 @@ Cyclic array test --INI-- --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- --EXPECT-- array -82a16182a162a163a164a165a16682a16182a162a163a164a165a16682c001c005 +82a16182a162a163a164a165a16683c001a16182a162a163a164a165a16682c0020005 array(2) { ["a"]=> array(2) { diff --git a/php/tests/026b.phpt b/php/tests/026b.phpt new file mode 100644 index 00000000..f7a3381f --- /dev/null +++ b/php/tests/026b.phpt @@ -0,0 +1,107 @@ +--TEST-- +Cyclic array test +--INI-- +--SKIPIF-- + array( + 'b' => 'c', + 'd' => 'e' + ), +); + +$a['f'] = &$a; + +test('array', $a, true); + +$a = array("foo" => &$b); +$b = array(1, 2, $a); +var_dump($a); +var_dump($k = msgpack_unserialize(msgpack_serialize($a))); + +$k["foo"][1] = "b"; +var_dump($k); +?> +--EXPECT-- +array +82a16182a162a163a164a165a16683c001a16182a162a163a164a165a16682c0020005 +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + &array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + *RECURSION* + } +} +OK +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + *RECURSION* + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } +} +array(1) { + ["foo"]=> + &array(3) { + [0]=> + int(1) + [1]=> + string(1) "b" + [2]=> + array(1) { + ["foo"]=> + *RECURSION* + } + } +} diff --git a/php/tests/027.phpt b/php/tests/027.phpt index ecb87841..c9c7cbd5 100644 --- a/php/tests/027.phpt +++ b/php/tests/027.phpt @@ -64,7 +64,7 @@ var_dump($_SESSION); --EXPECT-- bool(true) read -wrote: 82a3666f6f01a474657374a6666f6f626172 +wrote: 83c001a3666f6f01a474657374a6666f6f626172 array(2) { ["foo"]=> int(1) diff --git a/php/tests/028.phpt b/php/tests/028.phpt index 56805f9e..00db6751 100644 --- a/php/tests/028.phpt +++ b/php/tests/028.phpt @@ -1,6 +1,10 @@ --TEST-- Serialize object into session, full set --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- --EXPECTF-- read -write: 83a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c002c002a70042617200643282c002c002a5002a00643382c002c002a5002a00643282c002c003a2643382c002c003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002c00aa5002a00643282c002c00aa2643382c002c00aa70042617200643282c002c00ba5002a00643382c002c00b +write: 84c001a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c0020002a70042617200643282c0020002a5002a00643382c0020002a5002a00643282c0020003a2643382c0020003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002000aa5002a00643282c002000aa2643382c002000aa70042617200643282c002000ba5002a00643382c002000b array(3) { ["old"]=> object(Foo)#3 (3) { diff --git a/php/tests/028b.phpt b/php/tests/028b.phpt new file mode 100644 index 00000000..7331a576 --- /dev/null +++ b/php/tests/028b.phpt @@ -0,0 +1,167 @@ +--TEST-- +Serialize object into session, full set +--SKIPIF-- +d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +class Bar { + private static $s1 = array(); + protected static $s2 = array(); + public static $s3 = array(); + + public $d1; + private $d2; + protected $d3; + + public function __construct() { + } + + public function set($foo) { + $this->d1 = $foo; + $this->d2 = $foo; + $this->d3 = $foo; + } +} + +$output = ''; + +function open($path, $name) { + return true; +} + +function close() { + return true; +} + +function read($id) { + global $output; + $output .= "read" . PHP_EOL; + $a = new Bar(); + $b = new Foo($a); + $a->set($b); + $session = array('old' => $b); + return msgpack_serialize($session); +} + +function write($id, $data) { + global $output; + $output .= "write: "; + $output .= bin2hex($data) . PHP_EOL; + return true; +} + +function destroy($id) { + return true; +} + +function gc($time) { + return true; +} + +ini_set('session.serialize_handler', 'msgpack'); + +session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc'); + +session_start(); + +$_SESSION['test'] = "foobar"; +$a = new Bar(); +$b = new Foo($a); +$a->set($b); +$_SESSION['new'] = $a; + +session_write_close(); + +echo $output; +var_dump($_SESSION); +?> +--EXPECTF-- +read +write: 84c001a36f6c6484c0a3466f6fa700466f6f00643184c0a3426172a2643182c0020002a70042617200643282c0020002a5002a00643382c0020002a5002a00643282c0020003a2643382c0020003a474657374a6666f6f626172a36e657784c0a3426172a2643184c0a3466f6fa700466f6f00643182c002000aa5002a00643282c002000aa2643382c002000aa70042617200643282c002000ba5002a00643382c002000b +array(3) { + ["old"]=> + object(Foo)#3 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + [%r"?d2"?:protected"?%r]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + ["d3"]=> + object(Bar)#4 (3) { + ["d1"]=> + *RECURSION* + [%r"?d2"?:("Bar":)?private"?%r]=> + *RECURSION* + [%r"?d3"?:protected"?%r]=> + *RECURSION* + } + } + ["test"]=> + string(6) "foobar" + ["new"]=> + object(Bar)#5 (3) { + ["d1"]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d2"?:("Bar":)?private"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + [%r"?d3"?:protected"?%r]=> + object(Foo)#6 (3) { + [%r"?d1"?:("Foo":)?private"?%r]=> + *RECURSION* + [%r"?d2"?:protected"?%r]=> + *RECURSION* + ["d3"]=> + *RECURSION* + } + } +} diff --git a/php/tests/029.phpt b/php/tests/029.phpt index 3bd1e9dc..686abb92 100644 --- a/php/tests/029.phpt +++ b/php/tests/029.phpt @@ -9,12 +9,39 @@ phpinfo(INFO_MODULES); $str = ob_get_clean(); $array = explode("\n", $str); -$array = preg_grep('/^msgpack/', $array); -echo implode("\n", $array), PHP_EOL; +$section = false; +$blank = 0; +foreach ($array as $key => $val) +{ + if (strcmp($val, 'msgpack') == 0 || $section) + { + $section = true; + } + else + { + continue; + } + if (empty($val)) + { + $blank++; + if ($blank == 3) + { + $section = false; + } + } + + echo $val, PHP_EOL; +} --EXPECTF-- msgpack -msgpack support => enabled -msgpack version => %s -msgpack Session Support => enabled + +MessagePack Support => enabled +Session Support => enabled +extension Version => %s +header Version => %s + +Directive => Local Value => Master Value +msgpack.error_display => On => On +msgpack.php_only => On => On diff --git a/php/tests/030.phpt b/php/tests/030.phpt index ec8622dc..3b8d986e 100644 --- a/php/tests/030.phpt +++ b/php/tests/030.phpt @@ -56,9 +56,6 @@ foreach ($datas as $data) { } ?> --EXPECTF-- -output at 2: -array(0) { -} output at 3: array(1) { [0]=> diff --git a/php/tests/060.phpt b/php/tests/060.phpt index c0fda4c2..649d7886 100644 --- a/php/tests/060.phpt +++ b/php/tests/060.phpt @@ -1,6 +1,10 @@ --TEST-- Check for buffered streaming unserialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- 1, "two" => 2))', array("one" => 1, "two" => 2), false); @@ -234,11 +238,11 @@ array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/060b.phpt b/php/tests/060b.phpt new file mode 100644 index 00000000..0b947c8e --- /dev/null +++ b/php/tests/060b.phpt @@ -0,0 +1,313 @@ +--TEST-- +Check for buffered streaming unserialization +--SKIPIF-- +feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('bool: true', true); +test('bool: false', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('array', array(), false); +test('array(1, 2, 3)', array(1, 2, 3), false); +test('array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/061.phpt b/php/tests/061.phpt index ded494e0..7ecc0c9f 100644 --- a/php/tests/061.phpt +++ b/php/tests/061.phpt @@ -1,6 +1,10 @@ --TEST-- Check for unbuffered streaming unserialization --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/061b.phpt b/php/tests/061b.phpt new file mode 100644 index 00000000..efb3a9bf --- /dev/null +++ b/php/tests/061b.phpt @@ -0,0 +1,318 @@ +--TEST-- +Check for unbuffered streaming unserialization +--SKIPIF-- +execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/070.phpt b/php/tests/070.phpt index 4a00ddf5..893023b5 100644 --- a/php/tests/070.phpt +++ b/php/tests/070.phpt @@ -1,6 +1,10 @@ --TEST-- Check for alias functions --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/070b.phpt b/php/tests/070b.phpt new file mode 100644 index 00000000..109ddc1a --- /dev/null +++ b/php/tests/070b.phpt @@ -0,0 +1,297 @@ +--TEST-- +Check for alias functions +--SKIPIF-- + 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/071.phpt b/php/tests/071.phpt index cca351aa..431303b6 100644 --- a/php/tests/071.phpt +++ b/php/tests/071.phpt @@ -1,6 +1,10 @@ --TEST-- Check for class methods --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/071b.phpt b/php/tests/071b.phpt new file mode 100644 index 00000000..770d06ee --- /dev/null +++ b/php/tests/071b.phpt @@ -0,0 +1,299 @@ +--TEST-- +Check for class methods +--SKIPIF-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/072.phpt b/php/tests/072.phpt index d8cb1b99..ea79a56d 100644 --- a/php/tests/072.phpt +++ b/php/tests/072.phpt @@ -1,6 +1,10 @@ --TEST-- Check for class methods unpacker --SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} --FILE-- &array(1) { [0]=> - array(1) { + &array(1) { [0]=> &array(1) { [0]=> - array(1) { + &array(1) { [0]=> *RECURSION* } diff --git a/php/tests/072b.phpt b/php/tests/072b.phpt new file mode 100644 index 00000000..c7b0c3ce --- /dev/null +++ b/php/tests/072b.phpt @@ -0,0 +1,339 @@ +--TEST-- +Check for class methods unpacker +--SKIPIF-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/073.phpt b/php/tests/073.phpt new file mode 100644 index 00000000..d3a76379 --- /dev/null +++ b/php/tests/073.phpt @@ -0,0 +1,346 @@ +--TEST-- +Check for class unpacker +--SKIPIF-- += 0) { + echo "skip tests in PHP 5.3.2 and lower"; +} +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/073b.phpt b/php/tests/073b.phpt new file mode 100644 index 00000000..131a5346 --- /dev/null +++ b/php/tests/073b.phpt @@ -0,0 +1,340 @@ +--TEST-- +Check for class unpacker +--SKIPIF-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), false); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), false); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), false); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + &array(1) { + [0]=> + string(3) "foo" + } + [1]=> + &array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + &array(1) { + [0]=> + &array(1) { + [0]=> + *RECURSION* + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) +} +OK +array(2) { + [0]=> + object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + object(Obj)#%d (3) { + ["a"]=> + int(4) + [%r"?b"?:protected"?%r]=> + int(5) + [%r"?c"?:("Obj":)?private"?%r]=> + int(6) + } +} +OK +array(2) { + [0]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } + [1]=> + &object(Obj)#%d (3) { + ["a"]=> + int(1) + [%r"?b"?:protected"?%r]=> + int(2) + [%r"?c"?:("Obj":)?private"?%r]=> + int(3) + } +} +OK diff --git a/php/tests/080.phpt b/php/tests/080.phpt new file mode 100644 index 00000000..aba1cb63 --- /dev/null +++ b/php/tests/080.phpt @@ -0,0 +1,301 @@ +--TEST-- +disabled php only (ini_set) +--SKIPIF-- +--FILE-- + 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/081.phpt b/php/tests/081.phpt new file mode 100644 index 00000000..d22daaa0 --- /dev/null +++ b/php/tests/081.phpt @@ -0,0 +1,303 @@ +--TEST-- +disabled php only for class methods (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/082.phpt b/php/tests/082.phpt new file mode 100644 index 00000000..45a9d938 --- /dev/null +++ b/php/tests/082.phpt @@ -0,0 +1,346 @@ +--TEST-- +disabled php only for class methods unpacker (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/083.phpt b/php/tests/083.phpt new file mode 100644 index 00000000..203d8299 --- /dev/null +++ b/php/tests/083.phpt @@ -0,0 +1,347 @@ +--TEST-- +disabled php only for class unpacker (ini_set) +--SKIPIF-- +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/084.phpt b/php/tests/084.phpt new file mode 100644 index 00000000..74d061b5 --- /dev/null +++ b/php/tests/084.phpt @@ -0,0 +1,301 @@ +--TEST-- +disabled php only for class methods (constract) +--SKIPIF-- +--FILE-- +pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/085.phpt b/php/tests/085.phpt new file mode 100644 index 00000000..72aacc8b --- /dev/null +++ b/php/tests/085.phpt @@ -0,0 +1,344 @@ +--TEST-- +disabled php only for class methods unpacker (constract) +--SKIPIF-- +--FILE-- +pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/086.phpt b/php/tests/086.phpt new file mode 100644 index 00000000..aeaa3328 --- /dev/null +++ b/php/tests/086.phpt @@ -0,0 +1,345 @@ +--TEST-- +disabled php only for class unpacker (constract) +--SKIPIF-- +--FILE-- +pack($variable); + + $unpacker = new MessagePackUnpacker(false); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/087.phpt b/php/tests/087.phpt new file mode 100644 index 00000000..9bb4e49a --- /dev/null +++ b/php/tests/087.phpt @@ -0,0 +1,302 @@ +--TEST-- +disabled php only for class methods (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + $unserialized = $msgpack->unpack($serialized); + + var_dump($unserialized); + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/088.phpt b/php/tests/088.phpt new file mode 100644 index 00000000..7cbabb91 --- /dev/null +++ b/php/tests/088.phpt @@ -0,0 +1,345 @@ +--TEST-- +disabled php only for class methods unpacker (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + $unpacker = $msgpack->unpacker(); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK diff --git a/php/tests/089.phpt b/php/tests/089.phpt new file mode 100644 index 00000000..f3a05378 --- /dev/null +++ b/php/tests/089.phpt @@ -0,0 +1,347 @@ +--TEST-- +disabled php only for class unpacker (set option) +--SKIPIF-- +--FILE-- +setOption(MessagePack::OPT_PHPONLY, false); + + $serialized = $msgpack->pack($variable); + + $unpacker = new MessagePackUnpacker(); + $unpacker->setOption(MessagePack::OPT_PHPONLY, false); + + $length = strlen($serialized); + + if (rand(0, 1)) + { + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str = substr($serialized, $i, $len); + + $unpacker->feed($str); + if ($unpacker->execute()) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + $unpacker->reset(); + } + + $i += $len; + } + } + else + { + $str = ""; + $offset = 0; + + for ($i = 0; $i < $length;) + { + $len = rand(1, 10); + $str .= substr($serialized, $i, $len); + + if ($unpacker->execute($str, $offset)) + { + $unserialized = $unpacker->data(); + var_dump($unserialized); + + $unpacker->reset(); + $str = ""; + $offset = 0; + } + + $i += $len; + } + } + + if (!is_bool($test)) + { + echo $unserialized === $variable ? 'OK' : 'ERROR', PHP_EOL; + } + else + { + echo $test || $unserialized == $variable ? 'OK' : 'ERROR', PHP_EOL; + } +} + +test('null', null); + +test('boo:l true', true); +test('bool: true', false); + +test('zero: 0', 0); +test('small: 1', 1); +test('small: -1', -1); +test('medium: 1000', 1000); +test('medium: -1000', -1000); +test('large: 100000', 100000); +test('large: -100000', -100000); + +test('double: 123.456', 123.456); + +test('empty: ""', ""); +test('string: "foobar"', "foobar"); + +test('empty: array', array(), false); +test('empty: array(1, 2, 3)', array(1, 2, 3), false); +test('empty: array(array(1, 2, 3), arr...', array(array(1, 2, 3), array(4, 5, 6), array(7, 8, 9)), false); + +test('array("foo", "foo", "foo")', array("foo", "foo", "foo"), false); +test('array("one" => 1, "two" => 2))', array("one" => 1, "two" => 2), false); +test('array("kek" => "lol", "lol" => "kek")', array("kek" => "lol", "lol" => "kek"), false); +test('array("" => "empty")', array("" => "empty"), false); + +$a = array('foo'); +test('array($a, $a)', array($a, $a), false); +test('array(&$a, &$a)', array(&$a, &$a), false); + +$a = array(null); +$b = array(&$a); +$a[0] = &$b; + +test('cyclic', $a, true); + +$a = array( + 'a' => array( + 'b' => 'c', + 'd' => 'e' + ), + 'f' => array( + 'g' => 'h' + ) + ); + +test('array', $a, false); + +class Obj { + public $a; + protected $b; + private $c; + + function __construct($a, $b, $c) { + $this->a = $a; + $this->b = $b; + $this->c = $c; + } +} + +test('object', new Obj(1, 2, 3), true); + +test('object', array(new Obj(1, 2, 3), new Obj(4, 5, 6)), true); + +$o = new Obj(1, 2, 3); + +test('object', array(&$o, &$o), true); +--EXPECTF-- +NULL +OK +bool(true) +OK +bool(false) +OK +int(0) +OK +int(1) +OK +int(-1) +OK +int(1000) +OK +int(-1000) +OK +int(100000) +OK +int(-100000) +OK +float(123.456) +OK +string(0) "" +OK +string(6) "foobar" +OK +array(0) { +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(3) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } + [2]=> + array(3) { + [0]=> + int(7) + [1]=> + int(8) + [2]=> + int(9) + } +} +OK +array(3) { + [0]=> + string(3) "foo" + [1]=> + string(3) "foo" + [2]=> + string(3) "foo" +} +OK +array(2) { + ["one"]=> + int(1) + ["two"]=> + int(2) +} +OK +array(2) { + ["kek"]=> + string(3) "lol" + ["lol"]=> + string(3) "kek" +} +OK +array(1) { + [""]=> + string(5) "empty" +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(2) { + [0]=> + array(1) { + [0]=> + string(3) "foo" + } + [1]=> + array(1) { + [0]=> + string(3) "foo" + } +} +OK +array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + array(1) { + [0]=> + NULL + } + } + } + } +} +OK +array(2) { + ["a"]=> + array(2) { + ["b"]=> + string(1) "c" + ["d"]=> + string(1) "e" + } + ["f"]=> + array(1) { + ["g"]=> + string(1) "h" + } +} +OK +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) + } +} +OK +array(2) { + [0]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } + [1]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} +OK