Skip to content

Commit 3dc33ac

Browse files
committed
PHPC-779: Switch Decimal128 from O to C type serialization
1 parent 3cc2e10 commit 3dc33ac

File tree

4 files changed

+110
-7
lines changed

4 files changed

+110
-7
lines changed

src/BSON/Decimal128.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@
3434
#include <ext/standard/info.h>
3535
#include <Zend/zend_interfaces.h>
3636
#include <ext/spl/spl_iterators.h>
37+
#include <ext/standard/php_var.h>
38+
#if PHP_VERSION_ID >= 70000
39+
# include <zend_smart_str.h>
40+
#else
41+
# include <ext/standard/php_smart_str.h>
42+
#endif
3743
/* Our Compatability header */
3844
#include "phongo_compat.h"
3945

@@ -163,6 +169,96 @@ PHP_METHOD(Decimal128, __wakeup)
163169
}
164170
/* }}} */
165171

172+
/* {{{ proto string Decimal128::serialize()
173+
*/
174+
PHP_METHOD(Decimal128, serialize)
175+
{
176+
php_phongo_decimal128_t *intern;
177+
#if PHP_VERSION_ID >= 70000
178+
zval retval;
179+
#else
180+
zval *retval;
181+
#endif
182+
php_serialize_data_t var_hash;
183+
smart_str buf = { 0 };
184+
char outbuf[BSON_DECIMAL128_STRING];
185+
186+
intern = Z_DECIMAL128_OBJ_P(getThis());
187+
188+
if (zend_parse_parameters_none() == FAILURE) {
189+
return;
190+
}
191+
192+
bson_decimal128_to_string(&intern->decimal, outbuf);
193+
#if PHP_VERSION_ID >= 70000
194+
array_init_size(&retval, 1);
195+
ADD_ASSOC_STRING(&retval, "dec", outbuf);
196+
#else
197+
ALLOC_INIT_ZVAL(retval);
198+
array_init_size(retval, 1);
199+
ADD_ASSOC_STRING(retval, "dec", outbuf);
200+
#endif
201+
202+
PHP_VAR_SERIALIZE_INIT(var_hash);
203+
php_var_serialize(&buf, &retval, &var_hash TSRMLS_CC);
204+
smart_str_0(&buf);
205+
PHP_VAR_SERIALIZE_DESTROY(var_hash);
206+
207+
PHONGO_RETVAL_SMART_STR(buf);
208+
209+
smart_str_free(&buf);
210+
zval_ptr_dtor(&retval);
211+
}
212+
/* }}} */
213+
214+
/* {{{ proto string Decimal128::unserialize(string $serialized)
215+
*/
216+
PHP_METHOD(Decimal128, unserialize)
217+
{
218+
php_phongo_decimal128_t *intern;
219+
zend_error_handling error_handling;
220+
char *serialized;
221+
phongo_zpp_char_len serialized_len;
222+
#if PHP_VERSION_ID >= 70000
223+
zval props;
224+
#else
225+
zval *props;
226+
#endif
227+
php_unserialize_data_t var_hash;
228+
229+
intern = Z_DECIMAL128_OBJ_P(getThis());
230+
231+
zend_replace_error_handling(EH_THROW, phongo_exception_from_phongo_domain(PHONGO_ERROR_INVALID_ARGUMENT), &error_handling TSRMLS_CC);
232+
233+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &serialized_len) == FAILURE) {
234+
zend_restore_error_handling(&error_handling TSRMLS_CC);
235+
return;
236+
}
237+
zend_restore_error_handling(&error_handling TSRMLS_CC);
238+
239+
#if PHP_VERSION_ID < 70000
240+
ALLOC_INIT_ZVAL(props);
241+
#endif
242+
PHP_VAR_UNSERIALIZE_INIT(var_hash);
243+
if (!php_var_unserialize(&props, (const unsigned char**) &serialized, (unsigned char *) serialized + serialized_len, &var_hash TSRMLS_CC)) {
244+
zval_ptr_dtor(&props);
245+
phongo_throw_exception(PHONGO_ERROR_UNEXPECTED_VALUE TSRMLS_CC, "%s unserialization failed", ZSTR_VAL(php_phongo_decimal128_ce->name));
246+
247+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
248+
return;
249+
}
250+
PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
251+
252+
#if PHP_VERSION_ID >= 70000
253+
php_phongo_decimal128_init_from_hash(intern, HASH_OF(&props) TSRMLS_CC);
254+
#else
255+
php_phongo_decimal128_init_from_hash(intern, HASH_OF(props) TSRMLS_CC);
256+
#endif
257+
zval_ptr_dtor(&props);
258+
}
259+
/* }}} */
260+
261+
166262
/* {{{ BSON\Decimal128 */
167263

168264
ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___construct, 0, 0, 1)
@@ -173,6 +269,10 @@ ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128___set_state, 0, 0, 1)
173269
ZEND_ARG_ARRAY_INFO(0, properties, 0)
174270
ZEND_END_ARG_INFO()
175271

272+
ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_unserialize, 0, 0, 1)
273+
ZEND_ARG_INFO(0, serialized)
274+
ZEND_END_ARG_INFO()
275+
176276
ZEND_BEGIN_ARG_INFO_EX(ai_Decimal128_void, 0, 0, 0)
177277
ZEND_END_ARG_INFO()
178278

