Skip to content

Commit

Permalink
Added Map::find(), ArrayList::find(), supports ArrayList::offsetUnset()
Browse files Browse the repository at this point in the history
  • Loading branch information
matyhtf committed Jul 11, 2024
1 parent 936402e commit f5a800b
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 44 deletions.
29 changes: 6 additions & 23 deletions ext-src/php_swoole_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ struct ArrayItem {
void store(zval *zvalue);
void fetch(zval *return_value);
void release();
bool equals(zval *zvalue);

~ArrayItem() {
if (value.str) {
Expand Down Expand Up @@ -252,6 +253,7 @@ struct ZendArray : ThreadResource {
void keys(zval *return_value);
void values(zval *return_value);
void toArray(zval *return_value);
void find(zval *search, zval *return_value);

void intkey_offsetGet(zend_long index, zval *return_value) {
lock_.lock_rd();
Expand Down Expand Up @@ -288,29 +290,10 @@ struct ZendArray : ThreadResource {
lock_.unlock();
}

bool index_offsetGet(zval *zkey, zval *return_value) {
zend_long index = zval_get_long(zkey);
bool out_of_range = true;
lock_.lock_rd();
if (index_exists(index)) {
out_of_range = false;
ArrayItem *item = (ArrayItem *) zend_hash_index_find_ptr(&ht, index);
if (item) {
item->fetch(return_value);
}
}
lock_.unlock();
return !out_of_range;
}

bool index_offsetSet(zval *zkey, zval *zvalue);

void index_offsetExists(zval *zkey, zval *return_value) {
zend_long index = zval_get_long(zkey);
lock_.lock_rd();
RETVAL_BOOL(index_exists(index));
lock_.unlock();
}
bool index_offsetGet(zend_long index, zval *return_value);
bool index_offsetSet(zend_long index, zval *zvalue);
void index_offsetUnset(zend_long index);
void index_offsetExists(zend_long index, zval *return_value);

static void incr_update(ArrayItem *item, zval *zvalue, zval *return_value);
static ArrayItem *incr_create(zval *zvalue, zval *return_value);
Expand Down
1 change: 1 addition & 0 deletions ext-src/stubs/php_swoole_thread_arraylist.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public function offsetGet(mixed $key): mixed {}
public function offsetExists(mixed $key): bool {}
public function offsetSet(mixed $key, mixed $value): void {}
public function offsetUnset(mixed $key): void {}
public function find(mixed $value): int {}
public function count(): int {}
public function incr(mixed $key, mixed $value = 1): mixed {}
public function decr(mixed $key, mixed $value = 1): mixed {}
Expand Down
6 changes: 5 additions & 1 deletion ext-src/stubs/php_swoole_thread_arraylist_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 70c2427e37953ac2ceefe4c972cbd8b9845b43ab */
* Stub hash: 1ca9dca970881ea647b0ebc5431e857cdb973eb8 */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_ArrayList___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, array, IS_ARRAY, 1, "null")
Expand All @@ -22,6 +22,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_of
ZEND_ARG_TYPE_INFO(0, key, IS_MIXED, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_find, 0, 1, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_ArrayList_count, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()

Expand Down
1 change: 1 addition & 0 deletions ext-src/stubs/php_swoole_thread_map.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public function offsetGet(mixed $key): mixed {}
public function offsetExists(mixed $key): bool {}
public function offsetSet(mixed $key, mixed $value): void {}
public function offsetUnset(mixed $key): void {}
public function find(mixed $value): mixed {}
public function count(): int {}
public function keys(): array {}
public function values(): array {}
Expand Down
6 changes: 5 additions & 1 deletion ext-src/stubs/php_swoole_thread_map_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 40e24b68b9e9d7f7192a8f91e4b31b3020e9faca */
* Stub hash: 39226ea3aff361cc9530c65fe7de5a0e276a65fe */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Swoole_Thread_Map___construct, 0, 0, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, array, IS_ARRAY, 1, "null")
Expand All @@ -22,6 +22,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_offsetUn
ZEND_ARG_TYPE_INFO(0, key, IS_MIXED, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_find, 0, 1, IS_MIXED, 0)
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Swoole_Thread_Map_count, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()

Expand Down
80 changes: 76 additions & 4 deletions ext-src/swoole_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ void php_swoole_thread_minit(int module_number) {
swoole_thread_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE;
SW_SET_CLASS_CLONEABLE(swoole_thread, sw_zend_class_clone_deny);
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread, sw_zend_class_unset_property_deny);
SW_SET_CLASS_CUSTOM_OBJECT(
swoole_thread, thread_create_object, thread_free_object, ThreadObject, std);
SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread, thread_create_object, thread_free_object, ThreadObject, std);

zend_declare_property_long(swoole_thread_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY);
zend_declare_class_constant_long(
Expand Down Expand Up @@ -499,6 +498,26 @@ void ArrayItem::store(zval *zvalue) {
}
}

bool ArrayItem::equals(zval *zvalue) {
if (Z_TYPE_P(zvalue) != type) {
return false;
}
switch (type) {
case IS_LONG:
return Z_LVAL_P(zvalue) == value.lval;
case IS_DOUBLE:
return Z_DVAL_P(zvalue) == value.dval;
case IS_TRUE:
case IS_FALSE:
case IS_NULL:
return true;
case IS_STRING:
return zend_string_equals(value.str, Z_STR_P(zvalue));
default:
return false;
}
}

void ArrayItem::fetch(zval *return_value) {
switch (type) {
case IS_LONG:
Expand Down Expand Up @@ -695,8 +714,21 @@ void ZendArray::intkey_update(zval *zkey, zval *zvalue, zval *return_value) {
lock_.unlock();
}

bool ZendArray::index_offsetSet(zval *zkey, zval *zvalue) {
zend_long index = ZVAL_IS_NULL(zkey) ? -1 : zval_get_long(zkey);
bool ZendArray::index_offsetGet(zend_long index, zval *return_value) {
bool out_of_range = true;
lock_.lock_rd();
if (index_exists(index)) {
out_of_range = false;
ArrayItem *item = (ArrayItem *) zend_hash_index_find_ptr(&ht, index);
if (item) {
item->fetch(return_value);
}
}
lock_.unlock();
return !out_of_range;
}

bool ZendArray::index_offsetSet(zend_long index, zval *zvalue) {
auto item = new ArrayItem(zvalue);
bool success = true;
lock_.lock();
Expand Down Expand Up @@ -734,6 +766,26 @@ bool ZendArray::index_incr(zval *zkey, zval *zvalue, zval *return_value) {
return success;
}

void ZendArray::index_offsetExists(zend_long index, zval *return_value) {
lock_.lock_rd();
RETVAL_BOOL(index_exists(index));
lock_.unlock();
}

void ZendArray::index_offsetUnset(zend_long index) {
lock_.lock();
zend_long i = index;
zend_long n = zend_hash_num_elements(&ht);
HT_FLAGS(&ht) |= HASH_FLAG_PACKED | HASH_FLAG_STATIC_KEYS;
while (i < n) {
Z_PTR(ht.arData[i].val) = Z_PTR(ht.arData[i + 1].val);
i++;
}
ht.nNumUsed--;
ht.nNumOfElements--;
lock_.unlock();
}

bool ZendArray::index_decr(zval *zkey, zval *zvalue, zval *return_value) {
INIT_DECR_VALUE(zvalue);
return index_incr(zkey, &rvalue, return_value);
Expand Down Expand Up @@ -810,6 +862,26 @@ void ZendArray::toArray(zval *return_value) {
lock_.unlock();
}

void ZendArray::find(zval *search, zval *return_value) {
lock_.lock_rd();
zend_string *key;
zend_ulong index;
void *tmp;
ZEND_HASH_FOREACH_KEY_PTR(&ht, index, key, tmp) {
ArrayItem *item = (ArrayItem *) tmp;
if (item->equals(search)) {
if (key) {
RETVAL_STRINGL(ZSTR_VAL(key), ZSTR_LEN(key));
} else {
RETVAL_LONG(index);
}
break;
}
}
ZEND_HASH_FOREACH_END();
lock_.unlock();
}

ZendArray *ZendArray::from(zend_array *src) {
zend_string *key;
zend_ulong index;
Expand Down
44 changes: 31 additions & 13 deletions ext-src/swoole_thread_arraylist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static PHP_METHOD(swoole_thread_arraylist, offsetGet);
static PHP_METHOD(swoole_thread_arraylist, offsetExists);
static PHP_METHOD(swoole_thread_arraylist, offsetSet);
static PHP_METHOD(swoole_thread_arraylist, offsetUnset);
static PHP_METHOD(swoole_thread_arraylist, find);
static PHP_METHOD(swoole_thread_arraylist, count);
static PHP_METHOD(swoole_thread_arraylist, incr);
static PHP_METHOD(swoole_thread_arraylist, decr);
Expand Down Expand Up @@ -91,6 +92,7 @@ static const zend_function_entry swoole_thread_arraylist_methods[] = {
PHP_ME(swoole_thread_arraylist, offsetExists, arginfo_class_Swoole_Thread_ArrayList_offsetExists, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, offsetSet, arginfo_class_Swoole_Thread_ArrayList_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, offsetUnset, arginfo_class_Swoole_Thread_ArrayList_offsetUnset, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, find, arginfo_class_Swoole_Thread_ArrayList_find, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, incr, arginfo_class_Swoole_Thread_ArrayList_incr, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, decr, arginfo_class_Swoole_Thread_ArrayList_decr, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_arraylist, clean, arginfo_class_Swoole_Thread_ArrayList_clean, ZEND_ACC_PUBLIC)
Expand All @@ -105,11 +107,8 @@ void php_swoole_thread_arraylist_minit(int module_number) {
swoole_thread_arraylist_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NOT_SERIALIZABLE;
SW_SET_CLASS_CLONEABLE(swoole_thread_arraylist, sw_zend_class_clone_deny);
SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_thread_arraylist, sw_zend_class_unset_property_deny);
SW_SET_CLASS_CUSTOM_OBJECT(swoole_thread_arraylist,
arraylist_create_object,
arraylist_free_object,
ThreadArrayListObject,
std);
SW_SET_CLASS_CUSTOM_OBJECT(
swoole_thread_arraylist, arraylist_create_object, arraylist_free_object, ThreadArrayListObject, std);

zend_class_implements(swoole_thread_arraylist_ce, 2, zend_ce_arrayaccess, zend_ce_countable);
zend_declare_property_long(swoole_thread_arraylist_ce, ZEND_STRL("id"), 0, ZEND_ACC_PUBLIC | ZEND_ACC_READONLY);
Expand Down Expand Up @@ -140,27 +139,27 @@ static PHP_METHOD(swoole_thread_arraylist, __construct) {
}

static PHP_METHOD(swoole_thread_arraylist, offsetGet) {
zval *zkey;
zend_long index;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(zkey)
Z_PARAM_LONG(index)
ZEND_PARSE_PARAMETERS_END();

auto ao = arraylist_fetch_object_check(ZEND_THIS);
if (!ao->list->index_offsetGet(zkey, return_value)) {
if (!ao->list->index_offsetGet(index, return_value)) {
zend_throw_exception(swoole_exception_ce, "out of range", -1);
}
}

static PHP_METHOD(swoole_thread_arraylist, offsetExists) {
zval *zkey;
zend_long index;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(zkey)
Z_PARAM_LONG(index)
ZEND_PARSE_PARAMETERS_END();

auto ao = arraylist_fetch_object_check(ZEND_THIS);
ao->list->index_offsetExists(zkey, return_value);
ao->list->index_offsetExists(index, return_value);
}

static PHP_METHOD(swoole_thread_arraylist, offsetSet) {
Expand All @@ -173,7 +172,8 @@ static PHP_METHOD(swoole_thread_arraylist, offsetSet) {
ZEND_PARSE_PARAMETERS_END();

auto ao = arraylist_fetch_object_check(ZEND_THIS);
if (!ao->list->index_offsetSet(zkey, zvalue)) {
zend_long index = ZVAL_IS_NULL(zkey) ? -1 : zval_get_long(zkey);
if (!ao->list->index_offsetSet(index, zvalue)) {
zend_throw_exception(swoole_exception_ce, "out of range", -1);
}
}
Expand All @@ -195,7 +195,25 @@ static PHP_METHOD(swoole_thread_arraylist, decr) {
}

static PHP_METHOD(swoole_thread_arraylist, offsetUnset) {
zend_throw_exception(swoole_exception_ce, "unsupported", -3);
zend_long index;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_LONG(index)
ZEND_PARSE_PARAMETERS_END();

auto ao = arraylist_fetch_object_check(ZEND_THIS);
ao->list->index_offsetUnset(index);
}

static PHP_METHOD(swoole_thread_arraylist, find) {
zval *zvalue;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(zvalue)
ZEND_PARSE_PARAMETERS_END();

auto ao = arraylist_fetch_object_check(ZEND_THIS);
ao->list->find(zvalue, return_value);
}

static PHP_METHOD(swoole_thread_arraylist, count) {
Expand Down
13 changes: 13 additions & 0 deletions ext-src/swoole_thread_map.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static PHP_METHOD(swoole_thread_map, offsetGet);
static PHP_METHOD(swoole_thread_map, offsetExists);
static PHP_METHOD(swoole_thread_map, offsetSet);
static PHP_METHOD(swoole_thread_map, offsetUnset);
static PHP_METHOD(swoole_thread_map, find);
static PHP_METHOD(swoole_thread_map, count);
static PHP_METHOD(swoole_thread_map, keys);
static PHP_METHOD(swoole_thread_map, values);
Expand All @@ -95,6 +96,7 @@ static const zend_function_entry swoole_thread_map_methods[] = {
PHP_ME(swoole_thread_map, offsetExists, arginfo_class_Swoole_Thread_Map_offsetExists, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, offsetSet, arginfo_class_Swoole_Thread_Map_offsetSet, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, offsetUnset, arginfo_class_Swoole_Thread_Map_offsetUnset, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, find, arginfo_class_Swoole_Thread_Map_find, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, count, arginfo_class_Swoole_Thread_Map_count, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, incr, arginfo_class_Swoole_Thread_Map_incr, ZEND_ACC_PUBLIC)
PHP_ME(swoole_thread_map, decr, arginfo_class_Swoole_Thread_Map_decr, ZEND_ACC_PUBLIC)
Expand Down Expand Up @@ -230,6 +232,17 @@ static PHP_METHOD(swoole_thread_map, offsetUnset) {
ZEND_ARRAY_CALL_METHOD(mo->map, offsetUnset, zkey);
}

static PHP_METHOD(swoole_thread_map, find) {
zval *zvalue;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(zvalue)
ZEND_PARSE_PARAMETERS_END();

auto mo = map_fetch_object_check(ZEND_THIS);
mo->map->find(zvalue, return_value);
}

static PHP_METHOD(swoole_thread_map, count) {
auto mo = map_fetch_object_check(ZEND_THIS);
mo->map->count(return_value);
Expand Down
15 changes: 14 additions & 1 deletion tests/swoole_thread/arraylist.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ require __DIR__ . '/../include/bootstrap.php';

use Swoole\Thread\ArrayList;

$uuid = uniqid();
$array = [
random_int(1, 999999999999999999),
random_bytes(128),
uniqid(),
$uuid,
time(),
];

$l = new ArrayList($array);
Assert::eq(count($l), count($array));
Assert::eq($l->toArray(), $array);
Assert::eq($l->find($uuid), 2);

for ($i = 0; $i < count($array); $i++) {
Assert::eq($l[$i], $array[$i]);
Expand All @@ -41,5 +43,16 @@ try {
} catch (Throwable $e) {
Assert::contains($e->getMessage(), 'must be an array of type list');
}

$uuid2 = uniqid();
$l[] = $uuid2;
$count = count($l);

unset($l[1]);
Assert::eq(count($l), $count - 1);
Assert::eq($l[1], $uuid);
Assert::eq($l->find($uuid), 1);
Assert::eq($l->find($uuid2), $count - 2);

?>
--EXPECTF--
Loading

0 comments on commit f5a800b

Please sign in to comment.