static zend_object_handlers gmp_object_handlers;
typedef struct _gmp_object {
- zend_object std;
mpz_t num;
+ zend_object std;
} gmp_object;
typedef struct _gmp_temp {
#define IS_GMP(zval) \
(Z_TYPE_P(zval) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zval), gmp_ce TSRMLS_CC))
+#define GET_GMP_OBJECT_FROM_OBJ(obj) \
+ ((gmp_object *) ((char *) (obj) - XtOffsetOf(gmp_object, std)))
+#define GET_GMP_OBJECT_FROM_ZVAL(zv) \
+ GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zv))
+
#define GET_GMP_FROM_ZVAL(zval) \
- (((gmp_object *) zend_object_store_get_object((zval) TSRMLS_CC))->num)
+ GET_GMP_OBJECT_FROM_OBJ(Z_OBJ_P(zval))->num
/* The FETCH_GMP_ZVAL_* family of macros is used to fetch a gmp number
* (mpz_ptr) from a zval. If the zval is not a GMP instance, then we
}
#define INIT_GMP_RETVAL(gmpnumber) \
- gmp_create_ex(return_value, &gmpnumber TSRMLS_CC)
+ gmp_create(return_value, &gmpnumber TSRMLS_CC)
static void gmp_strval(zval *result, mpz_t gmpnum, long base);
static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC);
}
/* }}} */
-static inline long gmp_get_long(zval *zv) /* {{{ */
+static void gmp_free_object_storage(zend_object *obj TSRMLS_DC) /* {{{ */
{
- if (Z_TYPE_P(zv) == IS_LONG) {
- return Z_LVAL_P(zv);
- } else {
- zval tmp_zv;
- MAKE_COPY_ZVAL(&zv, &tmp_zv);
- convert_to_long(&tmp_zv);
- return Z_LVAL(tmp_zv);
- }
-}
-/* }}} */
+ gmp_object *intern = GET_GMP_OBJECT_FROM_OBJ(obj);
-static void gmp_free_object_storage(gmp_object *intern TSRMLS_DC) /* {{{ */
-{
mpz_clear(intern->num);
-
zend_object_std_dtor(&intern->std TSRMLS_CC);
- efree(intern);
}
/* }}} */
-static inline zend_object_value gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
+static inline zend_object *gmp_create_object_ex(zend_class_entry *ce, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
{
- zend_object_value retval;
- gmp_object *intern = emalloc(sizeof(gmp_object));
+ gmp_object *intern = emalloc(sizeof(gmp_object)
+ + sizeof(zval) * (ce->default_properties_count - 1));
zend_object_std_init(&intern->std, ce TSRMLS_CC);
object_properties_init(&intern->std, ce);
mpz_init(intern->num);
*gmpnum_target = intern->num;
+ intern->std.handlers = &gmp_object_handlers;
- retval.handle = zend_objects_store_put(
- intern, (zend_objects_store_dtor_t) zend_objects_destroy_object,
- (zend_objects_free_object_storage_t) gmp_free_object_storage,
- NULL TSRMLS_CC
- );
- retval.handlers = &gmp_object_handlers;
-
- return retval;
+ return &intern->std;
}
/* }}} */
-static zend_object_value gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
+static zend_object *gmp_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
{
mpz_ptr gmpnum_dummy;
return gmp_create_object_ex(ce, &gmpnum_dummy TSRMLS_CC);
}
/* }}} */
-static inline void gmp_create_ex(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
+static inline void gmp_create(zval *target, mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
{
- Z_TYPE_P(target) = IS_OBJECT;
- Z_OBJVAL_P(target) = gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC);
-}
-/* }}} */
-
-static zval *gmp_create(mpz_ptr *gmpnum_target TSRMLS_DC) /* {{{ */
-{
- zval *obj;
- MAKE_STD_ZVAL(obj);
- gmp_create_ex(obj, gmpnum_target TSRMLS_CC);
- return obj;
+ ZVAL_OBJ(target, gmp_create_object_ex(gmp_ce, gmpnum_target TSRMLS_CC));
}
/* }}} */
switch (type) {
case IS_STRING:
gmpnum = GET_GMP_FROM_ZVAL(readobj);
- INIT_PZVAL(writeobj);
gmp_strval(writeobj, gmpnum, 10);
return SUCCESS;
case IS_LONG:
gmpnum = GET_GMP_FROM_ZVAL(readobj);
- INIT_PZVAL(writeobj);
ZVAL_LONG(writeobj, mpz_get_si(gmpnum));
return SUCCESS;
case IS_DOUBLE:
gmpnum = GET_GMP_FROM_ZVAL(readobj);
- INIT_PZVAL(writeobj);
ZVAL_DOUBLE(writeobj, mpz_get_d(gmpnum));
return SUCCESS;
default:
{
HashTable *ht, *props = zend_std_get_properties(obj TSRMLS_CC);
mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(obj);
- zval *zv;
+ zval zv;
*is_temp = 1;
ALLOC_HASHTABLE(ht);
ZEND_INIT_SYMTABLE_EX(ht, zend_hash_num_elements(props) + 1, 0);
- zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+ zend_hash_copy(ht, props, (copy_ctor_func_t) zval_add_ref);
- MAKE_STD_ZVAL(zv);
- gmp_strval(zv, gmpnum, 10);
- zend_hash_update(ht, "num", sizeof("num"), &zv, sizeof(zval *), NULL);
+ gmp_strval(&zv, gmpnum, 10);
+ zend_hash_str_update(ht, "num", sizeof("num")-1, &zv);
return ht;
}
/* }}} */
-static zend_object_value gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */
+static zend_object *gmp_clone_obj(zval *obj TSRMLS_DC) /* {{{ */
{
- gmp_object *old_object = zend_object_store_get_object(obj TSRMLS_CC);
- zend_object_value new_object_val = gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC);
- gmp_object *new_object = zend_object_store_get_object_by_handle(
- new_object_val.handle TSRMLS_CC
- );
+ gmp_object *old_object = GET_GMP_OBJECT_FROM_ZVAL(obj);
+ gmp_object *new_object = GET_GMP_OBJECT_FROM_OBJ(gmp_create_object(Z_OBJCE_P(obj) TSRMLS_CC));
- zend_objects_clone_members(
- &new_object->std, new_object_val,
- &old_object->std, Z_OBJ_HANDLE_P(obj) TSRMLS_CC
- );
+ zend_objects_clone_members( &new_object->std, &old_object->std TSRMLS_CC);
mpz_set(new_object->num, old_object->num);
- return new_object_val;
+ return &new_object->std;
}
/* }}} */
static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zval *op1, zval *op2 TSRMLS_DC) {
- zval op2_copy;
- if (Z_TYPE_P(op2) != IS_LONG) {
- op2_copy = *op2;
- zval_copy_ctor(&op2_copy);
- convert_to_long(&op2_copy);
- op2 = &op2_copy;
- }
+ long shift = zval_get_long(op2);
- if (Z_LVAL_P(op2) < 0) {
+ if (shift < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shift cannot be negative");
RETVAL_FALSE;
} else {
FETCH_GMP_ZVAL(gmpnum_op, op1, temp);
INIT_GMP_RETVAL(gmpnum_result);
- op(gmpnum_result, gmpnum_op, (unsigned long) Z_LVAL_P(op2));
+ op(gmpnum_result, gmpnum_op, (unsigned long) shift);
FREE_GMP_TEMP(temp);
}
}
static int gmp_compare(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
gmp_cmp(result, op1, op2 TSRMLS_CC);
- if (Z_TYPE_P(result) == IS_BOOL) {
+ if (Z_TYPE_P(result) == IS_FALSE) {
ZVAL_LONG(result, 1);
}
return SUCCESS;
{
mpz_ptr gmpnum = GET_GMP_FROM_ZVAL(object);
smart_str buf = {0};
- zval zv, *zv_ptr = &zv;
+ zval zv;
php_serialize_data_t serialize_data = (php_serialize_data_t) data;
+ zend_array tmp_arr;
PHP_VAR_SERIALIZE_INIT(serialize_data);
- INIT_PZVAL(zv_ptr);
- gmp_strval(zv_ptr, gmpnum, 10);
- php_var_serialize(&buf, &zv_ptr, &serialize_data TSRMLS_CC);
- zval_dtor(zv_ptr);
+ gmp_strval(&zv, gmpnum, 10);
+ php_var_serialize(&buf, &zv, &serialize_data TSRMLS_CC);
+ zval_dtor(&zv);
- Z_ARRVAL_P(zv_ptr) = zend_std_get_properties(object TSRMLS_CC);
- Z_TYPE_P(zv_ptr) = IS_ARRAY;
- php_var_serialize(&buf, &zv_ptr, &serialize_data TSRMLS_CC);
+ ZVAL_ARR(&zv, &tmp_arr);
+ tmp_arr.ht = *zend_std_get_properties(object TSRMLS_CC);
+ php_var_serialize(&buf, &zv, &serialize_data TSRMLS_CC);
PHP_VAR_SERIALIZE_DESTROY(serialize_data);
- *buffer = (unsigned char *) buf.c;
- *buf_len = buf.len;
+ *buffer = (unsigned char *) estrndup(buf.s->val, buf.s->len);
+ *buf_len = buf.s->len;
+ STR_RELEASE(buf.s);
return SUCCESS;
}
/* }}} */
-static int gmp_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
+static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC) /* {{{ */
{
mpz_ptr gmpnum;
const unsigned char *p, *max;
- zval zv, *zv_ptr = &zv;
+ zval zv;
int retval = FAILURE;
php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data;
PHP_VAR_UNSERIALIZE_INIT(unserialize_data);
- gmp_create_ex(*object, &gmpnum TSRMLS_CC);
+ gmp_create(object, &gmpnum TSRMLS_CC);
p = buf;
max = buf + buf_len;
- INIT_ZVAL(zv);
- if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)
- || Z_TYPE_P(zv_ptr) != IS_STRING
- || convert_to_gmp(gmpnum, zv_ptr, 10 TSRMLS_CC) == FAILURE
+ if (!php_var_unserialize(&zv, &p, max, &unserialize_data TSRMLS_CC)
+ || Z_TYPE(zv) != IS_STRING
+ || convert_to_gmp(gmpnum, &zv, 10 TSRMLS_CC) == FAILURE
) {
zend_throw_exception(NULL, "Could not unserialize number", 0 TSRMLS_CC);
goto exit;
}
zval_dtor(&zv);
- INIT_ZVAL(zv);
- if (!php_var_unserialize(&zv_ptr, &p, max, &unserialize_data TSRMLS_CC)
- || Z_TYPE_P(zv_ptr) != IS_ARRAY
+ if (!php_var_unserialize(&zv, &p, max, &unserialize_data TSRMLS_CC)
+ || Z_TYPE(zv) != IS_ARRAY
) {
zend_throw_exception(NULL, "Could not unserialize properties", 0 TSRMLS_CC);
goto exit;
}
- if (zend_hash_num_elements(Z_ARRVAL_P(zv_ptr)) != 0) {
+ if (zend_hash_num_elements(Z_ARRVAL(zv)) != 0) {
zend_hash_copy(
- zend_std_get_properties(*object TSRMLS_CC), Z_ARRVAL_P(zv_ptr),
- (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)
+ zend_std_get_properties(object TSRMLS_CC), Z_ARRVAL(zv),
+ (copy_ctor_func_t) zval_add_ref
);
}
gmp_ce->unserialize = gmp_unserialize;
memcpy(&gmp_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ gmp_object_handlers.offset = XtOffsetOf(gmp_object, std);
+ gmp_object_handlers.free_obj = gmp_free_object_storage;
gmp_object_handlers.cast_object = gmp_cast_object;
gmp_object_handlers.get_debug_info = gmp_get_debug_info;
gmp_object_handlers.clone_obj = gmp_clone_obj;
{
switch (Z_TYPE_P(val)) {
case IS_LONG:
- case IS_BOOL: {
- mpz_set_si(gmpnumber, gmp_get_long(val));
+ case IS_FALSE:
+ case IS_TRUE: {
+ mpz_set_si(gmpnumber, zval_get_long(val));
return SUCCESS;
}
case IS_STRING: {
static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */
{
int num_len;
- char *out_string;
+ zend_string *str;
num_len = mpz_sizeinbase(gmpnum, abs(base));
if (mpz_sgn(gmpnum) < 0) {
num_len++;
}
- out_string = emalloc(num_len + 1);
- mpz_get_str(out_string, base, gmpnum);
+ str = STR_ALLOC(num_len, 0);
+ mpz_get_str(str->val, base, gmpnum);
/*
* From GMP documentation for mpz_sizeinbase():
* So let's check to see if we already have a \0 byte...
*/
- if (out_string[num_len - 1] == '\0') {
- num_len--;
+ if (str->val[str->len - 1] == '\0') {
+ str->len--;
} else {
- out_string[num_len] = '\0';
+ str->val[str->len] = '\0';
}
- ZVAL_STRINGL(result, out_string, num_len, 0);
+ ZVAL_STR(result, str);
}
/* }}} */
mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result1, gmpnum_result2;
int use_ui = 0;
gmp_temp_t temp_a, temp_b;
+ zval result1, result2;
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
}
}
+ gmp_create(&result1, &gmpnum_result1 TSRMLS_CC);
+ gmp_create(&result2, &gmpnum_result2 TSRMLS_CC);
+
array_init(return_value);
- add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
- add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
+ add_next_index_zval(return_value, &result1);
+ add_next_index_zval(return_value, &result2);
if (use_ui) {
gmp_ui_op(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) Z_LVAL_P(b_arg));
mpz_ptr gmpnum_result;
INIT_GMP_RETVAL(gmpnum_result);
- gmp_op(gmpnum_result, gmp_get_long(a_arg));
+ gmp_op(gmpnum_result, zval_get_long(a_arg));
}
/* }}} */
if (IS_GMP(gmpnumber_arg)) {
RETVAL_LONG(mpz_get_si(GET_GMP_FROM_ZVAL(gmpnumber_arg)));
} else {
- RETVAL_LONG(gmp_get_long(gmpnumber_arg));
+ RETVAL_LONG(zval_get_long(gmpnumber_arg));
}
}
/* }}} */
RETURN_FALSE;
}
} else {
- if (gmp_get_long(a_arg) < 0) {
+ if (zval_get_long(a_arg) < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number has to be greater than or equal to 0");
RETURN_FALSE;
}
zval *a_arg;
mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2;
gmp_temp_t temp_a;
+ zval result1, result2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &a_arg) == FAILURE){
return;
RETURN_FALSE;
}
+ gmp_create(&result1, &gmpnum_result1 TSRMLS_CC);
+ gmp_create(&result2, &gmpnum_result2 TSRMLS_CC);
+
array_init(return_value);
- add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
- add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
+ add_next_index_zval(return_value, &result1);
+ add_next_index_zval(return_value, &result2);
mpz_sqrtrem(gmpnum_result1, gmpnum_result2, gmpnum_a);
FREE_GMP_TEMP(temp_a);
long nth;
mpz_ptr gmpnum_a, gmpnum_result1, gmpnum_result2;
gmp_temp_t temp_a;
+ zval result1, result2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl", &a_arg, &nth) == FAILURE) {
return;
RETURN_FALSE;
}
+ gmp_create(&result1, &gmpnum_result1 TSRMLS_CC);
+ gmp_create(&result2, &gmpnum_result2 TSRMLS_CC);
+
array_init(return_value);
- add_index_zval(return_value, 0, gmp_create(&gmpnum_result1 TSRMLS_CC));
- add_index_zval(return_value, 1, gmp_create(&gmpnum_result2 TSRMLS_CC));
+ add_next_index_zval(return_value, &result1);
+ add_next_index_zval(return_value, &result2);
#if GMP_42_OR_NEWER
mpz_rootrem(gmpnum_result1, gmpnum_result2, gmpnum_a, (unsigned long) nth);
zval *a_arg, *b_arg;
mpz_ptr gmpnum_a, gmpnum_b, gmpnum_t, gmpnum_s, gmpnum_g;
gmp_temp_t temp_a, temp_b;
+ zval result_g, result_s, result_t;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a_arg, &b_arg) == FAILURE){
return;
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a);
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a);
+ gmp_create(&result_g, &gmpnum_g TSRMLS_CC);
+ gmp_create(&result_s, &gmpnum_s TSRMLS_CC);
+ gmp_create(&result_t, &gmpnum_t TSRMLS_CC);
+
array_init(return_value);
- add_assoc_zval(return_value, "g", gmp_create(&gmpnum_g TSRMLS_CC));
- add_assoc_zval(return_value, "s", gmp_create(&gmpnum_s TSRMLS_CC));
- add_assoc_zval(return_value, "t", gmp_create(&gmpnum_t TSRMLS_CC));
+ add_assoc_zval(return_value, "g", &result_g);
+ add_assoc_zval(return_value, "s", &result_s);
+ add_assoc_zval(return_value, "t", &result_t);
mpz_gcdext(gmpnum_g, gmpnum_s, gmpnum_t, gmpnum_a, gmpnum_b);
FREE_GMP_TEMP(temp_a);