@@ -181,6 +281,8 @@ static zend_function_entry php_phongo_decimal128_me[] = {
181281
PHP_ME(Decimal128, __set_state, ai_Decimal128___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
182282
PHP_ME(Decimal128, __toString, ai_Decimal128_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
183283
PHP_ME(Decimal128, __wakeup, ai_Decimal128_void, ZEND_ACC_PUBLIC)
284+
PHP_ME(Decimal128, serialize, ai_Decimal128_void, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
285+
PHP_ME(Decimal128, unserialize, ai_Decimal128_unserialize, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
184286
PHP_FE_END
185287
};
186288

@@ -271,6 +373,7 @@ PHP_MINIT_FUNCTION(Decimal128)
271373
PHONGO_CE_FINAL(php_phongo_decimal128_ce);
272374

273375
zend_class_implements(php_phongo_decimal128_ce TSRMLS_CC, 1, php_phongo_type_ce);
376+
zend_class_implements(php_phongo_decimal128_ce TSRMLS_CC, 1, zend_ce_serializable);
274377

275378
memcpy(&php_phongo_handler_decimal128, phongo_get_std_object_handlers(), sizeof(zend_object_handlers));
276379
php_phongo_handler_decimal128.get_properties = php_phongo_decimal128_get_properties;

tests/bson/bson-decimal128-serialization-001.phpt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ object(MongoDB\BSON\Decimal128)#%d (%d) {
2828
["dec"]=>
2929
string(9) "1234.5678"
3030
}
31-
string(61) "O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:9:"1234.5678";}"
31+
string(68) "C:23:"MongoDB\BSON\Decimal128":32:{a:1:{s:3:"dec";s:9:"1234.5678";}}"
3232
object(MongoDB\BSON\Decimal128)#%d (%d) {
3333
["dec"]=>
3434
string(9) "1234.5678"
@@ -38,7 +38,7 @@ object(MongoDB\BSON\Decimal128)#%d (%d) {
3838
["dec"]=>
3939
string(10) "-1234.5678"
4040
}
41-
string(63) "O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:10:"-1234.5678";}"
41+
string(70) "C:23:"MongoDB\BSON\Decimal128":34:{a:1:{s:3:"dec";s:10:"-1234.5678";}}"
4242
object(MongoDB\BSON\Decimal128)#%d (%d) {
4343
["dec"]=>
4444
string(10) "-1234.5678"
@@ -48,7 +48,7 @@ object(MongoDB\BSON\Decimal128)#%d (%d) {
4848
["dec"]=>
4949
string(11) "1.23456E-75"
5050
}
51-
string(64) "O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:11:"1.23456E-75";}"
51+
string(71) "C:23:"MongoDB\BSON\Decimal128":35:{a:1:{s:3:"dec";s:11:"1.23456E-75";}}"
5252
object(MongoDB\BSON\Decimal128)#%d (%d) {
5353
["dec"]=>
5454
string(11) "1.23456E-75"
@@ -58,7 +58,7 @@ object(MongoDB\BSON\Decimal128)#%d (%d) {
5858
["dec"]=>
5959
string(8) "Infinity"
6060
}
61-
string(60) "O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:8:"Infinity";}"
61+
string(67) "C:23:"MongoDB\BSON\Decimal128":31:{a:1:{s:3:"dec";s:8:"Infinity";}}"
6262
object(MongoDB\BSON\Decimal128)#%d (%d) {
6363
["dec"]=>
6464
string(8) "Infinity"
@@ -68,7 +68,7 @@ object(MongoDB\BSON\Decimal128)#%d (%d) {
6868
["dec"]=>
6969
string(3) "NaN"
7070
}
71-
string(55) "O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:3:"NaN";}"
71+
string(62) "C:23:"MongoDB\BSON\Decimal128":26:{a:1:{s:3:"dec";s:3:"NaN";}}"
7272
object(MongoDB\BSON\Decimal128)#%d (%d) {
7373
["dec"]=>
7474
string(3) "NaN"

tests/bson/bson-decimal128-serialization_error-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ MongoDB\BSON\Decimal128 unserialization requires "dec" string field
88
require_once __DIR__ . '/../utils/tools.php';
99

1010
echo throws(function() {
11-
unserialize('O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";i:0;}');
11+
unserialize('C:23:"MongoDB\BSON\Decimal128":20:{a:1:{s:3:"dec";i:0;}}');
1212
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1313

1414
?>

tests/bson/bson-decimal128-serialization_error-002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ MongoDB\BSON\Decimal128 unserialization requires valid decimal string
88
require_once __DIR__ . '/../utils/tools.php';
99

1010
echo throws(function() {
11-
unserialize('O:23:"MongoDB\BSON\Decimal128":1:{s:3:"dec";s:7:"INVALID";}');
11+
unserialize('C:23:"MongoDB\BSON\Decimal128":30:{a:1:{s:3:"dec";s:7:"INVALID";}}');
1212
}, 'MongoDB\Driver\Exception\InvalidArgumentException'), "\n";
1313

1414
?>

0 commit comments

Comments
 (0)