Coverage Report

Created: 2024-04-24 06:23

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