diff --git a/msgpack.c b/msgpack.c
index 6b92437..974d14f 100644
--- a/msgpack.c
+++ b/msgpack.c
@@ -42,6 +42,9 @@ STD_PHP_INI_BOOLEAN(
STD_PHP_INI_BOOLEAN(
"msgpack.php_only", "1", PHP_INI_ALL, OnUpdateBool,
php_only, zend_msgpack_globals, msgpack_globals)
+STD_PHP_INI_BOOLEAN(
+ "msgpack.assoc", "1", PHP_INI_ALL, OnUpdateBool,
+ assoc, zend_msgpack_globals, msgpack_globals)
STD_PHP_INI_BOOLEAN(
"msgpack.illegal_key_insert", "0", PHP_INI_ALL, OnUpdateBool,
illegal_key_insert, zend_msgpack_globals, msgpack_globals)
@@ -71,6 +74,7 @@ static void msgpack_init_globals(zend_msgpack_globals *msgpack_globals) /* {{{ *
}
msgpack_globals->php_only = 1;
+ msgpack_globals->assoc = 1;
msgpack_globals->illegal_key_insert = 0;
msgpack_globals->use_str8_serialization = 1;
@@ -92,6 +96,8 @@ static ZEND_MINIT_FUNCTION(msgpack) /* {{{ */ {
REGISTER_LONG_CONSTANT("MESSAGEPACK_OPT_PHPONLY",
MSGPACK_CLASS_OPT_PHPONLY, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MESSAGEPACK_OPT_ASSOC",
+ MSGPACK_CLASS_OPT_ASSOC, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
diff --git a/msgpack_class.c b/msgpack_class.c
index 69f3803..c339982 100644
--- a/msgpack_class.c
+++ b/msgpack_class.c
@@ -9,6 +9,7 @@
typedef struct {
long php_only;
+ zend_bool assoc;
zend_object object;
} php_msgpack_base_t;
@@ -18,6 +19,7 @@ typedef struct {
long offset;
msgpack_unpack_t mp;
long php_only;
+ zend_bool assoc;
zend_bool finished;
int error;
zend_object object;
@@ -175,6 +177,7 @@ static void php_msgpack_unpacker_free(zend_object *object) /* {{{ */ {
/* MessagePack */
static ZEND_METHOD(msgpack, __construct) /* {{{ */ {
zend_bool php_only = MSGPACK_G(php_only);
+ zend_bool assoc = MSGPACK_G(assoc);
php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &php_only) == FAILURE) {
@@ -182,6 +185,7 @@ static ZEND_METHOD(msgpack, __construct) /* {{{ */ {
}
base->php_only = php_only;
+ base->assoc = assoc;
}
/* }}} */
@@ -198,6 +202,9 @@ static ZEND_METHOD(msgpack, setOption) /* {{{ */ {
case MSGPACK_CLASS_OPT_PHPONLY:
base->php_only = i_zend_is_true(value);
break;
+ case MSGPACK_CLASS_OPT_ASSOC:
+ base->assoc = i_zend_is_true(value);
+ break;
default:
MSGPACK_WARNING("[msgpack] (MessagePack::setOption) "
"error setting msgpack option");
@@ -213,6 +220,7 @@ static ZEND_METHOD(msgpack, pack) /* {{{ */ {
zval *parameter;
smart_str buf = {0};
int php_only = MSGPACK_G(php_only);
+ zend_bool assoc = MSGPACK_G(assoc);
php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", ¶meter) == FAILURE) {
@@ -220,10 +228,12 @@ static ZEND_METHOD(msgpack, pack) /* {{{ */ {
}
MSGPACK_G(php_only) = base->php_only;
+ MSGPACK_G(assoc) = base->assoc;
php_msgpack_serialize(&buf, parameter);
MSGPACK_G(php_only) = php_only;
+ MSGPACK_G(assoc) = assoc;
if (buf.s) {
smart_str_0(&buf);
ZVAL_STR(return_value, buf.s);
@@ -238,6 +248,7 @@ static ZEND_METHOD(msgpack, unpack) /* {{{ */ {
zend_string *str;
zval *object = NULL;
zend_bool php_only = MSGPACK_G(php_only);
+ zend_bool assoc = MSGPACK_G(assoc);
php_msgpack_base_t *base = Z_MSGPACK_BASE_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &str, &object) == FAILURE) {
@@ -249,6 +260,7 @@ static ZEND_METHOD(msgpack, unpack) /* {{{ */ {
}
MSGPACK_G(php_only) = base->php_only;
+ MSGPACK_G(assoc) = base->assoc;
if (object == NULL) {
php_msgpack_unserialize(return_value, ZSTR_VAL(str), ZSTR_LEN(str));
@@ -263,6 +275,7 @@ static ZEND_METHOD(msgpack, unpack) /* {{{ */ {
}
MSGPACK_G(php_only) = php_only;
+ MSGPACK_G(assoc) = assoc;
}
/* }}} */
@@ -283,6 +296,7 @@ static ZEND_METHOD(msgpack, unpacker) /* {{{ */ {
/* MessagePackUnpacker */
static ZEND_METHOD(msgpack_unpacker, __construct) /* {{{ */ {
zend_bool php_only = MSGPACK_G(php_only);
+ zend_bool assoc = MSGPACK_G(assoc);
php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis());
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &php_only) == FAILURE) {
@@ -290,6 +304,7 @@ static ZEND_METHOD(msgpack_unpacker, __construct) /* {{{ */ {
}
unpacker->php_only = php_only;
+ unpacker->assoc = assoc;
unpacker->buffer.s = NULL;
unpacker->buffer.a = 0;
@@ -322,6 +337,9 @@ static ZEND_METHOD(msgpack_unpacker, setOption) /* {{{ */ {
case MSGPACK_CLASS_OPT_PHPONLY:
unpacker->php_only = i_zend_is_true(value);
break;
+ case MSGPACK_CLASS_OPT_ASSOC:
+ unpacker->assoc = i_zend_is_true(value);
+ break;
default:
MSGPACK_WARNING("[msgpack] (MessagePackUnpacker::setOption) "
"error setting msgpack option");
@@ -356,6 +374,7 @@ static ZEND_METHOD(msgpack_unpacker, execute) /* {{{ */ {
size_t len, off;
zend_string *str = NULL;
int ret, error_display = MSGPACK_G(error_display), php_only = MSGPACK_G(php_only);
+ zend_bool assoc = MSGPACK_G(assoc);
zval *offset = NULL;
php_msgpack_unpacker_t *unpacker = Z_MSGPACK_UNPACKER_P(getThis());
@@ -392,11 +411,13 @@ static ZEND_METHOD(msgpack_unpacker, execute) /* {{{ */ {
MSGPACK_G(error_display) = 0;
MSGPACK_G(php_only) = unpacker->php_only;
+ MSGPACK_G(assoc) = unpacker->assoc;
ret = template_execute(&unpacker->mp, data, len, &off);
MSGPACK_G(error_display) = error_display;
MSGPACK_G(php_only) = php_only;
+ MSGPACK_G(assoc) = assoc;
if (str != NULL) {
if (offset != NULL) {
@@ -490,6 +511,7 @@ void msgpack_init_class() /* {{{ */ {
msgpack_handlers.free_obj = php_msgpack_base_free;
zend_declare_class_constant_long(msgpack_ce, ZEND_STRS("OPT_PHPONLY") - 1, MSGPACK_CLASS_OPT_PHPONLY);
+ zend_declare_class_constant_long(msgpack_ce, ZEND_STRS("OPT_ASSOC") - 1, MSGPACK_CLASS_OPT_ASSOC);
/* unpacker */
INIT_CLASS_ENTRY(ce, "MessagePackUnpacker", msgpack_unpacker_methods);
diff --git a/msgpack_class.h b/msgpack_class.h
index f197523..3dcbf40 100644
--- a/msgpack_class.h
+++ b/msgpack_class.h
@@ -3,6 +3,7 @@
#define MSGPACK_CLASS_H
#define MSGPACK_CLASS_OPT_PHPONLY -1001
+#define MSGPACK_CLASS_OPT_ASSOC -1002
void msgpack_init_class();
diff --git a/msgpack_pack.c b/msgpack_pack.c
index c5da6d9..46ce165 100644
--- a/msgpack_pack.c
+++ b/msgpack_pack.c
@@ -247,7 +247,9 @@ static inline void msgpack_serialize_array(smart_str *buf, zval *val, HashTable
}
if (object) {
- if (MSGPACK_G(php_only)) {
+ if (!MSGPACK_G(assoc) && (!MSGPACK_G(php_only) || !strcmp(class_name, "stdClass"))) {
+ msgpack_pack_map(buf, n);
+ } else if (MSGPACK_G(php_only)) {
if (is_ref) {
msgpack_pack_map(buf, n + 2);
msgpack_pack_nil(buf);
diff --git a/msgpack_unpack.c b/msgpack_unpack.c
index 9ce1961..ffcd568 100644
--- a/msgpack_unpack.c
+++ b/msgpack_unpack.c
@@ -589,7 +589,7 @@ int msgpack_unserialize_map(msgpack_unserialize_data *unpack, unsigned int count
unpack->count = count;
if (count == 0) {
- if (MSGPACK_G(php_only)) {
+ if (MSGPACK_G(php_only) || !MSGPACK_G(assoc)) {
object_init(*obj);
} else {
array_init(*obj);
@@ -708,6 +708,10 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
container_val = Z_ISREF_P(*container) ? Z_REFVAL_P(*container) : *container;
+ if (!MSGPACK_G(assoc) && Z_TYPE_P(container_val) != IS_ARRAY && Z_TYPE_P(container_val) != IS_OBJECT) {
+ object_init(container_val);
+ }
+
if (Z_TYPE_P(container_val) == IS_OBJECT) {
switch (Z_TYPE_P(key)) {
case IS_LONG:
diff --git a/package.xml b/package.xml
index bfb53d7..8aa977b 100644
--- a/package.xml
+++ b/package.xml
@@ -173,6 +173,7 @@
+
diff --git a/php_msgpack.h b/php_msgpack.h
index 6bd4b4a..1574349 100644
--- a/php_msgpack.h
+++ b/php_msgpack.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_bool assoc;
zend_bool illegal_key_insert;
zend_bool use_str8_serialization;
struct {
diff --git a/tests/029.phpt b/tests/029.phpt
index a7e3887..49fa0dd 100644
--- a/tests/029.phpt
+++ b/tests/029.phpt
@@ -48,6 +48,7 @@ extension Version => %s
header Version => %s
Directive => Local Value => Master Value
+msgpack.assoc => %s => %s
msgpack.error_display => %s => %s
msgpack.illegal_key_insert => %s => %s
msgpack.php_only => %s => %s
diff --git a/tests/assoc.phpt b/tests/assoc.phpt
new file mode 100644
index 0000000..9f9047c
--- /dev/null
+++ b/tests/assoc.phpt
@@ -0,0 +1,90 @@
+--TEST--
+Map with assoc option
+--SKIPIF--
+--FILE--
+setOption(MESSAGEPACK_OPT_PHPONLY, $phpOnly);
+ $msgpack->setOption(MESSAGEPACK_OPT_ASSOC, $assoc);
+ } else {
+ $msgpack->setOption(MessagePack::OPT_PHPONLY, $phpOnly);
+ $msgpack->setOption(MessagePack::OPT_ASSOC, $assoc);
+ }
+ if (is_string($data)) {
+ $result = $msgpack->unpack(hex2bin($data));
+ } else {
+ $result = bin2hex($msgpack->pack($data));
+ }
+
+ printf("%s, %d, %d\n", $type, $phpOnly, $assoc);
+ var_dump($result);
+ return $result;
+}
+
+$emptyMapData = '80'; // {}
+test("empty map unpack", $emptyMapData, true, true);
+test("empty map unpack", $emptyMapData, false, true);
+test("empty map unpack", $emptyMapData, false, false);
+
+$mapData = '82a131a142a130a141'; // {"1":"B","0":"A"}
+$map = test("map unpack", $mapData, true, true);
+test("map pack", $map, true, true);
+$map = test("map unpack", $mapData, true, false);
+test("map pack", $map, true, false);
+
+$obj = new MyObj();
+$obj->member = 1;
+test("obj pack", $obj, true, true);
+test("obj pack", $obj, false, true);
+test("obj pack", $obj, true, false);
+test("obj pack", $obj, false, false);
+
+class MyObj
+{
+ public $member;
+}
+
+--EXPECTF--
+empty map unpack, 1, 1
+object(stdClass)#%d (0) {
+}
+empty map unpack, 0, 1
+array(0) {
+}
+empty map unpack, 0, 0
+object(stdClass)#%d (0) {
+}
+map unpack, 1, 1
+array(2) {
+ [1]=>
+ string(1) "B"
+ [0]=>
+ string(1) "A"
+}
+map pack, 1, 1
+string(14) "8201a14200a141"
+map unpack, 1, 0
+object(stdClass)#%d (2) {
+ ["1"]=>
+ string(1) "B"
+ ["0"]=>
+ string(1) "A"
+}
+map pack, 1, 0
+string(18) "82a131a142a130a141"
+obj pack, 1, 1
+string(32) "82c0a54d794f626aa66d656d62657201"
+obj pack, 0, 1
+string(4) "9101"
+obj pack, 1, 0
+string(32) "82c0a54d794f626aa66d656d62657201"
+obj pack, 0, 0
+string(18) "81a66d656d62657201"