]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ustrenum.cpp
ICU-6.2.22.tar.gz
[apple/icu.git] / icuSources / common / ustrenum.cpp
index 2fe2ef1aa5d18af55389ad7fbb956b3fa28900cb..22db32b87c1e15d2299e4d04515626e504ff5209 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002, International Business Machines
+* Copyright (c) 2002-2004, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Alan Liu
 */
 #include "unicode/ustring.h"
 #include "unicode/strenum.h"
+#include "unicode/putil.h"
 #include "uenumimp.h"
 #include "ustrenum.h"
 #include "cstring.h"
 #include "cmemory.h"
+#include "uassert.h"
+
+U_NAMESPACE_BEGIN
+// StringEnumeration implementation ---------------------------------------- ***
+
+StringEnumeration::StringEnumeration()
+    : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
+}
+
+StringEnumeration::~StringEnumeration() {
+    if (chars != NULL && chars != charsBuffer) {
+        uprv_free(chars);
+    }
+}
+
+// StringEnumeration base class clone() default implementation, does not clone
+StringEnumeration *
+StringEnumeration::clone() const {
+  return NULL;
+}
+
+const char *
+StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
+    const UnicodeString *s=snext(status);
+    if(s!=NULL) {
+        unistr=*s;
+        ensureCharsCapacity(unistr.length()+1, status);
+        if(U_SUCCESS(status)) {
+            if(resultLength!=NULL) {
+                *resultLength=unistr.length();
+            }
+            unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV);
+            return chars;
+        }
+    }
+
+    return NULL;
+}
+
+const UChar *
+StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
+    const UnicodeString *s=snext(status);
+    if(s!=NULL) {
+        unistr=*s;
+        if(U_SUCCESS(status)) {
+            if(resultLength!=NULL) {
+                *resultLength=unistr.length();
+            }
+            return unistr.getTerminatedBuffer();
+        }
+    }
+
+    return NULL;
+}
+
+void
+StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) {
+    if(U_SUCCESS(status) && capacity>charsCapacity) {
+        if(capacity<(charsCapacity+charsCapacity/2)) {
+            // avoid allocation thrashing
+            capacity=charsCapacity+charsCapacity/2;
+        }
+        if(chars!=charsBuffer) {
+            uprv_free(chars);
+        }
+        chars=(char *)uprv_malloc(capacity);
+        if(chars==NULL) {
+            chars=charsBuffer;
+            charsCapacity=sizeof(charsBuffer);
+            status=U_MEMORY_ALLOCATION_ERROR;
+        } else {
+            charsCapacity=capacity;
+        }
+    }
+}
+
+UnicodeString *
+StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
+    if(U_SUCCESS(status) && s!=NULL) {
+        if(length<0) {
+            length=(int32_t)uprv_strlen(s);
+        }
+
+        UChar *buffer=unistr.getBuffer(length+1);
+        if(buffer!=NULL) {
+            u_charsToUChars(s, buffer, length);
+            buffer[length]=0;
+            unistr.releaseBuffer(length);
+            return &unistr;
+        } else {
+            status=U_MEMORY_ALLOCATION_ERROR;
+        }
+    }
+
+    return NULL;
+}
+
+// UStringEnumeration implementation --------------------------------------- ***
+
+UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
+    uenum(_uenum) {
+    U_ASSERT(_uenum != 0);
+}
+
+UStringEnumeration::~UStringEnumeration() {
+    uenum_close(uenum);
+}
+
+int32_t UStringEnumeration::count(UErrorCode& status) const {
+    return uenum_count(uenum, &status);
+}
+
+const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
+    int32_t length;
+    const UChar* str = uenum_unext(uenum, &length, &status);
+    if (str == 0 || U_FAILURE(status)) {
+        return 0;
+    }
+    return &unistr.setTo(str, length);
+}
+
+void UStringEnumeration::reset(UErrorCode& status) {
+    uenum_reset(uenum, &status);
+}
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration/*, StringEnumeration*/)
+U_NAMESPACE_END
+
+// C wrapper --------------------------------------------------------------- ***
 
 #define THIS(en) ((StringEnumeration*)(en->context))
 
@@ -74,7 +204,7 @@ ustrenum_reset(UEnumeration* en,
  * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
  * The StringEnumeration pointer will be stored in 'context'.
  */
-static const UEnumeration TEMPLATE = {
+static const UEnumeration USTRENUM_VT = {
     NULL,
     NULL, // store StringEnumeration pointer here
     ustrenum_close,
@@ -99,7 +229,7 @@ uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) {
         if (result == NULL) {
             *ec = U_MEMORY_ALLOCATION_ERROR;
         } else {
-            uprv_memcpy(result, &TEMPLATE, sizeof(TEMPLATE));
+            uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
             result->context = adopted;
         }
     }
@@ -109,4 +239,75 @@ uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) {
     return result;
 }
 
-//eof
+// C wrapper --------------------------------------------------------------- ***
+
+U_CDECL_BEGIN
+
+typedef struct UCharStringEnumeration {
+    UEnumeration uenum;
+    int32_t index, count;
+} UCharStringEnumeration;
+
+static void U_CALLCONV
+ucharstrenum_close(UEnumeration* en) {
+    uprv_free(en);
+}
+
+static int32_t U_CALLCONV
+ucharstrenum_count(UEnumeration* en,
+                   UErrorCode* /*ec*/) {
+    return ((UCharStringEnumeration*)en)->count;
+}
+
+static const char* U_CALLCONV
+ucharstrenum_next(UEnumeration* en,
+                  int32_t* resultLength,
+                  UErrorCode* /*ec*/) {
+    UCharStringEnumeration *e = (UCharStringEnumeration*) en;
+    if (e->index >= e->count) {
+        return NULL;
+    }
+    const char* result = ((const char**)e->uenum.context)[e->index++];
+    if (resultLength) {
+        *resultLength = (int32_t)uprv_strlen(result);
+    }
+    return result;
+}
+
+static void U_CALLCONV
+ucharstrenum_reset(UEnumeration* en,
+                   UErrorCode* /*ec*/) {
+    ((UCharStringEnumeration*)en)->index = 0;
+}
+
+static const UEnumeration UCHARSTRENUM_VT = {
+    NULL,
+    NULL, // store StringEnumeration pointer here
+    ucharstrenum_close,
+    ucharstrenum_count,
+    uenum_unextDefault,
+    ucharstrenum_next,
+    ucharstrenum_reset
+};
+
+U_CDECL_END
+
+U_CAPI UEnumeration* U_EXPORT2
+uenum_openCharStringsEnumeration(const char** strings, int32_t count,
+                                 UErrorCode* ec) {
+    UCharStringEnumeration* result = NULL;
+    if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
+        result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
+        if (result == NULL) {
+            *ec = U_MEMORY_ALLOCATION_ERROR;
+        } else {
+            U_ASSERT((char*)result==(char*)(&result->uenum));
+            uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
+            result->uenum.context = strings;
+            result->index = 0;
+            result->count = count;
+        }
+    }
+    return (UEnumeration*) result;
+}
+