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