Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:27264 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 16495 invoked by uid 1010); 5 Jan 2007 05:50:05 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 16480 invoked from network); 5 Jan 2007 05:50:05 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 5 Jan 2007 05:50:05 -0000 Authentication-Results: pb1.pair.com smtp.mail=dshadow@zort.net; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=dshadow@zort.net; sender-id=unknown Received-SPF: error (pb1.pair.com: domain zort.net from 66.92.164.115 cause and error) X-PHP-List-Original-Sender: dshadow@zort.net X-Host-Fingerprint: 66.92.164.115 titan.zort.net Linux 2.6 Received: from [66.92.164.115] ([66.92.164.115:59363] helo=nova.zort.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D9/CF-25140-C07ED954 for ; Fri, 05 Jan 2007 00:50:05 -0500 Received: from [10.0.1.2] (pulsar.zort.net [66.92.164.204]) (authenticated bits=0) by nova.zort.net (8.13.8/8.13.8) with ESMTP id l055o1Sn031457 for ; Fri, 5 Jan 2007 00:50:02 -0500 Mime-Version: 1.0 (Apple Message framework v752.3) To: PHP internals Message-ID: <76AD94BE-DD27-490D-88F8-8D0EC4A2C4E6@zort.net> Content-Type: multipart/mixed; boundary=Apple-Mail-37-690436305 Date: Fri, 5 Jan 2007 00:49:57 -0500 X-Mailer: Apple Mail (2.752.3) Subject: [PATCH] New functions: array_key_index(), array_first(), array_last() From: dshadow@zort.net (John Bafford) --Apple-Mail-37-690436305 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Hello, Attached is a patch and corresponding test file I would like to submit for inclusion in PHP. I would like this patch to be included in PHP 5.2.1, as it is entirely new code (and thus shouldn't cause regressions), but as RC2 was just released earlier today, I understand if it must wait until PHP 5.2.2. This patch implements three new functions, as described below. mixed array_key_index(array input, int index [, mixed value]) Return the array's index'th key (and optionally, value) mixed array_first(array input [, mixed value]) Return the array's first key (and optionally, value) This is equivalent to array_key_index($input, 0 [, $value]); mixed array_last(array input [, mixed value]) Return the array's last key (and optionally, value) This is equivalent to array_key_index($input, -1 [, $value]); array_first() is a non-destructive way to get the first key (and value, if requested) from an array. array_first() is intended to replace code similar to the following: foreach($arr as $key => $val) break; reset($arr); $key = key($arr); reset($arr); list($key, $val) = each($arr); $key = array_keys($arr); $key = $key[0]; array_last() is the obvious counterpart to array_first(), returning the last key (and value, if requested) from an array. array_first() and array_last() are implemented via array_key_index(), which returns a key based on its order in the array. The index parameter functions similarly to substr()'s start parameter (>= 0 start from the beginning of the array, <= -1 start from the end.) All three functions leave the original array unmodified. In the event of an error (invalid parameters, or attempting to seek past the end of the array), all three functions return NULL and leave $value unchanged. Please let me know if you have any comments. Thanks, -John --Apple-Mail-37-690436305 Content-Transfer-Encoding: 7bit Content-Type: text/plain; x-unix-mode=0644; name=php-array-key-index.patch.txt Content-Disposition: attachment; filename=php-array-key-index.patch.txt Index: ext/standard/array.c =================================================================== RCS file: /repository/php-src/ext/standard/array.c,v retrieving revision 1.308.2.21.2.22 diff -u -u -r1.308.2.21.2.22 array.c --- ext/standard/array.c 1 Jan 2007 09:36:07 -0000 1.308.2.21.2.22 +++ ext/standard/array.c 5 Jan 2007 04:57:47 -0000 @@ -4528,6 +4528,115 @@ } /* }}} */ +/* {{{ php_array_key_index_common + keyOffset: 0: determine from parameters; 1 = first; -1 = last + */ +static void php_array_key_index_common(INTERNAL_FUNCTION_PARAMETERS, int keyOffset) +{ + zval *input, *value; + zval **arrValue; + HashPosition pos; + int key_type; + char *string_key; + uint string_key_len; + ulong num_key; + zend_bool direction; + + if(keyOffset == 0) { + //array_key_index(array input, int offset, [mixed value]) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "al|z", &input, &keyOffset, &value) == FAILURE) { + RETURN_NULL(); + } + } else { + if(keyOffset == 1) { + keyOffset = 0; + } + + //array_(first|last)(array input, [mixed value]) + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &input, &value) == FAILURE) { + RETURN_NULL(); + } + } + + //true == forward; false == backwards + direction = (keyOffset >= 0); + if(!direction) { + keyOffset = abs(keyOffset) - 1; + } + + if(keyOffset >= zend_hash_num_elements(Z_ARRVAL_P(input))) { + RETURN_NULL(); + } + + if(direction) { + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos); + } else { + zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(input), &pos); + } + + if(keyOffset >= 1) { + while(keyOffset--) { + if(direction) { + zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos); + } else { + zend_hash_move_backwards_ex(Z_ARRVAL_P(input), &pos); + } + } + } + + key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 0, &pos); + + switch(key_type) { + case HASH_KEY_IS_LONG: + RETVAL_LONG(num_key); + break; + + case HASH_KEY_IS_STRING: + RETVAL_STRINGL(string_key, string_key_len - 1, 1); + break; + + case HASH_KEY_NON_EXISTANT: + default: + RETURN_NULL(); + break; + } + + if(ZEND_NUM_ARGS() >= 2) { + zval_dtor(value); + + zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void**)&arrValue, &pos); + + *value = **arrValue; + zval_copy_ctor(value); + ZVAL_ADDREF(value); + } +} +/* }}} */ + +/* {{{ proto mixed array_key_index(array input, int index [, mixed value]) + Return the array's index key (and optionally, value) */ +PHP_FUNCTION(array_key_index) +{ + php_array_key_index_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto mixed array_first(array input [, mixed value]) + Return the array's first key (and optionally, value) */ +PHP_FUNCTION(array_first) +{ + php_array_key_index_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); +} +/* }}} */ + +/* {{{ proto mixed array_last(array input [, mixed value]) + Return the array's last key (and optionally, value) */ +PHP_FUNCTION(array_last) +{ + php_array_key_index_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, -1); +} +/* }}} */ + /* * Local variables: * tab-width: 4 Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.725.2.31.2.39 diff -u -u -r1.725.2.31.2.39 basic_functions.c --- ext/standard/basic_functions.c 1 Jan 2007 09:36:08 -0000 1.725.2.31.2.39 +++ ext/standard/basic_functions.c 5 Jan 2007 04:57:48 -0000 @@ -682,6 +682,19 @@ ZEND_ARG_INFO(0, keys) /* ARRAY_INFO(0, keys, 0) */ ZEND_ARG_INFO(0, values) /* ARRAY_INFO(0, values, 0) */ ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO(arginfo_array_key_index, 0) + ZEND_ARG_INFO(0, input) + ZEND_ARG_INFO(0, index) + ZEND_ARG_INFO(1, value) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO(arginfo_array_first, 0) + ZEND_ARG_INFO(0, input) + ZEND_ARG_INFO(1, value) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ basic_functions.c */ static @@ -3743,6 +3756,9 @@ PHP_FE(array_chunk, arginfo_array_chunk) PHP_FE(array_combine, arginfo_array_combine) PHP_FE(array_key_exists, arginfo_array_key_exists) + PHP_FE(array_key_index, arginfo_array_key_index) + PHP_FE(array_first, arginfo_array_first) + PHP_FE(array_last, arginfo_array_first) /* aliases from array.c */ PHP_FALIAS(pos, current, arginfo_current) Index: ext/standard/php_array.h =================================================================== RCS file: /repository/php-src/ext/standard/php_array.h,v retrieving revision 1.50.2.2.2.3 diff -u -u -r1.50.2.2.2.3 php_array.h --- ext/standard/php_array.h 1 Jan 2007 09:36:08 -0000 1.50.2.2.2.3 +++ ext/standard/php_array.h 5 Jan 2007 04:57:48 -0000 @@ -99,6 +99,9 @@ PHP_FUNCTION(array_key_exists); PHP_FUNCTION(array_chunk); PHP_FUNCTION(array_combine); +PHP_FUNCTION(array_key_index); +PHP_FUNCTION(array_first); +PHP_FUNCTION(array_last); HashTable* php_splice(HashTable *, int, int, zval ***, int, HashTable **); PHPAPI int php_array_merge(HashTable *dest, HashTable *src, int recursive TSRMLS_DC); --Apple-Mail-37-690436305 Content-Transfer-Encoding: 7bit Content-Type: text/plain; x-mac-type=54455854; x-unix-mode=0644; x-mac-creator=21526368; name=array_key_index.phpt.txt Content-Disposition: attachment; filename=array_key_index.phpt.txt --TEST-- Test array_key_index(), array_first(), and array_last() --FILE-- 'first', 'two' => 'middle', 'three' => 'last', ); $value = array('value has not been written to'); $key = array_first($arr, $value); echo "Testing array_first():\n"; var_dump($key); var_dump($value); echo "\n"; $key = array_last($arr, $value); echo "Testing array_last():\n"; var_dump($key); var_dump($value); echo "\n"; $key = array_key_index($arr, 1, $value); echo "Testing array_index() with positive offset:\n"; var_dump($key); var_dump($value); echo "\n"; $key = array_key_index($arr, -3, $value); echo "Testing array_index() with negative offset:\n"; var_dump($key); var_dump($value); echo "\n"; $key = array_key_index($arr, 3, $value); echo "Testing array_index() with positive offset past the end of the array:\n"; var_dump($key); var_dump($value); echo "\n"; $key = array_key_index($arr, -4, $value); echo "Testing array_index() with negative offset past the end of the array:\n"; var_dump($key); var_dump($value); ?> --EXPECT-- Testing array_first(): string(3) "one" string(5) "first" Testing array_last(): string(5) "three" string(4) "last" Testing array_index() with positive offset: string(3) "two" string(6) "middle" Testing array_index() with negative offset: string(3) "one" string(5) "first" Testing array_index() with positive offset past the end of the array: NULL string(5) "first" Testing array_index() with negative offset past the end of the array: NULL string(5) "first" --Apple-Mail-37-690436305 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed -- John Bafford dshadow@zort.net http://www.dshadow.com/ --Apple-Mail-37-690436305--