1
0
mirror of https://github.com/php/php-src.git synced 2026-04-27 18:23:26 +02:00

Port ext/gmp (one failure)

This commit is contained in:
Nikita Popov
2014-05-06 18:44:28 +02:00
parent 6e87a0857d
commit 4c5b5d7201
+94 -115
View File
@@ -191,8 +191,8 @@ zend_class_entry *gmp_ce;
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 {
@@ -218,8 +218,13 @@ 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
@@ -291,7 +296,7 @@ if (IS_GMP(zval)) { \
}
#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);
@@ -356,70 +361,41 @@ static void gmp_efree(void *ptr, size_t size)
}
/* }}} */
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));
}
/* }}} */
@@ -429,17 +405,14 @@ static int gmp_cast_object(zval *readobj, zval *writeobj, int type TSRMLS_DC) /*
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:
@@ -452,50 +425,37 @@ static HashTable *gmp_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ *
{
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 {
@@ -504,7 +464,7 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva
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);
}
}
@@ -563,7 +523,7 @@ static int gmp_do_operation(zend_uchar opcode, zval *result, zval *op1, zval *op
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;
@@ -574,64 +534,63 @@ static int gmp_serialize(zval *object, unsigned char **buffer, zend_uint *buf_le
{
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
);
}
@@ -663,6 +622,8 @@ ZEND_MINIT_FUNCTION(gmp)
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;
@@ -718,8 +679,9 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC)
{
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: {
@@ -759,15 +721,15 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, int base TSRMLS_DC)
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():
@@ -777,13 +739,13 @@ static void gmp_strval(zval *result, mpz_t gmpnum, long base) /* {{{ */
* 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);
}
/* }}} */
@@ -871,6 +833,7 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval
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);
@@ -898,9 +861,12 @@ static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval
}
}
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));
@@ -952,7 +918,7 @@ static inline void gmp_zval_unary_ui_op(zval *return_value, zval *a_arg, gmp_una
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));
}
/* }}} */
@@ -1063,7 +1029,7 @@ ZEND_FUNCTION(gmp_intval)
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));
}
}
/* }}} */
@@ -1259,7 +1225,7 @@ ZEND_FUNCTION(gmp_fact)
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;
}
@@ -1382,6 +1348,7 @@ ZEND_FUNCTION(gmp_sqrtrem)
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;
@@ -1395,9 +1362,12 @@ ZEND_FUNCTION(gmp_sqrtrem)
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);
@@ -1444,6 +1414,7 @@ ZEND_FUNCTION(gmp_rootrem)
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;
@@ -1462,9 +1433,12 @@ ZEND_FUNCTION(gmp_rootrem)
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);
@@ -1533,6 +1507,7 @@ ZEND_FUNCTION(gmp_gcdext)
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;
@@ -1541,10 +1516,14 @@ ZEND_FUNCTION(gmp_gcdext)
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);