Skip to content

Commit ec2332b

Browse files
author
Enno Woortmann
committed
Add implementation and tests for new methods
- array_key_first(array $a) Returns the key of the first element or null - array_key_last(array $a) Returns the key of the last element or null
1 parent 9565075 commit ec2332b

11 files changed

+655
-0
lines changed

Zend/zend_hash.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,11 @@ static zend_always_inline HashPosition _zend_hash_get_current_pos(const HashTabl
373373
return pos;
374374
}
375375

376+
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_first_pos(const HashTable *ht)
377+
{
378+
return _zend_hash_get_first_pos(ht);
379+
}
380+
376381
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos(const HashTable *ht)
377382
{
378383
return _zend_hash_get_current_pos(ht);

Zend/zend_hash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ ZEND_API zend_bool ZEND_FASTCALL zend_hash_str_exists(const HashTable *ht, const
232232
ZEND_API zend_bool ZEND_FASTCALL zend_hash_index_exists(const HashTable *ht, zend_ulong h);
233233

234234
/* traversing */
235+
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_first_pos(const HashTable *ht);
235236
ZEND_API HashPosition ZEND_FASTCALL zend_hash_get_current_pos(const HashTable *ht);
236237

237238
#define zend_hash_has_more_elements_ex(ht, pos) \

ext/standard/array.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4016,6 +4016,39 @@ PHP_FUNCTION(array_keys)
40164016
}
40174017
/* }}} */
40184018

4019+
/* {{{ proto mixed array_key_first(array stack)
4020+
Get the key of the first element of the array */
4021+
PHP_FUNCTION(array_key_first)
4022+
{
4023+
zval *stack; /* Input stack */
4024+
4025+
ZEND_PARSE_PARAMETERS_START(1, 1)
4026+
Z_PARAM_ARRAY_EX(stack, 0, 1)
4027+
ZEND_PARSE_PARAMETERS_END();
4028+
4029+
HashTable *target_hash = HASH_OF(stack);
4030+
HashPosition pos = zend_hash_get_first_pos(target_hash);
4031+
zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
4032+
}
4033+
/* }}} */
4034+
4035+
/* {{{ proto mixed array_key_last(array stack)
4036+
Get the key of the last element of the array */
4037+
PHP_FUNCTION(array_key_last)
4038+
{
4039+
zval *stack; /* Input stack */
4040+
HashPosition pos;
4041+
4042+
ZEND_PARSE_PARAMETERS_START(1, 1)
4043+
Z_PARAM_ARRAY_EX(stack, 0, 1)
4044+
ZEND_PARSE_PARAMETERS_END();
4045+
4046+
HashTable *target_hash = HASH_OF(stack);
4047+
zend_hash_internal_pointer_end_ex(target_hash, &pos);
4048+
zend_hash_get_current_key_zval_ex(target_hash, return_value, &pos);
4049+
}
4050+
/* }}} */
4051+
40194052
/* {{{ proto array array_values(array input)
40204053
Return just the values from the input array */
40214054
PHP_FUNCTION(array_values)

ext/standard/basic_functions.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,14 @@ ZEND_BEGIN_ARG_INFO(arginfo_array_values, 0)
422422
ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
423423
ZEND_END_ARG_INFO()
424424

425+
ZEND_BEGIN_ARG_INFO(arginfo_array_key_first, 0)
426+
ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
427+
ZEND_END_ARG_INFO()
428+
429+
ZEND_BEGIN_ARG_INFO(arginfo_array_key_last, 0)
430+
ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
431+
ZEND_END_ARG_INFO()
432+
425433
ZEND_BEGIN_ARG_INFO(arginfo_array_count_values, 0)
426434
ZEND_ARG_INFO(0, arg) /* ARRAY_INFO(0, arg, 0) */
427435
ZEND_END_ARG_INFO()
@@ -3362,6 +3370,8 @@ static const zend_function_entry basic_functions[] = { /* {{{ */
33623370
PHP_FE(array_replace, arginfo_array_replace)
33633371
PHP_FE(array_replace_recursive, arginfo_array_replace_recursive)
33643372
PHP_FE(array_keys, arginfo_array_keys)
3373+
PHP_FE(array_key_first, arginfo_array_key_first)
3374+
PHP_FE(array_key_last, arginfo_array_key_last)
33653375
PHP_FE(array_values, arginfo_array_values)
33663376
PHP_FE(array_count_values, arginfo_array_count_values)
33673377
PHP_FE(array_column, arginfo_array_column)

ext/standard/php_array.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ PHP_FUNCTION(array_merge_recursive);
6969
PHP_FUNCTION(array_replace);
7070
PHP_FUNCTION(array_replace_recursive);
7171
PHP_FUNCTION(array_keys);
72+
PHP_FUNCTION(array_key_first);
73+
PHP_FUNCTION(array_key_last);
7274
PHP_FUNCTION(array_values);
7375
PHP_FUNCTION(array_count_values);
7476
PHP_FUNCTION(array_column);
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
--TEST--
2+
Test array_key_first() function
3+
--FILE--
4+
<?php
5+
6+
array_key_first($GLOBALS);
7+
8+
/* Various combinations of arrays to be used for the test */
9+
$mixed_array = array(
10+
array(),
11+
array( 1,2,3,4,5,6,7,8,9 ),
12+
array( "One", "_Two", "Three", "Four", "Five" ),
13+
array( 6, "six", 7, "seven", 8, "eight", 9, "nine" ),
14+
array( "a" => "aaa", "A" => "AAA", "c" => "ccc", "d" => "ddd", "e" => "eee" ),
15+
array( "1" => "one", "2" => "two", "3" => "three", "4" => "four", "5" => "five" ),
16+
array( 1 => "one", 2 => "two", 3 => 7, 4 => "four", 5 => "five" ),
17+
array( "f" => "fff", "1" => "one", 4 => 6, "" => "blank", 2.4 => "float", "F" => "FFF",
18+
"blank" => "", 3.7 => 3.7, 5.4 => 7, 6 => 8.6, '5' => "Five", "4name" => "jonny", "a" => NULL, NULL => 3 ),
19+
array( 12, "name", 'age', '45' ),
20+
array( array("oNe", "tWo", 4), array(10, 20, 30, 40, 50), array() ),
21+
array( "one" => 1, "one" => 2, "three" => 3, 3, 4, 3 => 33, 4 => 44, 5, 6,
22+
5.4 => 54, 5.7 => 57, "5.4" => 554, "5.7" => 557 )
23+
);
24+
25+
/* Loop to test normal functionality with different arrays inputs */
26+
echo "\n*** Normal testing with various array inputs ***\n";
27+
28+
$counter = 1;
29+
foreach( $mixed_array as $sub_array )
30+
{
31+
echo "\n-- Input Array for Iteration $counter is --\n";
32+
print_r( $sub_array );
33+
echo "\nFirst key is :\n";
34+
var_dump( array_key_first($sub_array) );
35+
$counter++;
36+
}
37+
38+
echo"\nDone";
39+
?>
40+
--EXPECT--
41+
*** Normal testing with various array inputs ***
42+
43+
-- Input Array for Iteration 1 is --
44+
Array
45+
(
46+
)
47+
48+
First key is :
49+
NULL
50+
51+
-- Input Array for Iteration 2 is --
52+
Array
53+
(
54+
[0] => 1
55+
[1] => 2
56+
[2] => 3
57+
[3] => 4
58+
[4] => 5
59+
[5] => 6
60+
[6] => 7
61+
[7] => 8
62+
[8] => 9
63+
)
64+
65+
First key is :
66+
int(0)
67+
68+
-- Input Array for Iteration 3 is --
69+
Array
70+
(
71+
[0] => One
72+
[1] => _Two
73+
[2] => Three
74+
[3] => Four
75+
[4] => Five
76+
)
77+
78+
First key is :
79+
int(0)
80+
81+
-- Input Array for Iteration 4 is --
82+
Array
83+
(
84+
[0] => 6
85+
[1] => six
86+
[2] => 7
87+
[3] => seven
88+
[4] => 8
89+
[5] => eight
90+
[6] => 9
91+
[7] => nine
92+
)
93+
94+
First key is :
95+
int(0)
96+
97+
-- Input Array for Iteration 5 is --
98+
Array
99+
(
100+
[a] => aaa
101+
[A] => AAA
102+
[c] => ccc
103+
[d] => ddd
104+
[e] => eee
105+
)
106+
107+
First key is :
108+
string(1) "a"
109+
110+
-- Input Array for Iteration 6 is --
111+
Array
112+
(
113+
[1] => one
114+
[2] => two
115+
[3] => three
116+
[4] => four
117+
[5] => five
118+
)
119+
120+
First key is :
121+
int(1)
122+
123+
-- Input Array for Iteration 7 is --
124+
Array
125+
(
126+
[1] => one
127+
[2] => two
128+
[3] => 7
129+
[4] => four
130+
[5] => five
131+
)
132+
133+
First key is :
134+
int(1)
135+
136+
-- Input Array for Iteration 8 is --
137+
Array
138+
(
139+
[f] => fff
140+
[1] => one
141+
[4] => 6
142+
[] => 3
143+
[2] => float
144+
[F] => FFF
145+
[blank] =>
146+
[3] => 3.7
147+
[5] => Five
148+
[6] => 8.6
149+
[4name] => jonny
150+
[a] =>
151+
)
152+
153+
First key is :
154+
string(1) "f"
155+
156+
-- Input Array for Iteration 9 is --
157+
Array
158+
(
159+
[0] => 12
160+
[1] => name
161+
[2] => age
162+
[3] => 45
163+
)
164+
165+
First key is :
166+
int(0)
167+
168+
-- Input Array for Iteration 10 is --
169+
Array
170+
(
171+
[0] => Array
172+
(
173+
[0] => oNe
174+
[1] => tWo
175+
[2] => 4
176+
)
177+
178+
[1] => Array
179+
(
180+
[0] => 10
181+
[1] => 20
182+
[2] => 30
183+
[3] => 40
184+
[4] => 50
185+
)
186+
187+
[2] => Array
188+
(
189+
)
190+
191+
)
192+
193+
First key is :
194+
int(0)
195+
196+
-- Input Array for Iteration 11 is --
197+
Array
198+
(
199+
[one] => 2
200+
[three] => 3
201+
[0] => 3
202+
[1] => 4
203+
[3] => 33
204+
[4] => 44
205+
[5] => 57
206+
[6] => 6
207+
[5.4] => 554
208+
[5.7] => 557
209+
)
210+
211+
First key is :
212+
string(3) "one"
213+
214+
Done
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Test array_key_first() function (errors)
3+
--FILE--
4+
<?php
5+
6+
$empty_array = array();
7+
$number = 5;
8+
$str = "abc";
9+
10+
/* Various combinations of arrays to be used for the test */
11+
$mixed_array = array(
12+
array( 1,2,3,4,5,6,7,8,9 ),
13+
array( "One", "_Two", "Three", "Four", "Five" )
14+
);
15+
16+
/* Testing Error Conditions */
17+
echo "\n*** Testing Error Conditions ***\n";
18+
19+
/* Zero argument */
20+
var_dump( array_key_first() );
21+
22+
/* Scalar argument */
23+
var_dump( array_key_first($number) );
24+
25+
/* String argument */
26+
var_dump( array_key_first($str) );
27+
28+
/* Invalid Number of arguments */
29+
var_dump( array_key_first($mixed_array[0],$mixed_array[1]) );
30+
31+
/* Empty Array as argument */
32+
var_dump( array_key_first($empty_array) );
33+
34+
echo"\nDone";
35+
?>
36+
--EXPECTF--
37+
*** Testing Error Conditions ***
38+
39+
Warning: array_key_first() expects exactly 1 parameter, 0 given in %s on line %d
40+
NULL
41+
42+
Warning: array_key_first() expects parameter 1 to be array, int given in %s on line %d
43+
NULL
44+
45+
Warning: array_key_first() expects parameter 1 to be array, string given in %s on line %d
46+
NULL
47+
48+
Warning: array_key_first() expects exactly 1 parameter, 2 given in %s on line %d
49+
NULL
50+
NULL
51+
52+
Done
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Test array_key_first() function (variation)
3+
--FILE--
4+
<?php
5+
6+
/* Various combinations of arrays to be used for the test */
7+
$array = array( 1,2,3,4,5,6,7,8,9 );
8+
9+
echo"\n*** Checking for internal array pointer not being changed by array_key_first ***\n";
10+
11+
echo "\nCurrent Element is : ";
12+
var_dump( current($array) );
13+
14+
echo "\nNext Element is : ";
15+
var_dump( next($array) );
16+
17+
echo "\nFirst key is : ";
18+
var_dump( array_key_first($array) );
19+
20+
echo "\nCurrent Element after array_key_first operation is: ";
21+
var_dump( current($array) );
22+
23+
echo"\nDone";
24+
?>
25+
--EXPECT--
26+
*** Checking for internal array pointer not being changed by array_key_first ***
27+
28+
Current Element is : int(1)
29+
30+
Next Element is : int(2)
31+
32+
First key is : int(0)
33+
34+
Current Element after array_key_first operation is: int(2)
35+
36+
Done

0 commit comments

Comments
 (0)