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