andrei Tue Feb 7 20:01:29 2006 UTC Modified files: /php-src/ext/unicode unicode_iterators.c Log: Implement reverse iteration for codeunits and codepoints. Combining sequences are next. # This is ugly, though. # foreach (new TextIterator($a, # TextIterator::CODE_POINT|TextIterator::REVERSE) as $k => $c) { # var_dump("$k: $c"); # } # Any suggestions? http://cvs.php.net/viewcvs.cgi/php-src/ext/unicode/unicode_iterators.c?r1=1.15&r2=1.16&diff_format=u Index: php-src/ext/unicode/unicode_iterators.c diff -u php-src/ext/unicode/unicode_iterators.c:1.15 php-src/ext/unicode/unicode_iterators.c:1.16 --- php-src/ext/unicode/unicode_iterators.c:1.15 Tue Feb 7 00:13:54 2006 +++ php-src/ext/unicode/unicode_iterators.c Tue Feb 7 20:01:28 2006 @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: unicode_iterators.c,v 1.15 2006/02/07 00:13:54 andrei Exp $ */ +/* $Id: unicode_iterators.c,v 1.16 2006/02/07 20:01:28 andrei Exp $ */ /* * TODO @@ -36,8 +36,8 @@ ITER_TYPE_LAST, } text_iter_type; -const uint32_t ITER_REVERSE = 0x100; -const uint32_t ITER_TYPE_MASK = 0xFF; +static const uint32_t ITER_REVERSE = 0x100; +static const uint32_t ITER_TYPE_MASK = 0xFF; typedef struct { zend_object std; @@ -46,13 +46,14 @@ text_iter_type type; zval* current; size_t current_alloc; + long flags; union { struct { uint32_t index; uint32_t offset; } cp; struct { - uint32_t index; + int32_t index; } cu; struct { uint32_t index; @@ -82,7 +83,11 @@ static int text_iter_cu_valid(text_iter_obj* object TSRMLS_DC) { - return (object->u.cu.index < object->text_len); + if (object->flags & ITER_REVERSE) { + return (object->u.cu.index >= 0); + } else { + return (object->u.cu.index < object->text_len); + } } static void text_iter_cu_current(text_iter_obj* object TSRMLS_DC) @@ -94,17 +99,33 @@ static int text_iter_cu_key(text_iter_obj* object TSRMLS_DC) { - return object->u.cu.index; + if (object->flags & ITER_REVERSE) { + return object->text_len - object->u.cu.index - 1; + } else { + return object->u.cu.index; + } } static void text_iter_cu_next(text_iter_obj* object TSRMLS_DC) { - object->u.cu.index++; + if (object->flags & ITER_REVERSE) { + if (object->u.cu.index >= 0) { + object->u.cu.index--; + } + } else { + if (object->u.cu.index < object->text_len) { + object->u.cu.index++; + } + } } static void text_iter_cu_rewind(text_iter_obj *object TSRMLS_DC) { - object->u.cu.index = 0; + if (object->flags & ITER_REVERSE) { + object->u.cu.index = object->text_len-1; + } else { + object->u.cu.index = 0; + } } static text_iter_ops text_iter_cu_ops = { @@ -119,7 +140,11 @@ static int text_iter_cp_valid(text_iter_obj* object TSRMLS_DC) { - return (object->u.cp.offset < object->text_len); + if (object->flags & ITER_REVERSE) { + return (object->u.cp.offset > 0); + } else { + return (object->u.cp.offset < object->text_len); + } } static void text_iter_cp_current(text_iter_obj* object TSRMLS_DC) @@ -128,7 +153,11 @@ int32_t tmp, buf_len; tmp = object->u.cp.offset; - U16_NEXT(object->text, tmp, object->text_len, cp); + if (object->flags & ITER_REVERSE) { + U16_PREV(object->text, 0, tmp, cp); + } else { + 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; Z_USTRLEN_P(object->current) = buf_len; @@ -141,13 +170,21 @@ static void text_iter_cp_next(text_iter_obj* object TSRMLS_DC) { - U16_FWD_1(object->text, object->u.cp.offset, object->text_len); + if (object->flags & ITER_REVERSE) { + U16_BACK_1(object->text, 0, object->u.cp.offset); + } else { + U16_FWD_1(object->text, object->u.cp.offset, object->text_len); + } object->u.cp.index++; } static void text_iter_cp_rewind(text_iter_obj *object TSRMLS_DC) { - object->u.cp.offset = 0; + if (object->flags & ITER_REVERSE) { + object->u.cp.offset = object->text_len; + } else { + object->u.cp.offset = 0; + } object->u.cp.index = 0; } @@ -371,11 +408,12 @@ intern->text_len = text_len; if (ZEND_NUM_ARGS() > 1) { ti_type = flags & ITER_TYPE_MASK; - if (flags < ITER_TYPE_LAST) { + if (ti_type < ITER_TYPE_LAST) { intern->type = ti_type; } else { php_error(E_WARNING, "Invalid iterator type in TextIterator constructor"); } + intern->flags = flags; } iter_ops[intern->type]->rewind(intern TSRMLS_CC); @@ -445,6 +483,8 @@ zend_declare_class_constant_long(text_iterator_ce, "CODE_UNIT", sizeof("CODE_UNIT")-1, ITER_CODE_UNIT TSRMLS_CC); zend_declare_class_constant_long(text_iterator_ce, "CODE_POINT", sizeof("CODE_POINT")-1, ITER_CODE_POINT TSRMLS_CC); zend_declare_class_constant_long(text_iterator_ce, "COMB_SEQUENCE", sizeof("COMB_SEQUENCE")-1, ITER_COMB_SEQUENCE TSRMLS_CC); + + zend_declare_class_constant_long(text_iterator_ce, "REVERSE", sizeof("REVERSE")-1, ITER_REVERSE TSRMLS_CC); } /*
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php