Line data Source code
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 :
19 : #include "unicode/putil.h"
20 : #include "uenumimp.h"
21 : #include "cmemory.h"
22 :
23 : /* Layout of the baseContext buffer. */
24 : typedef struct {
25 : int32_t len; /* number of bytes available starting at 'data' */
26 : char data; /* actual data starts here */
27 : } _UEnumBuffer;
28 :
29 : /* Extra bytes to allocate in the baseContext buffer. */
30 : static const int32_t PAD = 8;
31 :
32 : /* Return a pointer to the baseContext buffer, possibly allocating
33 : or reallocating it if at least 'capacity' bytes are not available. */
34 0 : static void* _getBuffer(UEnumeration* en, int32_t capacity) {
35 :
36 0 : if (en->baseContext != NULL) {
37 0 : if (((_UEnumBuffer*) en->baseContext)->len < capacity) {
38 0 : capacity += PAD;
39 0 : en->baseContext = uprv_realloc(en->baseContext,
40 : sizeof(int32_t) + capacity);
41 0 : if (en->baseContext == NULL) {
42 0 : return NULL;
43 : }
44 0 : ((_UEnumBuffer*) en->baseContext)->len = capacity;
45 : }
46 : } else {
47 0 : capacity += PAD;
48 0 : en->baseContext = uprv_malloc(sizeof(int32_t) + capacity);
49 0 : if (en->baseContext == NULL) {
50 0 : return NULL;
51 : }
52 0 : ((_UEnumBuffer*) en->baseContext)->len = capacity;
53 : }
54 :
55 0 : return (void*) & ((_UEnumBuffer*) en->baseContext)->data;
56 : }
57 :
58 : U_CAPI void U_EXPORT2
59 0 : uenum_close(UEnumeration* en)
60 : {
61 0 : if (en) {
62 0 : if (en->close != NULL) {
63 0 : if (en->baseContext) {
64 0 : uprv_free(en->baseContext);
65 : }
66 0 : en->close(en);
67 : } else { /* this seems dangerous, but we better kill the object */
68 0 : uprv_free(en);
69 : }
70 : }
71 0 : }
72 :
73 : U_CAPI int32_t U_EXPORT2
74 0 : uenum_count(UEnumeration* en, UErrorCode* status)
75 : {
76 0 : if (!en || U_FAILURE(*status)) {
77 0 : return -1;
78 : }
79 0 : if (en->count != NULL) {
80 0 : return en->count(en, status);
81 : } else {
82 0 : *status = U_UNSUPPORTED_ERROR;
83 0 : return -1;
84 : }
85 : }
86 :
87 : /* Don't call this directly. Only uenum_unext should be calling this. */
88 : U_CAPI const UChar* U_EXPORT2
89 0 : uenum_unextDefault(UEnumeration* en,
90 : int32_t* resultLength,
91 : UErrorCode* status)
92 : {
93 0 : UChar *ustr = NULL;
94 0 : int32_t len = 0;
95 0 : if (en->next != NULL) {
96 0 : const char *cstr = en->next(en, &len, status);
97 0 : if (cstr != NULL) {
98 0 : ustr = (UChar*) _getBuffer(en, (len+1) * sizeof(UChar));
99 0 : if (ustr == NULL) {
100 0 : *status = U_MEMORY_ALLOCATION_ERROR;
101 : } else {
102 0 : u_charsToUChars(cstr, ustr, len+1);
103 : }
104 : }
105 : } else {
106 0 : *status = U_UNSUPPORTED_ERROR;
107 : }
108 0 : if (resultLength) {
109 0 : *resultLength = len;
110 : }
111 0 : return ustr;
112 : }
113 :
114 : /* Don't call this directly. Only uenum_next should be calling this. */
115 : U_CAPI const char* U_EXPORT2
116 0 : uenum_nextDefault(UEnumeration* en,
117 : int32_t* resultLength,
118 : UErrorCode* status)
119 : {
120 0 : if (en->uNext != NULL) {
121 : char *tempCharVal;
122 0 : const UChar *tempUCharVal = en->uNext(en, resultLength, status);
123 0 : if (tempUCharVal == NULL) {
124 0 : return NULL;
125 : }
126 : tempCharVal = (char*)
127 0 : _getBuffer(en, (*resultLength+1) * sizeof(char));
128 0 : if (!tempCharVal) {
129 0 : *status = U_MEMORY_ALLOCATION_ERROR;
130 0 : return NULL;
131 : }
132 0 : u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength + 1);
133 0 : return tempCharVal;
134 : } else {
135 0 : *status = U_UNSUPPORTED_ERROR;
136 0 : return NULL;
137 : }
138 : }
139 :
140 : U_CAPI const UChar* U_EXPORT2
141 0 : uenum_unext(UEnumeration* en,
142 : int32_t* resultLength,
143 : UErrorCode* status)
144 : {
145 0 : if (!en || U_FAILURE(*status)) {
146 0 : return NULL;
147 : }
148 0 : if (en->uNext != NULL) {
149 0 : return en->uNext(en, resultLength, status);
150 : } else {
151 0 : *status = U_UNSUPPORTED_ERROR;
152 0 : return NULL;
153 : }
154 : }
155 :
156 : U_CAPI const char* U_EXPORT2
157 0 : uenum_next(UEnumeration* en,
158 : int32_t* resultLength,
159 : UErrorCode* status)
160 : {
161 0 : if (!en || U_FAILURE(*status)) {
162 0 : return NULL;
163 : }
164 0 : if (en->next != NULL) {
165 0 : if (resultLength != NULL) {
166 0 : return en->next(en, resultLength, status);
167 : }
168 : else {
169 0 : int32_t dummyLength=0;
170 0 : return en->next(en, &dummyLength, status);
171 : }
172 : } else {
173 0 : *status = U_UNSUPPORTED_ERROR;
174 0 : return NULL;
175 : }
176 : }
177 :
178 : U_CAPI void U_EXPORT2
179 0 : uenum_reset(UEnumeration* en, UErrorCode* status)
180 : {
181 0 : if (!en || U_FAILURE(*status)) {
182 0 : return;
183 : }
184 0 : if (en->reset != NULL) {
185 0 : en->reset(en, status);
186 : } else {
187 0 : *status = U_UNSUPPORTED_ERROR;
188 : }
189 : }
|