tor-browser

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

ufmt_cmn.cpp (6584B)


      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) 1998-2014, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 ******************************************************************************
     10 *
     11 * File ufmt_cmn.c
     12 *
     13 * Modification History:
     14 *
     15 *   Date        Name        Description
     16 *   12/02/98    stephen     Creation.
     17 *   03/12/99    stephen     Modified for new C API.
     18 *   03/15/99    stephen     Added defaultCPToUnicode, unicodeToDefaultCP
     19 *   07/19/99    stephen     Fixed bug in defaultCPToUnicode
     20 ******************************************************************************
     21 */
     22 
     23 #include "cstring.h"
     24 #include "cmemory.h"
     25 #include "ufmt_cmn.h"
     26 #include "unicode/uchar.h"
     27 #include "unicode/ucnv.h"
     28 #include "ustr_cnv.h"
     29 
     30 #if !UCONFIG_NO_CONVERSION
     31 
     32 
     33 #define DIGIT_0     0x0030
     34 #define DIGIT_9     0x0039
     35 #define LOWERCASE_A 0x0061
     36 #define UPPERCASE_A 0x0041
     37 #define LOWERCASE_Z 0x007A
     38 #define UPPERCASE_Z 0x005A
     39 
     40 int
     41 ufmt_digitvalue(char16_t c)
     42 {
     43    if( ((c>=DIGIT_0)&&(c<=DIGIT_9)) ||
     44        ((c>=LOWERCASE_A)&&(c<=LOWERCASE_Z)) ||
     45        ((c>=UPPERCASE_A)&&(c<=UPPERCASE_Z))  )
     46    {
     47      return c - DIGIT_0 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0);
     48    }
     49    else
     50    {
     51      return -1;
     52    }
     53 }
     54 
     55 UBool
     56 ufmt_isdigit(char16_t  c,
     57             int32_t     radix)
     58 {
     59    int digitVal = ufmt_digitvalue(c);
     60 
     61    return digitVal < radix && digitVal >= 0;
     62 }
     63 
     64 #define TO_UC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0037 + a)
     65 #define TO_LC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0057 + a)
     66 
     67 void 
     68 ufmt_64tou(char16_t  *buffer,
     69          int32_t   *len,
     70          uint64_t  value, 
     71          uint8_t  radix,
     72          UBool     uselower,
     73          int32_t   minDigits)
     74 {
     75    int32_t  length = 0;
     76    uint32_t digit;
     77    char16_t *left, *right, temp;
     78    
     79    do {
     80        digit = static_cast<uint32_t>(value % radix);
     81        value = value / radix;
     82        buffer[length++] = static_cast<char16_t>(uselower ? TO_LC_DIGIT(digit)
     83            : TO_UC_DIGIT(digit));
     84    } while(value);
     85 
     86    /* pad with zeroes to make it minDigits long */
     87    if(minDigits != -1 && length < minDigits) {
     88        while(length < minDigits && length < *len)
     89            buffer[length++] = DIGIT_0;  /*zero padding */
     90    }
     91 
     92    /* reverse the buffer */
     93    left     = buffer;
     94    right = buffer + length;
     95    while(left < --right) {
     96        temp     = *left;
     97        *left++     = *right;
     98        *right     = temp;
     99    }
    100    
    101    *len = length;
    102 }
    103 
    104 void 
    105 ufmt_ptou(char16_t *buffer,
    106          int32_t   *len,
    107          void      *value, 
    108          UBool     uselower)
    109 {
    110    int32_t i;
    111    int32_t length = 0;
    112    uint8_t* ptrIdx = reinterpret_cast<uint8_t*>(&value);
    113 
    114 #if U_IS_BIG_ENDIAN
    115    for (i = 0; i < (int32_t)sizeof(void *); i++)
    116 #else
    117    for (i = static_cast<int32_t>(sizeof(void*)) - 1; i >= 0; i--)
    118 #endif
    119    {
    120        uint8_t byteVal = ptrIdx[i];
    121        uint16_t firstNibble = static_cast<uint16_t>(byteVal >> 4);
    122        uint16_t secondNibble = static_cast<uint16_t>(byteVal & 0xF);
    123        if (uselower) {
    124            buffer[length++]=TO_LC_DIGIT(firstNibble);
    125            buffer[length++]=TO_LC_DIGIT(secondNibble);
    126        }
    127        else {
    128            buffer[length++]=TO_UC_DIGIT(firstNibble);
    129            buffer[length++]=TO_UC_DIGIT(secondNibble);
    130        }
    131    }
    132 
    133    *len = length;
    134 }
    135 
    136 int64_t
    137 ufmt_uto64(const char16_t  *buffer,
    138          int32_t     *len,
    139          int8_t     radix)
    140 {
    141    const char16_t  *limit;
    142    int32_t         count;
    143    uint64_t        result;
    144    
    145    
    146    /* initialize parameters */
    147    limit     = buffer + *len;
    148    count     = 0;
    149    result    = 0;
    150    
    151    /* iterate through buffer */
    152    while(ufmt_isdigit(*buffer, radix) && buffer < limit) {
    153        
    154        /* read the next digit */
    155        result *= radix;
    156        result += ufmt_digitvalue(*buffer++);
    157        
    158        /* increment our count */
    159        ++count;
    160    }
    161    
    162    *len = count;
    163    return static_cast<int64_t>(result);
    164 }
    165 
    166 #define NIBBLE_PER_BYTE 2
    167 void *
    168 ufmt_utop(const char16_t  *buffer,
    169          int32_t     *len)
    170 {
    171    int32_t count, resultIdx, incVal, offset;
    172    /* This union allows the pointer to be written as an array. */
    173    union {
    174        void *ptr;
    175        uint8_t bytes[sizeof(void*)];
    176    } result;
    177    
    178    /* initialize variables */
    179    count      = 0;
    180    offset     = 0;
    181    result.ptr = nullptr;
    182 
    183    /* Skip the leading zeros */
    184    while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) {
    185        count++;
    186        offset++;
    187    }
    188 
    189    /* iterate through buffer, stop when you hit the end */
    190    while(count < *len && ufmt_isdigit(buffer[count], 16)) {
    191        /* increment the count consumed */
    192        ++count;
    193    }
    194 
    195    /* detect overflow */
    196    if (count - offset > static_cast<int32_t>(sizeof(void*) * NIBBLE_PER_BYTE)) {
    197        offset = count - static_cast<int32_t>(sizeof(void*) * NIBBLE_PER_BYTE);
    198    }
    199    
    200    /* Initialize the direction of the input */
    201 #if U_IS_BIG_ENDIAN
    202    incVal = -1;
    203    resultIdx = (int32_t)(sizeof(void*) - 1);
    204 #else
    205    incVal = 1;
    206    resultIdx = 0;
    207 #endif
    208    /* Write how much was consumed. */
    209    *len = count;
    210    while(--count >= offset) {
    211        /* Get the first nibble of the byte */
    212        uint8_t byte = static_cast<uint8_t>(ufmt_digitvalue(buffer[count]));
    213 
    214        if (count > offset) {
    215            /* Get the second nibble of the byte when available */
    216            byte = static_cast<uint8_t>(byte + (ufmt_digitvalue(buffer[--count]) << 4));
    217        }
    218        /* Write the byte into the array */
    219        result.bytes[resultIdx] = byte;
    220        resultIdx += incVal;
    221    }
    222 
    223    return result.ptr;
    224 }
    225 
    226 char16_t*
    227 ufmt_defaultCPToUnicode(const char *s, int32_t sSize,
    228                        char16_t *target, int32_t tSize)
    229 {
    230    char16_t *alias;
    231    UErrorCode status = U_ZERO_ERROR;
    232    UConverter *defConverter = u_getDefaultConverter(&status);
    233 
    234    if (U_FAILURE(status) || defConverter == nullptr)
    235        return nullptr;
    236 
    237    if(sSize <= 0) {
    238        sSize = static_cast<int32_t>(uprv_strlen(s)) + 1;
    239    }
    240    
    241    /* perform the conversion in one swoop */
    242    if (target != nullptr) {
    243        alias = target;
    244        ucnv_toUnicode(defConverter, &alias, alias + tSize, &s, s + sSize - 1, 
    245            nullptr, true, &status);
    246        
    247        
    248        /* add the null terminator */
    249        *alias = 0x0000;
    250    }
    251    
    252    u_releaseDefaultConverter(defConverter);
    253    
    254    return target;
    255 }
    256 
    257 
    258 #endif