resourcebundle_iterator.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. +----------------------------------------------------------------------+
  3. | This source file is subject to version 3.01 of the PHP license, |
  4. | that is bundled with this package in the file LICENSE, and is |
  5. | available through the world-wide-web at the following url: |
  6. | https://www.php.net/license/3_01.txt |
  7. | If you did not receive a copy of the PHP license and are unable to |
  8. | obtain it through the world-wide-web, please send a note to |
  9. | license@php.net so we can mail you a copy immediately. |
  10. +----------------------------------------------------------------------+
  11. | Authors: Hans-Peter Oeri (University of St.Gallen) <hp@oeri.ch> |
  12. +----------------------------------------------------------------------+
  13. */
  14. #include <php.h>
  15. #include <zend.h>
  16. #include <zend_API.h>
  17. #include "resourcebundle/resourcebundle.h"
  18. #include "resourcebundle/resourcebundle_class.h"
  19. #include "resourcebundle/resourcebundle_iterator.h"
  20. /*
  21. * Although libicu offers iterator functions, they are not used here: libicu does iterate
  22. * irrespective of array indices. Those cannot be recreated afterwards. Arrays as well as tables
  23. * can however be accessed by numerical index, with table keys readable ex post.
  24. */
  25. /* {{{ resourcebundle_iterator_read */
  26. static void resourcebundle_iterator_read( ResourceBundle_iterator *iterator )
  27. {
  28. UErrorCode icuerror = U_ZERO_ERROR;
  29. ResourceBundle_object *rb = iterator->subject;
  30. rb->child = ures_getByIndex( rb->me, iterator->i, rb->child, &icuerror );
  31. if (U_SUCCESS(icuerror)) {
  32. /* ATTN: key extraction must be the first thing to do... rb->child might be reset in read! */
  33. if (iterator->is_table) {
  34. iterator->currentkey = estrdup( ures_getKey( rb->child ) );
  35. }
  36. resourcebundle_extract_value( &iterator->current, rb );
  37. }
  38. else {
  39. // zend_throw_exception( spl_ce_OutOfRangeException, "Running past end of ResourceBundle", 0);
  40. ZVAL_UNDEF(&iterator->current);
  41. }
  42. }
  43. /* }}} */
  44. /* {{{ resourcebundle_iterator_invalidate */
  45. static void resourcebundle_iterator_invalidate( zend_object_iterator *iter )
  46. {
  47. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  48. if (!Z_ISUNDEF(iterator->current)) {
  49. zval_ptr_dtor( &iterator->current );
  50. ZVAL_UNDEF(&iterator->current);
  51. }
  52. if (iterator->currentkey) {
  53. efree( iterator->currentkey );
  54. iterator->currentkey = NULL;
  55. }
  56. }
  57. /* }}} */
  58. /* {{{ resourcebundle_iterator_dtor */
  59. static void resourcebundle_iterator_dtor( zend_object_iterator *iter )
  60. {
  61. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  62. zval *object = &iterator->intern.data;
  63. resourcebundle_iterator_invalidate( iter );
  64. zval_ptr_dtor(object);
  65. }
  66. /* }}} */
  67. /* {{{ resourcebundle_iterator_has_more */
  68. static int resourcebundle_iterator_has_more( zend_object_iterator *iter )
  69. {
  70. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  71. return (iterator->i < iterator->length) ? SUCCESS : FAILURE;
  72. }
  73. /* }}} */
  74. /* {{{ resourcebundle_iterator_current */
  75. static zval *resourcebundle_iterator_current( zend_object_iterator *iter )
  76. {
  77. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  78. if (Z_ISUNDEF(iterator->current)) {
  79. resourcebundle_iterator_read( iterator);
  80. }
  81. return &iterator->current;
  82. }
  83. /* }}} */
  84. /* {{{ resourcebundle_iterator_key */
  85. static void resourcebundle_iterator_key( zend_object_iterator *iter, zval *key )
  86. {
  87. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  88. if (Z_ISUNDEF(iterator->current)) {
  89. resourcebundle_iterator_read( iterator);
  90. }
  91. if (iterator->is_table) {
  92. ZVAL_STRING(key, iterator->currentkey);
  93. } else {
  94. ZVAL_LONG(key, iterator->i);
  95. }
  96. }
  97. /* }}} */
  98. /* {{{ resourcebundle_iterator_step */
  99. static void resourcebundle_iterator_step( zend_object_iterator *iter )
  100. {
  101. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  102. iterator->i++;
  103. resourcebundle_iterator_invalidate( iter );
  104. }
  105. /* }}} */
  106. /* {{{ resourcebundle_iterator_has_reset */
  107. static void resourcebundle_iterator_reset( zend_object_iterator *iter )
  108. {
  109. ResourceBundle_iterator *iterator = (ResourceBundle_iterator *) iter;
  110. iterator->i = 0;
  111. resourcebundle_iterator_invalidate( iter );
  112. }
  113. /* }}} */
  114. /* {{{ resourcebundle_iterator_funcs */
  115. static const zend_object_iterator_funcs resourcebundle_iterator_funcs = {
  116. resourcebundle_iterator_dtor,
  117. resourcebundle_iterator_has_more,
  118. resourcebundle_iterator_current,
  119. resourcebundle_iterator_key,
  120. resourcebundle_iterator_step,
  121. resourcebundle_iterator_reset,
  122. resourcebundle_iterator_invalidate,
  123. NULL, /* get_gc */
  124. };
  125. /* }}} */
  126. /* {{{ resourcebundle_get_iterator */
  127. zend_object_iterator *resourcebundle_get_iterator( zend_class_entry *ce, zval *object, int byref )
  128. {
  129. ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P(object );
  130. ResourceBundle_iterator *iterator = emalloc( sizeof( ResourceBundle_iterator ) );
  131. if (byref) {
  132. php_error( E_ERROR, "ResourceBundle does not support writable iterators" );
  133. }
  134. zend_iterator_init(&iterator->intern);
  135. Z_ADDREF_P(object);
  136. ZVAL_OBJ(&iterator->intern.data, Z_OBJ_P(object));
  137. iterator->intern.funcs = &resourcebundle_iterator_funcs;
  138. iterator->subject = rb;
  139. /* The iterated rb can only be either URES_TABLE or URES_ARRAY
  140. * All other types are returned as php primitives!
  141. */
  142. iterator->is_table = (ures_getType( rb->me ) == URES_TABLE);
  143. iterator->length = ures_getSize( rb->me );
  144. ZVAL_UNDEF(&iterator->current);
  145. iterator->currentkey = NULL;
  146. iterator->i = 0;
  147. return (zend_object_iterator *) iterator;
  148. }
  149. /* }}} */