tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ustrenum.cpp (11022B)


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