tor-browser

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

ustr_cnv.cpp (6208B)


      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 *   file name:  ustr_cnv.cpp
     11 *   encoding:   UTF-8
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2004aug24
     16 *   created by: Markus W. Scherer
     17 *
     18 *   Character conversion functions moved here from ustring.c
     19 */
     20 
     21 #include "unicode/utypes.h"
     22 
     23 #if !UCONFIG_NO_CONVERSION
     24 
     25 #include "unicode/ustring.h"
     26 #include "unicode/ucnv.h"
     27 #include "cstring.h"
     28 #include "cmemory.h"
     29 #include "umutex.h"
     30 #include "ustr_cnv.h"
     31 #include "ucnv_bld.h"
     32 
     33 /* mutexed access to a shared default converter ----------------------------- */
     34 
     35 static UConverter *gDefaultConverter = nullptr;
     36 
     37 U_CAPI UConverter* U_EXPORT2
     38 u_getDefaultConverter(UErrorCode *status)
     39 {
     40    UConverter *converter = nullptr;
     41    
     42    if (gDefaultConverter != nullptr) {
     43        icu::umtx_lock(nullptr);
     44        
     45        /* need to check to make sure it wasn't taken out from under us */
     46        if (gDefaultConverter != nullptr) {
     47            converter = gDefaultConverter;
     48            gDefaultConverter = nullptr;
     49        }
     50        icu::umtx_unlock(nullptr);
     51    }
     52 
     53    /* if the cache was empty, create a converter */
     54    if(converter == nullptr) {
     55        converter = ucnv_open(nullptr, status);
     56        if(U_FAILURE(*status)) {
     57            ucnv_close(converter);
     58            converter = nullptr;
     59        }
     60    }
     61 
     62    return converter;
     63 }
     64 
     65 U_CAPI void U_EXPORT2
     66 u_releaseDefaultConverter(UConverter *converter)
     67 {
     68    if(gDefaultConverter == nullptr) {
     69        if (converter != nullptr) {
     70            ucnv_reset(converter);
     71        }
     72        ucnv_enableCleanup();
     73        icu::umtx_lock(nullptr);
     74        if(gDefaultConverter == nullptr) {
     75            gDefaultConverter = converter;
     76            converter = nullptr;
     77        }
     78        icu::umtx_unlock(nullptr);
     79    }
     80 
     81    if(converter != nullptr) {
     82        ucnv_close(converter);
     83    }
     84 }
     85 
     86 U_CAPI void U_EXPORT2
     87 u_flushDefaultConverter()
     88 {
     89    UConverter *converter = nullptr;
     90    
     91    if (gDefaultConverter != nullptr) {
     92        icu::umtx_lock(nullptr);
     93        
     94        /* need to check to make sure it wasn't taken out from under us */
     95        if (gDefaultConverter != nullptr) {
     96            converter = gDefaultConverter;
     97            gDefaultConverter = nullptr;
     98        }
     99        icu::umtx_unlock(nullptr);
    100    }
    101 
    102    /* if the cache was populated, flush it */
    103    if(converter != nullptr) {
    104         ucnv_close(converter);
    105    }
    106 }
    107 
    108 
    109 /* conversions between char* and char16_t* ------------------------------------- */
    110 
    111 /* maximum string length for u_uastrcpy() and u_austrcpy() implementations */
    112 #define MAX_STRLEN 0x0FFFFFFF
    113 
    114 /*
    115 returns the minimum of (the length of the null-terminated string) and n.
    116 */
    117 static int32_t u_astrnlen(const char *s1, int32_t n)
    118 {
    119    int32_t len = 0;
    120 
    121    if (s1)
    122    {
    123        while (n-- && *(s1++))
    124        {
    125            len++;
    126        }
    127    }
    128    return len;
    129 }
    130 
    131 U_CAPI char16_t*  U_EXPORT2
    132 u_uastrncpy(char16_t *ucs1,
    133           const char *s2,
    134           int32_t n)
    135 {
    136  char16_t *target = ucs1;
    137  UErrorCode err = U_ZERO_ERROR;
    138  UConverter *cnv = u_getDefaultConverter(&err);
    139  if(U_SUCCESS(err) && cnv != nullptr) {
    140    ucnv_reset(cnv);
    141    ucnv_toUnicode(cnv,
    142                   &target,
    143                   ucs1+n,
    144                   &s2,
    145                   s2+u_astrnlen(s2, n),
    146                   nullptr,
    147                   true,
    148                   &err);
    149    ucnv_reset(cnv); /* be good citizens */
    150    u_releaseDefaultConverter(cnv);
    151    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
    152      *ucs1 = 0; /* failure */
    153    }
    154    if(target < (ucs1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
    155      *target = 0;  /* terminate */
    156    }
    157  } else {
    158    *ucs1 = 0;
    159  }
    160  return ucs1;
    161 }
    162 
    163 U_CAPI char16_t*  U_EXPORT2
    164 u_uastrcpy(char16_t *ucs1,
    165          const char *s2 )
    166 {
    167  UErrorCode err = U_ZERO_ERROR;
    168  UConverter *cnv = u_getDefaultConverter(&err);
    169  if(U_SUCCESS(err) && cnv != nullptr) {
    170    ucnv_toUChars(cnv,
    171                    ucs1,
    172                    MAX_STRLEN,
    173                    s2,
    174                    (int32_t)uprv_strlen(s2),
    175                    &err);
    176    u_releaseDefaultConverter(cnv);
    177    if(U_FAILURE(err)) {
    178      *ucs1 = 0;
    179    }
    180  } else {
    181    *ucs1 = 0;
    182  }
    183  return ucs1;
    184 }
    185 
    186 /*
    187 returns the minimum of (the length of the null-terminated string) and n.
    188 */
    189 static int32_t u_ustrnlen(const char16_t *ucs1, int32_t n)
    190 {
    191    int32_t len = 0;
    192 
    193    if (ucs1)
    194    {
    195        while (n-- && *(ucs1++))
    196        {
    197            len++;
    198        }
    199    }
    200    return len;
    201 }
    202 
    203 U_CAPI char*  U_EXPORT2
    204 u_austrncpy(char *s1,
    205        const char16_t *ucs2,
    206        int32_t n)
    207 {
    208  char *target = s1;
    209  UErrorCode err = U_ZERO_ERROR;
    210  UConverter *cnv = u_getDefaultConverter(&err);
    211  if(U_SUCCESS(err) && cnv != nullptr) {
    212    ucnv_reset(cnv);
    213    ucnv_fromUnicode(cnv,
    214                  &target,
    215                  s1+n,
    216                  &ucs2,
    217                  ucs2+u_ustrnlen(ucs2, n),
    218                  nullptr,
    219                  true,
    220                  &err);
    221    ucnv_reset(cnv); /* be good citizens */
    222    u_releaseDefaultConverter(cnv);
    223    if(U_FAILURE(err) && (err != U_BUFFER_OVERFLOW_ERROR) ) {
    224      *s1 = 0; /* failure */
    225    }
    226    if(target < (s1+n)) { /* U_BUFFER_OVERFLOW_ERROR isn't an err, just means no termination will happen. */
    227      *target = 0;  /* terminate */
    228    }
    229  } else {
    230    *s1 = 0;
    231  }
    232  return s1;
    233 }
    234 
    235 U_CAPI char*  U_EXPORT2
    236 u_austrcpy(char *s1,
    237         const char16_t *ucs2 )
    238 {
    239  UErrorCode err = U_ZERO_ERROR;
    240  UConverter *cnv = u_getDefaultConverter(&err);
    241  if(U_SUCCESS(err) && cnv != nullptr) {
    242    int32_t len = ucnv_fromUChars(cnv,
    243                  s1,
    244                  MAX_STRLEN,
    245                  ucs2,
    246                  -1,
    247                  &err);
    248    u_releaseDefaultConverter(cnv);
    249    s1[len] = 0;
    250  } else {
    251    *s1 = 0;
    252  }
    253  return s1;
    254 }
    255 
    256 #endif