Coverage Report

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