mirror of
https://github.com/php/php-src.git
synced 2025-08-18 15:08:55 +02:00
Abstract the iterator interface so that we can add new types.
This commit is contained in:
parent
94e3087be7
commit
4a3bf22b81
1 changed files with 54 additions and 22 deletions
|
@ -34,8 +34,15 @@ typedef struct {
|
|||
uint32_t text_len;
|
||||
text_iter_type type;
|
||||
zval* current;
|
||||
int32_t offset;
|
||||
int32_t index;
|
||||
union {
|
||||
struct {
|
||||
int32_t offset;
|
||||
int32_t index;
|
||||
} cp;
|
||||
struct {
|
||||
int32_t index;
|
||||
} cu;
|
||||
} u;
|
||||
} text_iter_obj;
|
||||
|
||||
typedef struct {
|
||||
|
@ -43,17 +50,30 @@ typedef struct {
|
|||
text_iter_obj* object;
|
||||
} text_iter_it;
|
||||
|
||||
typedef struct {
|
||||
int (*valid) (text_iter_obj* object TSRMLS_DC);
|
||||
void (*current)(text_iter_obj* object TSRMLS_DC);
|
||||
int (*key) (text_iter_obj* object TSRMLS_DC);
|
||||
void (*next) (text_iter_obj* object TSRMLS_DC);
|
||||
void (*rewind) (text_iter_obj* object TSRMLS_DC);
|
||||
} text_iter_ops;
|
||||
|
||||
PHPAPI zend_class_entry* text_iterator_aggregate_ce;
|
||||
PHPAPI zend_class_entry* text_iterator_ce;
|
||||
|
||||
/* Code unit ops */
|
||||
|
||||
static text_iter_ops text_iter_cu_ops = {
|
||||
};
|
||||
|
||||
/* Code point ops */
|
||||
|
||||
static int text_iter_cp_valid(text_iter_obj* object TSRMLS_DC)
|
||||
{
|
||||
return (object->offset < object->text_len);
|
||||
return (object->u.cp.offset < object->text_len);
|
||||
}
|
||||
|
||||
static void text_iter_cp_get_current_data(text_iter_obj* object TSRMLS_DC)
|
||||
static void text_iter_cp_current(text_iter_obj* object TSRMLS_DC)
|
||||
{
|
||||
UChar32 cp;
|
||||
int32_t tmp, buf_len;
|
||||
|
@ -62,7 +82,7 @@ static void text_iter_cp_get_current_data(text_iter_obj* object TSRMLS_DC)
|
|||
MAKE_STD_ZVAL(object->current);
|
||||
Z_USTRVAL_P(object->current) = eumalloc(3);
|
||||
Z_TYPE_P(object->current) = IS_UNICODE;
|
||||
tmp = object->offset;
|
||||
tmp = object->u.cp.offset;
|
||||
U16_NEXT(object->text, tmp, object->text_len, cp);
|
||||
buf_len = zend_codepoint_to_uchar(cp, Z_USTRVAL_P(object->current));
|
||||
Z_USTRVAL_P(object->current)[buf_len] = 0;
|
||||
|
@ -70,15 +90,15 @@ static void text_iter_cp_get_current_data(text_iter_obj* object TSRMLS_DC)
|
|||
}
|
||||
}
|
||||
|
||||
static int text_iter_cp_get_current_key(text_iter_obj* object TSRMLS_DC)
|
||||
static int text_iter_cp_key(text_iter_obj* object TSRMLS_DC)
|
||||
{
|
||||
return object->index;
|
||||
return object->u.cp.index;
|
||||
}
|
||||
|
||||
static void text_iter_cp_move_forward(text_iter_obj* object TSRMLS_DC)
|
||||
static void text_iter_cp_next(text_iter_obj* object TSRMLS_DC)
|
||||
{
|
||||
U16_FWD_1(object->text, object->offset, object->text_len);
|
||||
object->index++;
|
||||
U16_FWD_1(object->text, object->u.cp.offset, object->text_len);
|
||||
object->u.cp.index++;
|
||||
if (object->current) {
|
||||
zval_ptr_dtor(&object->current);
|
||||
object->current = NULL;
|
||||
|
@ -87,14 +107,26 @@ static void text_iter_cp_move_forward(text_iter_obj* object TSRMLS_DC)
|
|||
|
||||
static void text_iter_cp_rewind(text_iter_obj *object TSRMLS_DC)
|
||||
{
|
||||
object->offset = 0;
|
||||
object->index = 0;
|
||||
object->u.cp.offset = 0;
|
||||
object->u.cp.index = 0;
|
||||
if (object->current) {
|
||||
zval_ptr_dtor(&object->current);
|
||||
object->current = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static text_iter_ops text_iter_cp_ops = {
|
||||
text_iter_cp_valid,
|
||||
text_iter_cp_current,
|
||||
text_iter_cp_key,
|
||||
text_iter_cp_next,
|
||||
text_iter_cp_rewind,
|
||||
};
|
||||
|
||||
static text_iter_ops* iter_ops[2] = {
|
||||
&text_iter_cu_ops,
|
||||
&text_iter_cp_ops,
|
||||
};
|
||||
|
||||
/* Iterator Funcs */
|
||||
|
||||
|
@ -110,7 +142,7 @@ static int text_iter_valid(zend_object_iterator* iter TSRMLS_DC)
|
|||
text_iter_it* iterator = (text_iter_it *) iter;
|
||||
text_iter_obj* object = iterator->object;
|
||||
|
||||
if (text_iter_cp_valid(object TSRMLS_CC))
|
||||
if (iter_ops[object->type]->valid(object TSRMLS_CC))
|
||||
return SUCCESS;
|
||||
else
|
||||
return FAILURE;
|
||||
|
@ -121,7 +153,7 @@ static void text_iter_get_current_data(zend_object_iterator* iter, zval*** data
|
|||
text_iter_it* iterator = (text_iter_it *) iter;
|
||||
text_iter_obj* object = iterator->object;
|
||||
|
||||
text_iter_cp_get_current_data(object TSRMLS_CC);
|
||||
iter_ops[object->type]->current(object TSRMLS_CC);
|
||||
*data = &object->current;
|
||||
}
|
||||
|
||||
|
@ -130,7 +162,7 @@ static int text_iter_get_current_key(zend_object_iterator* iter, char **str_key,
|
|||
text_iter_it* iterator = (text_iter_it *) iter;
|
||||
text_iter_obj* object = iterator->object;
|
||||
|
||||
*int_key = text_iter_cp_get_current_key(object TSRMLS_CC);
|
||||
*int_key = iter_ops[object->type]->key(object TSRMLS_CC);
|
||||
return HASH_KEY_IS_LONG;
|
||||
}
|
||||
|
||||
|
@ -139,7 +171,7 @@ static void text_iter_move_forward(zend_object_iterator* iter TSRMLS_DC)
|
|||
text_iter_it* iterator = (text_iter_it *) iter;
|
||||
text_iter_obj* object = iterator->object;
|
||||
|
||||
text_iter_cp_move_forward(object TSRMLS_CC);
|
||||
iter_ops[object->type]->next(object TSRMLS_CC);
|
||||
}
|
||||
|
||||
static void text_iter_rewind(zend_object_iterator* iter TSRMLS_DC)
|
||||
|
@ -147,7 +179,7 @@ static void text_iter_rewind(zend_object_iterator* iter TSRMLS_DC)
|
|||
text_iter_it* iterator = (text_iter_it *) iter;
|
||||
text_iter_obj* object = iterator->object;
|
||||
|
||||
text_iter_cp_rewind(object TSRMLS_CC);
|
||||
iter_ops[object->type]->rewind(object TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_object_iterator_funcs text_iter_cp_funcs = {
|
||||
|
@ -234,7 +266,7 @@ PHP_METHOD(TextIterator, current)
|
|||
zval *object = getThis();
|
||||
text_iter_obj *intern = (text_iter_obj*) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
text_iter_cp_get_current_data(intern TSRMLS_CC);
|
||||
iter_ops[intern->type]->current(intern TSRMLS_CC);
|
||||
RETURN_UNICODEL(Z_USTRVAL_P(intern->current), Z_USTRLEN_P(intern->current), 1);
|
||||
}
|
||||
|
||||
|
@ -243,7 +275,7 @@ PHP_METHOD(TextIterator, next)
|
|||
zval *object = getThis();
|
||||
text_iter_obj *intern = (text_iter_obj*) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
text_iter_cp_move_forward(intern TSRMLS_CC);
|
||||
iter_ops[intern->type]->next(intern TSRMLS_CC);
|
||||
}
|
||||
|
||||
PHP_METHOD(TextIterator, key)
|
||||
|
@ -251,7 +283,7 @@ PHP_METHOD(TextIterator, key)
|
|||
zval *object = getThis();
|
||||
text_iter_obj *intern = (text_iter_obj*) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
RETURN_LONG(text_iter_cp_get_current_key(intern TSRMLS_CC));
|
||||
RETURN_LONG(iter_ops[intern->type]->key(intern TSRMLS_CC));
|
||||
}
|
||||
|
||||
PHP_METHOD(TextIterator, valid)
|
||||
|
@ -259,7 +291,7 @@ PHP_METHOD(TextIterator, valid)
|
|||
zval *object = getThis();
|
||||
text_iter_obj *intern = (text_iter_obj*) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
RETURN_BOOL(text_iter_cp_valid(intern TSRMLS_CC));
|
||||
RETURN_BOOL(iter_ops[intern->type]->valid(intern TSRMLS_CC));
|
||||
}
|
||||
|
||||
PHP_METHOD(TextIterator, rewind)
|
||||
|
@ -267,7 +299,7 @@ PHP_METHOD(TextIterator, rewind)
|
|||
zval *object = getThis();
|
||||
text_iter_obj *intern = (text_iter_obj*) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
text_iter_cp_rewind(intern TSRMLS_CC);
|
||||
iter_ops[object->type]->rewind(intern TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zend_function_entry text_iterator_funcs[] = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue