tor-browser

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

uenum.cpp (5273B)


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