]> granicus.if.org Git - php/commitdiff
MFH: Implement toArray,fromArray and get_properties (Thanks Tony for the patches)
authorEtienne Kneuss <colder@php.net>
Sun, 13 Jul 2008 15:59:52 +0000 (15:59 +0000)
committerEtienne Kneuss <colder@php.net>
Sun, 13 Jul 2008 15:59:52 +0000 (15:59 +0000)
ext/spl/spl_fixedarray.c
ext/spl/tests/fixedarray_016.phpt
ext/spl/tests/fixedarray_017.phpt
ext/spl/tests/fixedarray_018.phpt
ext/spl/tests/fixedarray_019.phpt
ext/spl/tests/fixedarray_020.phpt [new file with mode: 0644]

index 2ca36b79578ffc9c735cccaec1ff4a5b2ed46332..e70b6d4e7c8c3413da98b436427b916314f8dbd9 100644 (file)
@@ -145,46 +145,24 @@ static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_
 }
 /* }}} */
 
-static HashTable* spl_fixedarray_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
+static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */
 {
        spl_fixedarray_object *intern  = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
-       HashTable *rv;
-       zval *tmp, zrv, *fixedarray_array;
-       char *pnstr;
-       int  pnlen;
-       int  i = 0;;
-
-       *is_temp = 1;
-
-       ALLOC_HASHTABLE(rv);
-       ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
-
-       INIT_PZVAL(&zrv);
-       Z_ARRVAL(zrv) = rv;
-
-       zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
-       ALLOC_INIT_ZVAL(fixedarray_array);
-       array_init(fixedarray_array);
-
+       int  i = 0;
 
        if (intern->array) {
                for (i = 0; i < intern->array->size; i++) {
                        if (intern->array->elements[i]) {
-                               add_index_zval(fixedarray_array, i, (zval *)intern->array->elements[i]);
+                               zend_hash_index_update(intern->std.properties, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
                                Z_ADDREF_P(intern->array->elements[i]);
                        } else {
-                               add_index_zval(fixedarray_array, i, (zval *)EG(uninitialized_zval_ptr));
+                               zend_hash_index_update(intern->std.properties, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
                                Z_ADDREF_P(EG(uninitialized_zval_ptr));
                        }
                }
        }
 
-       pnstr = spl_gen_private_prop_name(spl_ce_SplFixedArray, "array", sizeof("array")-1, &pnlen TSRMLS_CC);
-       add_assoc_zval_ex(&zrv, pnstr, pnlen+1, fixedarray_array);
-       efree(pnstr);
-
-       return rv;
+       return intern->std.properties;
 }
 /* }}}} */
 
@@ -586,6 +564,119 @@ SPL_METHOD(SplFixedArray, count)
 }
 /* }}} */
 
+/* {{{ proto object SplFixedArray::toArray()
+*/
+SPL_METHOD(SplFixedArray, toArray)
+{
+       spl_fixedarray_object *intern;
+       zval *ret, *tmp;
+       HashTable *ret_ht, *obj_ht;
+
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) {
+               return;
+       }
+
+       intern = (spl_fixedarray_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+       ALLOC_HASHTABLE(ret_ht);
+       zend_hash_init(ret_ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+       ALLOC_INIT_ZVAL(ret);
+       Z_TYPE_P(ret) = IS_ARRAY;
+       obj_ht = spl_fixedarray_object_get_properties(getThis() TSRMLS_CC);
+       zend_hash_copy(ret_ht, obj_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       Z_ARRVAL_P(ret) = ret_ht;
+
+       RETURN_ZVAL(ret, 1, 1);
+}
+/* }}} */
+
+/* {{{ proto object SplFixedArray::fromArray(array data[, bool save_indexes])
+*/
+SPL_METHOD(SplFixedArray, fromArray)
+{
+       zval *data;
+       spl_fixedarray *array;
+       spl_fixedarray_object *intern;
+       int num;
+       zend_bool save_indexes = 1;
+
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &data, &save_indexes)) {
+               return;
+       }
+
+       array = ecalloc(1, sizeof(*array));
+       num = zend_hash_num_elements(Z_ARRVAL_P(data));
+       
+       if (num > 0 && save_indexes) {
+               zval **element, *value;
+               char *str_index;
+               ulong num_index, max_index = 0;
+               long tmp;
+
+               for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
+                       zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
+                       zend_hash_move_forward(Z_ARRVAL_P(data))
+                       ) {
+                       if (zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0) != HASH_KEY_IS_LONG || (long)num_index < 0) {
+                               efree(array);
+                               zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "array must contain only positive integer keys");
+                               return;
+                       }
+
+                       if (num_index > max_index) {
+                               max_index = num_index;
+                       }
+               }
+
+               tmp = max_index + 1;
+               if (tmp <= 0) {
+                       efree(array);
+                       zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0 TSRMLS_CC, "integer overflow detected");
+                       return;
+               }
+               spl_fixedarray_init(array, tmp TSRMLS_CC);
+
+               for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
+                       zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
+                       zend_hash_move_forward(Z_ARRVAL_P(data))
+                       ) {
+                       
+                       zend_hash_get_current_key(Z_ARRVAL_P(data), &str_index, &num_index, 0);
+                       value = *element;
+
+                       SEPARATE_ARG_IF_REF(value);
+                       array->elements[num_index] = value;
+               }
+
+       } else if (num > 0 && !save_indexes) {
+               zval **element, *value;
+               long i = 0;
+               
+               spl_fixedarray_init(array, num TSRMLS_CC);
+               
+               for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(data));
+                       zend_hash_get_current_data(Z_ARRVAL_P(data), (void **) &element) == SUCCESS;
+                       zend_hash_move_forward(Z_ARRVAL_P(data))
+                       ) {
+                       
+                       value = *element;
+
+                       SEPARATE_ARG_IF_REF(value);
+                       array->elements[i] = value;
+                       i++;
+               }
+       } else {
+               spl_fixedarray_init(array, 0 TSRMLS_CC);
+       }
+
+       object_init_ex(return_value, spl_ce_SplFixedArray);
+       Z_TYPE_P(return_value) = IS_OBJECT;
+
+       intern = (spl_fixedarray_object *)zend_object_store_get_object(return_value TSRMLS_CC);
+       intern->array = array;
+}
+/* }}} */
+
 /* {{{ proto int SplFixedArray::getSize(void)
 */
 SPL_METHOD(SplFixedArray, getSize)
