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