uenum.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // © 2016 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. /*
  4. *******************************************************************************
  5. *
  6. * Copyright (C) 2002-2012, International Business Machines
  7. * Corporation and others. All Rights Reserved.
  8. *
  9. *******************************************************************************
  10. * file name: uenum.c
  11. * encoding: UTF-8
  12. * tab size: 8 (not used)
  13. * indentation:2
  14. *
  15. * created on: 2002jul08
  16. * created by: Vladimir Weinstein
  17. */
  18. #include "unicode/putil.h"
  19. #include "uenumimp.h"
  20. #include "cmemory.h"
  21. /* Layout of the baseContext buffer. */
  22. typedef struct {
  23. int32_t len; /* number of bytes available starting at 'data' */
  24. char data; /* actual data starts here */
  25. } _UEnumBuffer;
  26. /* Extra bytes to allocate in the baseContext buffer. */
  27. static const int32_t PAD = 8;
  28. /* Return a pointer to the baseContext buffer, possibly allocating
  29. or reallocating it if at least 'capacity' bytes are not available. */
  30. static void* _getBuffer(UEnumeration* en, int32_t capacity) {
  31. if (en->baseContext != nullptr) {
  32. if (((_UEnumBuffer*) en->baseContext)->len < capacity) {
  33. capacity += PAD;
  34. en->baseContext = uprv_realloc(en->baseContext,
  35. sizeof(int32_t) + capacity);
  36. if (en->baseContext == nullptr) {
  37. return nullptr;
  38. }
  39. ((_UEnumBuffer*) en->baseContext)->len = capacity;
  40. }
  41. } else {
  42. capacity += PAD;
  43. en->baseContext = uprv_malloc(sizeof(int32_t) + capacity);
  44. if (en->baseContext == nullptr) {
  45. return nullptr;
  46. }
  47. ((_UEnumBuffer*) en->baseContext)->len = capacity;
  48. }
  49. return (void*) & ((_UEnumBuffer*) en->baseContext)->data;
  50. }
  51. U_CAPI void U_EXPORT2
  52. uenum_close(UEnumeration* en)
  53. {
  54. if (en) {
  55. if (en->close != nullptr) {
  56. if (en->baseContext) {
  57. uprv_free(en->baseContext);
  58. }
  59. en->close(en);
  60. } else { /* this seems dangerous, but we better kill the object */
  61. uprv_free(en);
  62. }
  63. }
  64. }
  65. U_CAPI int32_t U_EXPORT2
  66. uenum_count(UEnumeration* en, UErrorCode* status)
  67. {
  68. if (!en || U_FAILURE(*status)) {
  69. return -1;
  70. }
  71. if (en->count != nullptr) {
  72. return en->count(en, status);
  73. } else {
  74. *status = U_UNSUPPORTED_ERROR;
  75. return -1;
  76. }
  77. }
  78. /* Don't call this directly. Only uenum_unext should be calling this. */
  79. U_CAPI const char16_t* U_EXPORT2
  80. uenum_unextDefault(UEnumeration* en,
  81. int32_t* resultLength,
  82. UErrorCode* status)
  83. {
  84. char16_t *ustr = nullptr;
  85. int32_t len = 0;
  86. if (en->next != nullptr) {
  87. const char *cstr = en->next(en, &len, status);
  88. if (cstr != nullptr) {
  89. ustr = (char16_t*) _getBuffer(en, (len+1) * sizeof(char16_t));
  90. if (ustr == nullptr) {
  91. *status = U_MEMORY_ALLOCATION_ERROR;
  92. } else {
  93. u_charsToUChars(cstr, ustr, len+1);
  94. }
  95. }
  96. } else {
  97. *status = U_UNSUPPORTED_ERROR;
  98. }
  99. if (resultLength) {
  100. *resultLength = len;
  101. }
  102. return ustr;
  103. }
  104. /* Don't call this directly. Only uenum_next should be calling this. */
  105. U_CAPI const char* U_EXPORT2
  106. uenum_nextDefault(UEnumeration* en,
  107. int32_t* resultLength,
  108. UErrorCode* status)
  109. {
  110. if (en->uNext != nullptr) {
  111. char *tempCharVal;
  112. const char16_t *tempUCharVal = en->uNext(en, resultLength, status);
  113. if (tempUCharVal == nullptr) {
  114. return nullptr;
  115. }
  116. tempCharVal = (char*)
  117. _getBuffer(en, (*resultLength+1) * sizeof(char));
  118. if (!tempCharVal) {
  119. *status = U_MEMORY_ALLOCATION_ERROR;
  120. return nullptr;
  121. }
  122. u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength + 1);
  123. return tempCharVal;
  124. } else {
  125. *status = U_UNSUPPORTED_ERROR;
  126. return nullptr;
  127. }
  128. }
  129. U_CAPI const char16_t* U_EXPORT2
  130. uenum_unext(UEnumeration* en,
  131. int32_t* resultLength,
  132. UErrorCode* status)
  133. {
  134. if (!en || U_FAILURE(*status)) {
  135. return nullptr;
  136. }
  137. if (en->uNext != nullptr) {
  138. return en->uNext(en, resultLength, status);
  139. } else {
  140. *status = U_UNSUPPORTED_ERROR;
  141. return nullptr;
  142. }
  143. }
  144. U_CAPI const char* U_EXPORT2
  145. uenum_next(UEnumeration* en,
  146. int32_t* resultLength,
  147. UErrorCode* status)
  148. {
  149. if (!en || U_FAILURE(*status)) {
  150. return nullptr;
  151. }
  152. if (en->next != nullptr) {
  153. if (resultLength != nullptr) {
  154. return en->next(en, resultLength, status);
  155. }
  156. else {
  157. int32_t dummyLength=0;
  158. return en->next(en, &dummyLength, status);
  159. }
  160. } else {
  161. *status = U_UNSUPPORTED_ERROR;
  162. return nullptr;
  163. }
  164. }
  165. U_CAPI void U_EXPORT2
  166. uenum_reset(UEnumeration* en, UErrorCode* status)
  167. {
  168. if (!en || U_FAILURE(*status)) {
  169. return;
  170. }
  171. if (en->reset != nullptr) {
  172. en->reset(en, status);
  173. } else {
  174. *status = U_UNSUPPORTED_ERROR;
  175. }
  176. }