]> granicus.if.org Git - icu/commitdiff
ICU-7197 add API for constructing UEnumerations.
authorSteven R. Loomis <srl@icu-project.org>
Thu, 9 Aug 2012 00:04:51 +0000 (00:04 +0000)
committerSteven R. Loomis <srl@icu-project.org>
Thu, 9 Aug 2012 00:04:51 +0000 (00:04 +0000)
X-SVN-Rev: 32137

icu4c/source/common/unicode/uenum.h
icu4c/source/common/ustrenum.cpp
icu4c/source/common/ustrenum.h
icu4c/source/test/cintltst/uenumtst.c

index 21e82b2384a54c88c0a8259417db6870af09ebce..393f4c4caf48812869fa84df23b94ba2beba357e 100644 (file)
@@ -171,4 +171,39 @@ uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec)
 
 #endif
 
+#ifndef U_HIDE_DRAFT_API
+/**
+ * Given an array of const UChar* strings, return a UEnumeration.  String pointers from 0..count-1 must not be null.
+ * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close.
+ * \snippet test/cintltst/uenumtst.c uenum_openUCharStringsEnumeration
+ * @param strings array of const UChar* strings (each null terminated). All storage is owned by the caller.
+ * @param count length of the array
+ * @param ec error code
+ * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory.
+ * @see uenum_close
+ * @draft ICU 50
+ */
+U_CAPI UEnumeration* U_EXPORT2
+uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count,
+                                 UErrorCode* ec);
+#endif
+
+/* Note:  next function is not hidden as draft, as it is used internally (it was formerly an internal function). */
+
+/**
+ * Given an array of const char* strings (invariant chars only), return a UEnumeration.  String pointers from 0..count-1 must not be null.
+ * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close.
+ * \snippet test/cintltst/uenumtst.c uenum_openCharStringsEnumeration
+ * @param strings array of char* strings (each null terminated).  All storage is owned by the caller.
+ * @param count length of the array
+ * @param ec error code
+ * @return the new UEnumeration object. Caller is responsible for calling uenum_close to free memory
+ * @see uenum_close
+ * @draft ICU 50
+ */
+U_CAPI UEnumeration* U_EXPORT2
+uenum_openCharStringsEnumeration(const char* const strings[], int32_t count,
+                                 UErrorCode* ec);
+
+
 #endif
index 3956615db315c55905a3493ab7991f51aa2082ae..01b6a6fbd100c636406a844d2681fc9851a149cb 100644 (file)
@@ -270,6 +270,22 @@ ucharstrenum_count(UEnumeration* en,
     return ((UCharStringEnumeration*)en)->count;
 }
 
+static const UChar* U_CALLCONV
+ucharstrenum_unext(UEnumeration* en,
+                  int32_t* resultLength,
+                  UErrorCode* /*ec*/) {
+    UCharStringEnumeration *e = (UCharStringEnumeration*) en;
+    if (e->index >= e->count) {
+        return NULL;
+    }
+    const UChar* result = ((const UChar**)e->uenum.context)[e->index++];
+    if (resultLength) {
+        *resultLength = (int32_t)u_strlen(result);
+    }
+    return result;
+}
+
+
 static const char* U_CALLCONV
 ucharstrenum_next(UEnumeration* en,
                   int32_t* resultLength,
@@ -301,10 +317,20 @@ static const UEnumeration UCHARSTRENUM_VT = {
     ucharstrenum_reset
 };
 
+static const UEnumeration UCHARSTRENUM_U_VT = {
+    NULL,
+    NULL, // store StringEnumeration pointer here
+    ucharstrenum_close,
+    ucharstrenum_count,
+    ucharstrenum_unext,
+    uenum_nextDefault,
+    ucharstrenum_reset
+};
+
 U_CDECL_END
 
 U_CAPI UEnumeration* U_EXPORT2
-uenum_openCharStringsEnumeration(const char* const* strings, int32_t count,
+uenum_openCharStringsEnumeration(const char* const strings[], int32_t count,
                                  UErrorCode* ec) {
     UCharStringEnumeration* result = NULL;
     if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
@@ -322,4 +348,24 @@ uenum_openCharStringsEnumeration(const char* const* strings, int32_t count,
     return (UEnumeration*) result;
 }
 
+U_CAPI UEnumeration* U_EXPORT2
+uenum_openUCharStringsEnumeration(const UChar* const 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_U_VT, sizeof(UCHARSTRENUM_U_VT));
+            result->uenum.context = (void*)strings;
+            result->index = 0;
+            result->count = count;
+        }
+    }
+    return (UEnumeration*) result;
+}
+
 
