resourcebundle_iterator.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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: Hans-Peter Oeri (University of St.Gallen) <hp@oeri.ch> |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include <php.h>
  17. #include <zend.h>
  18. #include <zend_API.h>
  19. #include "resourcebundle/resourcebundle.h"
  20. #include "resourcebundle/resourcebundle_class.h"
  21. #include "resourcebundle/resourcebundle_iterator.h"
  22. /*
  23. * Although libicu offers iterator functions, they are not used here: libicu does iterate
  24. * irrespective of array indices. Those cannot be recreated afterwards. Arrays as well as tables
  25. * can however be accessed by numerical index, with table keys readable ex post.
  26. */
  27. /* {{{ resourcebundle_iterator_read */
  28. static void resourcebundle_iterator_read( ResourceBundle_iterator *iterator TSRMLS_DC )
  29. {
  30. UErrorCode icuerror = U_ZERO_ERROR;
  31. ResourceBundle_object *rb = iterator->subject;
  32. rb->child = ures_getByIndex( rb->me, iterator->i, rb->child, &icuerror );
  33. if (U_SUCCESS(icuerror)) {
  34. /* ATTN: key extraction must be the first thing to do... rb->child might be reset in read! */
  35. if (iterator->is_table) {
  36. iterator->currentkey = estrdup( ures_getKey( rb->child ) );
  37. }
  38. MAKE_STD_ZVAL( iterator->current );
  39. resourcebundle_extract_value( iterator->current, rb TSRMLS_CC );
  40. }
  41. else {
  42. // zend_throw_exception( spl_ce_OutOfRangeException, "Running past end of ResourceBundle", 0 TSRMLS_CC);
  43. iterator->current = NULL;
  44. }
  45. }
  46. /* }}} */
  47. /* {{{ resourcebundle_iterator_invalidate */
  48. static void resourcebundle_iterator_invalidate( zend_object_iterator *iter TSRMLS_DC )
  49. {
  50. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  51. if (iterator->current) {
  52. zval_ptr_dtor( &iterator->current );
  53. iterator->current = NULL;
  54. }
  55. if (iterator->currentkey) {
  56. efree( iterator->currentkey );
  57. iterator->currentkey = NULL;
  58. }
  59. }
  60. /* }}} */
  61. /* {{{ resourcebundle_iterator_dtor */
  62. static void resourcebundle_iterator_dtor( zend_object_iterator *iter TSRMLS_DC )
  63. {
  64. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  65. zval *object = (zval *)iterator->intern.data;
  66. resourcebundle_iterator_invalidate( iter TSRMLS_CC );
  67. Z_DELREF_P(object);
  68. efree(iterator);
  69. }
  70. /* }}} */
  71. /* {{{ resourcebundle_iterator_has_more */
  72. static int resourcebundle_iterator_has_more( zend_object_iterator *iter TSRMLS_DC )
  73. {
  74. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  75. return (iterator->i < iterator->length) ? SUCCESS : FAILURE;
  76. }
  77. /* }}} */
  78. /* {{{ resourcebundle_iterator_current */
  79. static void resourcebundle_iterator_current( zend_object_iterator *iter, zval ***data TSRMLS_DC )
  80. {
  81. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  82. if (!iterator->current) {
  83. resourcebundle_iterator_read( iterator TSRMLS_CC);
  84. }
  85. *data = &iterator->current;
  86. }
  87. /* }}} */
  88. /* {{{ resourcebundle_iterator_key */
  89. static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key TSRMLS_DC )
  90. {
  91. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  92. if (!iterator->current) {
  93. resourcebundle_iterator_read( iterator TSRMLS_CC);
  94. }
  95. if (iterator->is_table) {
  96. ZVAL_STRING(key, iterator->currentkey, 1);
  97. } else {
  98. ZVAL_LONG(key, iterator->i);
  99. }
  100. }
  101. /* }}} */
  102. /* {{{ resourcebundle_iterator_has_more */
  103. static void resourcebundle_iterator_step( zend_object_iterator *iter TSRMLS_DC )
  104. {
  105. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  106. iterator->i++;
  107. resourcebundle_iterator_invalidate( iter TSRMLS_CC );
  108. }
  109. /* }}} */
  110. /* {{{ resourcebundle_iterator_has_reset */
  111. static void resourcebundle_iterator_reset( zend_object_iterator *iter TSRMLS_DC )
  112. {
  113. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  114. iterator->i = 0;
  115. resourcebundle_iterator_invalidate( iter TSRMLS_CC );
  116. }
  117. /* }}} */
  118. /* {{{ resourcebundle_iterator_funcs */
  119. static zend_object_iterator_funcs resourcebundle_iterator_funcs = {
  120. resourcebundle_iterator_dtor,
  121. resourcebundle_iterator_has_more,
  122. resourcebundle_iterator_current,
  123. resourcebundle_iterator_key,
  124. resourcebundle_iterator_step,
  125. resourcebundle_iterator_reset,
  126. resourcebundle_iterator_invalidate
  127. };
  128. /* }}} */
  129. /* {{{ resourcebundle_get_iterator */
  130. zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref TSRMLS_DC )
  131. {
  132. ResourceBundle_object *rb = (ResourceBundle_object *) zend_object_store_get_object( object TSRMLS_CC );
  133. ResourceBundle_iterator *iterator = emalloc( sizeof( ResourceBundle_iterator ) );
  134. if (byref) {
  135. php_error( E_ERROR, "ResourceBundle does not support writable iterators" );
  136. }
  137. Z_ADDREF_P(object);
  138. iterator->intern.data = (void *) object;
  139. iterator->intern.funcs = &resourcebundle_iterator_funcs;
  140. iterator->subject = rb;
  141. /* The iterated rb can only be either URES_TABLE or URES_ARRAY
  142. * All other types are returned as php primitives!
  143. */
  144. iterator->is_table = (ures_getType( rb->me ) == URES_TABLE);
  145. iterator->length = ures_getSize( rb->me );
  146. iterator->current = NULL;
  147. iterator->currentkey = NULL;
  148. iterator->i = 0;
  149. return (zend_object_iterator *) iterator;
  150. }
  151. /* }}} */
  152. /*
  153. * Local variables:
  154. * tab-width: 4
  155. * c-basic-offset: 4
  156. * End:
  157. * vim600: noet sw=4 ts=4 fdm=marker
  158. * vim<600: noet sw=4 ts=4
  159. */