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/common - common_enum.cpp (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 123 141 87.2 %
Date: 2014-07-21 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       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 "../intl_cppshims.h"
      22             : 
      23             : // Fix build on Windows/old versions of ICU
      24             : #include <stdio.h>
      25             : 
      26             : #include "common_enum.h"
      27             : 
      28             : extern "C" {
      29             : #include <zend_interfaces.h>
      30             : #include <zend_exceptions.h>
      31             : }
      32             : 
      33             : zend_class_entry *IntlIterator_ce_ptr;
      34             : zend_object_handlers IntlIterator_handlers;
      35             : 
      36          21 : void zoi_with_current_dtor(zend_object_iterator *iter TSRMLS_DC)
      37             : {
      38          21 :         zoi_with_current *zoiwc = (zoi_with_current*)iter;
      39             :         
      40          21 :         if (zoiwc->wrapping_obj) {
      41             :                 /* we have to copy the pointer because zoiwc->wrapping_obj may be
      42             :                  * changed midway the execution of zval_ptr_dtor() */
      43           8 :                 zval *zwo = zoiwc->wrapping_obj;
      44             :                 
      45             :                 /* object is still here, we can rely on it to call this again and
      46             :                  * destroy this object */
      47           8 :                 zval_ptr_dtor(&zwo);
      48             :         } else {
      49             :                 /* Object not here anymore (we've been called by the object free handler)
      50             :                  * Note that the iterator wrapper objects (that also depend on this
      51             :                  * structure) call this function earlier, in the destruction phase, which
      52             :                  * precedes the object free phase. Therefore there's no risk on this
      53             :                  * function being called by the iterator wrapper destructor function and
      54             :                  * not finding the memory of this iterator allocated anymore. */
      55          13 :                 iter->funcs->invalidate_current(iter TSRMLS_CC);
      56          13 :                 zoiwc->destroy_it(iter TSRMLS_CC);
      57          13 :                 efree(iter);
      58             :         }
      59          21 : }
      60             : 
      61        1394 : U_CFUNC int zoi_with_current_valid(zend_object_iterator *iter TSRMLS_DC)
      62             : {
      63        1394 :         return ((zoi_with_current*)iter)->current != NULL ? SUCCESS : FAILURE;
      64             : }
      65             : 
      66        1379 : U_CFUNC void zoi_with_current_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC)
      67             : {
      68        1379 :         *data = &((zoi_with_current*)iter)->current;
      69        1379 : }
      70             : 
      71        1410 : U_CFUNC void zoi_with_current_invalidate_current(zend_object_iterator *iter TSRMLS_DC)
      72             : {
      73        1410 :         zoi_with_current *zoi_iter = (zoi_with_current*)iter;
      74        1410 :         if (zoi_iter->current) {
      75        1381 :                 zval_ptr_dtor(&zoi_iter->current);
      76        1381 :                 zoi_iter->current = NULL; //valid would return FAILURE now
      77             :         }
      78        1410 : }
      79             : 
      80        1340 : static void string_enum_current_move_forward(zend_object_iterator *iter TSRMLS_DC)
      81             : {
      82        1340 :         zoi_with_current *zoi_iter = (zoi_with_current*)iter;
      83        1340 :         INTLITERATOR_METHOD_INIT_VARS;
      84             : 
      85        1340 :         iter->funcs->invalidate_current(iter TSRMLS_CC);
      86             : 
      87        1340 :         object = zoi_iter->wrapping_obj;
      88        1340 :         INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
      89             : 
      90             :         int32_t result_length;
      91             :         const char *result = ((StringEnumeration*)iter->data)->next(
      92        1340 :                 &result_length, INTLITERATOR_ERROR_CODE(ii));
      93             : 
      94        1340 :         intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii) TSRMLS_CC);
      95        1340 :         if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) {
      96             :                 intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii),
      97           0 :                         "Error fetching next iteration element", 0 TSRMLS_CC);
      98        1340 :         } else if (result) {
      99        1332 :                 MAKE_STD_ZVAL(zoi_iter->current);
     100        1332 :                 ZVAL_STRINGL(zoi_iter->current, result, result_length, 1);
     101             :         } //else we've reached the end of the enum, nothing more is required
     102        1340 : }
     103             : 
     104          10 : static void string_enum_rewind(zend_object_iterator *iter TSRMLS_DC)
     105             : {
     106          10 :         zoi_with_current *zoi_iter = (zoi_with_current*)iter;
     107          10 :         INTLITERATOR_METHOD_INIT_VARS;
     108             : 
     109          10 :         if (zoi_iter->current) {
     110           2 :                 iter->funcs->invalidate_current(iter TSRMLS_CC);
     111             :         }
     112             : 
     113          10 :         object = zoi_iter->wrapping_obj;
     114          10 :         INTLITERATOR_METHOD_FETCH_OBJECT_NO_CHECK;
     115             : 
     116          10 :         ((StringEnumeration*)iter->data)->reset(INTLITERATOR_ERROR_CODE(ii));
     117             : 
     118          10 :         intl_error_set_code(NULL, INTLITERATOR_ERROR_CODE(ii) TSRMLS_CC);
     119          10 :         if (U_FAILURE(INTLITERATOR_ERROR_CODE(ii))) {
     120             :                 intl_errors_set_custom_msg(INTL_DATA_ERROR_P(ii),
     121           0 :                         "Error resetting enumeration", 0 TSRMLS_CC);
     122             :         } else {
     123          10 :                 iter->funcs->move_forward(iter TSRMLS_CC);
     124             :         }
     125          10 : }
     126             : 
     127           6 : static void string_enum_destroy_it(zend_object_iterator *iter TSRMLS_DC)
     128             : {
     129           6 :         delete (StringEnumeration*)iter->data;
     130           6 : }
     131             : 
     132             : static zend_object_iterator_funcs string_enum_object_iterator_funcs = {
     133             :         zoi_with_current_dtor,
     134             :         zoi_with_current_valid,
     135             :         zoi_with_current_get_current_data,
     136             :         NULL,
     137             :         string_enum_current_move_forward,
     138             :         string_enum_rewind,
     139             :         zoi_with_current_invalidate_current
     140             : };
     141             : 
     142           6 : U_CFUNC void IntlIterator_from_StringEnumeration(StringEnumeration *se, zval *object TSRMLS_DC)
     143             : {
     144             :         IntlIterator_object *ii;
     145           6 :         object_init_ex(object, IntlIterator_ce_ptr);
     146           6 :         ii = (IntlIterator_object*)zend_object_store_get_object(object TSRMLS_CC);
     147           6 :         ii->iterator = (zend_object_iterator*)emalloc(sizeof(zoi_with_current));
     148           6 :         ii->iterator->data = (void*)se;
     149           6 :         ii->iterator->funcs = &string_enum_object_iterator_funcs;
     150           6 :         ii->iterator->index = 0;
     151           6 :         ((zoi_with_current*)ii->iterator)->destroy_it = string_enum_destroy_it;
     152           6 :         ((zoi_with_current*)ii->iterator)->wrapping_obj = object;
     153           6 :         ((zoi_with_current*)ii->iterator)->current = NULL;
     154           6 : }
     155             : 
     156          12 : static void IntlIterator_objects_free(zend_object *object TSRMLS_DC)
     157             : {
     158          12 :         IntlIterator_object     *ii = (IntlIterator_object*) object;
     159             : 
     160          12 :         if (ii->iterator) {
     161          12 :                 zval **wrapping_objp = &((zoi_with_current*)ii->iterator)->wrapping_obj;
     162          12 :                 *wrapping_objp = NULL;
     163          12 :                 ii->iterator->funcs->dtor(ii->iterator TSRMLS_CC);
     164             :         }
     165          12 :         intl_error_reset(INTLITERATOR_ERROR_P(ii) TSRMLS_CC);
     166             : 
     167          12 :         zend_object_std_dtor(&ii->zo TSRMLS_CC);
     168             : 
     169          12 :         efree(ii);
     170          12 : }
     171             : 
     172           8 : static zend_object_iterator *IntlIterator_get_iterator(
     173             :         zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC)
     174             : {
     175           8 :         if (by_ref) {
     176             :                 zend_throw_exception(NULL,
     177           0 :                         "Iteration by reference is not supported", 0 TSRMLS_CC);
     178           0 :                 return NULL;
     179             :         }
     180             : 
     181             :         IntlIterator_object *ii = (IntlIterator_object*)
     182           8 :                 zend_object_store_get_object(object TSRMLS_CC);
     183             : 
     184           8 :         if (ii->iterator == NULL) {
     185             :                 zend_throw_exception(NULL,
     186           0 :                         "The IntlIterator is not properly constructed", 0 TSRMLS_CC);
     187           0 :                 return NULL;
     188             :         }
     189             : 
     190           8 :         zval_add_ref(&object);
     191             : 
     192           8 :         return ii->iterator;
     193             : }
     194             : 
     195          12 : static zend_object_value IntlIterator_object_create(zend_class_entry *ce TSRMLS_DC)
     196             : {
     197             :         zend_object_value       retval;
     198             :         IntlIterator_object     *intern;
     199             : 
     200          12 :         intern = (IntlIterator_object*)ecalloc(1, sizeof(IntlIterator_object));
     201             :         
     202          12 :         zend_object_std_init(&intern->zo, ce TSRMLS_CC);
     203             : #if PHP_VERSION_ID < 50399
     204             :     zend_hash_copy(intern->zo.properties, &(ce->default_properties),
     205             :         (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*));
     206             : #else
     207          12 :     object_properties_init((zend_object*) intern, ce);
     208             : #endif
     209          12 :         intl_error_init(INTLITERATOR_ERROR_P(intern) TSRMLS_CC);
     210          12 :         intern->iterator = NULL;
     211             : 
     212             :         retval.handle = zend_objects_store_put(
     213             :                 intern,
     214             :                 (zend_objects_store_dtor_t)zend_objects_destroy_object,
     215             :                 (zend_objects_free_object_storage_t)IntlIterator_objects_free,
     216          12 :                 NULL TSRMLS_CC);
     217             : 
     218          12 :         retval.handlers = &IntlIterator_handlers;
     219             : 
     220          12 :         return retval;
     221             : }
     222             : 
     223          33 : static PHP_METHOD(IntlIterator, current)
     224             : {
     225             :         zval **data;
     226          33 :         INTLITERATOR_METHOD_INIT_VARS;
     227             : 
     228          33 :         if (zend_parse_parameters_none() == FAILURE) {
     229             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     230           0 :                         "IntlIterator::current: bad arguments", 0 TSRMLS_CC);
     231           0 :                 return;
     232             :         }
     233             : 
     234          33 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     235          33 :         ii->iterator->funcs->get_current_data(ii->iterator, &data TSRMLS_CC);
     236          33 :         if (data && *data) {
     237          66 :                 RETURN_ZVAL(*data, 1, 0);
     238             :         }
     239             : }
     240             : 
     241          33 : static PHP_METHOD(IntlIterator, key)
     242             : {
     243          33 :         INTLITERATOR_METHOD_INIT_VARS;
     244             : 
     245          33 :         if (zend_parse_parameters_none() == FAILURE) {
     246             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     247           0 :                         "IntlIterator::key: bad arguments", 0 TSRMLS_CC);
     248           0 :                 return;
     249             :         }
     250             : 
     251          33 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     252             : 
     253          33 :         if (ii->iterator->funcs->get_current_key) {
     254          33 :                 ii->iterator->funcs->get_current_key(ii->iterator, return_value TSRMLS_CC);
     255             :         } else {
     256           0 :                 RETURN_LONG(ii->iterator->index);
     257             :         }
     258             : }
     259             : 
     260          33 : static PHP_METHOD(IntlIterator, next)
     261             : {
     262          33 :         INTLITERATOR_METHOD_INIT_VARS;
     263             : 
     264          33 :         if (zend_parse_parameters_none() == FAILURE) {
     265             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     266           0 :                         "IntlIterator::next: bad arguments", 0 TSRMLS_CC);
     267           0 :                 return;
     268             :         }
     269             : 
     270          33 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     271          33 :         ii->iterator->funcs->move_forward(ii->iterator TSRMLS_CC);
     272             :         /* foreach also advances the index after the last iteration,
     273             :          * so I see no problem in incrementing the index here unconditionally */
     274          33 :         ii->iterator->index++;
     275             : }
     276             : 
     277           8 : static PHP_METHOD(IntlIterator, rewind)
     278             : {
     279           8 :         INTLITERATOR_METHOD_INIT_VARS;
     280             : 
     281           8 :         if (zend_parse_parameters_none() == FAILURE) {
     282             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     283           0 :                         "IntlIterator::rewind: bad arguments", 0 TSRMLS_CC);
     284           0 :                 return;
     285             :         }
     286             : 
     287           8 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     288           8 :         if (ii->iterator->funcs->rewind) {
     289           8 :                 ii->iterator->funcs->rewind(ii->iterator TSRMLS_CC);
     290             :         } else {
     291             :                 intl_errors_set(INTLITERATOR_ERROR_P(ii), U_UNSUPPORTED_ERROR,
     292           0 :                         "IntlIterator::rewind: rewind not supported", 0 TSRMLS_CC);
     293             :         }
     294             : }
     295             : 
     296          39 : static PHP_METHOD(IntlIterator, valid)
     297             : {
     298          39 :         INTLITERATOR_METHOD_INIT_VARS;
     299             : 
     300          39 :         if (zend_parse_parameters_none() == FAILURE) {
     301             :                 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     302           0 :                         "IntlIterator::valid: bad arguments", 0 TSRMLS_CC);
     303           0 :                 return;
     304             :         }
     305             : 
     306          39 :         INTLITERATOR_METHOD_FETCH_OBJECT;
     307          39 :         RETURN_BOOL(ii->iterator->funcs->valid(ii->iterator TSRMLS_CC) == SUCCESS);
     308             : }
     309             : 
     310             : ZEND_BEGIN_ARG_INFO_EX(ainfo_se_void, 0, 0, 0)
     311             : ZEND_END_ARG_INFO()
     312             : 
     313             : static zend_function_entry IntlIterator_class_functions[] = {
     314             :         PHP_ME(IntlIterator,    current,        ainfo_se_void,                  ZEND_ACC_PUBLIC)
     315             :         PHP_ME(IntlIterator,    key,            ainfo_se_void,                  ZEND_ACC_PUBLIC)
     316             :         PHP_ME(IntlIterator,    next,           ainfo_se_void,                  ZEND_ACC_PUBLIC)
     317             :         PHP_ME(IntlIterator,    rewind,         ainfo_se_void,                  ZEND_ACC_PUBLIC)
     318             :         PHP_ME(IntlIterator,    valid,          ainfo_se_void,                  ZEND_ACC_PUBLIC)
     319             :         PHP_FE_END
     320             : };
     321             : 
     322             : 
     323             : /* {{{ intl_register_IntlIterator_class
     324             :  * Initialize 'IntlIterator' class
     325             :  */
     326       21257 : U_CFUNC void intl_register_IntlIterator_class(TSRMLS_D)
     327             : {
     328             :         zend_class_entry ce;
     329             : 
     330             :         /* Create and register 'IntlIterator' class. */
     331       21257 :         INIT_CLASS_ENTRY(ce, "IntlIterator", IntlIterator_class_functions);
     332       21257 :         ce.create_object = IntlIterator_object_create;
     333       21257 :         IntlIterator_ce_ptr = zend_register_internal_class(&ce TSRMLS_CC);
     334       21257 :         IntlIterator_ce_ptr->get_iterator = IntlIterator_get_iterator;
     335             :         zend_class_implements(IntlIterator_ce_ptr TSRMLS_CC, 1,
     336       21257 :                 zend_ce_iterator);
     337             : 
     338             :         memcpy(&IntlIterator_handlers, zend_get_std_object_handlers(),
     339       21257 :                 sizeof IntlIterator_handlers);
     340       21257 :         IntlIterator_handlers.clone_obj = NULL;
     341             : 
     342       21257 : }

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:11 +0000 (3 days ago)

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