PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/intl/breakiterator - breakiterator_iterators.cpp (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 116 130 89.2 %
Date: 2014-09-27 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | This source file is subject to version 3.01 of the PHP license,      |
       6             :    | that is bundled with this package in the file LICENSE, and is        |
       7             :    | available through the world-wide-web at the following url:           |
       8             :    | http://www.php.net/license/3_01.txt                                  |
       9             :    | If you did not receive a copy of the PHP license and are unable to   |
      10             :    | obtain it through the world-wide-web, please send a note to          |
      11             :    | license@php.net so we can mail you a copy immediately.               |
      12             :    +----------------------------------------------------------------------+
      13             :    | Authors: Gustavo Lopes <cataphract@php.net>                          |
      14             :    +----------------------------------------------------------------------+
      15             : */
      16             : 
      17             : #ifdef HAVE_CONFIG_H
      18             : #include "config.h"
      19             : #endif
      20             : 
      21             : #include <unicode/brkiter.h>
      22             : 
      23             : #include "breakiterator_iterators.h"
      24             : #include "../common/common_enum.h"
      25             : 
      26             : extern "C" {
      27             : #define USE_BREAKITERATOR_POINTER
      28             : #include "breakiterator_class.h"
      29             : #include "../intl_convert.h"
      30             : #include "../locale/locale.h"
      31             : #include <zend_exceptions.h>
      32             : }
      33             : 
      34             : static zend_class_entry *IntlPartsIterator_ce_ptr;
      35             : static zend_object_handlers IntlPartsIterator_handlers;
      36             : 
      37             : /* BreakIterator's iterator */
      38             : 
      39          17 : inline BreakIterator *_breakiter_prolog(zend_object_iterator *iter TSRMLS_DC)
      40             : {
      41             :         BreakIterator_object *bio;
      42          17 :         bio = Z_INTL_BREAKITERATOR_P(&iter->data);
      43          17 :         intl_errors_reset(BREAKITER_ERROR_P(bio) TSRMLS_CC);
      44          17 :         if (bio->biter == NULL) {
      45             :                 intl_errors_set(BREAKITER_ERROR_P(bio), U_INVALID_STATE_ERROR,
      46             :                         "The BreakIterator object backing the PHP iterator is not "
      47           0 :                         "properly constructed", 0 TSRMLS_CC);
      48             :         }
      49          17 :         return bio->biter;
      50             : }
      51             : 
      52           1 : static void _breakiterator_destroy_it(zend_object_iterator *iter TSRMLS_DC)
      53             : {
      54           1 :         zval_ptr_dtor(&iter->data);
      55           1 : }
      56             : 
      57          16 : static void _breakiterator_move_forward(zend_object_iterator *iter TSRMLS_DC)
      58             : {
      59          16 :         BreakIterator *biter = _breakiter_prolog(iter TSRMLS_CC);
      60          16 :         zoi_with_current *zoi_iter = (zoi_with_current*)iter;
      61             : 
      62          16 :         iter->funcs->invalidate_current(iter TSRMLS_CC);
      63             : 
      64          16 :         if (biter == NULL) {
      65           0 :                 return;
      66             :         }
      67             : 
      68          16 :         int32_t pos = biter->next();
      69          16 :         if (pos != BreakIterator::DONE) {
      70          15 :                 ZVAL_LONG(&zoi_iter->current, (zend_long)pos);
      71             :         } //else we've reached the end of the enum, nothing more is required
      72             : }
      73             : 
      74           1 : static void _breakiterator_rewind(zend_object_iterator *iter TSRMLS_DC)
      75             : {
      76           1 :         BreakIterator *biter = _breakiter_prolog(iter TSRMLS_CC);
      77           1 :         zoi_with_current *zoi_iter = (zoi_with_current*)iter;
      78             : 
      79           1 :         int32_t pos = biter->first();
      80           1 :         ZVAL_LONG(&zoi_iter->current, (zend_long)pos);
      81           1 : }
      82             : 
      83             : static zend_object_iterator_funcs breakiterator_iterator_funcs = {
      84             :         zoi_with_current_dtor,
      85             :         zoi_with_current_valid,
      86             :         zoi_with_current_get_current_data,
      87             :         NULL,
      88             :         _breakiterator_move_forward,
      89             :         _breakiterator_rewind,
      90             :         zoi_with_current_invalidate_current
      91             : };
      92             : 
      93           1 : U_CFUNC zend_object_iterator *_breakiterator_get_iterator(
      94             :         zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
      95             : {
      96             :         BreakIterator_object *bio;
      97           1 :         if (by_ref) {
      98             :                 zend_throw_exception(NULL,
      99           0 :                         "Iteration by reference is not supported", 0 TSRMLS_CC);
     100           0 :                 return NULL;
     101             :         }
     102             : 
     103           1 :         bio = Z_INTL_BREAKITERATOR_P(object);
     104           1 :         BreakIterator *biter = bio->biter;
     105             : 
     106           1 :         if (biter == NULL) {
     107             :                 zend_throw_exception(NULL,
     108           0 :                         "The BreakIterator is not properly constructed", 0 TSRMLS_CC);
     109           0 :                 return NULL;
     110             :         }
     111             : 
     112           1 :         zoi_with_current *zoi_iter = static_cast<zoi_with_current*>(emalloc(sizeof *zoi_iter));
     113           1 :         zend_iterator_init(&zoi_iter->zoi TSRMLS_CC);
     114           1 :         ZVAL_COPY(&zoi_iter->zoi.data, object);
     115           1 :         zoi_iter->zoi.funcs = &breakiterator_iterator_funcs;
     116           1 :         zoi_iter->zoi.index = 0;
     117           1 :         zoi_iter->destroy_it = _breakiterator_destroy_it;
     118           1 :         ZVAL_UNDEF(&zoi_iter->wrapping_obj); /* not used; object is in zoi.data */
     119           1 :         ZVAL_UNDEF(&zoi_iter->current);
     120             : 
     121           1 :         return reinterpret_cast<zend_object_iterator *>(zoi_iter);
     122             : }
     123             : 
     124             : /* BreakIterator parts iterator */
     125             : 
     126             : typedef struct zoi_break_iter_parts {
     127             :         zoi_with_current zoi_cur;
     128             :         parts_iter_key_type key_type;
     129             :         BreakIterator_object *bio; /* so we don't have to fetch it all the time */
     130             : } zoi_break_iter_parts;
     131             : 
     132           6 : static void _breakiterator_parts_destroy_it(zend_object_iterator *iter TSRMLS_DC)
     133             : {
     134           6 :         zval_ptr_dtor(&iter->data);
     135           6 : }
     136             : 
     137          33 : static void _breakiterator_parts_get_current_key(zend_object_iterator *iter, zval *key TSRMLS_DC)
     138             : {
     139             :         /* the actual work is done in move_forward and rewind */
     140          33 :         ZVAL_LONG(key, iter->index);
     141          33 : }
     142             : 
     143          39 : static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_DC)
     144             : {
     145          39 :         zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter;
     146          39 :         BreakIterator_object *bio = zoi_bit->bio;
     147             : 
     148          39 :         iter->funcs->invalidate_current(iter TSRMLS_CC);
     149             : 
     150             :         int32_t cur,
     151             :                         next;
     152             : 
     153          39 :         cur = bio->biter->current();
     154          39 :         if (cur == BreakIterator::DONE) {
     155           0 :                 return;
     156             :         }
     157          39 :         next = bio->biter->next();
     158          39 :         if (next == BreakIterator::DONE) {
     159           6 :                 return;
     160             :         }
     161             : 
     162          33 :         if (zoi_bit->key_type == PARTS_ITERATOR_KEY_LEFT) {
     163           5 :                 iter->index = cur;
     164          28 :         } else if (zoi_bit->key_type == PARTS_ITERATOR_KEY_RIGHT) {
     165           5 :                 iter->index = next;
     166             :         }
     167             :         /* else zoi_bit->key_type == PARTS_ITERATOR_KEY_SEQUENTIAL
     168             :          * No need to do anything, the engine increments ->index */
     169             : 
     170          33 :         const char      *s = Z_STRVAL(bio->text);
     171          33 :         int32_t         slen = Z_STRLEN(bio->text);
     172             :         zend_string     *res;
     173             : 
     174          33 :         if (next == BreakIterator::DONE) {
     175           0 :                 next = slen;
     176             :         }
     177             :         assert(next <= slen && next >= cur);
     178          66 :         res = zend_string_alloc(next - cur, 0);
     179             : 
     180          33 :         memcpy(res->val, &s[cur], res->len);
     181          33 :         res->val[res->len] = '\0';
     182             : 
     183          33 :         ZVAL_STR(&zoi_bit->zoi_cur.current, res);
     184             : }
     185             : 
     186           6 : static void _breakiterator_parts_rewind(zend_object_iterator *iter TSRMLS_DC)
     187             : {
     188           6 :         zoi_break_iter_parts *zoi_bit = (zoi_break_iter_parts*)iter;
     189           6 :         BreakIterator_object *bio = zoi_bit->bio;
     190             : 
     191          12 :         if (!Z_ISUNDEF(zoi_bit->zoi_cur.current)) {
     192           0 :                 iter->funcs->invalidate_current(iter TSRMLS_CC);
     193             :         }
     194             : 
     195           6 :         bio->biter->first();
     196             : 
     197           6 :         iter->funcs->move_forward(iter TSRMLS_CC);
     198           6 : }
     199             : 
     200             : static zend_object_iterator_funcs breakiterator_parts_it_funcs = {
     201             :         zoi_with_current_dtor,
     202             :         zoi_with_current_valid,
     203             :         zoi_with_current_get_current_data,
     204             :         _breakiterator_parts_get_current_key,
     205             :         _breakiterator_parts_move_forward,
     206             :         _breakiterator_parts_rewind,
     207             :         zoi_with_current_invalidate_current
     208             : };
     209             : 
     210           6 : void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv,
     211             :                                                                                    zval *object,
     212             :                                                                                    parts_iter_key_type key_type TSRMLS_DC)
     213             : {
     214             :         IntlIterator_object *ii;
     215             : 
     216           6 :         object_init_ex(object, IntlPartsIterator_ce_ptr);
     217           6 :         ii = Z_INTL_ITERATOR_P(object);
     218             : 
     219           6 :         ii->iterator = (zend_object_iterator*)emalloc(sizeof(zoi_break_iter_parts));
     220           6 :         zend_iterator_init(ii->iterator TSRMLS_CC);
     221             : 
     222           6 :         ZVAL_COPY(&ii->iterator->data, break_iter_zv);
     223           6 :         ii->iterator->funcs = &breakiterator_parts_it_funcs;
     224           6 :         ii->iterator->index = 0;
     225             : 
     226           6 :         ((zoi_with_current*)ii->iterator)->destroy_it = _breakiterator_parts_destroy_it;
     227           6 :         ZVAL_COPY_VALUE(&((zoi_with_current*)ii->iterator)->wrapping_obj, object);
     228           6 :         ZVAL_UNDEF(&((zoi_with_current*)ii->iterator)->current);
     229             : 
     230           6 :         ((zoi_break_iter_parts*)ii->iterator)->bio = Z_INTL_BREAKITERATOR_P(break_iter_zv);
     231             : 
     232             :         assert(((zoi_break_iter_parts*)ii->iterator)->bio->biter != NULL);
     233             : 
     234           6 :         ((zoi_break_iter_parts*)ii->iterator)->key_type = key_type;
     235           6 : }
     236             : 
     237           6 : U_CFUNC zend_object *IntlPartsIterator_object_create(zend_class_entry *ce TSRMLS_DC)
     238             : {
     239           6 :         zend_object *retval = IntlIterator_ce_ptr->create_object(ce TSRMLS_CC);
     240           6 :         retval->handlers = &IntlPartsIterator_handlers;
     241             : 
     242           6 :         return retval;
     243             : }
     244             : 
     245           5 : U_CFUNC zend_function *IntlPartsIterator_get_method(zend_object **object_ptr, zend_string *method, const zval *key TSRMLS_DC)
     246             : {
     247             :         zend_function *ret;
     248             :         zend_string *lc_method_name;
     249             :         ALLOCA_FLAG(use_heap);
     250             : 
     251           5 :         if (key == NULL) {
     252           0 :                 STR_ALLOCA_ALLOC(lc_method_name, method->len, use_heap);
     253           0 :                 zend_str_tolower_copy(lc_method_name->val, method->val, method->len);
     254             :         } else {
     255           5 :                 lc_method_name = Z_STR_P(key);
     256             :         }
     257             : 
     258           5 :         if (method->len == sizeof("getrulestatus") - 1
     259             :                         && memcmp("getrulestatus", Z_STRVAL_P(key),   method->len) == 0) {
     260           1 :                 IntlIterator_object *obj = php_intl_iterator_fetch_object(*object_ptr);
     261           2 :                 if (obj->iterator && !Z_ISUNDEF(obj->iterator->data)) {
     262           1 :                         zval *break_iter_zv = &obj->iterator->data;
     263           1 :                         *object_ptr = Z_OBJ_P(break_iter_zv);
     264           1 :                         ret = Z_OBJ_HANDLER_P(break_iter_zv, get_method)(object_ptr, method, key TSRMLS_CC);
     265           1 :                         goto end;
     266             :                 }
     267             :         }
     268             : 
     269           4 :         ret = std_object_handlers.get_method(object_ptr, method, key TSRMLS_CC);
     270             : 
     271             : end:
     272           5 :         if (key == NULL) {
     273           0 :                 STR_ALLOCA_FREE(lc_method_name, use_heap);
     274             :         }
     275             : 
     276           5 :         return ret;
     277             : }
     278             : 
     279          32 : U_CFUNC PHP_METHOD(IntlPartsIterator, getBreakIterator)
     280             : {
     281          32 :         INTLITERATOR_METHOD_INIT_VARS;
     282             : 
     283          32 :         if (zend_parse_parameters_none() == FAILURE) {
     284             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     285           0 :                         "IntlPartsIterator::getBreakIterator: bad arguments", 0 TSRMLS_CC);
     286           0 :                 return;
     287             :         }
     288             : 
     289          32 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     290             : 
     291          32 :         zval *biter_zval = &ii->iterator->data;
     292          96 :         RETURN_ZVAL(biter_zval, 1, 0);
     293             : }
     294             : 
     295             : ZEND_BEGIN_ARG_INFO_EX(ainfo_parts_it_void, 0, 0, 0)
     296             : ZEND_END_ARG_INFO()
     297             : 
     298             : static const zend_function_entry IntlPartsIterator_class_functions[] = {
     299             :         PHP_ME(IntlPartsIterator,       getBreakIterator,       ainfo_parts_it_void,    ZEND_ACC_PUBLIC)
     300             :         PHP_FE_END
     301             : };
     302             : 
     303       20352 : U_CFUNC void breakiterator_register_IntlPartsIterator_class(TSRMLS_D)
     304             : {
     305             :         zend_class_entry ce;
     306             : 
     307             :         /* Create and register 'BreakIterator' class. */
     308       20352 :         INIT_CLASS_ENTRY(ce, "IntlPartsIterator", IntlPartsIterator_class_functions);
     309             :         IntlPartsIterator_ce_ptr = zend_register_internal_class_ex(&ce,
     310       20352 :                         IntlIterator_ce_ptr TSRMLS_CC);
     311       20352 :         IntlPartsIterator_ce_ptr->create_object = IntlPartsIterator_object_create;
     312             : 
     313             :         memcpy(&IntlPartsIterator_handlers, &IntlIterator_handlers,
     314       20352 :                         sizeof IntlPartsIterator_handlers);
     315       20352 :         IntlPartsIterator_handlers.get_method = IntlPartsIterator_get_method;
     316             : 
     317             : #define PARTSITER_DECL_LONG_CONST(name) \
     318             :         zend_declare_class_constant_long(IntlPartsIterator_ce_ptr, #name, \
     319             :                 sizeof(#name) - 1, PARTS_ITERATOR_ ## name TSRMLS_CC)
     320             : 
     321       20352 :         PARTSITER_DECL_LONG_CONST(KEY_SEQUENTIAL);
     322       20352 :         PARTSITER_DECL_LONG_CONST(KEY_LEFT);
     323       20352 :         PARTSITER_DECL_LONG_CONST(KEY_RIGHT);
     324             : 
     325             : #undef PARTSITER_DECL_LONG_CONST
     326       20352 : }

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:10 +0000 (4 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.