├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── config.m4 ├── php_char_to_str.c ├── php_char_to_str.h ├── php_xarray.c ├── php_xarray.h └── tests ├── array_add ├── assoc.phpt ├── assoc_not_override.phpt └── basic.phpt ├── array_build └── basic.phpt ├── array_each ├── change_value.phpt ├── simple.phpt └── stop.phpt ├── array_first ├── array_first_empty.phpt ├── basic.phpt ├── default.phpt └── not-found.phpt ├── array_floatval └── index.phpt ├── array_intval ├── assoc.phpt └── index.phpt ├── array_is_indexed ├── indexed_array.phpt └── non_indexed_array.phpt ├── array_keys_join ├── join_with_dash.phpt └── join_without_delim.phpt ├── array_keys_prefix └── basic.phpt ├── array_keys_replace ├── basic.phpt └── fullmatch.phpt ├── array_keys_suffix └── basic.phpt ├── array_pluck_by_idx.phpt ├── array_pluck_by_idx_02.phpt ├── array_pluck_by_str.phpt └── array_remove └── basic.phpt /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | *.lo 3 | *.la 4 | .libs 5 | acinclude.m4 6 | aclocal.m4 7 | autom4te.cache 8 | build 9 | config.guess 10 | config.h 11 | config.h.in 12 | config.log 13 | config.nice 14 | config.status 15 | config.sub 16 | configure 17 | configure.in 18 | include 19 | install-sh 20 | libtool 21 | ltmain.sh 22 | Makefile 23 | Makefile.fragments 24 | Makefile.global 25 | Makefile.objects 26 | missing 27 | mkinstalldirs 28 | modules 29 | run-tests.php 30 | tests/*/*.diff 31 | tests/*/*.out 32 | tests/*/*.php 33 | tests/*/*.exp 34 | tests/*/*.log 35 | tests/*/*.sh 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.6 5 | - 5.5 6 | 7 | env: 8 | - NO_INTERACTION=1 9 | 10 | compiler: 11 | - gcc 12 | 13 | install: 14 | - sudo apt-get update -qq 15 | - sudo apt-get install -qq automake pkg-config build-essential libtool automake autoconf m4 gnulib php5-dev 16 | 17 | script: 18 | - phpize 19 | - ./configure 20 | - make 21 | - make test 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ============================= 3 | 4 | ### Sat Oct 17 19:06:41 2015 - 28d37d4850547a388f09fd09f9d3258633775415 5 | 6 | - Fixes memory leak issues. 7 | - Functions deleting keys now return new array instead of manipulating the 8 | array reference. (e.g. `array_remove`, `array_keys_replace`) 9 | 10 | ### alpha v0.1 11 | 12 | - Added `array_keys_replace` function with `XARRAY_FULLMATCH` constant. 13 | - Added `array_intval` function. 14 | - Added `array_floatval` function. 15 | - Added `array_add` function. 16 | - Added `array_remove` function. 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | xarray 2 | ======================================================== 3 | 4 | The missing PHP array functions you are looking for, implemented in extension. 5 | 6 | xarray implements the commonly used array functions in extension to improve 7 | performance and simplify array operations. 8 | 9 | If you found any array functions that might be commonly used and can be shared, 10 | please open a RFC (request for comments) issue. Please note that a RFC document 11 | should include comprehensive examples including input structure, output 12 | structure and background. 13 | 14 | [![Build Status](https://travis-ci.org/c9s/xarray.svg)](https://travis-ci.org/c9s/xarray) 15 | 16 | ## Stability 17 | 18 | - Release: alpha (The package is ready for testing by hard core users. Features 19 | are still being developed, but the program should work. Subsequent releases 20 | may have major changes.) 21 | 22 | - API: alpha (The API is starting to stabilize, but may still have major 23 | changes.) 24 | 25 | ## Required PHP 26 | 27 | - PHP 5.4.x (not tested) 28 | - PHP 5.5.x 29 | - PHP 5.6.x 30 | 31 | ## Installation 32 | 33 | phpize 34 | ./configure 35 | make install 36 | 37 | ## Functions 38 | 39 | ### array\_is\_indexed 40 | 41 | ```php 42 | bool array_is_indexed(array $array) 43 | ``` 44 | 45 | `array_is_indexed` function returns true when all the keys in the given array are 46 | long integer keys. (0, 1, 3, 100). 47 | 48 | 49 | ### array\_is\_assoc 50 | 51 | ```php 52 | bool array_is_assoc(array $array) 53 | ``` 54 | 55 | `array_is_assoc` function returns true when all the keys in the given array are 56 | string type keys. ('foo', 'bar'). 57 | 58 | 59 | ### array\_keys\_join 60 | 61 | ```php 62 | string array_keys_join(array $array, [string $delim]) 63 | ``` 64 | 65 | `array_keys_join` is useful when generating cache keys from array keys, this 66 | reduces the overhead of using `join('-', array_keys($array));`. 67 | 68 | ##### Design 69 | 70 | The delimeter argument is in the second position because it's optional. 71 | 72 | The built-in functions in PHP like `join($delim, $strings)`, `explode($delim, 73 | $string)` requires delimeter to join/explode string hence it's better to put 74 | the delimeter argument in the first position. 75 | 76 | ##### Example 77 | 78 | ```php 79 | echo array_keys_join([ "foo" => 1, "bar" => 123], "-"); 80 | echo array_keys_join([ "a" => 1, "b" => 123, "c" => "kkk" ], "-"); 81 | ``` 82 | 83 | Which outputs: 84 | 85 | ``` 86 | foo-bar 87 | a-b-c 88 | ``` 89 | 90 | ### array\_pluck 91 | 92 | ```php 93 | array array_pluck(array $array, [long $key | string $key]) 94 | ``` 95 | 96 | `array_pluck` is used for extracting element from array inside the given array. 97 | 98 | ##### Background 99 | 100 | `array_column` was implemented in PHP 5.5.x and PHP 7, however if you use PHP 101 | 5.4 or lower, you can install this extension to do the same thing. 102 | 103 | 104 | ##### Example 105 | 106 | Extracting element by string key: 107 | 108 | 109 | ```php 110 | $a = array( 111 | array( 'name' => "John", 'phone' => '123456' ), 112 | array( 'name' => "Mary", 'phone' => '123457' ), 113 | array( 'name' => "Lisa", 'phone' => '123458' ), 114 | ); 115 | $a = array_pluck($a, 'name'); 116 | print_r($a); 117 | ``` 118 | 119 | Outputs: 120 | 121 | ``` 122 | Array 123 | ( 124 | [0] => John 125 | [1] => Mary 126 | [2] => Lisa 127 | ) 128 | ``` 129 | 130 | Extracting element by index key: 131 | 132 | ```php 133 | $a = array( 134 | array(2 => "John"), 135 | array(2 => "Mary"), 136 | array(2 => "Lisa"), 137 | ); 138 | $a = array_pluck($a, 2); 139 | print_r($a); 140 | ``` 141 | 142 | Outputs: 143 | 144 | ``` 145 | Array 146 | ( 147 | [0] => John 148 | [1] => Mary 149 | [2] => Lisa 150 | ) 151 | ``` 152 | 153 | ##### See Also 154 | 155 | - 156 | 157 | 158 | 159 | ### array\_first 160 | 161 | ```php 162 | mixed array_first(array $array, callable $callable) 163 | ``` 164 | 165 | `array_first` returns the first element in an array passing a given truth test. 166 | 167 | ##### Example 168 | 169 | ```php 170 | $a = array( 171 | 0 => "John", 172 | 1 => "Mary", 173 | 2 => "Lisa", 174 | ); 175 | $a = array_first($a, function($key, $value) { 176 | return $key == 1; 177 | }); 178 | print_r($a); 179 | ``` 180 | 181 | Outputs: 182 | 183 | ``` 184 | Mary 185 | ``` 186 | 187 | 188 | 189 | ### array\_each 190 | 191 | ```php 192 | void array_each(array $array, callable $builder) 193 | ``` 194 | 195 | `array_each` iterates the array keys and values through a callback. 196 | 197 | If false value is returned from the callback, the iteration will stop. 198 | 199 | ##### FAQ 200 | 201 | > `array_each` - this is just a foreach with an isolated scope and function 202 | overhead on every iteration, why would I want that? 203 | 204 | `array_each` is pretty much like `array_map` except it doesn't return any value. 205 | 206 | Sometimes you want to pass a iteration handler from external, and `array_map` 207 | is a way to do this, but `array_map` only pass array value to your closure. 208 | 209 | `array_each` is faster than `array_map` because it's simpler and it doesn't 210 | return value. 211 | 212 | ##### Example 213 | 214 | ```php 215 | $a = array( 216 | 0 => "John", 217 | 1 => "Mary", 218 | 2 => "Lisa", 219 | ); 220 | $b = []; 221 | array_each($a, function($key, $value) use(&$b) { 222 | $b[$key] = $value; 223 | }); 224 | print_r($b); 225 | ``` 226 | 227 | The example above will output: 228 | 229 | ``` 230 | Array 231 | ( 232 | [0] => John 233 | [1] => Mary 234 | [2] => Lisa 235 | ) 236 | ``` 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | ### array\_build 248 | 249 | ```php 250 | array array_build(array $array, callable $builder) 251 | ``` 252 | 253 | `array_build` builds the new array with new keys and new values. 254 | 255 | 256 | ##### Builder 257 | 258 | The array builder must return a key-value pair to insert a new item. 259 | If null value or false value is returned, the entry will be ignored. 260 | 261 | ```php 262 | list($newKey, $newValue) = $builder($key, $value); 263 | ``` 264 | 265 | ##### Example 266 | 267 | ```php 268 | $a = array( 269 | array("name" => "John", "id" => "j"), 270 | array("name" => "Mary", "id" => "m"), 271 | array("name" => "Lisa", "id" => "l"), 272 | ); 273 | $b = array(); 274 | $b = array_build($a, function($key, $value) { 275 | return array($value['id'], $value['name']); 276 | }); 277 | print_r($b); 278 | ``` 279 | 280 | The example above will output: 281 | 282 | ``` 283 | Array 284 | ( 285 | [j] => John 286 | [m] => Mary 287 | [l] => Lisa 288 | ) 289 | ``` 290 | 291 | 292 | 293 | 294 | ### array\_keys\_prefix 295 | 296 | ```php 297 | array array_keys_prefix(array $array, string $prefix) 298 | ``` 299 | 300 | `array_keys_prefix` returns a new array by prepending prefix string from the original keys. 301 | 302 | ##### Example 303 | 304 | ```php 305 | $a = array( 306 | "name" => "John", 307 | "id" => "j", 308 | "phone" => "+886975123123", 309 | ); 310 | $b = array_keys_prefix($a, "my_"); 311 | print_r($b); 312 | ``` 313 | 314 | The example above will output: 315 | 316 | ``` 317 | Array 318 | ( 319 | [my_name] => John 320 | [my_id] => j 321 | [my_phone] => +886975123123 322 | ) 323 | ``` 324 | 325 | 326 | 327 | 328 | ### array\_keys\_suffix 329 | 330 | ```php 331 | array array_keys_suffix(array $array, string $suffix) 332 | ``` 333 | 334 | Append suffix string to the keys. 335 | 336 | ##### Example 337 | 338 | ```php 339 | $a = array( 340 | "create" => 1, 341 | "update" => 2, 342 | ); 343 | $b = array_keys_suffix($a, "_at"); 344 | print_r($b); 345 | ``` 346 | 347 | The example above will output: 348 | 349 | ``` 350 | Array 351 | ( 352 | [create_at] => 1 353 | [update_at] => 2 354 | ) 355 | ``` 356 | 357 | 358 | 359 | ### array\_keys\_replace 360 | 361 | ```php 362 | array array_keys_replace(array $array, array $replacements [, $options = 0]) 363 | ``` 364 | 365 | Replace all occurrences of the keys in the array with the replacement string 366 | 367 | `$options` is optional, if `XARRAY_FULLMATCH` is given, only keys full matched will be replaced. 368 | 369 | ##### Example 370 | 371 | ```php 372 | $a = array( 373 | "id" => 12345, 374 | "name" => "John", 375 | "phone" => "+886975123123", 376 | "created_at" => "2012-01-01", 377 | "updated_at" => "2012-02-02", 378 | ); 379 | $a = array_keys_replace($a, array( 380 | "_at" => "_on", 381 | )); 382 | print_r($a); 383 | ``` 384 | 385 | The example above will output: 386 | 387 | ``` 388 | Array 389 | ( 390 | [name] => John 391 | [phone] => +886975123123 392 | [created_on] => 2012-01-01 393 | [updated_on] => 2012-02-02 394 | [id] => 12345 395 | ) 396 | ``` 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | ### array\_add 407 | 408 | ```php 409 | string array_add(array $array, string|long $key, $elemnt) 410 | ``` 411 | 412 | `array_add` add the new element into the given array only when the key is not set. 413 | 414 | ##### FAQ 415 | 416 | > `array_add` - why do I need the overhead of a function call, when I can do `$a[*key*] = *value*` 417 | 418 | The reason has been described in the document: array_add only adds data when the key doesn't exist. 419 | 420 | You can treat it as a set operation, you used to write: 421 | 422 | ```php 423 | $array = []; 424 | if (!isset($array["key"])) { 425 | $array["key"] = 10; 426 | } 427 | if (!isset($array["key"])) { 428 | $array["key"] = 20; 429 | } 430 | ``` 431 | 432 | Now you can write: 433 | 434 | ```php 435 | $array = [ ]; 436 | array_add($array, "key", 10); // key => 10, return true 437 | array_add($array, "key", 20); // key => 10 still, return false 438 | ``` 439 | 440 | 441 | 442 | ##### Example 443 | 444 | ```php 445 | $a = array( 446 | "foo" => "a", 447 | "zoo" => "c", 448 | ); 449 | array_add($a, "bar", "b"); 450 | print_r($a); 451 | ``` 452 | 453 | The example above will output: 454 | 455 | ``` 456 | Array 457 | ( 458 | [foo] => a 459 | [zoo] => c 460 | [bar] => b 461 | ) 462 | ``` 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | ### array\_remove 471 | 472 | ```php 473 | array array_remove(array $array, callable $callback) 474 | ``` 475 | 476 | `array_remove` remove the element from the given array by the callback. 477 | 478 | ##### FAQ 479 | 480 | > `array_remove` is just `array_filter`, why do I need another function for that? 481 | 482 | In PHP 5.5, `array_filter` only passes value to the callback. In PHP 5.6, a 483 | new option was added to support passing both key and value to the callback, 484 | however PHP 5.5 doesn't have this option. 485 | 486 | Implementing this function in extension makes passing both key, value possible. 487 | 488 | ##### Example 489 | 490 | ```php 491 | $a = array( 492 | "foo" => "a", 493 | "bar" => "b", 494 | "zoo" => "c", 495 | ); 496 | // delete "foo" key from $a 497 | $a = array_remove($a, function($key, $value) { 498 | return $value === "b"; 499 | }); 500 | print_r($a); 501 | ``` 502 | 503 | The example above will output: 504 | 505 | ``` 506 | Array 507 | ( 508 | [foo] => a 509 | [zoo] => c 510 | ) 511 | ``` 512 | 513 | 514 | 515 | 516 | 517 | 518 | ### array\_intval 519 | 520 | ```php 521 | array array_intval(array $array [, int $base]) 522 | ``` 523 | 524 | `array_intval` convert the array values into intval through `intval` function. 525 | 526 | Return the new array with int values. 527 | 528 | ##### Example 529 | 530 | ```php 531 | $a = array( "01", "2", "3", "10", 100 => "20"); 532 | $b = array_intval($a); 533 | print_r($b); 534 | ``` 535 | 536 | The example above will output: 537 | 538 | ``` 539 | Array 540 | ( 541 | [0] => 1 542 | [1] => 2 543 | [2] => 3 544 | [3] => 10 545 | [4] => 20 546 | ) 547 | ``` 548 | 549 | 550 | 551 | 552 | 553 | ### array\_floatval 554 | 555 | ```php 556 | array array_floatval(array $array) 557 | ``` 558 | 559 | `array_doubleval` convert the array values into floatval through `floatval` function. 560 | 561 | Return the new array with int values. 562 | 563 | ##### Example 564 | 565 | ```php 566 | $a = array("1.111", "2.222"); 567 | $b = array_floatval($a); 568 | print_r($b); 569 | ``` 570 | 571 | The example above will output: 572 | 573 | ``` 574 | Array 575 | ( 576 | [0] => 1.111 577 | [1] => 2.222 578 | ) 579 | ``` 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | ## Benchmarks 588 | 589 | 590 | phparrayindexed 3024 times 0.331036ms/op 591 | xarrayindexed 90108 times 0.011106ms/op 592 | xarrayassoc 63230 times 0.015821ms/op 593 | 594 | phparraykeysjoin 13631 times 0.073684ms/op 595 | xarraykeysjoin 21539 times 0.048384ms/op 596 | 597 | phparraypluck 6185 times 0.163442ms/op 598 | xarraypluck 20788 times 0.049178ms/op 599 | 600 | phparrayfirst 24618 times 0.040935ms/op 601 | xarrayfirst 80697 times 0.012496ms/op 602 | 603 | phparrayeach_foreach 300 times 3.377887ms/op 604 | phparrayeach_arraymap 342 times 2.981806ms/op 605 | xarrayeach 348 times 2.875893ms/op 606 | 607 | phparraybuild 261 times 3.845187ms/op 608 | xarraybuild 295 times 3.421549ms/op 609 | 610 | phparraykeysprefix 3773 times 0.266558ms/op 611 | xarraykeysprefix 8133 times 0.123620ms/op 612 | 613 | phparraykeyssuffix 3644 times 0.277876ms/op 614 | xarraykeyssuffix 5147 times 0.194443ms/op 615 | 616 | phparraykeysreplace 674 times 1.514104ms/op 617 | xarraykeysreplace 561761 times 0.001782ms/op 618 | 619 | phparrayadd 1265078 times 0.000795ms/op 620 | xarrayadd 768043 times 0.001321ms/op 621 | 622 | 623 | 624 | ## FAQ 625 | 626 | Q: Why `array_keys_join` and `array_keys_prefix` are named with `keys` in plural. 627 | 628 | A: The `keys` means the operation works on multiple keys, not just one of them. 629 | 630 | 631 | 632 | 633 | 634 | 635 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(xarray, whether to enable foo extension support, 2 | [--enable-xarray Enable xarray extension support]) 3 | PHP_NEW_EXTENSION(xarray, php_xarray.c php_char_to_str.c, $ext_shared) 4 | -------------------------------------------------------------------------------- /php_char_to_str.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "standard/php_string.h" 4 | 5 | 6 | 7 | 8 | 9 | 10 | /** 11 | * Faster php_char_to_str_ex 12 | */ 13 | PHPAPI int php_char_to_str_cs(char *str, uint len, char from, char *to, int to_len, zval *result) 14 | { 15 | int char_count = 0; 16 | int replaced = 0; 17 | char *source, *target, *tmp, *source_end=str+len, *tmp_end = NULL; 18 | 19 | char * p = str, * e = p + len; 20 | char * s; 21 | while ((p = memchr(p, from, (e - p)))) { 22 | char_count++; 23 | p++; 24 | } 25 | 26 | if (char_count == 0) { 27 | ZVAL_STRINGL(result, str, len, 1); 28 | return 0; 29 | } 30 | 31 | Z_STRLEN_P(result) = len + (char_count * (to_len - 1)); 32 | Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1); 33 | Z_TYPE_P(result) = IS_STRING; 34 | 35 | p = str, e = p + len, s = str; 36 | while ((p = memchr(p, from, (e - p)))) { 37 | memcpy(target, s, (p - s)); 38 | target += p - s; 39 | memcpy(target, to, to_len); 40 | target += to_len; 41 | p++; 42 | s = p; 43 | } 44 | if (s < e) { 45 | memcpy(target, s, (e - s)); 46 | target += e - s; 47 | } 48 | *target = 0; 49 | return replaced; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /php_char_to_str.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_CHAR_TO_STR_H 2 | #define PHP_CHAR_TO_STR_H 3 | 4 | #include 5 | #include 6 | #include "standard/php_string.h" 7 | 8 | PHPAPI int php_char_to_str_cs(char *str, uint len, char from, char *to, int to_len, zval *result); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /php_xarray.c: -------------------------------------------------------------------------------- 1 | #include "php_xarray.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "php_char_to_str.h" 8 | 9 | PHP_MINIT_FUNCTION(xarray); 10 | PHP_MSHUTDOWN_FUNCTION(xarray); 11 | PHP_MINFO_FUNCTION(xarray); 12 | 13 | #if COMPILE_DL_XARRAY 14 | ZEND_GET_MODULE(xarray) 15 | #endif 16 | 17 | 18 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_is_assoc, 0, 0, 1) 19 | ZEND_ARG_ARRAY_INFO(0, array, 0) 20 | ZEND_END_ARG_INFO() 21 | 22 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_is_indexed, 0, 0, 1) 23 | ZEND_ARG_ARRAY_INFO(0, array, 0) 24 | ZEND_END_ARG_INFO() 25 | 26 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys_join, 0, 0, 1) 27 | ZEND_ARG_ARRAY_INFO(0, array, 0) 28 | ZEND_ARG_INFO(0, delim) 29 | ZEND_END_ARG_INFO() 30 | 31 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_pluck, 0, 0, 2) 32 | ZEND_ARG_ARRAY_INFO(0, array, 0) 33 | ZEND_ARG_INFO(0, plurk key) 34 | ZEND_END_ARG_INFO() 35 | 36 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_first, 0, 0, 2) 37 | ZEND_ARG_ARRAY_INFO(0, array, 0) 38 | ZEND_ARG_INFO(0, callable_tester) 39 | ZEND_END_ARG_INFO() 40 | 41 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_each, 0, 0, 2) 42 | ZEND_ARG_ARRAY_INFO(0, array, 0) 43 | ZEND_ARG_INFO(0, callable) 44 | ZEND_END_ARG_INFO() 45 | 46 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_intval, 0, 0, 1) 47 | ZEND_ARG_ARRAY_INFO(0, array, 0) 48 | ZEND_ARG_INFO(0, base) 49 | ZEND_END_ARG_INFO() 50 | 51 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_floatval, 0, 0, 1) 52 | ZEND_ARG_ARRAY_INFO(0, array, 0) 53 | ZEND_END_ARG_INFO() 54 | 55 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_build, 0, 0, 2) 56 | ZEND_ARG_ARRAY_INFO(0, array, 0) 57 | ZEND_ARG_INFO(0, callable_builder) 58 | ZEND_END_ARG_INFO() 59 | 60 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_remove, 0, 0, 2) 61 | ZEND_ARG_ARRAY_INFO(0, array, 1) 62 | ZEND_ARG_INFO(0, callable_builder) 63 | ZEND_END_ARG_INFO() 64 | 65 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys_prefix, 0, 0, 2) 66 | ZEND_ARG_ARRAY_INFO(0, array, 0) 67 | ZEND_ARG_INFO(0, prefix) 68 | ZEND_END_ARG_INFO() 69 | 70 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys_suffix, 0, 0, 2) 71 | ZEND_ARG_ARRAY_INFO(0, array, 0) 72 | ZEND_ARG_INFO(0, suffix) 73 | ZEND_END_ARG_INFO() 74 | 75 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_add, 0, 0, 3) 76 | ZEND_ARG_ARRAY_INFO(1, array, 0) 77 | ZEND_ARG_INFO(0, key) 78 | ZEND_ARG_INFO(0, element) 79 | ZEND_END_ARG_INFO() 80 | 81 | ZEND_BEGIN_ARG_INFO_EX(arginfo_array_keys_replace, 0, 0, 2) 82 | ZEND_ARG_ARRAY_INFO(1, array, 0) 83 | ZEND_ARG_INFO(0, replacements) 84 | ZEND_END_ARG_INFO() 85 | 86 | 87 | static const zend_function_entry xarray_functions[] = { 88 | PHP_FE(array_is_indexed, arginfo_array_is_indexed) 89 | PHP_FE(array_is_assoc, arginfo_array_is_assoc) 90 | PHP_FE(array_keys_join, arginfo_array_keys_join) 91 | PHP_FE(array_pluck, arginfo_array_pluck) 92 | PHP_FE(array_first, arginfo_array_first) 93 | PHP_FE(array_each, arginfo_array_each) 94 | PHP_FE(array_build, arginfo_array_build) 95 | PHP_FE(array_remove, arginfo_array_remove) 96 | PHP_FE(array_keys_prefix, arginfo_array_keys_prefix) 97 | PHP_FE(array_keys_suffix, arginfo_array_keys_suffix) 98 | PHP_FE(array_add, arginfo_array_add) 99 | PHP_FE(array_keys_replace, arginfo_array_keys_replace) 100 | PHP_FE(array_intval, arginfo_array_intval) 101 | PHP_FE(array_floatval, arginfo_array_floatval) 102 | PHP_FE_END 103 | }; 104 | 105 | 106 | zend_module_entry xarray_module_entry = { 107 | STANDARD_MODULE_HEADER, 108 | "xarray", 109 | xarray_functions, // where you define your functions 110 | PHP_MINIT(xarray), 111 | PHP_MSHUTDOWN(xarray), 112 | NULL, // PHP_RINIT(xarray) 113 | NULL, // PHP_RSHUTDOWN(xarray) 114 | PHP_MINFO(xarray), 115 | XARRAY_VERSION, 116 | STANDARD_MODULE_PROPERTIES 117 | }; 118 | 119 | PHP_MINIT_FUNCTION(xarray) { 120 | REGISTER_LONG_CONSTANT("XARRAY_FULLMATCH", PHP_XARRAY_FULLMATCH, CONST_CS | CONST_PERSISTENT); 121 | REGISTER_LONG_CONSTANT("XARRAY_PARTIALMATCH", PHP_XARRAY_PARTIALMATCH, CONST_CS | CONST_PERSISTENT); 122 | return SUCCESS; 123 | } 124 | 125 | PHP_MSHUTDOWN_FUNCTION(xarray) { 126 | return SUCCESS; 127 | } 128 | 129 | PHP_MINFO_FUNCTION(xarray) { 130 | } 131 | 132 | 133 | /* 134 | static function is_indexed_array( & $array) { 135 | $keys = array_keys($array); 136 | $keys2 = array_filter($keys,'is_numeric'); 137 | return count($keys) == count($keys2); 138 | } 139 | */ 140 | PHP_FUNCTION(array_is_indexed) { 141 | zval *array; 142 | 143 | // for php7 144 | // zend_ulong num_key; 145 | // zend_string *key; 146 | char *key; 147 | uint key_len; 148 | ulong num_index; 149 | 150 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { 151 | RETURN_FALSE; 152 | } 153 | 154 | HashTable *arr_hash = Z_ARRVAL_P(array); 155 | HashPosition pos; 156 | zval **data; 157 | 158 | for(zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 159 | zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pos) == SUCCESS; 160 | zend_hash_move_forward_ex(arr_hash, &pos)) 161 | { 162 | if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) { 163 | RETURN_FALSE; 164 | } 165 | } 166 | RETURN_TRUE; 167 | } 168 | 169 | 170 | PHP_FUNCTION(array_is_assoc) { 171 | zval *array; 172 | 173 | // for php7 174 | // zend_ulong num_key; 175 | // zend_string *key; 176 | char *key; 177 | uint key_len; 178 | ulong num_index; 179 | 180 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { 181 | RETURN_FALSE; 182 | } 183 | 184 | HashTable *arr_hash = Z_ARRVAL_P(array); 185 | HashPosition pos; 186 | zval **data; 187 | 188 | for(zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 189 | zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pos) == SUCCESS; 190 | zend_hash_move_forward_ex(arr_hash, &pos)) 191 | { 192 | if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_LONG) { 193 | RETURN_FALSE; 194 | } 195 | } 196 | RETURN_TRUE; 197 | } 198 | 199 | 200 | PHP_FUNCTION(array_each) { 201 | 202 | zval *array; 203 | zend_fcall_info fci; 204 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache; 205 | zval *default_value; 206 | 207 | zval **args[2]; 208 | zval *retval; 209 | 210 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af|z", &array, &fci, &fci_cache, &default_value) == FAILURE) { 211 | RETURN_FALSE; 212 | } 213 | 214 | fci.retval_ptr_ptr = &retval; 215 | fci.param_count = 2; 216 | fci.no_separation = 0; 217 | 218 | HashTable *arr_hash; 219 | HashPosition pos; 220 | zval **arr_value; 221 | 222 | arr_hash = Z_ARRVAL_P(array); 223 | zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 224 | while (zend_hash_get_current_data_ex(arr_hash, (void **)&arr_value, &pos) == SUCCESS) { 225 | 226 | zval *arr_key = NULL; 227 | MAKE_STD_ZVAL(arr_key); 228 | 229 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 230 | args[0] = &arr_key; 231 | args[1] = arr_value; 232 | fci.params = args; 233 | 234 | if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { 235 | if (Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 0) { 236 | if (retval) { 237 | zval_ptr_dtor(&arr_key); 238 | zval_ptr_dtor(&retval); 239 | } 240 | break; 241 | } 242 | } 243 | if (retval) { 244 | zval_ptr_dtor(&retval); 245 | } 246 | 247 | zval_ptr_dtor(&arr_key); 248 | zend_hash_move_forward_ex(arr_hash, &pos); 249 | } 250 | } 251 | 252 | 253 | 254 | 255 | PHP_FUNCTION(array_boolval) { 256 | zval *array; 257 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { 258 | RETURN_FALSE; 259 | } 260 | 261 | zval **array_value; 262 | HashTable *array_hash; 263 | HashPosition pos; 264 | 265 | char *string_key; 266 | uint string_key_len; 267 | ulong num_index; 268 | 269 | array_hash = Z_ARRVAL_P(array); 270 | array_init(return_value); 271 | zend_hash_internal_pointer_reset_ex(array_hash, &pos); 272 | while (zend_hash_get_current_data_ex(array_hash, (void **)&array_value, &pos) == SUCCESS) { 273 | switch (zend_hash_get_current_key_ex(array_hash, &string_key, &string_key_len, &num_index, 0, &pos)) { 274 | case HASH_KEY_IS_STRING: 275 | SEPARATE_ZVAL(array_value); 276 | Z_ADDREF_PP(array_value); 277 | convert_to_boolean(*array_value); 278 | zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, array_value, sizeof(zval *), NULL); 279 | break; 280 | case HASH_KEY_IS_LONG: 281 | SEPARATE_ZVAL(array_value); 282 | Z_ADDREF_PP(array_value); 283 | convert_to_boolean(*array_value); 284 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), array_value, sizeof(zval *), NULL); 285 | break; 286 | } 287 | zend_hash_move_forward_ex(array_hash, &pos); 288 | } 289 | } 290 | 291 | 292 | 293 | 294 | PHP_FUNCTION(array_floatval) { 295 | zval *array; 296 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { 297 | RETURN_FALSE; 298 | } 299 | 300 | zval **array_value; 301 | HashTable *array_hash; 302 | HashPosition pos; 303 | 304 | char *string_key; 305 | uint string_key_len; 306 | ulong num_index; 307 | 308 | array_hash = Z_ARRVAL_P(array); 309 | array_init(return_value); 310 | zend_hash_internal_pointer_reset_ex(array_hash, &pos); 311 | while (zend_hash_get_current_data_ex(array_hash, (void **)&array_value, &pos) == SUCCESS) { 312 | switch (zend_hash_get_current_key_ex(array_hash, &string_key, &string_key_len, &num_index, 0, &pos)) { 313 | case HASH_KEY_IS_STRING: 314 | SEPARATE_ZVAL(array_value); 315 | Z_ADDREF_PP(array_value); 316 | convert_to_double(*array_value); 317 | zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, array_value, sizeof(zval *), NULL); 318 | break; 319 | case HASH_KEY_IS_LONG: 320 | SEPARATE_ZVAL(array_value); 321 | Z_ADDREF_PP(array_value); 322 | convert_to_double(*array_value); 323 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), array_value, sizeof(zval *), NULL); 324 | break; 325 | } 326 | zend_hash_move_forward_ex(array_hash, &pos); 327 | } 328 | } 329 | 330 | 331 | 332 | PHP_FUNCTION(array_intval) { 333 | zval *array; 334 | long base = 10; 335 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|l", &array, &base) == FAILURE) { 336 | RETURN_FALSE; 337 | } 338 | 339 | zval **array_value; 340 | HashTable *array_hash; 341 | HashPosition pos; 342 | 343 | char *string_key; 344 | uint string_key_len; 345 | ulong num_index; 346 | 347 | array_hash = Z_ARRVAL_P(array); 348 | array_init(return_value); 349 | zend_hash_internal_pointer_reset_ex(array_hash, &pos); 350 | while (zend_hash_get_current_data_ex(array_hash, (void **)&array_value, &pos) == SUCCESS) { 351 | switch (zend_hash_get_current_key_ex(array_hash, &string_key, &string_key_len, &num_index, 0, &pos)) { 352 | case HASH_KEY_IS_STRING: 353 | SEPARATE_ZVAL(array_value); 354 | Z_ADDREF_PP(array_value); 355 | convert_to_long_base(*array_value, base); 356 | zend_hash_update(Z_ARRVAL_P(return_value), string_key, string_key_len, array_value, sizeof(zval *), NULL); 357 | break; 358 | case HASH_KEY_IS_LONG: 359 | SEPARATE_ZVAL(array_value); 360 | Z_ADDREF_PP(array_value); 361 | convert_to_long_base(*array_value, base); 362 | zend_hash_next_index_insert(Z_ARRVAL_P(return_value), array_value, sizeof(zval *), NULL); 363 | break; 364 | } 365 | zend_hash_move_forward_ex(array_hash, &pos); 366 | } 367 | } 368 | 369 | 370 | 371 | 372 | 373 | 374 | PHP_FUNCTION(array_build) { 375 | 376 | zval *array; 377 | zend_fcall_info fci; 378 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache; 379 | zval **args[2]; 380 | zval *retval; 381 | 382 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &fci, &fci_cache) == FAILURE) { 383 | RETURN_FALSE; 384 | } 385 | 386 | 387 | // configure callable parameters 388 | fci.retval_ptr_ptr = &retval; 389 | fci.param_count = 2; 390 | fci.no_separation = 0; 391 | 392 | 393 | HashTable *arr_hash; 394 | HashPosition pos; 395 | zval **arr_value; 396 | 397 | arr_hash = Z_ARRVAL_P(array); 398 | 399 | array_init(return_value); 400 | int numelems = zend_hash_num_elements(arr_hash); 401 | if (numelems == 0) { 402 | return; 403 | } 404 | 405 | zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 406 | while (zend_hash_get_current_data_ex(arr_hash, (void **)&arr_value, &pos) == SUCCESS) { 407 | 408 | zval *arr_key = NULL; 409 | MAKE_STD_ZVAL(arr_key); 410 | 411 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 412 | args[0] = &arr_key; 413 | args[1] = arr_value; 414 | fci.params = args; 415 | 416 | if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS && retval) { 417 | if (Z_TYPE_P(retval) == IS_ARRAY) { 418 | zval **new_key = NULL; 419 | zval **new_value = NULL; 420 | if (zend_hash_index_find(Z_ARRVAL_P(retval), 0, (void**) &new_key) == FAILURE) { 421 | zval_ptr_dtor(&arr_key); 422 | if (retval) { 423 | zval_ptr_dtor(&retval); 424 | } 425 | continue; 426 | } 427 | if (zend_hash_index_find(Z_ARRVAL_P(retval), 1, (void**) &new_value) == FAILURE) { 428 | zval_ptr_dtor(&arr_key); 429 | if (retval) { 430 | zval_ptr_dtor(&retval); 431 | } 432 | continue; 433 | } 434 | 435 | if (Z_TYPE_PP(new_key) == IS_STRING) { 436 | 437 | Z_ADDREF_PP(new_value); 438 | add_assoc_zval_ex(return_value, Z_STRVAL_PP(new_key), Z_STRLEN_PP(new_key) + 1, *new_value); 439 | 440 | } else if (Z_TYPE_PP(new_key) == IS_LONG) { 441 | 442 | Z_ADDREF_PP(new_value); 443 | add_index_zval(return_value, Z_LVAL_PP(new_key), *new_value); 444 | 445 | } 446 | } 447 | zval_ptr_dtor(&retval); 448 | } 449 | 450 | zval_ptr_dtor(&arr_key); 451 | zend_hash_move_forward_ex(arr_hash, &pos); 452 | } 453 | } 454 | 455 | 456 | 457 | 458 | PHP_FUNCTION(array_remove) { 459 | 460 | zval *array; 461 | zend_fcall_info fci; 462 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache; 463 | zval **args[2]; 464 | zval *retval; 465 | 466 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af", &array, &fci, &fci_cache) == FAILURE) { 467 | RETURN_FALSE; 468 | } 469 | 470 | 471 | // configure callable parameters 472 | fci.retval_ptr_ptr = &retval; 473 | fci.param_count = 2; 474 | fci.no_separation = 0; 475 | 476 | HashTable *arr_hash; 477 | HashPosition pos; 478 | zval **arr_value; 479 | 480 | arr_hash = Z_ARRVAL_P(array); 481 | 482 | int numelems = zend_hash_num_elements(arr_hash); 483 | if (numelems == 0) { 484 | return; 485 | } 486 | 487 | array_init(return_value); 488 | zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 489 | while (zend_hash_get_current_data_ex(arr_hash, (void **)&arr_value, &pos) == SUCCESS) { 490 | 491 | zval *arr_key = NULL; 492 | MAKE_STD_ZVAL(arr_key); 493 | 494 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 495 | args[0] = &arr_key; 496 | args[1] = arr_value; 497 | fci.params = args; 498 | 499 | if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS) { 500 | if (retval) { 501 | if (Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 1) { 502 | 503 | } else { 504 | if (Z_TYPE_P(arr_key) == IS_LONG) { 505 | 506 | Z_ADDREF_PP(arr_value); 507 | add_index_zval(return_value, Z_LVAL_P(arr_key), *arr_value); 508 | 509 | } else if (Z_TYPE_P(arr_key) == IS_STRING) { 510 | 511 | Z_ADDREF_PP(arr_value); 512 | add_assoc_zval_ex(return_value, Z_STRVAL_P(arr_key), Z_STRLEN_P(arr_key) + 1, *arr_value); 513 | 514 | } 515 | } 516 | zval_ptr_dtor(&retval); 517 | } 518 | 519 | } 520 | zend_hash_move_forward_ex(arr_hash, &pos); 521 | zval_ptr_dtor(&arr_key); 522 | } 523 | } 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | PHP_FUNCTION(array_first) { 532 | 533 | zval *array; 534 | zend_fcall_info fci; 535 | zend_fcall_info_cache fci_cache = empty_fcall_info_cache; 536 | zval *default_value = NULL; 537 | 538 | zval **args[2]; 539 | zval *retval; 540 | 541 | 542 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "af|z", &array, &fci, &fci_cache, &default_value) == FAILURE) { 543 | RETURN_FALSE; 544 | } 545 | 546 | 547 | // configure callable parameters 548 | fci.retval_ptr_ptr = &retval; 549 | fci.param_count = 2; 550 | fci.no_separation = 0; 551 | 552 | 553 | HashTable *arr_hash; 554 | HashPosition pos; 555 | zval **arr_value; 556 | 557 | arr_hash = Z_ARRVAL_P(array); 558 | 559 | int numelems = zend_hash_num_elements(arr_hash); 560 | if (numelems == 0) { 561 | if (default_value != NULL) { 562 | *return_value = *default_value; 563 | zval_copy_ctor(return_value); 564 | return; 565 | } else { 566 | RETURN_NULL(); 567 | } 568 | } 569 | 570 | // array_init(return_value); 571 | zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 572 | while (zend_hash_get_current_data_ex(arr_hash, (void **)&arr_value, &pos) == SUCCESS) { 573 | zval *arr_key = NULL; 574 | MAKE_STD_ZVAL(arr_key); 575 | 576 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 577 | args[0] = &arr_key; 578 | args[1] = arr_value; 579 | fci.params = args; 580 | 581 | if (zend_call_function(&fci, &fci_cache TSRMLS_CC) == SUCCESS) { 582 | if (retval) { 583 | if (Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval)) { 584 | *return_value = **arr_value; 585 | zval_copy_ctor(return_value); 586 | zval_ptr_dtor(&retval); 587 | zval_ptr_dtor(&arr_key); 588 | return; 589 | // add_next_index_zval(return_value, *arr_value); 590 | } 591 | zval_ptr_dtor(&retval); 592 | } 593 | } 594 | zend_hash_move_forward_ex(arr_hash, &pos); 595 | zval_ptr_dtor(&arr_key); 596 | } 597 | 598 | 599 | if (default_value != NULL) { 600 | *return_value = *default_value; 601 | zval_copy_ctor(return_value); 602 | return; 603 | 604 | } else { 605 | 606 | RETURN_NULL(); 607 | 608 | } 609 | } 610 | 611 | 612 | PHP_FUNCTION(array_keys_prefix) { 613 | zval *array; 614 | char *prefix; 615 | int prefix_len; 616 | 617 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "as", &array, &prefix, &prefix_len) == FAILURE) { 618 | RETURN_FALSE; 619 | } 620 | 621 | HashTable *arr_hash = Z_ARRVAL_P(array); 622 | HashPosition pos; 623 | zval **item; 624 | int numelems, i = 0; 625 | int str_len; 626 | 627 | numelems = zend_hash_num_elements(arr_hash); 628 | if (numelems == 0) { 629 | return; 630 | } 631 | 632 | 633 | array_init(return_value); 634 | for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 635 | zend_hash_get_current_data_ex(arr_hash, (void**) &item, &pos) == SUCCESS; 636 | zend_hash_move_forward_ex(arr_hash, &pos)) 637 | { 638 | zval *arr_key = NULL; 639 | MAKE_STD_ZVAL(arr_key); 640 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 641 | if (Z_TYPE_P(arr_key) == IS_STRING) { 642 | smart_str implstr = {0}; 643 | smart_str_appendl(&implstr, prefix, prefix_len); 644 | smart_str_appendl(&implstr, Z_STRVAL_P(arr_key), Z_STRLEN_P(arr_key)); 645 | smart_str_0(&implstr); 646 | add_assoc_zval_ex(return_value, implstr.c, implstr.len + 1, *item); 647 | smart_str_free(&implstr); 648 | } else { 649 | add_index_zval(return_value, Z_LVAL_P(arr_key), *item); 650 | } 651 | zval_ptr_dtor(&arr_key); 652 | } 653 | } 654 | 655 | 656 | PHP_FUNCTION(array_keys_replace) { 657 | zval *array; 658 | zval *replacement; 659 | long options = 0; 660 | 661 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa|l", &array, &replacement, &options) == FAILURE) { 662 | RETURN_FALSE; 663 | } 664 | 665 | 666 | HashTable *array_hash = Z_ARRVAL_P(array); 667 | HashPosition pos; 668 | HashTable *replacement_hash = Z_ARRVAL_P(replacement); 669 | HashPosition replacement_pos; 670 | 671 | zend_hash_internal_pointer_reset_ex(array_hash, &pos); 672 | zval **tmp; 673 | 674 | char *str_index; 675 | uint str_index_len; 676 | ulong num_index; 677 | 678 | array_init(return_value); 679 | while (SUCCESS == zend_hash_get_current_data_ex(array_hash, (void **) &tmp, &pos)) { 680 | 681 | // for string keys, replace it 682 | if (zend_hash_get_current_key_ex(array_hash, &str_index, &str_index_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) { 683 | 684 | // reset replacemnet hash pointer 685 | zend_hash_internal_pointer_reset_ex(replacement_hash, &replacement_pos); 686 | 687 | zval **replace_value = NULL; 688 | while (SUCCESS == zend_hash_get_current_data_ex(replacement_hash, (void **) &replace_value, &replacement_pos)) { 689 | char *replace_key = NULL; 690 | uint replace_key_len = 0; 691 | ulong num_index; 692 | if (zend_hash_get_current_key_ex(replacement_hash, 693 | &replace_key, &replace_key_len, &num_index, 0, 694 | &replacement_pos) == HASH_KEY_IS_STRING 695 | ) { 696 | if (options == 0) { 697 | 698 | char *replace_result = NULL; 699 | int replace_result_len; 700 | replace_result = php_str_to_str_ex( 701 | str_index, 702 | str_index_len, 703 | replace_key, 704 | replace_key_len - 1, // don't include \0 705 | Z_STRVAL_PP(replace_value), 706 | Z_STRLEN_PP(replace_value), 707 | &replace_result_len, 708 | 1, NULL); 709 | 710 | Z_ADDREF_PP(tmp); 711 | add_assoc_zval_ex(return_value, replace_result, replace_result_len, *tmp); 712 | efree(replace_result); 713 | 714 | } else if (options & PHP_XARRAY_FULLMATCH) { 715 | 716 | if (strnatcmp_ex(str_index, str_index_len, replace_key, replace_key_len, 0) == 0) { 717 | Z_ADDREF_PP(tmp); 718 | add_assoc_zval_ex(return_value, Z_STRVAL_PP(replace_value), Z_STRLEN_PP(replace_value) + 1, *tmp); 719 | } else { 720 | Z_ADDREF_PP(tmp); 721 | add_assoc_zval_ex(return_value, str_index, str_index_len, *tmp); 722 | } 723 | 724 | } 725 | } 726 | zend_hash_move_forward_ex(replacement_hash, &replacement_pos); 727 | } 728 | } else { 729 | add_next_index_zval(return_value, *tmp); 730 | } 731 | 732 | zend_hash_move_forward_ex(array_hash, &pos); 733 | } 734 | } 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | PHP_FUNCTION(array_keys_suffix) { 744 | zval *array; 745 | char *suffix; 746 | int suffix_len; 747 | 748 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "as", &array, &suffix, &suffix_len) == FAILURE) { 749 | RETURN_FALSE; 750 | } 751 | 752 | HashTable *arr_hash = Z_ARRVAL_P(array); 753 | HashPosition pos; 754 | zval **item; 755 | int numelems, i = 0; 756 | int str_len; 757 | 758 | numelems = zend_hash_num_elements(arr_hash); 759 | if (numelems == 0) { 760 | return; 761 | } 762 | 763 | // create new array in return_value 764 | array_init(return_value); 765 | for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 766 | zend_hash_get_current_data_ex(arr_hash, (void**) &item, &pos) == SUCCESS; 767 | zend_hash_move_forward_ex(arr_hash, &pos)) 768 | { 769 | zval *arr_key = NULL; 770 | MAKE_STD_ZVAL(arr_key); 771 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 772 | if (Z_TYPE_P(arr_key) == IS_STRING) { 773 | smart_str implstr = {0}; 774 | smart_str_appendl(&implstr, Z_STRVAL_P(arr_key), Z_STRLEN_P(arr_key)); 775 | smart_str_appendl(&implstr, suffix, suffix_len); 776 | smart_str_0(&implstr); 777 | add_assoc_zval_ex(return_value, implstr.c, implstr.len + 1, *item); 778 | smart_str_free(&implstr); 779 | } else { 780 | add_index_zval(return_value, Z_LVAL_P(arr_key), *item); 781 | } 782 | zval_ptr_dtor(&arr_key); 783 | } 784 | } 785 | 786 | 787 | 788 | 789 | 790 | 791 | PHP_FUNCTION(array_pluck) { 792 | zval *array; 793 | zval *plurk_key = NULL; 794 | 795 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &array, &plurk_key) == FAILURE) { 796 | RETURN_FALSE; 797 | } 798 | 799 | array_init(return_value); 800 | 801 | HashTable *arr_hash = Z_ARRVAL_P(array); 802 | HashPosition pos; 803 | zval **item; 804 | int numelems, i = 0; 805 | int str_len; 806 | 807 | numelems = zend_hash_num_elements(arr_hash); 808 | if (numelems == 0) { 809 | return; 810 | } 811 | 812 | zval **tmp; 813 | if (Z_TYPE_P(plurk_key) == IS_STRING) { 814 | for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 815 | zend_hash_get_current_data_ex(arr_hash, (void**) &item, &pos) == SUCCESS; 816 | zend_hash_move_forward_ex(arr_hash, &pos)) 817 | { 818 | if (Z_TYPE_PP(item) != IS_ARRAY) { 819 | continue; 820 | } 821 | if (zend_hash_find(Z_ARRVAL_PP(item), Z_STRVAL_P(plurk_key), Z_STRLEN_P(plurk_key) + 1, (void **) &tmp) == SUCCESS) { 822 | Z_ADDREF_PP(tmp); 823 | add_next_index_zval(return_value, *tmp); 824 | } 825 | } 826 | } else if (Z_TYPE_P(plurk_key) == IS_LONG) { 827 | 828 | for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 829 | zend_hash_get_current_data_ex(arr_hash, (void**) &item, &pos) == SUCCESS; 830 | zend_hash_move_forward_ex(arr_hash, &pos)) 831 | { 832 | if (Z_TYPE_PP(item) != IS_ARRAY) { 833 | continue; 834 | } 835 | if (zend_hash_index_find(Z_ARRVAL_PP(item), Z_LVAL_P(plurk_key), (void **) &tmp) == SUCCESS) { 836 | Z_ADDREF_PP(tmp); 837 | add_next_index_zval(return_value, *tmp); 838 | } 839 | } 840 | 841 | } 842 | 843 | } 844 | 845 | 846 | PHP_FUNCTION(array_keys_join) { 847 | zval *array; 848 | 849 | // for php7 850 | // zend_ulong num_key; 851 | // zend_string *key; 852 | char *key; 853 | uint key_len; 854 | ulong num_index; 855 | 856 | zval *delim = NULL; 857 | zval *udelim = NULL; 858 | char default_delim = 0; 859 | 860 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &array, &udelim) == FAILURE) { 861 | RETURN_FALSE; 862 | } 863 | 864 | HashTable *arr_hash = Z_ARRVAL_P(array); 865 | HashPosition pos; 866 | zval **item; 867 | int numelems, i = 0; 868 | int str_len; 869 | 870 | 871 | zval tmp_val; 872 | smart_str implstr = {0}; 873 | 874 | 875 | numelems = zend_hash_num_elements(arr_hash); 876 | if (numelems == 0) { 877 | RETURN_EMPTY_STRING(); 878 | } 879 | 880 | 881 | 882 | if (udelim) { 883 | delim = udelim; 884 | } else { 885 | MAKE_STD_ZVAL(delim); 886 | #define _IMPL_EMPTY "" 887 | ZVAL_STRINGL(delim, _IMPL_EMPTY, sizeof(_IMPL_EMPTY) - 1, 0); 888 | } 889 | 890 | 891 | for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); 892 | zend_hash_get_current_data_ex(arr_hash, (void**) &item, &pos) == SUCCESS; 893 | zend_hash_move_forward_ex(arr_hash, &pos)) 894 | { 895 | zval *arr_key = NULL; 896 | MAKE_STD_ZVAL(arr_key); 897 | zend_hash_get_current_key_zval_ex(arr_hash, arr_key, &pos); 898 | 899 | /* 900 | if (zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_LONG) { 901 | RETURN_FALSE; 902 | } 903 | */ 904 | 905 | switch ((arr_key)->type) { 906 | case IS_STRING: 907 | smart_str_appendl(&implstr, Z_STRVAL_P(arr_key), Z_STRLEN_P(arr_key)); 908 | break; 909 | 910 | case IS_LONG: { 911 | char stmp[MAX_LENGTH_OF_LONG + 1]; 912 | str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_LVAL_P(arr_key)); 913 | smart_str_appendl(&implstr, stmp, str_len); 914 | } 915 | break; 916 | 917 | case IS_BOOL: 918 | if (Z_LVAL_P(arr_key) == 1) { 919 | smart_str_appendl(&implstr, "1", sizeof("1")-1); 920 | } 921 | break; 922 | 923 | case IS_NULL: 924 | break; 925 | 926 | case IS_DOUBLE: { 927 | char *stmp; 928 | str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_P(arr_key)); 929 | smart_str_appendl(&implstr, stmp, str_len); 930 | efree(stmp); 931 | } 932 | break; 933 | 934 | case IS_OBJECT: { 935 | int copy; 936 | zval expr; 937 | zend_make_printable_zval(arr_key, &expr, ©); 938 | smart_str_appendl(&implstr, Z_STRVAL(expr), Z_STRLEN(expr)); 939 | if (copy) { 940 | zval_dtor(&expr); 941 | } 942 | } 943 | break; 944 | 945 | default: 946 | tmp_val = *arr_key; 947 | zval_copy_ctor(&tmp_val); 948 | convert_to_string(&tmp_val); 949 | smart_str_appendl(&implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val)); 950 | zval_dtor(&tmp_val); 951 | break; 952 | } 953 | if (++i != numelems) { 954 | smart_str_appendl(&implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim)); 955 | } 956 | zval_ptr_dtor(&arr_key); 957 | } 958 | 959 | smart_str_0(&implstr); 960 | 961 | 962 | if (udelim == NULL) { 963 | FREE_ZVAL(delim); 964 | } 965 | // zval_dtor(delim); 966 | 967 | if (implstr.len) { 968 | RETURN_STRINGL(implstr.c, implstr.len, 0); 969 | } else { 970 | smart_str_free(&implstr); 971 | RETURN_EMPTY_STRING(); 972 | } 973 | } 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | PHP_FUNCTION(array_add) { 983 | zval *array; 984 | zval *new_elem = NULL; 985 | zval *key; 986 | 987 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "azz", &array, &key, &new_elem) == FAILURE) { 988 | RETURN_FALSE; 989 | } 990 | 991 | HashTable *arr_hash; 992 | HashPosition pos; 993 | zval **item; 994 | zval *tmp; 995 | int numelems, i = 0; 996 | 997 | arr_hash = Z_ARRVAL_P(array); 998 | 999 | if (Z_TYPE_P(key) == IS_STRING) { 1000 | if (zend_hash_find(arr_hash, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **) &tmp) == FAILURE) { 1001 | Z_ADDREF_P(new_elem); 1002 | add_assoc_zval_ex(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, new_elem); 1003 | RETURN_TRUE; 1004 | } 1005 | } else if (Z_TYPE_P(key) == IS_LONG) { 1006 | if (zend_hash_index_find(arr_hash, Z_LVAL_P(key), (void **) &tmp) == FAILURE) { 1007 | 1008 | Z_ADDREF_P(new_elem); 1009 | add_index_zval(array, Z_LVAL_P(key), new_elem); 1010 | RETURN_TRUE; 1011 | } 1012 | } else { 1013 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "array keys must be long or string type."); 1014 | } 1015 | RETURN_FALSE; 1016 | } 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | -------------------------------------------------------------------------------- /php_xarray.h: -------------------------------------------------------------------------------- 1 | #ifndef _PHP_XARRAY_H 2 | #define _PHP_XARRAY_H 3 | #ifdef HAVE_CONFIG_H 4 | #include "config.h" 5 | #endif 6 | 7 | #ifdef ZTS 8 | #warning php_ext_uv module will *NEVER* be thread-safe 9 | #include 10 | #endif 11 | 12 | #include 13 | 14 | #define XARRAY_VERSION "0.1.1" 15 | #define PHP_XARRAY_FULLMATCH 1 16 | #define PHP_XARRAY_PARTIALMATCH (1<<1) 17 | 18 | extern zend_module_entry xarray_module_entry; 19 | 20 | PHP_FUNCTION(array_is_indexed); 21 | 22 | PHP_FUNCTION(array_is_assoc); 23 | 24 | PHP_FUNCTION(array_keys_join); 25 | 26 | PHP_FUNCTION(array_pluck); 27 | 28 | PHP_FUNCTION(array_first); 29 | 30 | PHP_FUNCTION(array_each); 31 | 32 | PHP_FUNCTION(array_intval); 33 | 34 | PHP_FUNCTION(array_floatval); 35 | 36 | PHP_FUNCTION(array_boolval); 37 | 38 | PHP_FUNCTION(array_build); 39 | 40 | PHP_FUNCTION(array_remove); 41 | 42 | PHP_FUNCTION(array_keys_prefix); 43 | 44 | PHP_FUNCTION(array_keys_suffix); 45 | 46 | PHP_FUNCTION(array_add); 47 | 48 | PHP_FUNCTION(array_keys_replace); 49 | 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /tests/array_add/assoc.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_add assoc 3 | --FILE-- 4 | "a", 7 | "zoo" => "c", 8 | ); 9 | array_add($a, "bar", "b"); 10 | print_r($a); 11 | --EXPECT-- 12 | Array 13 | ( 14 | [foo] => a 15 | [zoo] => c 16 | [bar] => b 17 | ) 18 | -------------------------------------------------------------------------------- /tests/array_add/assoc_not_override.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_add assoc 3 | --FILE-- 4 | "a", 7 | "zoo" => "c", 8 | ); 9 | array_add($a, "foo", "b"); 10 | print_r($a); 11 | --EXPECT-- 12 | Array 13 | ( 14 | [foo] => a 15 | [zoo] => c 16 | ) 17 | -------------------------------------------------------------------------------- /tests/array_add/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_add index 3 | --FILE-- 4 | "a", 7 | 2 => "c", 8 | ); 9 | array_add($a, 1, "b"); 10 | print_r($a); 11 | --EXPECT-- 12 | Array 13 | ( 14 | [0] => a 15 | [2] => c 16 | [1] => b 17 | ) 18 | -------------------------------------------------------------------------------- /tests/array_build/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_build basic 3 | --FILE-- 4 | "John", "id" => "j"), 7 | array("name" => "Mary", "id" => "m"), 8 | array("name" => "Lisa", "id" => "l"), 9 | ); 10 | $b = array_build($a, function($key, $value) use(&$b) { 11 | return array($value['id'], $value['name']); 12 | }); 13 | print_r($b); 14 | --EXPECT-- 15 | Array 16 | ( 17 | [j] => John 18 | [m] => Mary 19 | [l] => Lisa 20 | ) 21 | -------------------------------------------------------------------------------- /tests/array_each/change_value.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_each but change the given value 3 | --FILE-- 4 | "John", 7 | 1 => "Mary", 8 | 2 => "Lisa", 9 | ); 10 | array_each($a, function($key, & $value) { 11 | $value = "123"; 12 | }); 13 | print_r($a); 14 | --EXPECT-- 15 | Array 16 | ( 17 | [0] => 123 18 | [1] => 123 19 | [2] => 123 20 | ) 21 | -------------------------------------------------------------------------------- /tests/array_each/simple.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_each 3 | --FILE-- 4 | "John", 7 | 1 => "Mary", 8 | 2 => "Lisa", 9 | ); 10 | $b = []; 11 | array_each($a, function($key, $value) use(&$b) { 12 | $b[$key] = $value; 13 | }); 14 | print_r($b); 15 | --EXPECT-- 16 | Array 17 | ( 18 | [0] => John 19 | [1] => Mary 20 | [2] => Lisa 21 | ) 22 | -------------------------------------------------------------------------------- /tests/array_each/stop.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_each stop 3 | --FILE-- 4 | "John", 7 | 1 => "Mary", 8 | 2 => "Lisa", 9 | 3 => "Harry", 10 | ); 11 | $b = []; 12 | array_each($a, function($key, $value) use(&$b) { 13 | $b[$key] = $value; 14 | if ($key == 2) { 15 | return false; 16 | } 17 | }); 18 | print_r($b); 19 | --EXPECT-- 20 | Array 21 | ( 22 | [0] => John 23 | [1] => Mary 24 | [2] => Lisa 25 | ) 26 | -------------------------------------------------------------------------------- /tests/array_first/array_first_empty.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_first with empty array 3 | --FILE-- 4 | "John", 7 | 1 => "Mary", 8 | 2 => "Lisa", 9 | ); 10 | $b = array_first($a, function($key, $value) { 11 | if ($key !== 1) { 12 | return true; 13 | } 14 | return false; 15 | }); 16 | print_r($b); 17 | --EXPECT-- 18 | John 19 | -------------------------------------------------------------------------------- /tests/array_first/default.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_first not found should return default value 3 | --FILE-- 4 | "a", 7 | 1 => "b", 8 | 2 => "c" 9 | ); 10 | $b = array_first($a, function($key, $value) { 11 | if ($value == "d") { 12 | return true; 13 | } 14 | return false; 15 | }, "not-found-default"); 16 | print_r($b); 17 | --EXPECT-- 18 | not-found-default 19 | -------------------------------------------------------------------------------- /tests/array_first/not-found.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_first not found should return null 3 | --FILE-- 4 | "a", 7 | 1 => "b", 8 | 2 => "c" 9 | ); 10 | $b = array_first($a, function($key, $value) { 11 | if ($value == "d") { 12 | return true; 13 | } 14 | return false; 15 | }); 16 | print_r($b); 17 | --EXPECT-- 18 | -------------------------------------------------------------------------------- /tests/array_floatval/index.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_floatval on index array 3 | --FILE-- 4 | "20"); 6 | $b = array_floatval($a); 7 | print_r($b); 8 | foreach ($b as $val) { 9 | echo gettype($val), PHP_EOL; 10 | } 11 | --EXPECT-- 12 | Array 13 | ( 14 | [0] => 1.234 15 | [1] => 2.222 16 | [2] => 3.333 17 | [3] => 10 18 | [4] => 20 19 | ) 20 | double 21 | double 22 | double 23 | double 24 | double 25 | -------------------------------------------------------------------------------- /tests/array_intval/assoc.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_intval on assoc array 3 | --FILE-- 4 | "1", 7 | "bar" => "2", 8 | "zoo" => "3", 9 | "xee" => "10", 10 | "yaa" => "20" 11 | ); 12 | $b = array_intval($a); 13 | print_r($b); 14 | foreach ($b as $val) { 15 | echo gettype($val), PHP_EOL; 16 | } 17 | --EXPECT-- 18 | Array 19 | ( 20 | [foo] => 1 21 | [bar] => 2 22 | [zoo] => 3 23 | [xee] => 10 24 | [yaa] => 20 25 | ) 26 | integer 27 | integer 28 | integer 29 | integer 30 | integer 31 | -------------------------------------------------------------------------------- /tests/array_intval/index.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_intval on index array 3 | --FILE-- 4 | "20"); 6 | $b = array_intval($a); 7 | print_r($b); 8 | foreach ($b as $val) { 9 | echo gettype($val), PHP_EOL; 10 | } 11 | --EXPECT-- 12 | Array 13 | ( 14 | [0] => 1 15 | [1] => 2 16 | [2] => 3 17 | [3] => 10 18 | [4] => 20 19 | ) 20 | integer 21 | integer 22 | integer 23 | integer 24 | integer 25 | -------------------------------------------------------------------------------- /tests/array_is_indexed/indexed_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_is_indexed 3 | --FILE-- 4 | "a", 1 => "b" )); 6 | echo $ret ? "ok\n" : "fail\n"; 7 | --EXPECT-- 8 | ok 9 | -------------------------------------------------------------------------------- /tests/array_is_indexed/non_indexed_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check for non-indexed array 3 | --FILE-- 4 | "a", "foo" => "b" )); 6 | echo $ret == false ? "ok" : "fail"; 7 | --EXPECT-- 8 | ok 9 | -------------------------------------------------------------------------------- /tests/array_keys_join/join_with_dash.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_join 3 | --FILE-- 4 | 0, "bar" => 0), "-"); 6 | --EXPECT-- 7 | foo-bar 8 | -------------------------------------------------------------------------------- /tests/array_keys_join/join_without_delim.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_join without delim 3 | --FILE-- 4 | 0, "bar" => 0)); 6 | --EXPECT-- 7 | foobar 8 | -------------------------------------------------------------------------------- /tests/array_keys_prefix/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_prefix basic 3 | --FILE-- 4 | "John", 7 | "id" => "j", 8 | "phone" => "+886975123123", 9 | ); 10 | $b = array_keys_prefix($a, "my_"); 11 | print_r($b); 12 | --EXPECT-- 13 | Array 14 | ( 15 | [my_name] => John 16 | [my_id] => j 17 | [my_phone] => +886975123123 18 | ) 19 | -------------------------------------------------------------------------------- /tests/array_keys_replace/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_replace basic 3 | --FILE-- 4 | 12345, 7 | "name" => "John", 8 | "phone" => "+886975123123", 9 | "created_at" => "2012-01-01", 10 | "updated_at" => "2012-02-02", 11 | ); 12 | $a = array_keys_replace($a, array( 13 | "_at" => "_on", 14 | )); 15 | print_r($a); 16 | --EXPECT-- 17 | Array 18 | ( 19 | [id] => 12345 20 | [name] => John 21 | [phone] => +886975123123 22 | [created_on] => 2012-01-01 23 | [updated_on] => 2012-02-02 24 | ) 25 | -------------------------------------------------------------------------------- /tests/array_keys_replace/fullmatch.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_replace full match 3 | --FILE-- 4 | 12345, 7 | "name" => "John", 8 | "first_name" => "Lin", 9 | "phone" => "+886975123123", 10 | "created_at" => "2012-01-01", 11 | "updated_at" => "2012-02-02", 12 | ); 13 | $a = array_keys_replace($a, array("name" => "nickname"), XARRAY_FULLMATCH); 14 | print_r($a); 15 | --EXPECT-- 16 | Array 17 | ( 18 | [id] => 12345 19 | [nickname] => John 20 | [first_name] => Lin 21 | [phone] => +886975123123 22 | [created_at] => 2012-01-01 23 | [updated_at] => 2012-02-02 24 | ) 25 | -------------------------------------------------------------------------------- /tests/array_keys_suffix/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_keys_suffix basic 3 | --FILE-- 4 | "John", 7 | "id" => "j", 8 | "phone" => "+886975123123", 9 | ); 10 | $b = array_keys_suffix($a, "_string"); 11 | print_r($b); 12 | --EXPECT-- 13 | Array 14 | ( 15 | [name_string] => John 16 | [id_string] => j 17 | [phone_string] => +886975123123 18 | ) 19 | -------------------------------------------------------------------------------- /tests/array_pluck_by_idx.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_pluck 3 | --FILE-- 4 | "John"), 7 | array(2 => "Mary"), 8 | array(2 => "Lisa"), 9 | ); 10 | $a = array_pluck($a, 2); 11 | print_r($a); 12 | --EXPECT-- 13 | Array 14 | ( 15 | [0] => John 16 | [1] => Mary 17 | [2] => Lisa 18 | ) 19 | -------------------------------------------------------------------------------- /tests/array_pluck_by_idx_02.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_pluck 3 | --FILE-- 4 | "John"), 7 | array(1 => "Mary"), 8 | array(2 => "Lisa"), 9 | ); 10 | $a = array_pluck($a, 2); 11 | print_r($a); 12 | --EXPECT-- 13 | Array 14 | ( 15 | [0] => John 16 | [1] => Lisa 17 | ) 18 | -------------------------------------------------------------------------------- /tests/array_pluck_by_str.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_pluck 3 | --FILE-- 4 | "John" ), 7 | array( 'name' => "Mary" ), 8 | array( 'name' => "Lisa" ), 9 | ); 10 | $a = array_pluck($a, 'name'); 11 | print_r($a); 12 | --EXPECT-- 13 | Array 14 | ( 15 | [0] => John 16 | [1] => Mary 17 | [2] => Lisa 18 | ) 19 | -------------------------------------------------------------------------------- /tests/array_remove/basic.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Check array_remove 3 | --FILE-- 4 | "a", 7 | "bar" => "b", 8 | "zoo" => "c", 9 | ); 10 | // delete "foo" key from $a 11 | $a = array_remove($a, function($key, $value) { 12 | return $value === "b"; 13 | }); 14 | print_r($a); 15 | --EXPECT-- 16 | Array 17 | ( 18 | [foo] => a 19 | [zoo] => c 20 | ) 21 | --------------------------------------------------------------------------------