@@ -936,15 +1027,23 @@ ZEND_BEGIN_ARG_INFO(arginfo_fixedarray_setSize, 0)
        ZEND_ARG_INFO(0, value)
 ZEND_END_ARG_INFO()
 
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_fixedarray_fromArray, 0, 0, 1)
+       ZEND_ARG_INFO(0, data)
+       ZEND_ARG_INFO(0, save_indexes)
+ZEND_END_ARG_INFO()
+
 static zend_function_entry spl_funcs_SplFixedArray[] = { /* {{{ */
        SPL_ME(SplFixedArray, __construct,     NULL, ZEND_ACC_PUBLIC)
        SPL_ME(SplFixedArray, count,           NULL,                           ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, toArray,         NULL,                           ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, fromArray,       arginfo_fixedarray_fromArray,   ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
        SPL_ME(SplFixedArray, getSize,         NULL,                           ZEND_ACC_PUBLIC)
-       SPL_ME(SplFixedArray, setSize,         arginfo_fixedarray_setSize,      ZEND_ACC_PUBLIC)
-       SPL_ME(SplFixedArray, offsetExists,    arginfo_fixedarray_offsetGet,    ZEND_ACC_PUBLIC)
-       SPL_ME(SplFixedArray, offsetGet,       arginfo_fixedarray_offsetGet,    ZEND_ACC_PUBLIC)
-       SPL_ME(SplFixedArray, offsetSet,       arginfo_fixedarray_offsetSet,    ZEND_ACC_PUBLIC)
-       SPL_ME(SplFixedArray, offsetUnset,     arginfo_fixedarray_offsetGet,    ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, setSize,         arginfo_fixedarray_setSize,     ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, offsetExists,    arginfo_fixedarray_offsetGet,   ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, offsetGet,       arginfo_fixedarray_offsetGet,   ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, offsetSet,       arginfo_fixedarray_offsetSet,   ZEND_ACC_PUBLIC)
+       SPL_ME(SplFixedArray, offsetUnset,     arginfo_fixedarray_offsetGet,   ZEND_ACC_PUBLIC)
        SPL_ME(SplFixedArray, rewind,          NULL,                           ZEND_ACC_PUBLIC)
        SPL_ME(SplFixedArray, current,         NULL,                           ZEND_ACC_PUBLIC)
        SPL_ME(SplFixedArray, key,             NULL,                           ZEND_ACC_PUBLIC)
@@ -966,7 +1065,7 @@ PHP_MINIT_FUNCTION(spl_fixedarray)
        spl_handler_SplFixedArray.unset_dimension = spl_fixedarray_object_unset_dimension;
        spl_handler_SplFixedArray.has_dimension   = spl_fixedarray_object_has_dimension;
        spl_handler_SplFixedArray.count_elements  = spl_fixedarray_object_count_elements;
-       spl_handler_SplFixedArray.get_debug_info  = spl_fixedarray_object_get_debug_info;
+       spl_handler_SplFixedArray.get_properties  = spl_fixedarray_object_get_properties;
 
        REGISTER_SPL_IMPLEMENTS(SplFixedArray, Iterator);
        REGISTER_SPL_IMPLEMENTS(SplFixedArray, ArrayAccess);
index d41a24f0f265851a74f8eeae2cd942cabfbd1b92..fb61ee3647dae710728fdfb85e2b849ca9bb03dd 100644 (file)
@@ -9,12 +9,9 @@ var_dump(empty($a[0]), empty($a[1]), $a);
 --EXPECTF--
 bool(false)
 bool(true)
-object(SplFixedArray)#1 (1) {
-  ["array":"SplFixedArray":private]=>
-  array(2) {
-    [0]=>
-    string(3) "foo"
-    [1]=>
-    NULL
-  }
+object(SplFixedArray)#%d (2) {
+  [0]=>
+  string(3) "foo"
+  [1]=>
+  NULL
 }
index d41a24f0f265851a74f8eeae2cd942cabfbd1b92..fb61ee3647dae710728fdfb85e2b849ca9bb03dd 100644 (file)
@@ -9,12 +9,9 @@ var_dump(empty($a[0]), empty($a[1]), $a);
 --EXPECTF--
 bool(false)
 bool(true)
-object(SplFixedArray)#1 (1) {
-  ["array":"SplFixedArray":private]=>
-  array(2) {
-    [0]=>
-    string(3) "foo"
-    [1]=>
-    NULL
-  }
+object(SplFixedArray)#%d (2) {
+  [0]=>
+  string(3) "foo"
+  [1]=>
+  NULL
 }
