Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
CismonX | 9a7a72dd29 | |
CismonX | 66934839e8 | |
CismonX | 96a7c69edd | |
CismonX | f4b5e60ba9 | |
CismonX | 9cd6222d39 | |
CismonX | d7f2835fc0 | |
CismonX | eeb0b4e809 | |
CismonX | 368a49271a | |
CismonX | 1baf525cd7 | |
CismonX | 426d80e5b1 | |
CismonX | 8d9f4d773b | |
CismonX | 394fdbf5f0 | |
CismonX | da855f8844 | |
CismonX | 5f3f4f1d96 |
|
@ -1 +1,3 @@
|
|||
*.h linguist-language=C
|
||||
*.h linguist-language=C
|
||||
stubs/* linguist-documentation
|
||||
config.m4 linguist-detectable=false
|
||||
|
|
|
@ -28,11 +28,14 @@ missing
|
|||
mkinstalldirs
|
||||
modules
|
||||
run-tests.php
|
||||
tests/*/*.diff
|
||||
tests/*/*.out
|
||||
tests/*/*.php
|
||||
tests/*/*.exp
|
||||
tests/*/*.log
|
||||
tests/*/*.sh
|
||||
tests/*.diff
|
||||
tests/*.out
|
||||
tests/*.php
|
||||
tests/*.exp
|
||||
tests/*.log
|
||||
tests/*.sh
|
||||
.idea/
|
||||
.vscode/
|
||||
*.gcov
|
||||
*.gcda
|
||||
*.gcno
|
||||
|
|
13
.travis.yml
13
.travis.yml
|
@ -1,16 +1,19 @@
|
|||
dist: xenial
|
||||
group: edge
|
||||
|
||||
language: php
|
||||
|
||||
dist: bionic
|
||||
|
||||
php:
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
- nightly
|
||||
- 7.4
|
||||
|
||||
script:
|
||||
- phpize
|
||||
- ./configure
|
||||
- make
|
||||
- make EXTRA_CFLAGS='-coverage' EXTRA_LDFLAGS='-fprofile-arcs'
|
||||
- make test
|
||||
- gcov --object-directory=src/.libs src/collections_methods.c
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
|
4
LICENSE
4
LICENSE
|
@ -1,6 +1,6 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018 CismonX
|
||||
Copyright (c) 2018-2020 CismonX<admin@cismon.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
THE SOFTWARE.
|
||||
|
|
101
README.md
101
README.md
|
@ -1,57 +1,33 @@
|
|||
# ext-collections
|
||||
|
||||
[![Travis-CI](https://travis-ci.org/CismonX/ext-collections.svg?branch=master)](https://travis-ci.org/CismonX/ext-collections)
|
||||
[![MIT license](https://img.shields.io/badge/licence-MIT-blue.svg)](https://opensource.org/licenses/MIT)
|
||||
[![Travis-CI](https://travis-ci.com/CismonX/ext-collections.svg?branch=master)](https://travis-ci.com/CismonX/ext-collections)
|
||||
[![Codecov](https://codecov.io/gh/CismonX/ext-collections/branch/master/graphs/badge.svg)](https://codecov.io/gh/CismonX/ext-collections)
|
||||
[![MIT license](https://img.shields.io/badge/licence-MIT-blue.svg)](LICENSE)
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
This PHP extension provides a set of useful functional-style operations on PHP arrays, which makes array manipulation simple and scalable.
|
||||
This PHP extension provides a set of useful and convenient operations on PHP arrays, which makes working with arrays simple and scalable.
|
||||
|
||||
Method names and functionalities are inspired by [Kotlin.Collections](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/).
|
||||
Method names and functionalities are inspired by [Kotlin.Collections](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/), having a slightly different style than that of [Laravel Collections](https://laravel.com/docs/5.8/collections).
|
||||
|
||||
### 1.1 Notes
|
||||
Requires PHP version >= 7.1 and < 8.0 (master branch).
|
||||
|
||||
* Requires PHP 7.1 and above.
|
||||
* Thread safety:
|
||||
* Distinct objects: **safe**.
|
||||
* Shared objects: **unsafe**.
|
||||
### 1.1 Example
|
||||
|
||||
## 2. Documentation
|
||||
|
||||
### 2.1 Functionalities
|
||||
|
||||
See [stubs](stubs/) directory for signature of all classes and methods of this extension, with PHPDoc. They can also serve as IDE helper.
|
||||
|
||||
### 2.2 PHP-style access
|
||||
|
||||
The `Collection` class implements `ArrayAccess` and `Countable` interface internally, you can treat an instance of `Collection` as an `ArrayObject`.
|
||||
|
||||
* The `isset()`, `unset()` keywords can be used on elements of `Collection`.
|
||||
* Elements can be accessed via property and bracket expression.
|
||||
* `empty()`, `count()` can be used on instance of `Collection`.
|
||||
* Elements can be traversed via `foreach()` keyword.
|
||||
|
||||
### 2.4 Notes
|
||||
|
||||
* The `Collection::xxxTo()` methods will preserve the original key-value pairs of destination `Collection` when keys collide.
|
||||
* Some methods of `Collection` involves comparing two of its elements, which accepts `$flags` as one of its arguments. When these methods are being invoked, make sure all elements are of the same type (numeric/string/others), otherwise you're likely to get a segfault.
|
||||
|
||||
## 3. Example
|
||||
|
||||
Here is a simple example for how to work with arrays gracefully using this extension.
|
||||
Here is a simple example on how to work with arrays gracefully using this extension.
|
||||
|
||||
```php
|
||||
$employees = [
|
||||
['name' => 'Alice', 'sex' => 'female', 'age' => 35],
|
||||
['name' => 'Bob', 'sex' => 'male', 'age' => 29],
|
||||
['name' => 'David', 'sex' => 'male', 'age' => 40],
|
||||
['name' => 'Benjamin', 'sex' => 'male', 'age' => 32]
|
||||
['name' => 'Alice', 'gender' => 'female', 'age' => 35],
|
||||
['name' => 'Bob', 'gender' => 'male', 'age' => 29],
|
||||
['name' => 'David', 'gender' => 'male', 'age' => 40],
|
||||
['name' => 'Benjamin', 'gender' => 'male', 'age' => 32]
|
||||
];
|
||||
// Trying to get an array of names of male employees,
|
||||
// sorted by the descending order of their age.
|
||||
$names = Collection::init($employees)
|
||||
->filter(function ($value) {
|
||||
return $value['sex'] == 'male';
|
||||
return $value['gender'] == 'male';
|
||||
})
|
||||
->sortedByDescending(function ($value) {
|
||||
return $value['age'];
|
||||
|
@ -62,3 +38,54 @@ $names = Collection::init($employees)
|
|||
->toArray();
|
||||
// You got $names == ['David', 'Benjamin', 'Bob'].
|
||||
```
|
||||
|
||||
## 2. Getting Started
|
||||
|
||||
### 2.1 Installation
|
||||
|
||||
Like other PHP extensions, ext-collections can be built and installed with a few commands:
|
||||
|
||||
```bash
|
||||
phpize
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Include it in your PHP configuration file to enable this extension:
|
||||
|
||||
```php.ini
|
||||
extension=collections.so
|
||||
```
|
||||
|
||||
Building on Windows is not as convenient, however, pre-built binaries for Windows are provided in the [releases](https://github.com/CismonX/ext-collections/releases). If you want to build it yourself, follow the [official PHP wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2).
|
||||
|
||||
### 2.2 API Reference
|
||||
|
||||
See [stubs](stubs/) directory for signatures of all classes and methods of this extension, with PHPDoc. They can also serve as IDE helper.
|
||||
|
||||
### 2.3 PHP-style Access
|
||||
|
||||
The `Collection` class implements `ArrayAccess` and `Countable` interface internally, you can treat an instance of `Collection` as an `ArrayObject`.
|
||||
|
||||
* The `isset()`, `unset()` keywords can be used on elements of `Collection`.
|
||||
* Elements can be accessed via property or bracket expression.
|
||||
* `empty()`, `count()` can be used on instance of `Collection`.
|
||||
* Elements can be traversed via `foreach()` keyword.
|
||||
|
||||
## 3. Notes
|
||||
|
||||
* The `Collection::xxxTo()` methods will preserve the original key-value pairs of destination `Collection` when keys collide.
|
||||
* Some methods of `Collection` involves comparing two of its elements, which accepts `$flags` as one of its arguments. When these methods are being invoked, make sure all elements are of the same type (numeric/string/others), otherwise you're likely to get a segfault.
|
||||
|
||||
### 3.1 Copy-on-write Mechanism
|
||||
|
||||
Class `Collection` does not introduce new data structures internally. Instead, it only holds a pointer to a `zend_array`, and all its methods works directly on top of `zend_array`. Which means conversion between `Collection` and `array` does not involve copying, until write operation is performed on one of the duplicates.
|
||||
|
||||
```php
|
||||
$foo = ['a', 'b']; // arr0: refcount = 1
|
||||
$bar = Collection::init($foo); // arr0: refcount = 2, no copying of either `zend_array` or its elements
|
||||
echo $bar->containsValue('a'); // arr0: refcount = 2, read operation, no copying
|
||||
$bar->shuffle(); // arr0: refcount = 1, arr1: refcount = 1, write operation, `zend_array` is separated
|
||||
$baz = $bar->toArray(); // arr0: refcount = 1, arr1: refcount = 2, no copying
|
||||
```
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ignore:
|
||||
- "src/collections.c"
|
|
@ -6,12 +6,6 @@
|
|||
|
||||
#include "php_collections_me.h"
|
||||
|
||||
// ZEND_ACC_CTOR is removed in PHP 7.4
|
||||
// Removing the flag does not affect the constructor from being recognized.
|
||||
#if PHP_VERSION_ID >= 70400
|
||||
#define ZEND_ACC_CTOR 0
|
||||
#endif
|
||||
|
||||
ZEND_BEGIN_ARG_INFO(action_arginfo, 0)
|
||||
ZEND_ARG_CALLABLE_INFO(0, action, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
|
|
@ -15,36 +15,38 @@
|
|||
#define GC_DELREF(p) --GC_REFCOUNT(p)
|
||||
#endif
|
||||
|
||||
// Thread safty assured global variables.
|
||||
#define FCI_G COLLECTIONS_G(fci)
|
||||
#define FCC_G COLLECTIONS_G(fcc)
|
||||
#define REF_G COLLECTIONS_G(ref)
|
||||
#define CMP_G COLLECTIONS_G(cmp)
|
||||
|
||||
#define Z_COLLECTION_P(val) (Z_OBJ_P(val)->properties)
|
||||
#define THIS_COLLECTION Z_COLLECTION_P(getThis())
|
||||
#define THIS_COLLECTION Z_COLLECTION_P(&EX(This))
|
||||
#define PAIR_FIRST(obj) OBJ_PROP_NUM(obj, 0)
|
||||
#define PAIR_SECOND(obj) OBJ_PROP_NUM(obj, 1)
|
||||
|
||||
#define IS_COLLECTION(val) \
|
||||
Z_TYPE(val) == IS_OBJECT && Z_OBJCE(val) == collections_collection_ce
|
||||
(Z_TYPE(val) == IS_OBJECT && Z_OBJCE(val) == collections_collection_ce)
|
||||
#define IS_PAIR(val) \
|
||||
Z_TYPE(val) == IS_OBJECT && Z_OBJCE(val) == collections_pair_ce
|
||||
(Z_TYPE(val) == IS_OBJECT && Z_OBJCE(val) == collections_pair_ce)
|
||||
|
||||
// Separation on the zend_array held by the collection.
|
||||
#define SEPARATE_COLLECTION(ht, obj) \
|
||||
if (GC_REFCOUNT(ht) > 1) { \
|
||||
GC_DELREF(ht); \
|
||||
ht = Z_OBJ_P(obj)->properties = zend_array_dup(ht); \
|
||||
}
|
||||
#define SEPARATE_CURRENT_COLLECTION(ht) \
|
||||
SEPARATE_COLLECTION(ht, getThis())
|
||||
SEPARATE_COLLECTION(ht, &EX(This))
|
||||
|
||||
#define INIT_FCI(fci, num_args) \
|
||||
zval params[num_args], retval; \
|
||||
(fci)->size = sizeof(zend_fcall_info); \
|
||||
(fci)->param_count = (num_args); \
|
||||
(fci)->retval = &retval; \
|
||||
(fci)->params = params
|
||||
|
||||
// Invoke callback function, passing bucket value as 1st arg, key as 2nd.
|
||||
#define CALLBACK_KEYVAL_INVOKE(params, bucket) \
|
||||
ZVAL_COPY_VALUE(&(params)[0], &(bucket)->val); \
|
||||
if ((bucket)->key) { \
|
||||
|
@ -54,6 +56,7 @@
|
|||
} \
|
||||
zend_call_function(&fci, &fcc)
|
||||
|
||||
// Several E_WARNING level error messages. Could use exceptions instead.
|
||||
#define PHP_COLLECTIONS_ERROR(type, msg) \
|
||||
php_error_docref(NULL, type, msg)
|
||||
#define ERR_BAD_ARGUMENT_TYPE() \
|
||||
|
@ -74,6 +77,7 @@
|
|||
PHP_COLLECTIONS_ERROR(E_WARNING, "The array should be packed")
|
||||
#define ERR_SILENCED()
|
||||
|
||||
// Validate and extract zend_array from collection.
|
||||
#define ELEMENTS_VALIDATE(elements, err, err_then) \
|
||||
zend_array* elements##_arr; \
|
||||
if (IS_COLLECTION(*elements)) { \
|
||||
|
@ -86,13 +90,14 @@
|
|||
}
|
||||
|
||||
#define ARRAY_NEW(name, size) \
|
||||
zend_array* (name) = (zend_array*)emalloc(sizeof(zend_array)); \
|
||||
zend_array* (name) = emalloc(sizeof(zend_array)); \
|
||||
zend_hash_init(name, size, NULL, ZVAL_PTR_DTOR, 0)
|
||||
#define ARRAY_NEW_EX(name, other) \
|
||||
ARRAY_NEW(name, zend_hash_num_elements(other))
|
||||
#define ARRAY_CLONE(dest, src) \
|
||||
zend_array* (dest) = zend_array_dup(src);
|
||||
|
||||
// Creates a new collection which wraps the given zend_array.
|
||||
#define RETVAL_NEW_COLLECTION(ht) \
|
||||
{ \
|
||||
zend_object* _obj = create_collection_obj(); \
|
||||
|
@ -168,8 +173,7 @@ static zend_always_inline void array_update_bucket(zend_array* ht, Bucket* bucke
|
|||
static zend_always_inline zend_object* create_object(zend_class_entry* ce,
|
||||
zend_object_handlers* handlers)
|
||||
{
|
||||
zend_object* obj = (zend_object*)ecalloc(1, sizeof(zend_object) +
|
||||
zend_object_properties_size(ce));
|
||||
zend_object* obj = emalloc(sizeof(zend_object) + zend_object_properties_size(ce));
|
||||
zend_object_std_init(obj, ce);
|
||||
object_properties_init(obj, ce);
|
||||
obj->handlers = handlers;
|
||||
|
@ -202,7 +206,7 @@ static zend_always_inline zend_array* array_group_fetch(zend_array* ht, zval* ke
|
|||
zval* group_val = zend_hash_index_find(ht, Z_LVAL_P(key));
|
||||
if (UNEXPECTED(group_val == NULL)) {
|
||||
zval tmp_val;
|
||||
group = (zend_array*)emalloc(sizeof(zend_array));
|
||||
group = emalloc(sizeof(zend_array));
|
||||
zend_hash_init(group, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
ZVAL_ARR(&tmp_val, group);
|
||||
zend_hash_index_add(ht, Z_LVAL_P(key), &tmp_val);
|
||||
|
@ -216,7 +220,7 @@ static zend_always_inline zend_array* array_group_fetch(zend_array* ht, zval* ke
|
|||
zval* group_val = zend_hash_find(ht, Z_STR_P(key));
|
||||
if (UNEXPECTED(group_val == NULL)) {
|
||||
zval tmp_val;
|
||||
group = (zend_array*)emalloc(sizeof(zend_array));
|
||||
group = emalloc(sizeof(zend_array));
|
||||
zend_hash_init(group, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
ZVAL_ARR(&tmp_val, group);
|
||||
zend_hash_add(ht, Z_STR_P(key), &tmp_val);
|
||||
|
@ -553,7 +557,7 @@ static zend_always_inline void array_slice_by(zend_array* ht, zend_array* other,
|
|||
}
|
||||
return;
|
||||
}
|
||||
Bucket* ref_this = (Bucket*)malloc(num_this * sizeof(Bucket));
|
||||
Bucket* ref_this = malloc(num_this * sizeof(Bucket));
|
||||
compare_func_t cmp = NULL;
|
||||
equal_check_func_t eql;
|
||||
uint32_t idx = 0;
|
||||
|
@ -570,7 +574,7 @@ static zend_always_inline void array_slice_by(zend_array* ht, zend_array* other,
|
|||
CMP_G = cmp;
|
||||
zend_sort(ref_this, num_this, sizeof(Bucket), packed ? bucket_compare_with_idx : cmp,
|
||||
(swap_func_t)zend_hash_bucket_packed_swap);
|
||||
Bucket* ref_other = (Bucket*)malloc(num_other * sizeof(Bucket));
|
||||
Bucket* ref_other = malloc(num_other * sizeof(Bucket));
|
||||
uint32_t idx_other = 0;
|
||||
ZEND_HASH_FOREACH_BUCKET(other, Bucket* bucket)
|
||||
Bucket* dest = &ref_other[idx_other++];
|
||||
|
@ -686,15 +690,16 @@ void collection_write_dimension(zval* object, zval* offset, zval* value)
|
|||
Z_TRY_ADDREF_P(value);
|
||||
}
|
||||
|
||||
void collection_write_property(zval* object, zval* member, zval* value, void** unused)
|
||||
zobj_write_prop_ret_t collection_write_property(zval* object, zval* member, zval* value, void** unused)
|
||||
{
|
||||
collection_write_dimension(object, member, value);
|
||||
#if PHP_VERSION_ID >= 70400
|
||||
return value;
|
||||
#endif
|
||||
}
|
||||
|
||||
zval* collection_read_dimension(zval* object, zval* offset, int type, zval* rv)
|
||||
{
|
||||
// Note that we don't handle type. So don't do any fancy things with Collection
|
||||
// such as fetching a reference of a value, etc.
|
||||
zend_array* current = Z_COLLECTION_P(object);
|
||||
zval* found = NULL;
|
||||
if (Z_TYPE_P(offset) == IS_LONG) {
|
||||
|
@ -999,7 +1004,7 @@ PHP_METHOD(Collection, binarySearchBy)
|
|||
}
|
||||
INIT_FCI(&fci, 2);
|
||||
uint32_t range = to_idx - from_idx;
|
||||
Bucket* ref = (Bucket*)malloc(range * sizeof(Bucket));
|
||||
Bucket* ref = malloc(range * sizeof(Bucket));
|
||||
compare_func_t cmp = NULL;
|
||||
uint32_t idx = 0;
|
||||
Bucket* bucket = current->arData + from_idx;
|
||||
|
@ -1043,7 +1048,7 @@ PHP_METHOD(Collection, chunked)
|
|||
zend_array* chunk = NULL;
|
||||
ZEND_HASH_FOREACH_BUCKET(current, Bucket* bucket)
|
||||
if (num_remaining == 0) {
|
||||
chunk = (zend_array*)emalloc(sizeof(zend_array));
|
||||
chunk = emalloc(sizeof(zend_array));
|
||||
zend_hash_init(chunk, 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
num_remaining = size;
|
||||
}
|
||||
|
@ -1270,7 +1275,7 @@ PHP_METHOD(Collection, copyOfRange)
|
|||
PHP_METHOD(Collection, count)
|
||||
{
|
||||
zend_long count;
|
||||
collection_count_elements(getThis(), &count);
|
||||
collection_count_elements(&EX(This), &count);
|
||||
RETVAL_LONG(count);
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1285,7 @@ PHP_METHOD(Collection, distinct)
|
|||
compare_func_t cmp = NULL;
|
||||
equal_check_func_t eql = NULL;
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
Bucket* ref = (Bucket*)malloc(num_elements * sizeof(Bucket));
|
||||
Bucket* ref = malloc(num_elements * sizeof(Bucket));
|
||||
ARRAY_CLONE(distinct, current);
|
||||
uint32_t idx = 0;
|
||||
ZEND_HASH_FOREACH_BUCKET(distinct, Bucket* bucket)
|
||||
|
@ -1310,7 +1315,7 @@ PHP_METHOD(Collection, distinctBy)
|
|||
compare_func_t cmp = NULL;
|
||||
equal_check_func_t eql = NULL;
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
Bucket* ref = (Bucket*)malloc(num_elements * sizeof(Bucket));
|
||||
Bucket* ref = malloc(num_elements * sizeof(Bucket));
|
||||
ARRAY_CLONE(distinct, current);
|
||||
uint32_t idx = 0;
|
||||
INIT_FCI(&fci, 2);
|
||||
|
@ -2324,7 +2329,7 @@ PHP_METHOD(Collection, onEach)
|
|||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||
zval_ptr_dtor(&retval);
|
||||
ZEND_HASH_FOREACH_END();
|
||||
RETVAL_ZVAL(getThis(), 1, 0);
|
||||
RETVAL_ZVAL(&EX(This), 1, 0);
|
||||
}
|
||||
|
||||
PHP_METHOD(Collection, partition)
|
||||
|
@ -2731,7 +2736,7 @@ PHP_METHOD(Collection, sortBy)
|
|||
zend_array* current = THIS_COLLECTION;
|
||||
SEPARATE_CURRENT_COLLECTION(current);
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
zval* sort_by = (zval*)malloc(num_elements * sizeof(zval));
|
||||
zval* sort_by = malloc(num_elements * sizeof(zval));
|
||||
INIT_FCI(&fci, 2);
|
||||
compare_func_t cmp = NULL;
|
||||
uint32_t idx = 0;
|
||||
|
@ -2769,7 +2774,7 @@ PHP_METHOD(Collection, sortByDescending)
|
|||
zend_array* current = THIS_COLLECTION;
|
||||
SEPARATE_CURRENT_COLLECTION(current);
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
zval* sort_by = (zval*)malloc(num_elements * sizeof(zval));
|
||||
zval* sort_by = malloc(num_elements * sizeof(zval));
|
||||
INIT_FCI(&fci, 2);
|
||||
compare_func_t cmp = NULL;
|
||||
uint32_t idx = 0;
|
||||
|
@ -2868,7 +2873,7 @@ PHP_METHOD(Collection, sortedBy)
|
|||
zend_array* current = THIS_COLLECTION;
|
||||
ARRAY_CLONE(sorted, current);
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
zval* sort_by = (zval*)malloc(num_elements * sizeof(zval));
|
||||
zval* sort_by = malloc(num_elements * sizeof(zval));
|
||||
INIT_FCI(&fci, 2);
|
||||
compare_func_t cmp = NULL;
|
||||
uint32_t idx = 0;
|
||||
|
@ -2907,7 +2912,7 @@ PHP_METHOD(Collection, sortedByDescending)
|
|||
zend_array* current = THIS_COLLECTION;
|
||||
ARRAY_CLONE(sorted, current);
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
zval* sort_by = (zval*)malloc(num_elements * sizeof(zval));
|
||||
zval* sort_by = malloc(num_elements * sizeof(zval));
|
||||
INIT_FCI(&fci, 2);
|
||||
compare_func_t cmp = NULL;
|
||||
uint32_t idx = 0;
|
||||
|
@ -3098,7 +3103,7 @@ PHP_METHOD(Collection, takeLast)
|
|||
zend_bool packed = HT_IS_PACKED(current);
|
||||
uint32_t idx = current->nNumUsed;
|
||||
zend_long num_taken = n;
|
||||
Bucket** taken = (Bucket**)malloc(num_taken * sizeof(Bucket*));
|
||||
Bucket** taken = malloc(num_taken * sizeof(Bucket*));
|
||||
// Note that the original element orders should be preserved as in kotlin.
|
||||
for (; num_taken > 0 && idx > 0; --idx) {
|
||||
Bucket* bucket = current->arData + idx - 1;
|
||||
|
@ -3132,7 +3137,7 @@ PHP_METHOD(Collection, takeLastWhile)
|
|||
ARRAY_NEW(new_collection, 8);
|
||||
zend_bool packed = HT_IS_PACKED(current);
|
||||
uint32_t num_elements = zend_hash_num_elements(current);
|
||||
Bucket** taken = (Bucket**)malloc(num_elements * sizeof(Bucket*));
|
||||
Bucket** taken = malloc(num_elements * sizeof(Bucket*));
|
||||
ZEND_HASH_REVERSE_FOREACH_BUCKET(current, Bucket* bucket)
|
||||
CALLBACK_KEYVAL_INVOKE(params, bucket);
|
||||
if (zend_is_true(&retval)) {
|
||||
|
@ -3234,7 +3239,7 @@ PHP_METHOD(Collection, union)
|
|||
uint32_t num_elements = zend_hash_num_elements(new_collection);
|
||||
compare_func_t cmp = NULL;
|
||||
equal_check_func_t eql = NULL;
|
||||
Bucket* ref = (Bucket*)malloc(num_elements * sizeof(Bucket));
|
||||
Bucket* ref = malloc(num_elements * sizeof(Bucket));
|
||||
uint32_t idx = 0;
|
||||
ZEND_HASH_FOREACH_BUCKET(new_collection, Bucket* bucket)
|
||||
if (UNEXPECTED(cmp == NULL)) {
|
||||
|
@ -3422,7 +3427,7 @@ PHP_METHOD(Pair, __construct)
|
|||
ZEND_PARSE_PARAMETERS_END();
|
||||
Z_TRY_ADDREF_P(first);
|
||||
Z_TRY_ADDREF_P(second);
|
||||
zend_object* current = Z_OBJ_P(getThis());
|
||||
zend_object* current = Z_OBJ_P(&EX(This));
|
||||
pair_update_first(current, first);
|
||||
pair_update_second(current, second);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
extern zend_module_entry collections_module_entry;
|
||||
#define phpext_collections_ptr &collections_module_entry
|
||||
|
||||
#define PHP_COLLECTIONS_VERSION "0.1.0"
|
||||
#define PHP_COLLECTIONS_VERSION "0.1.2"
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
#define PHP_COLLECTIONS_API __declspec(dllexport)
|
||||
|
@ -28,6 +28,14 @@ extern zend_module_entry collections_module_entry;
|
|||
|
||||
#if PHP_VERSION_ID < 70100
|
||||
#error "This extension requires PHP 7.1 and above."
|
||||
#elif PHP_VERSION_ID >= 80000
|
||||
#error "This extension does not yet support PHP 8.0 (which is under development)."
|
||||
#endif
|
||||
|
||||
#if PHP_VERSION_ID >= 70400
|
||||
typedef zval* zobj_write_prop_ret_t;
|
||||
#else
|
||||
typedef void zobj_write_prop_ret_t;
|
||||
#endif
|
||||
|
||||
#define PHP_COLLECTIONS_COMPARE_NATURAL (1 << 0)
|
||||
|
@ -62,7 +70,7 @@ void collection_write_dimension(zval* object, zval* offset, zval* value);
|
|||
zval* collection_read_dimension(zval* object, zval* offset, int type, zval* rv);
|
||||
void collection_unset_dimension(zval* object, zval* offset);
|
||||
int collection_has_property(zval* object, zval* member, int has_set_exists, void**);
|
||||
void collection_write_property(zval* object, zval* member, zval* value, void**);
|
||||
zobj_write_prop_ret_t collection_write_property(zval* object, zval* member, zval* value, void**);
|
||||
zval* collection_read_property(zval* object, zval* member, int type, void**, zval* rv);
|
||||
void collection_unset_property(zval* object, zval* member, void**);
|
||||
|
||||
|
|
Reference in New Issue