Back to index

php5  5.3.10
resourcebundle_iterator.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | This source file is subject to version 3.01 of the PHP license,      |
00006    | that is bundled with this package in the file LICENSE, and is        |
00007    | available through the world-wide-web at the following url:           |
00008    | http://www.php.net/license/3_01.txt                                  |
00009    | If you did not receive a copy of the PHP license and are unable to   |
00010    | obtain it through the world-wide-web, please send a note to          |
00011    | license@php.net so we can mail you a copy immediately.               |
00012    +----------------------------------------------------------------------+
00013    | Authors: Hans-Peter Oeri (University of St.Gallen) <hp@oeri.ch>      |
00014    +----------------------------------------------------------------------+
00015  */
00016 
00017 #include <php.h>
00018 #include <zend.h>
00019 #include <zend_API.h>
00020 
00021 #include "resourcebundle/resourcebundle.h"
00022 #include "resourcebundle/resourcebundle_class.h"
00023 #include "resourcebundle/resourcebundle_iterator.h"
00024 
00025 /*
00026  * Although libicu offers iterator functions, they are not used here: libicu does iterate
00027  * irrespective of array indices. Those cannot be recreated afterwards. Arrays as well as tables
00028  * can however be accessed by numerical index, with table keys readable ex post.
00029  */
00030 
00031 /* {{{ resourcebundle_iterator_read */
00032 static void resourcebundle_iterator_read( ResourceBundle_iterator *iterator TSRMLS_DC ) 
00033 {
00034        UErrorCode icuerror = U_ZERO_ERROR;
00035        ResourceBundle_object *rb = iterator->subject;
00036 
00037        rb->child = ures_getByIndex( rb->me, iterator->i, rb->child, &icuerror );
00038 
00039        if (U_SUCCESS(icuerror)) {
00040               /* ATTN: key extraction must be the first thing to do... rb->child might be reset in read! */
00041               if (iterator->is_table) {
00042                      iterator->currentkey = estrdup( ures_getKey( rb->child ) );
00043               }
00044               MAKE_STD_ZVAL( iterator->current );
00045               resourcebundle_extract_value( iterator->current, rb TSRMLS_CC );
00046        }
00047        else {
00048               // zend_throw_exception( spl_ce_OutOfRangeException, "Running past end of ResourceBundle", 0 TSRMLS_CC);
00049               iterator->current = NULL;
00050        }
00051 }
00052 /* }}} */
00053 
00054 /* {{{ resourcebundle_iterator_invalidate */
00055 static void resourcebundle_iterator_invalidate( zend_object_iterator *iter TSRMLS_DC ) 
00056 {
00057        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00058 
00059        if (iterator->current) {
00060               zval_ptr_dtor( &iterator->current );
00061               iterator->current = NULL;
00062        }
00063        if (iterator->currentkey) {
00064               efree( iterator->currentkey );
00065               iterator->currentkey = NULL;
00066        }
00067 }
00068 /* }}} */
00069 
00070 /* {{{ resourcebundle_iterator_dtor */
00071 static void resourcebundle_iterator_dtor( zend_object_iterator *iter TSRMLS_DC )
00072 {
00073        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00074        zval                    *object = (zval *)iterator->intern.data;
00075 
00076        resourcebundle_iterator_invalidate( iter TSRMLS_CC );
00077 
00078        Z_DELREF_P(object);
00079 
00080        efree(iterator);
00081 }
00082 /* }}} */
00083 
00084 /* {{{ resourcebundle_iterator_has_more */
00085 static int resourcebundle_iterator_has_more( zend_object_iterator *iter TSRMLS_DC )
00086 {
00087        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00088        return (iterator->i < iterator->length) ? SUCCESS : FAILURE;
00089 }
00090 /* }}} */
00091 
00092 /* {{{ resourcebundle_iterator_current */
00093 static void resourcebundle_iterator_current( zend_object_iterator *iter, zval ***data TSRMLS_DC )
00094 {
00095        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00096        if (!iterator->current) {
00097               resourcebundle_iterator_read( iterator TSRMLS_CC);
00098        }
00099        *data = &iterator->current;
00100 }
00101 /* }}} */
00102 
00103 /* {{{ resourcebundle_iterator_key */
00104 static int resourcebundle_iterator_key( zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC )
00105 {
00106        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00107 
00108        if (!iterator->current) {
00109               resourcebundle_iterator_read( iterator TSRMLS_CC);
00110        }
00111        if (iterator->is_table) {
00112               *str_key = estrdup( iterator->currentkey );
00113               *str_key_len = strlen( iterator->currentkey ) + 1;
00114               return HASH_KEY_IS_STRING;
00115        }
00116        else {
00117               *int_key = iterator->i;
00118               return HASH_KEY_IS_LONG;
00119        }
00120 }
00121 /* }}} */
00122 
00123 /* {{{ resourcebundle_iterator_has_more */
00124 static void resourcebundle_iterator_step( zend_object_iterator *iter TSRMLS_DC )
00125 {
00126        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00127 
00128        iterator->i++;
00129        resourcebundle_iterator_invalidate( iter TSRMLS_CC );
00130 }
00131 /* }}} */
00132 
00133 /* {{{ resourcebundle_iterator_has_reset */
00134 static void resourcebundle_iterator_reset( zend_object_iterator *iter TSRMLS_DC )
00135 {
00136        ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
00137 
00138        iterator->i = 0;
00139        resourcebundle_iterator_invalidate( iter TSRMLS_CC );
00140 }
00141 /* }}} */
00142 
00143 /* {{{ resourcebundle_iterator_funcs */
00144 static zend_object_iterator_funcs resourcebundle_iterator_funcs = {
00145        resourcebundle_iterator_dtor,
00146        resourcebundle_iterator_has_more,
00147        resourcebundle_iterator_current,
00148        resourcebundle_iterator_key,
00149        resourcebundle_iterator_step,
00150        resourcebundle_iterator_reset,
00151        resourcebundle_iterator_invalidate
00152 };
00153 /* }}} */
00154 
00155 /* {{{ resourcebundle_get_iterator */
00156 zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref TSRMLS_DC )
00157 {
00158        ResourceBundle_object   *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
00159        ResourceBundle_iterator *iterator = emalloc( sizeof( ResourceBundle_iterator ) );
00160 
00161        if (byref) {
00162             php_error( E_ERROR, "ResourceBundle does not support writable iterators" );
00163        }
00164 
00165        Z_ADDREF_P(object);
00166        iterator->intern.data = (void *) object;
00167        iterator->intern.funcs = &resourcebundle_iterator_funcs;
00168 
00169        iterator->subject = rb;
00170 
00171        /* The iterated rb can only be either URES_TABLE or URES_ARRAY
00172         * All other types are returned as php primitives!
00173         */
00174        iterator->is_table = (ures_getType( rb->me ) == URES_TABLE);
00175        iterator->length = ures_getSize( rb->me );
00176 
00177        iterator->current = NULL;
00178        iterator->currentkey = NULL;
00179        iterator->i = 0;
00180 
00181        return (zend_object_iterator *) iterator;
00182 }
00183 /* }}} */
00184 
00185 /*
00186  * Local variables:
00187  * tab-width: 4
00188  * c-basic-offset: 4
00189  * End:
00190  * vim600: noet sw=4 ts=4 fdm=marker
00191  * vim<600: noet sw=4 ts=4
00192  */