+// end C Wrapper
index 21b168316b8c14fa3aec7512fd28a9a4f5f90493..ef5863aed01eee570c3606557b560dea1010084d 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-* Copyright (c) 2002-2009, International Business Machines
+* Copyright (c) 2002-2012, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Alan Liu
 #include "unicode/uenum.h"
 #include "unicode/strenum.h"
 
-/**
- * Given an array of const char* strings (invariant chars only),
- * return a UEnumeration.  Must have strings[i] != 0 for i in
- * 0..count-1.
- */
-U_CAPI UEnumeration* U_EXPORT2
-uenum_openCharStringsEnumeration(const char* const* strings, int32_t count,
-                                 UErrorCode* ec);
-
 //----------------------------------------------------------------------
 U_NAMESPACE_BEGIN
 
index 2d9ed6c0ab89faaa74cdbe707a6d7a69dde1c69d..a1772898030cecee78ba4617d90cc8d88e151f17 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2002-2003, International Business Machines
+*   Copyright (C) 2002-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -297,6 +297,161 @@ static void DefaultNextTest(void) {
     uenum_close(en);
 }
 
+static void verifyEnumeration(int line, UEnumeration *u, const char * const * compareToChar, const UChar * const * compareToUChar, int32_t expect_count) {
+  UErrorCode status = U_ZERO_ERROR;
+  int32_t got_count,i,len;
+  const char *c;
+  UChar buf[1024];
+
+  log_verbose("%s:%d: verifying enumeration..\n", __FILE__, line);
+
+  uenum_reset(u, &status);
+  if(U_FAILURE(status)) {
+    log_err("%s:%d: FAIL: could not reset char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
+    return;
+  }
+
+  got_count = uenum_count(u, &status);
+  if(U_FAILURE(status)) {
+    log_err("%s:%d: FAIL: could not count char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
+    return;
+  }
+  
+  if(got_count!=expect_count) {
+    log_err("%s:%d: FAIL: expect count %d got %d\n", __FILE__, line, expect_count, got_count);
+  } else {
+    log_verbose("%s:%d: OK: got count %d\n", __FILE__, line, got_count);
+  }
+
+  if(compareToChar!=NULL) { /* else, not invariant */
+    for(i=0;i<got_count;i++) {
+      c = uenum_next(u,&len, &status);
+      if(U_FAILURE(status)) {
+        log_err("%s:%d: FAIL: could not iterate to next after %d: %s\n", __FILE__, line, i, u_errorName(status));
+        return;
+      }
+      if(c==NULL) {
+        log_err("%s:%d: FAIL: got NULL for next after %d: %s\n", __FILE__, line, i, u_errorName(status));
+        return;
+      }
+      
+      if(strcmp(c,compareToChar[i])) {
+        log_err("%s:%d: FAIL: string #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], c);
+      } else {
+        log_verbose("%s:%d: OK: string #%d got '%s'\n", __FILE__, line, i, c);
+      }
+      
+      if(len!=strlen(compareToChar[i])) {
+        log_err("%s:%d: FAIL: string #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
+      } else {
+        log_verbose("%s:%d: OK: string #%d got len %d\n", __FILE__, line, i, len);
+      }
+    }
+  }
+
+  /* now try U */
+  uenum_reset(u, &status);
+  if(U_FAILURE(status)) {
+    log_err("%s:%d: FAIL: could not reset again char strings enumeration: %s\n", __FILE__, line, u_errorName(status));
+    return;
+  }
+
+  for(i=0;i<got_count;i++) {
+    const UChar *ustr = uenum_unext(u,&len, &status);
+    if(U_FAILURE(status)) {
+      log_err("%s:%d: FAIL: could not iterate to unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
+      return;
+    }
+    if(ustr==NULL) {
+      log_err("%s:%d: FAIL: got NULL for unext after %d: %s\n", __FILE__, line, i, u_errorName(status));
+      return;
+    }
+    if(compareToChar!=NULL) {
+      u_charsToUChars(compareToChar[i], buf, strlen(compareToChar[i])+1);
+      if(u_strncmp(ustr,buf,len)) {
+        int j;
+        log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, compareToChar[i], austrdup(ustr));
+        for(j=0;ustr[j]&&buf[j];j++) {
+          log_verbose("  @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],buf[j]);
+        }
+      } else {
+        log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, compareToChar[i]);
+      }
+      
+      if(len!=strlen(compareToChar[i])) {
+        log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, strlen(compareToChar[i]), len);
+      } else {
+        log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
+      }
+    }
+
+    if(compareToUChar!=NULL) {
+      if(u_strcmp(ustr,compareToUChar[i])) {
+        int j;
+        log_err("%s:%d: FAIL: ustring #%d expected '%s' got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i]), austrdup(ustr));
+        for(j=0;ustr[j]&&compareToUChar[j];j++) {
+          log_verbose("  @ %d\t<U+%04X> vs <U+%04X>\n", j, ustr[j],compareToUChar[j]);
+        }
+      } else {
+        log_verbose("%s:%d: OK: ustring #%d got '%s'\n", __FILE__, line, i, austrdup(compareToUChar[i]));
+      }
+      
+      if(len!=u_strlen(compareToUChar[i])) {
+        log_err("%s:%d: FAIL: ustring #%d expected len %d got %d\n", __FILE__, line, i, u_strlen(compareToUChar[i]), len);
+      } else {
+        log_verbose("%s:%d: OK: ustring #%d got len %d\n", __FILE__, line, i, len);
+      }
+    }
+  }
+}
+
+
+
+
+
+static void TestCharStringsEnumeration(void)  {
+  UErrorCode status = U_ZERO_ERROR;
+
+  /* //! [uenum_openCharStringsEnumeration] */
+  const char* strings[] = { "Firstly", "Secondly", "Thirdly", "Fourthly" };
+  UEnumeration *u = uenum_openCharStringsEnumeration(strings, 4, &status);
+  /* //! [uenum_openCharStringsEnumeration] */
+  if(U_FAILURE(status)) {
+    log_err("FAIL: could not open char strings enumeration: %s\n", u_errorName(status));
+    return;
+  }
+
+  verifyEnumeration(__LINE__, u, strings, NULL, 4);
+
+  uenum_close(u);
+}
+
+static void TestUCharStringsEnumeration(void)  {
+  UErrorCode status = U_ZERO_ERROR;
+  /* //! [uenum_openUCharStringsEnumeration] */
+  static const UChar nko_1[] = {0x07c1,0}, nko_2[] = {0x07c2}, nko_3[] = {0x07c3,0}, nko_4[] = {0x07c4,0};
+  static const UChar* ustrings[] = {  nko_1, nko_2, nko_3, nko_4  };
+  UEnumeration *u = uenum_openUCharStringsEnumeration(ustrings, 4, &status);
+  /* //! [uenum_openUCharStringsEnumeration] */
+  if(U_FAILURE(status)) {
+    log_err("FAIL: could not open uchar strings enumeration: %s\n", u_errorName(status));
+    return;
+  }
+
+  verifyEnumeration(__LINE__, u, NULL, ustrings, 4);
+  uenum_close(u);
+
+
+  u =  uenum_openUCharStringsEnumeration(test2, 4, &status);
+  if(U_FAILURE(status)) {
+    log_err("FAIL: could not reopen uchar strings enumeration: %s\n", u_errorName(status));
+    return;
+  }
+  verifyEnumeration(__LINE__, u, test1, NULL, 4); /* same string */
+  uenum_close(u);
+  
+}
+
 void addEnumerationTest(TestNode** root);
 
 void addEnumerationTest(TestNode** root)
@@ -304,4 +459,6 @@ void addEnumerationTest(TestNode** root)
     addTest(root, &EnumerationTest, "tsutil/uenumtst/EnumerationTest");
     addTest(root, &EmptyEnumerationTest, "tsutil/uenumtst/EmptyEnumerationTest");
     addTest(root, &DefaultNextTest, "tsutil/uenumtst/DefaultNextTest");
+    addTest(root, &TestCharStringsEnumeration, "tsutil/uenumtst/TestCharStringsEnumeration");
+    addTest(root, &TestUCharStringsEnumeration, "tsutil/uenumtst/TestUCharStringsEnumeration");
 }