Skip to content

BSON serialization spec compliance #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 29, 2015
Merged
6 changes: 6 additions & 0 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ if test "$MONGODB" != "no"; then
PHP_CHECK_GCC_ARG(-Wdeclaration-after-statement, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wdeclaration-after-statement")
dnl PHP_CHECK_GCC_ARG(-Werror, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Werror")

PHP_MONGODB_FOUND_VERSION=`${PHP_CONFIG} --version`
PHP_MONGODB_FOUND_VERNUM=`echo "${PHP_MONGODB_FOUND_VERSION}" | $AWK 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 100 + [$]2) * 100 + [$]3;}'`

if test "$PHP_MONGODB_FOUND_VERNUM" -ge "50400"; then
PHP_CHECK_GCC_ARG(-Wno-cast-qual, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wno-cast-qual")
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't do this. Instead, fix the consts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for 5.3?

5.4+ rightfully lists the args as const char *, so there's no need there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this.
Just for reference, which exact case prompted this change?
Isn't it also valid for the arginfos?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arginfos appear to be declared as static const in PHP 5.3. I only saw these warnings with zend_parse_parameters() and possibly one other macro (not arginfo).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, here are a few of these errors from 5.3:

/home/jmikola/workspace/mongodb/phpc/src/bson.c: In function ‘zif_fromPHP’:
/home/jmikola/workspace/mongodb/phpc/src/bson.c:967:55: warning: passing argument 3 of ‘zend_parse_parameters’ discards ‘const’ qualifier from pointer target type
  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "A", &data) == FAILURE) {
                                                       ^
In file included from /home/jmikola/bin/php-bin/php-5.3/include/php/main/php.h:38:0,
                 from /home/jmikola/workspace/mongodb/phpc/src/bson.c:29:
/home/jmikola/bin/php-bin/php-5.3/include/php/Zend/zend_API.h:245:14: note: expected ‘char *’ but argument is of type ‘const char *’
 ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
              ^
/home/jmikola/workspace/mongodb/phpc/src/bson.c:974:1: warning: passing argument 3 of ‘_estrndup’ discards ‘const’ qualifier from pointer target type
  RETVAL_STRINGL((const char *) bson_get_data(bson), bson->len, 1);
 ^

A full log of the stderr output from a 5.3 build is here: https://gist.github.com/jmikola/e3a3f7da387333187864

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't care any more, as we can drop 5.3 :-D


MAINTAINER_CFLAGS="-Wextra $_MAINTAINER_CFLAGS -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-missing-field-initializers"
STD_CFLAGS="-g -O0 -Wall"
Expand Down
6 changes: 6 additions & 0 deletions phongo_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
zend_hash_copy(*_std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
#endif

#if PHP_VERSION_ID < 50400
# define str_efree(s) efree((char*)s)
#else
# include <Zend/zend_string.h>
#endif

#if PHP_VERSION_ID >= 50500
#define ITERATOR_GET_CURRENT_KEY(it, z) \
(it).funcs->get_current_key(&(it), z TSRMLS_CC);
Expand Down
22 changes: 21 additions & 1 deletion src/BSON/Binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

PHONGO_API zend_class_entry *php_phongo_binary_ce;

zend_object_handlers php_phongo_handler_binary;

/* {{{ proto BSON\Binary Binary::__construct(string $data, int $subtype)
Construct a new BSON Binary type */
PHP_METHOD(Binary, __construct)
Expand Down Expand Up @@ -152,10 +154,25 @@ zend_object_value php_phongo_binary_create_object(zend_class_entry *class_type T
object_properties_init(&intern->std, class_type);

retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, php_phongo_binary_free_object, NULL TSRMLS_CC);
retval.handlers = phongo_get_std_object_handlers();
retval.handlers = &php_phongo_handler_binary;

return retval;
} /* }}} */

HashTable *php_phongo_binary_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
{
php_phongo_binary_t *intern;
zval retval = zval_used_for_init;

intern = (php_phongo_binary_t *)zend_object_store_get_object(object TSRMLS_CC);
*is_temp = 1;
array_init_size(&retval, 2);

add_assoc_stringl_ex(&retval, ZEND_STRS("data"), intern->data, intern->data_len, 1);
add_assoc_long_ex(&retval, ZEND_STRS("subtype"), intern->subtype);

return Z_ARRVAL(retval);
} /* }}} */
/* }}} */

/* {{{ PHP_MINIT_FUNCTION */
Expand All @@ -170,6 +187,9 @@ PHP_MINIT_FUNCTION(Binary)

zend_class_implements(php_phongo_binary_ce TSRMLS_CC, 1, php_phongo_type_ce);

memcpy(&php_phongo_handler_binary, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
php_phongo_handler_binary.get_debug_info = php_phongo_binary_get_debug_info;

zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_GENERIC"), BSON_SUBTYPE_BINARY TSRMLS_CC);
zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_FUNCTION"), BSON_SUBTYPE_FUNCTION TSRMLS_CC);
zend_declare_class_constant_long(php_phongo_binary_ce, ZEND_STRL("TYPE_OLD_BINARY"), BSON_SUBTYPE_BINARY_DEPRECATED TSRMLS_CC);
Expand Down
206 changes: 103 additions & 103 deletions src/bson.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@

#define PHONGO_ODM_FIELD_NAME "__pclass"

#define PHONGO_IS_CLASS_INSTANTIATABLE(ce) \
(!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)))

PHP_MINIT_FUNCTION(bson)
{
(void)type; /* We don't care if we are loaded via dl() or extension= */
Expand Down Expand Up @@ -211,8 +214,12 @@ bool php_phongo_bson_visit_binary(const bson_iter_t *iter ARG_UNUSED, const char
zval *zchild = NULL;
TSRMLS_FETCH();

if (v_subtype == 0x80 && strcmp(key, PHONGO_ODM_FIELD_NAME) ==0) {
((php_phongo_bson_state *)data)->odm = zend_fetch_class((char *)v_binary, v_binary_len, ZEND_FETCH_CLASS_AUTO|ZEND_FETCH_CLASS_SILENT TSRMLS_CC);
if (v_subtype == 0x80 && strcmp(key, PHONGO_ODM_FIELD_NAME) == 0) {
zend_class_entry *found_ce = zend_fetch_class((char *)v_binary, v_binary_len, ZEND_FETCH_CLASS_AUTO|ZEND_FETCH_CLASS_SILENT TSRMLS_CC);

if (found_ce && PHONGO_IS_CLASS_INSTANTIATABLE(found_ce) && instanceof_function(found_ce, php_phongo_persistable_ce TSRMLS_CC)) {
((php_phongo_bson_state *)data)->odm = found_ce;
}
}

MAKE_STD_ZVAL(zchild);
Expand Down Expand Up @@ -463,26 +470,28 @@ bool php_phongo_bson_visit_document(const bson_iter_t *iter ARG_UNUSED, const ch
array_init(state.zchild);

if (!bson_iter_visit_all(&child, &php_bson_visitors, &state)) {
if (state.odm) {
/* If php_phongo_bson_visit_binary() finds an ODM class, it should
* supersede a default type map and named document class. */
if (state.odm && state.map.document_type == PHONGO_TYPEMAP_NONE) {
state.map.document_type = PHONGO_TYPEMAP_CLASS;
}

switch(state.map.document_type) {
case PHONGO_TYPEMAP_NATIVE_ARRAY:
add_assoc_zval(retval, key, state.zchild);
Z_SET_REFCOUNT_P(state.zchild, 1);
break;

case PHONGO_TYPEMAP_CLASS:
if (instanceof_function(state.odm ? state.odm : state.map.document, php_phongo_unserializable_ce TSRMLS_CC)) {
zval *obj = NULL;
case PHONGO_TYPEMAP_CLASS: {
zval *obj = NULL;

MAKE_STD_ZVAL(obj);
object_init_ex(obj, state.odm ? state.odm : state.map.document);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state.zchild);
add_assoc_zval(retval, key, obj);
zval_ptr_dtor(&state.zchild);
break;
}
MAKE_STD_ZVAL(obj);
object_init_ex(obj, state.odm ? state.odm : state.map.document);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state.zchild);
add_assoc_zval(retval, key, obj);
zval_ptr_dtor(&state.zchild);
break;
}

case PHONGO_TYPEMAP_NATIVE_OBJECT:
default:
Expand Down Expand Up @@ -514,23 +523,17 @@ bool php_phongo_bson_visit_array(const bson_iter_t *iter ARG_UNUSED, const char
if (!bson_iter_visit_all(&child, &php_bson_visitors, &state)) {

switch(state.map.array_type) {
case PHONGO_TYPEMAP_CLASS:
if (instanceof_function(state.map.array, php_phongo_unserializable_ce TSRMLS_CC)) {
zval *obj = NULL;

MAKE_STD_ZVAL(obj);
object_init_ex(obj, state.map.array);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state.zchild);
add_assoc_zval(retval, key, obj);
zval_ptr_dtor(&state.zchild);
break;
}
/* If the object someehow doesn't implement php_phongo_unserializable_ce then use stdclass.
* This is needed as we need to know how to pass the state.zchild to the class to populate it.
* Not all classes have ctor that accepts first parameter array of values.
*/
case PHONGO_TYPEMAP_CLASS: {
zval *obj = NULL;

MAKE_STD_ZVAL(obj);
object_init_ex(obj, state.map.array);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state.zchild);
add_assoc_zval(retval, key, obj);
zval_ptr_dtor(&state.zchild);
break;
}

/* break intentionally omitted */
case PHONGO_TYPEMAP_NATIVE_OBJECT:
object_and_properties_init(state.zchild, zend_standard_class_def, Z_ARRVAL_P(state.zchild));
add_assoc_zval(retval, key, state.zchild);
Expand Down Expand Up @@ -617,8 +620,8 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
return;
}

if (Z_TYPE_P(obj_data) != IS_ARRAY) {
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Expected %s() to return an array, %s given", BSON_SERIALIZE_FUNC_NAME, zend_get_type_by_const(Z_TYPE_P(obj_data)));
if (Z_TYPE_P(obj_data) != IS_ARRAY && !(Z_TYPE_P(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(obj_data), zend_standard_class_def TSRMLS_CC))) {
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Expected %s::%s() to return an array or stdClass, %s given", Z_OBJCE_P(object)->name, BSON_SERIALIZE_FUNC_NAME, (Z_TYPE_P(obj_data) == IS_OBJECT ? Z_OBJCE_P(obj_data)->name : zend_get_type_by_const(Z_TYPE_P(obj_data))));
zval_ptr_dtor(&obj_data);

return;
Expand All @@ -630,14 +633,22 @@ void object_to_bson(zval *object, php_phongo_bson_flags_t flags, const char *key
tmp_ht->nApplyCount++;
}

bson_append_document_begin(bson, key, key_len, &child);
if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce TSRMLS_CC)) {
if (flags & PHONGO_BSON_ADD_CHILD_ODS) {
bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(object)->name, strlen(Z_OBJCE_P(object)->name));
/* Persistable objects must always be serialized as BSON documents;
* otherwise, infer based on bsonSerialize()'s return value. */
if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce TSRMLS_CC) || php_phongo_is_array_or_document(&obj_data TSRMLS_CC) == IS_OBJECT) {
bson_append_document_begin(bson, key, key_len, &child);
if (instanceof_function(Z_OBJCE_P(object), php_phongo_persistable_ce TSRMLS_CC)) {
if (flags & PHONGO_BSON_ADD_CHILD_ODS) {
bson_append_binary(&child, PHONGO_ODM_FIELD_NAME, -1, 0x80, (const uint8_t *)Z_OBJCE_P(object)->name, strlen(Z_OBJCE_P(object)->name));
}
}
zval_to_bson(obj_data, flags, &child, NULL TSRMLS_CC);
bson_append_document_end(bson, &child);
} else {
bson_append_array_begin(bson, key, key_len, &child);
zval_to_bson(obj_data, flags, &child, NULL TSRMLS_CC);
bson_append_array_end(bson, &child);
}
zval_to_bson(obj_data, flags, &child, NULL TSRMLS_CC);
bson_append_document_end(bson, &child);

if (tmp_ht) {
tmp_ht->nApplyCount--;
Expand Down Expand Up @@ -779,8 +790,8 @@ PHONGO_API void zval_to_bson(zval *data, php_phongo_bson_flags_t flags, bson_t *
break;
}

if (Z_TYPE_P(obj_data) != IS_ARRAY) {
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Expected %s() to return an array, %s given", BSON_SERIALIZE_FUNC_NAME, zend_get_type_by_const(Z_TYPE_P(obj_data)));
if (Z_TYPE_P(obj_data) != IS_ARRAY && !(Z_TYPE_P(obj_data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(obj_data), zend_standard_class_def TSRMLS_CC))) {
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "Expected %s::%s() to return an array or stdClass, %s given", Z_OBJCE_P(data)->name, BSON_SERIALIZE_FUNC_NAME, (Z_TYPE_P(obj_data) == IS_OBJECT ? Z_OBJCE_P(obj_data)->name : zend_get_type_by_const(Z_TYPE_P(obj_data))));

break;
}
Expand Down Expand Up @@ -902,9 +913,9 @@ int bson_to_zval(const unsigned char *data, int data_len, php_phongo_bson_state
array_init(state->zchild);
bson_iter_visit_all(&iter, &php_bson_visitors, state);

/* If php_phongo_bson_visit_binary() finds an ODM class, it supersedes our
* document type. */
if (state->odm) {
/* If php_phongo_bson_visit_binary() finds an ODM class, it should supersede
* a default type map and named root class. */
if (state->odm && state->map.root_type == PHONGO_TYPEMAP_NONE) {
state->map.root_type = PHONGO_TYPEMAP_CLASS;
}

Expand All @@ -913,19 +924,16 @@ int bson_to_zval(const unsigned char *data, int data_len, php_phongo_bson_state
/* Nothing to do here */
break;

case PHONGO_TYPEMAP_CLASS:
/* If the class implements Unserializable, initialize the object
* from our array data; otherwise, fall through to native object. */
if (instanceof_function(state->odm ? state->odm : state->map.root, php_phongo_unserializable_ce TSRMLS_CC)) {
zval *obj = NULL;

MAKE_STD_ZVAL(obj);
object_init_ex(obj, state->odm ? state->odm : state->map.root);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state->zchild);
zval_ptr_dtor(&state->zchild);
state->zchild = obj;
break;
}
case PHONGO_TYPEMAP_CLASS: {
zval *obj = NULL;

MAKE_STD_ZVAL(obj);
object_init_ex(obj, state->odm ? state->odm : state->map.root);
zend_call_method_with_1_params(&obj, NULL, NULL, BSON_UNSERIALIZE_FUNC_NAME, NULL, state->zchild);
zval_ptr_dtor(&state->zchild);
state->zchild = obj;
break;
}

case PHONGO_TYPEMAP_NATIVE_OBJECT:
default:
Expand Down Expand Up @@ -964,71 +972,63 @@ PHP_FUNCTION(fromPHP)
}
/* }}} */

static void apply_classname_to_state(const char *classname, int classname_len, php_phongo_bson_typemap_types *type, zend_class_entry **type_ce TSRMLS_DC)
{
if (!strcasecmp(classname, "array")) {
*type = PHONGO_TYPEMAP_NATIVE_ARRAY;
*type_ce = NULL;
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
*type = PHONGO_TYPEMAP_NATIVE_OBJECT;
*type_ce = NULL;
} else {
zend_class_entry *found_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO|ZEND_FETCH_CLASS_SILENT TSRMLS_CC);

if (!found_ce) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Class %s does not exist", classname);
} else if (!PHONGO_IS_CLASS_INSTANTIATABLE(found_ce)) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Class %s is not instantiatable", classname);
} else if (!instanceof_function(found_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
phongo_throw_exception(PHONGO_ERROR_INVALID_ARGUMENT TSRMLS_CC, "Class %s does not implement %s\\Unserializable", classname, BSON_NAMESPACE);
} else {
*type = PHONGO_TYPEMAP_CLASS;
*type_ce = found_ce;
}
}
}

void php_phongo_bson_typemap_to_state(zval *typemap, php_phongo_bson_typemap *map TSRMLS_DC)
{
if (typemap) {
char *classname;
int classname_len;
zend_bool classname_free = 0;
char *classname;
int classname_len;
zend_bool classname_free = 0;

classname = php_array_fetchl_string(typemap, "array", sizeof("array")-1, &classname_len, &classname_free);
if (classname_len) {
if (!strcasecmp(classname, "array")) {
map->array_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
map->array_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
} else {
zend_class_entry *array_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
map->array_type = PHONGO_TYPEMAP_CLASS;

if (instanceof_function(array_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
map->array = array_ce;
}
}
if (classname_free) {
efree(classname);
}
apply_classname_to_state(classname, classname_len, &map->array_type, &map->array TSRMLS_CC);
}
if (classname_free) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could classname_free be set if classname_len is 0?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on char *php_array_zval_to_string(zval *z, int *plen, zend_bool *pfree) in php_array_api.h, pfree is only set to zero if zval *z is NULL or a string, in which case its direct value is returned. I believe I encountered a memory leak in the test where I passed in null to each type map key. This uses STR_EMPTY_ALLOC(), which might return an interned or allocated, empty string (which is why I started using str_efree() on it, since efree() isn't aware of interned strings).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If classname_len is 0, then there isn't anything to free, so classname_free can hardly be set?
Shouldn't this then be moved inside the if (classname_len) ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, an empty string could still be allocated as a single null byte and classname_len would be zero. I think it's quite independent from classname_len.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

str_efree(classname);
}

classname = php_array_fetchl_string(typemap, "document", sizeof("document")-1, &classname_len, &classname_free);
if (classname_len) {
if (!strcasecmp(classname, "array")) {
map->document_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
map->document_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
} else {
zend_class_entry *document_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
map->document_type = PHONGO_TYPEMAP_CLASS;

if (instanceof_function(document_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
map->document = document_ce;
}
}
if (classname_free) {
efree(classname);
}
apply_classname_to_state(classname, classname_len, &map->document_type, &map->document TSRMLS_CC);
}
if (classname_free) {
str_efree(classname);
}

classname = php_array_fetchl_string(typemap, "root", sizeof("root")-1, &classname_len, &classname_free);
if (classname_len) {
if (!strcasecmp(classname, "array")) {
map->root_type = PHONGO_TYPEMAP_NATIVE_ARRAY;
} else if (!strcasecmp(classname, "stdclass") || !strcasecmp(classname, "object")) {
map->root_type = PHONGO_TYPEMAP_NATIVE_OBJECT;
} else {
zend_class_entry *root_ce = zend_fetch_class(classname, classname_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
map->root_type = PHONGO_TYPEMAP_CLASS;

if (instanceof_function(root_ce, php_phongo_unserializable_ce TSRMLS_CC)) {
map->root = root_ce;
}
}
if (classname_free) {
efree(classname);
}
apply_classname_to_state(classname, classname_len, &map->root_type, &map->root TSRMLS_CC);
}
if (classname_free) {
str_efree(classname);
}
}
}

/* {{{ proto array|object BSON\toPHP(string $bson [, array $typemap = array()])
Returns the PHP representation of a BSON value, optionally converting it into a custom class */
PHP_FUNCTION(toPHP)
Expand Down
6 changes: 3 additions & 3 deletions tests/bson/bson-encode-002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ $bson = fromPHP(array('embed' => new NumericArray));
echo toJSON($bson), "\n";
echo "Encoded BSON:\n";
hex_dump($bson);
$value = toPHP($bson, array("document" => 'NumericArray'));
$value = toPHP($bson, array("array" => 'NumericArray'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this change the meaning of the test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original test was written before allowing Serializables to encode as a BSON array. The original intention of this test is just to round-trip the data from NumericArray to BSON and back to NumericArray. Since the value does get stored as a BSON array, the type map needed an update.

echo "Decoded BSON:\n";
var_dump($value);

Expand Down Expand Up @@ -131,9 +131,9 @@ object(NumericArray)#%d (0) {
}

Testing embedded NumericArray:
{ "embed" : { "0" : 1, "1" : 2, "2" : 3 } }
{ "embed" : [ 1, 2, 3 ] }
Encoded BSON:
0 : 26 00 00 00 03 65 6d 62 65 64 00 1a 00 00 00 10 [&....embed......]
0 : 26 00 00 00 04 65 6d 62 65 64 00 1a 00 00 00 10 [&....embed......]
10 : 30 00 01 00 00 00 10 31 00 02 00 00 00 10 32 00 [0......1......2.]
20 : 03 00 00 00 00 00 [......]
NumericArray::bsonUnserialize() was called with data:
Expand Down
Loading