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