]> granicus.if.org Git - php/commitdiff
Port ext/gmp (one failure)
authorNikita Popov <nikic@php.net>
Tue, 6 May 2014 16:44:28 +0000 (18:44 +0200)
committerNikita Popov <nikic@php.net>
Tue, 6 May 2014 17:03:48 +0000 (19:03 +0200)
ext/gmp/gmp.c

index cd50896cc7d4c17997c7a513416f632bd7fb704f..df7c912938d6bd1a05d33f0523509a187a47354f 100644 (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);