1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 *******************************************************************************
6 * Copyright (C) 2002-2012, International Business Machines
7 * Corporation and others. All Rights Reserved.
9 *******************************************************************************
12 * tab size: 8 (not used)
15 * created on: 2002jul08
16 * created by: Vladimir Weinstein
19 #include "unicode/putil.h"
23 /* Layout of the baseContext buffer. */
25 int32_t len
; /* number of bytes available starting at 'data' */
26 char data
; /* actual data starts here */
29 /* Extra bytes to allocate in the baseContext buffer. */
30 static const int32_t PAD
= 8;
32 /* Return a pointer to the baseContext buffer, possibly allocating
33 or reallocating it if at least 'capacity' bytes are not available. */
34 static void* _getBuffer(UEnumeration
* en
, int32_t capacity
) {
36 if (en
->baseContext
!= NULL
) {
37 if (((_UEnumBuffer
*) en
->baseContext
)->len
< capacity
) {
39 en
->baseContext
= uprv_realloc(en
->baseContext
,
40 sizeof(int32_t) + capacity
);
41 if (en
->baseContext
== NULL
) {
44 ((_UEnumBuffer
*) en
->baseContext
)->len
= capacity
;
48 en
->baseContext
= uprv_malloc(sizeof(int32_t) + capacity
);
49 if (en
->baseContext
== NULL
) {
52 ((_UEnumBuffer
*) en
->baseContext
)->len
= capacity
;
55 return (void*) & ((_UEnumBuffer
*) en
->baseContext
)->data
;
59 uenum_close(UEnumeration
* en
)
62 if (en
->close
!= NULL
) {
63 if (en
->baseContext
) {
64 uprv_free(en
->baseContext
);
67 } else { /* this seems dangerous, but we better kill the object */
73 U_CAPI
int32_t U_EXPORT2
74 uenum_count(UEnumeration
* en
, UErrorCode
* status
)
76 if (!en
|| U_FAILURE(*status
)) {
79 if (en
->count
!= NULL
) {
80 return en
->count(en
, status
);
82 *status
= U_UNSUPPORTED_ERROR
;
87 /* Don't call this directly. Only uenum_unext should be calling this. */
88 U_CAPI
const UChar
* U_EXPORT2
89 uenum_unextDefault(UEnumeration
* en
,
90 int32_t* resultLength
,
95 if (en
->next
!= NULL
) {
96 const char *cstr
= en
->next(en
, &len
, status
);
98 ustr
= (UChar
*) _getBuffer(en
, (len
+1) * sizeof(UChar
));
100 *status
= U_MEMORY_ALLOCATION_ERROR
;
102 u_charsToUChars(cstr
, ustr
, len
+1);
106 *status
= U_UNSUPPORTED_ERROR
;
114 /* Don't call this directly. Only uenum_next should be calling this. */
115 U_CAPI
const char* U_EXPORT2
116 uenum_nextDefault(UEnumeration
* en
,
117 int32_t* resultLength
,
120 if (en
->uNext
!= NULL
) {
122 const UChar
*tempUCharVal
= en
->uNext(en
, resultLength
, status
);
123 if (tempUCharVal
== NULL
) {
126 tempCharVal
= (char*)
127 _getBuffer(en
, (*resultLength
+1) * sizeof(char));
129 *status
= U_MEMORY_ALLOCATION_ERROR
;
132 u_UCharsToChars(tempUCharVal
, tempCharVal
, *resultLength
+ 1);
135 *status
= U_UNSUPPORTED_ERROR
;
140 U_CAPI
const UChar
* U_EXPORT2
141 uenum_unext(UEnumeration
* en
,
142 int32_t* resultLength
,
145 if (!en
|| U_FAILURE(*status
)) {
148 if (en
->uNext
!= NULL
) {
149 return en
->uNext(en
, resultLength
, status
);
151 *status
= U_UNSUPPORTED_ERROR
;
156 U_CAPI
const char* U_EXPORT2
157 uenum_next(UEnumeration
* en
,
158 int32_t* resultLength
,
161 if (!en
|| U_FAILURE(*status
)) {
164 if (en
->next
!= NULL
) {
165 if (resultLength
!= NULL
) {
166 return en
->next(en
, resultLength
, status
);
169 int32_t dummyLength
=0;
170 return en
->next(en
, &dummyLength
, status
);
173 *status
= U_UNSUPPORTED_ERROR
;
178 U_CAPI
void U_EXPORT2
179 uenum_reset(UEnumeration
* en
, UErrorCode
* status
)
181 if (!en
|| U_FAILURE(*status
)) {
184 if (en
->reset
!= NULL
) {
185 en
->reset(en
, status
);
187 *status
= U_UNSUPPORTED_ERROR
;