intl/icu/source/common/ustrenum.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2 **********************************************************************
     3 * Copyright (c) 2002-2012, International Business Machines
     4 * Corporation and others.  All Rights Reserved.
     5 **********************************************************************
     6 * Author: Alan Liu
     7 * Created: November 11 2002
     8 * Since: ICU 2.4
     9 **********************************************************************
    10 */
    11 #include "utypeinfo.h"  // for 'typeid' to work 
    13 #include "unicode/ustring.h"
    14 #include "unicode/strenum.h"
    15 #include "unicode/putil.h"
    16 #include "uenumimp.h"
    17 #include "ustrenum.h"
    18 #include "cstring.h"
    19 #include "cmemory.h"
    20 #include "uassert.h"
    22 U_NAMESPACE_BEGIN
    23 // StringEnumeration implementation ---------------------------------------- ***
    25 StringEnumeration::StringEnumeration()
    26     : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
    27 }
    29 StringEnumeration::~StringEnumeration() {
    30     if (chars != NULL && chars != charsBuffer) {
    31         uprv_free(chars);
    32     }
    33 }
    35 // StringEnumeration base class clone() default implementation, does not clone
    36 StringEnumeration *
    37 StringEnumeration::clone() const {
    38   return NULL;
    39 }
    41 const char *
    42 StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
    43     const UnicodeString *s=snext(status);
    44     if(U_SUCCESS(status) && s!=NULL) {
    45         unistr=*s;
    46         ensureCharsCapacity(unistr.length()+1, status);
    47         if(U_SUCCESS(status)) {
    48             if(resultLength!=NULL) {
    49                 *resultLength=unistr.length();
    50             }
    51             unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV);
    52             return chars;
    53         }
    54     }
    56     return NULL;
    57 }
    59 const UChar *
    60 StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
    61     const UnicodeString *s=snext(status);
    62     if(U_SUCCESS(status) && s!=NULL) {
    63         unistr=*s;
    64         if(resultLength!=NULL) {
    65             *resultLength=unistr.length();
    66         }
    67         return unistr.getTerminatedBuffer();
    68     }
    70     return NULL;
    71 }
    73 const UnicodeString *
    74 StringEnumeration::snext(UErrorCode &status) {
    75     int32_t length;
    76     const char *s=next(&length, status);
    77     return setChars(s, length, status);
    78 }
    80 void
    81 StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) {
    82     if(U_SUCCESS(status) && capacity>charsCapacity) {
    83         if(capacity<(charsCapacity+charsCapacity/2)) {
    84             // avoid allocation thrashing
    85             capacity=charsCapacity+charsCapacity/2;
    86         }
    87         if(chars!=charsBuffer) {
    88             uprv_free(chars);
    89         }
    90         chars=(char *)uprv_malloc(capacity);
    91         if(chars==NULL) {
    92             chars=charsBuffer;
    93             charsCapacity=sizeof(charsBuffer);
    94             status=U_MEMORY_ALLOCATION_ERROR;
    95         } else {
    96             charsCapacity=capacity;
    97         }
    98     }
    99 }
   101 UnicodeString *
   102 StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
   103     if(U_SUCCESS(status) && s!=NULL) {
   104         if(length<0) {
   105             length=(int32_t)uprv_strlen(s);
   106         }
   108         UChar *buffer=unistr.getBuffer(length+1);
   109         if(buffer!=NULL) {
   110             u_charsToUChars(s, buffer, length);
   111             buffer[length]=0;
   112             unistr.releaseBuffer(length);
   113             return &unistr;
   114         } else {
   115             status=U_MEMORY_ALLOCATION_ERROR;
   116         }
   117     }
   119     return NULL;
   120 }
   121 UBool 
   122 StringEnumeration::operator==(const StringEnumeration& that)const {
   123     return typeid(*this) == typeid(that); 
   124 }
   126 UBool
   127 StringEnumeration::operator!=(const StringEnumeration& that)const {
   128     return !operator==(that);
   129 }
   131 // UStringEnumeration implementation --------------------------------------- ***
   133 UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
   134     uenum(_uenum) {
   135     U_ASSERT(_uenum != 0);
   136 }
   138 UStringEnumeration::~UStringEnumeration() {
   139     uenum_close(uenum);
   140 }
   142 int32_t UStringEnumeration::count(UErrorCode& status) const {
   143     return uenum_count(uenum, &status);
   144 }
   146 const char *UStringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
   147     return uenum_next(uenum, resultLength, &status);
   148 }
   150 const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
   151     int32_t length;
   152     const UChar* str = uenum_unext(uenum, &length, &status);
   153     if (str == 0 || U_FAILURE(status)) {
   154         return 0;
   155     }
   156     return &unistr.setTo(str, length);
   157 }
   159 void UStringEnumeration::reset(UErrorCode& status) {
   160     uenum_reset(uenum, &status);
   161 }
   163 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration)
   164 U_NAMESPACE_END
   166 // C wrapper --------------------------------------------------------------- ***
   168 #define THIS(en) ((icu::StringEnumeration*)(en->context))
   170 U_CDECL_BEGIN
   172 /**
   173  * Wrapper API to make StringEnumeration look like UEnumeration.
   174  */
   175 static void U_CALLCONV
   176 ustrenum_close(UEnumeration* en) {
   177     delete THIS(en);
   178     uprv_free(en);
   179 }
   181 /**
   182  * Wrapper API to make StringEnumeration look like UEnumeration.
   183  */
   184 static int32_t U_CALLCONV
   185 ustrenum_count(UEnumeration* en,
   186                UErrorCode* ec)
   187 {
   188     return THIS(en)->count(*ec);
   189 }
   191 /**
   192  * Wrapper API to make StringEnumeration look like UEnumeration.
   193  */
   194 static const UChar* U_CALLCONV
   195 ustrenum_unext(UEnumeration* en,
   196                int32_t* resultLength,
   197                UErrorCode* ec)
   198 {
   199     return THIS(en)->unext(resultLength, *ec);
   200 }
   202 /**
   203  * Wrapper API to make StringEnumeration look like UEnumeration.
   204  */
   205 static const char* U_CALLCONV
   206 ustrenum_next(UEnumeration* en,
   207               int32_t* resultLength,
   208               UErrorCode* ec)
   209 {
   210     return THIS(en)->next(resultLength, *ec);
   211 }
   213 /**
   214  * Wrapper API to make StringEnumeration look like UEnumeration.
   215  */
   216 static void U_CALLCONV
   217 ustrenum_reset(UEnumeration* en,
   218                UErrorCode* ec)
   219 {
   220     THIS(en)->reset(*ec);
   221 }
   223 /**
   224  * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
   225  * The StringEnumeration pointer will be stored in 'context'.
   226  */
   227 static const UEnumeration USTRENUM_VT = {
   228     NULL,
   229     NULL, // store StringEnumeration pointer here
   230     ustrenum_close,
   231     ustrenum_count,
   232     ustrenum_unext,
   233     ustrenum_next,
   234     ustrenum_reset
   235 };
   237 U_CDECL_END
   239 /**
   240  * Given a StringEnumeration, wrap it in a UEnumeration.  The
   241  * StringEnumeration is adopted; after this call, the caller must not
   242  * delete it (regardless of error status).
   243  */
   244 U_CAPI UEnumeration* U_EXPORT2
   245 uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec) { 
   246     UEnumeration* result = NULL;
   247     if (U_SUCCESS(*ec) && adopted != NULL) {
   248         result = (UEnumeration*) uprv_malloc(sizeof(UEnumeration));
   249         if (result == NULL) {
   250             *ec = U_MEMORY_ALLOCATION_ERROR;
   251         } else {
   252             uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
   253             result->context = adopted;
   254         }
   255     }
   256     if (result == NULL) {
   257         delete adopted;
   258     }
   259     return result;
   260 }
   262 // C wrapper --------------------------------------------------------------- ***
   264 U_CDECL_BEGIN
   266 typedef struct UCharStringEnumeration {
   267     UEnumeration uenum;
   268     int32_t index, count;
   269 } UCharStringEnumeration;
   271 static void U_CALLCONV
   272 ucharstrenum_close(UEnumeration* en) {
   273     uprv_free(en);
   274 }
   276 static int32_t U_CALLCONV
   277 ucharstrenum_count(UEnumeration* en,
   278                    UErrorCode* /*ec*/) {
   279     return ((UCharStringEnumeration*)en)->count;
   280 }
   282 static const UChar* U_CALLCONV
   283 ucharstrenum_unext(UEnumeration* en,
   284                   int32_t* resultLength,
   285                   UErrorCode* /*ec*/) {
   286     UCharStringEnumeration *e = (UCharStringEnumeration*) en;
   287     if (e->index >= e->count) {
   288         return NULL;
   289     }
   290     const UChar* result = ((const UChar**)e->uenum.context)[e->index++];
   291     if (resultLength) {
   292         *resultLength = (int32_t)u_strlen(result);
   293     }
   294     return result;
   295 }
   298 static const char* U_CALLCONV
   299 ucharstrenum_next(UEnumeration* en,
   300                   int32_t* resultLength,
   301                   UErrorCode* /*ec*/) {
   302     UCharStringEnumeration *e = (UCharStringEnumeration*) en;
   303     if (e->index >= e->count) {
   304         return NULL;
   305     }
   306     const char* result = ((const char**)e->uenum.context)[e->index++];
   307     if (resultLength) {
   308         *resultLength = (int32_t)uprv_strlen(result);
   309     }
   310     return result;
   311 }
   313 static void U_CALLCONV
   314 ucharstrenum_reset(UEnumeration* en,
   315                    UErrorCode* /*ec*/) {
   316     ((UCharStringEnumeration*)en)->index = 0;
   317 }
   319 static const UEnumeration UCHARSTRENUM_VT = {
   320     NULL,
   321     NULL, // store StringEnumeration pointer here
   322     ucharstrenum_close,
   323     ucharstrenum_count,
   324     uenum_unextDefault,
   325     ucharstrenum_next,
   326     ucharstrenum_reset
   327 };
   329 static const UEnumeration UCHARSTRENUM_U_VT = {
   330     NULL,
   331     NULL, // store StringEnumeration pointer here
   332     ucharstrenum_close,
   333     ucharstrenum_count,
   334     ucharstrenum_unext,
   335     uenum_nextDefault,
   336     ucharstrenum_reset
   337 };
   339 U_CDECL_END
   341 U_CAPI UEnumeration* U_EXPORT2
   342 uenum_openCharStringsEnumeration(const char* const strings[], int32_t count,
   343                                  UErrorCode* ec) {
   344     UCharStringEnumeration* result = NULL;
   345     if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
   346         result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
   347         if (result == NULL) {
   348             *ec = U_MEMORY_ALLOCATION_ERROR;
   349         } else {
   350             U_ASSERT((char*)result==(char*)(&result->uenum));
   351             uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
   352             result->uenum.context = (void*)strings;
   353             result->index = 0;
   354             result->count = count;
   355         }
   356     }
   357     return (UEnumeration*) result;
   358 }
   360 U_CAPI UEnumeration* U_EXPORT2
   361 uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count,
   362                                  UErrorCode* ec) {
   363     UCharStringEnumeration* result = NULL;
   364     if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
   365         result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
   366         if (result == NULL) {
   367             *ec = U_MEMORY_ALLOCATION_ERROR;
   368         } else {
   369             U_ASSERT((char*)result==(char*)(&result->uenum));
   370             uprv_memcpy(result, &UCHARSTRENUM_U_VT, sizeof(UCHARSTRENUM_U_VT));
   371             result->uenum.context = (void*)strings;
   372             result->index = 0;
   373             result->count = count;
   374         }
   375     }
   376     return (UEnumeration*) result;
   377 }
   380 // end C Wrapper

mercurial