index 4965bb527948169f98475a8e285244fe2a4222d2..84ab1091953b9372fdc3533eac0dd5c1529b5b1f 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-SPL: SplFixedArray with overriden count()
+SPL: FixedArray: overriden count()
 --FILE--
 <?php
 $obj = new SplFixedArray(2);
index e8537cabd77ca2c4fc8cefdf996aa4b39a15348e..f28edfda413b396e4b39191ca6a59f60a1fc73a5 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-SPL: SplFixedArray with overriden iterator methods
+SPL: FixedArray: overriden iterator methods
 --FILE--
 <?php
 class SplFixedArray2 extends SplFixedArray {
diff --git a/ext/spl/tests/fixedarray_020.phpt b/ext/spl/tests/fixedarray_020.phpt
new file mode 100644 (file)
index 0000000..c0ff6e3
--- /dev/null
@@ -0,0 +1,36 @@
+--TEST--
+SPL: FixedArray: fromArray/toArray + get_properties
+--FILE--
+<?php
+$a = array(1=>'foo', 2=>'bar', 0=>'gee');
+$fa = SplFixedArray::fromArray($a, false);
+var_dump(count($fa), $fa->toArray() === array_values($a));
+
+$fa = SplFixedArray::fromArray($a, true);
+var_dump(count($fa), $fa->toArray() === $a, $fa->toArray() === (array)$fa);
+
+try {
+    echo "From Array with string keys, no preserve\n";
+    SplFixedArray::fromArray(array("foo"=>"bar"), false);
+    echo "No exception\n";
+} catch (Exception $e) {
+    echo "Exception: ".$e->getMessage()."\n";
+}
+try {
+    echo "From Array with string keys, preserve\n";
+    SplFixedArray::fromArray(array("foo"=>"bar"), true);
+    echo "No exception\n";
+} catch (Exception $e) {
+    echo "Exception: ".$e->getMessage()."\n";
+}
+?>
+--EXPECT--
+int(3)
+bool(true)
+int(3)
+bool(false)
+bool(true)
+From Array with string keys, no preserve
+No exception
+From Array with string keys, preserve
+Exception: array must contain only positive integer keys