Coverage Report

Created: 2025-10-31 09:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/node/deps/icu-small/source/common/unicode/char16ptr.h
Line
Count
Source
1
// © 2017 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
// char16ptr.h
5
// created: 2017feb28 Markus W. Scherer
6
7
#ifndef __CHAR16PTR_H__
8
#define __CHAR16PTR_H__
9
10
#include "unicode/utypes.h"
11
12
#if U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
13
14
#include <cstddef>
15
#include <string_view>
16
#include <type_traits>
17
18
#endif
19
20
/**
21
 * \file
22
 * \brief C++ API: char16_t pointer wrappers with
23
 *        implicit conversion from bit-compatible raw pointer types.
24
 *        Also conversion functions from char16_t * to UChar * and OldUChar *.
25
 */
26
27
/**
28
 * \def U_ALIASING_BARRIER
29
 * Barrier for pointer anti-aliasing optimizations even across function boundaries.
30
 * @internal
31
 */
32
#ifdef U_ALIASING_BARRIER
33
    // Use the predefined value.
34
#elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
35
#   define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
36
#elif defined(U_IN_DOXYGEN)
37
#   define U_ALIASING_BARRIER(ptr)
38
#endif
39
40
// ICU DLL-exported
41
#if U_SHOW_CPLUSPLUS_API
42
43
U_NAMESPACE_BEGIN
44
45
/**
46
 * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
47
 * @stable ICU 59
48
 */
49
class U_COMMON_API Char16Ptr final {
50
public:
51
    /**
52
     * Copies the pointer.
53
     * @param p pointer
54
     * @stable ICU 59
55
     */
56
    inline Char16Ptr(char16_t *p);
57
#if !U_CHAR16_IS_TYPEDEF
58
    /**
59
     * Converts the pointer to char16_t *.
60
     * @param p pointer to be converted
61
     * @stable ICU 59
62
     */
63
    inline Char16Ptr(uint16_t *p);
64
#endif
65
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
66
    /**
67
     * Converts the pointer to char16_t *.
68
     * (Only defined if U_SIZEOF_WCHAR_T==2.)
69
     * @param p pointer to be converted
70
     * @stable ICU 59
71
     */
72
    inline Char16Ptr(wchar_t *p);
73
#endif
74
    /**
75
     * nullptr constructor.
76
     * @param p nullptr
77
     * @stable ICU 59
78
     */
79
    inline Char16Ptr(std::nullptr_t p);
80
    /**
81
     * Destructor.
82
     * @stable ICU 59
83
     */
84
    inline ~Char16Ptr();
85
86
    /**
87
     * Pointer access.
88
     * @return the wrapped pointer
89
     * @stable ICU 59
90
     */
91
    inline char16_t *get() const;
92
    /**
93
     * char16_t pointer access via type conversion (e.g., static_cast).
94
     * @return the wrapped pointer
95
     * @stable ICU 59
96
     */
97
0
    inline operator char16_t *() const { return get(); }
98
99
private:
100
    Char16Ptr() = delete;
101
102
#ifdef U_ALIASING_BARRIER
103
0
    template<typename T> static char16_t *cast(T *t) {
104
0
        U_ALIASING_BARRIER(t);
105
0
        return reinterpret_cast<char16_t *>(t);
106
0
    }
107
108
    char16_t *p_;
109
#else
110
    union {
111
        char16_t *cp;
112
        uint16_t *up;
113
        wchar_t *wp;
114
    } u_;
115
#endif
116
};
117
118
/// \cond
119
#ifdef U_ALIASING_BARRIER
120
121
Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
122
#if !U_CHAR16_IS_TYPEDEF
123
Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
124
#endif
125
#if U_SIZEOF_WCHAR_T==2
126
Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
127
#endif
128
Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
129
Char16Ptr::~Char16Ptr() {
130
    U_ALIASING_BARRIER(p_);
131
}
132
133
0
char16_t *Char16Ptr::get() const { return p_; }
134
135
#else
136
137
Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
138
#if !U_CHAR16_IS_TYPEDEF
139
Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
140
#endif
141
#if U_SIZEOF_WCHAR_T==2
142
Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
143
#endif
144
Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
145
Char16Ptr::~Char16Ptr() {}
146
147
char16_t *Char16Ptr::get() const { return u_.cp; }
148
149
#endif
150
/// \endcond
151
152
/**
153
 * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
154
 * @stable ICU 59
155
 */
156
class U_COMMON_API ConstChar16Ptr final {
157
public:
158
    /**
159
     * Copies the pointer.
160
     * @param p pointer
161
     * @stable ICU 59
162
     */
163
    inline ConstChar16Ptr(const char16_t *p);
164
#if !U_CHAR16_IS_TYPEDEF
165
    /**
166
     * Converts the pointer to char16_t *.
167
     * @param p pointer to be converted
168
     * @stable ICU 59
169
     */
170
    inline ConstChar16Ptr(const uint16_t *p);
171
#endif
172
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
173
    /**
174
     * Converts the pointer to char16_t *.
175
     * (Only defined if U_SIZEOF_WCHAR_T==2.)
176
     * @param p pointer to be converted
177
     * @stable ICU 59
178
     */
179
    inline ConstChar16Ptr(const wchar_t *p);
180
#endif
181
    /**
182
     * nullptr constructor.
183
     * @param p nullptr
184
     * @stable ICU 59
185
     */
186
    inline ConstChar16Ptr(const std::nullptr_t p);
187
188
    /**
189
     * Destructor.
190
     * @stable ICU 59
191
     */
192
    inline ~ConstChar16Ptr();
193
194
    /**
195
     * Pointer access.
196
     * @return the wrapped pointer
197
     * @stable ICU 59
198
     */
199
    inline const char16_t *get() const;
200
    /**
201
     * char16_t pointer access via type conversion (e.g., static_cast).
202
     * @return the wrapped pointer
203
     * @stable ICU 59
204
     */
205
0
    inline operator const char16_t *() const { return get(); }
206
207
private:
208
    ConstChar16Ptr() = delete;
209
210
#ifdef U_ALIASING_BARRIER
211
0
    template<typename T> static const char16_t *cast(const T *t) {
212
0
        U_ALIASING_BARRIER(t);
213
0
        return reinterpret_cast<const char16_t *>(t);
214
0
    }
215
216
    const char16_t *p_;
217
#else
218
    union {
219
        const char16_t *cp;
220
        const uint16_t *up;
221
        const wchar_t *wp;
222
    } u_;
223
#endif
224
};
225
226
/// \cond
227
#ifdef U_ALIASING_BARRIER
228
229
ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
230
#if !U_CHAR16_IS_TYPEDEF
231
ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
232
#endif
233
#if U_SIZEOF_WCHAR_T==2
234
ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
235
#endif
236
ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
237
ConstChar16Ptr::~ConstChar16Ptr() {
238
    U_ALIASING_BARRIER(p_);
239
}
240
241
0
const char16_t *ConstChar16Ptr::get() const { return p_; }
242
243
#else
244
245
ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
246
#if !U_CHAR16_IS_TYPEDEF
247
ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
248
#endif
249
#if U_SIZEOF_WCHAR_T==2
250
ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
251
#endif
252
ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
253
ConstChar16Ptr::~ConstChar16Ptr() {}
254
255
const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
256
257
#endif
258
/// \endcond
259
260
U_NAMESPACE_END
261
262
#endif  // U_SHOW_CPLUSPLUS_API
263
264
// Usable in header-only definitions
265
#if U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
266
267
namespace U_ICU_NAMESPACE_OR_INTERNAL {
268
269
#ifndef U_FORCE_HIDE_INTERNAL_API
270
/** @internal */
271
template<typename T, typename = std::enable_if_t<std::is_same_v<T, UChar>>>
272
0
inline const char16_t *uprv_char16PtrFromUChar(const T *p) {
273
0
    if constexpr (std::is_same_v<UChar, char16_t>) {
274
0
        return p;
275
0
    } else {
276
0
#if U_SHOW_CPLUSPLUS_API
277
0
        return ConstChar16Ptr(p).get();
278
0
#else
279
0
#ifdef U_ALIASING_BARRIER
280
0
        U_ALIASING_BARRIER(p);
281
0
#endif
282
0
        return reinterpret_cast<const char16_t *>(p);
283
0
#endif
284
0
    }
285
0
}
286
#if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
287
/** @internal */
288
inline const char16_t *uprv_char16PtrFromUint16(const uint16_t *p) {
289
#if U_SHOW_CPLUSPLUS_API
290
    return ConstChar16Ptr(p).get();
291
#else
292
#ifdef U_ALIASING_BARRIER
293
    U_ALIASING_BARRIER(p);
294
#endif
295
    return reinterpret_cast<const char16_t *>(p);
296
#endif
297
}
298
#endif
299
#if U_SIZEOF_WCHAR_T==2
300
/** @internal */
301
inline const char16_t *uprv_char16PtrFromWchar(const wchar_t *p) {
302
#if U_SHOW_CPLUSPLUS_API
303
    return ConstChar16Ptr(p).get();
304
#else
305
#ifdef U_ALIASING_BARRIER
306
    U_ALIASING_BARRIER(p);
307
#endif
308
    return reinterpret_cast<const char16_t *>(p);
309
#endif
310
}
311
#endif
312
#endif
313
314
/**
315
 * Converts from const char16_t * to const UChar *.
316
 * Includes an aliasing barrier if available.
317
 * @param p pointer
318
 * @return p as const UChar *
319
 * @stable ICU 59
320
 */
321
0
inline const UChar *toUCharPtr(const char16_t *p) {
322
0
#ifdef U_ALIASING_BARRIER
323
0
    U_ALIASING_BARRIER(p);
324
0
#endif
325
0
    return reinterpret_cast<const UChar *>(p);
326
0
}
327
328
/**
329
 * Converts from char16_t * to UChar *.
330
 * Includes an aliasing barrier if available.
331
 * @param p pointer
332
 * @return p as UChar *
333
 * @stable ICU 59
334
 */
335
0
inline UChar *toUCharPtr(char16_t *p) {
336
0
#ifdef U_ALIASING_BARRIER
337
0
    U_ALIASING_BARRIER(p);
338
0
#endif
339
0
    return reinterpret_cast<UChar *>(p);
340
0
}
341
342
/**
343
 * Converts from const char16_t * to const OldUChar *.
344
 * Includes an aliasing barrier if available.
345
 * @param p pointer
346
 * @return p as const OldUChar *
347
 * @stable ICU 59
348
 */
349
0
inline const OldUChar *toOldUCharPtr(const char16_t *p) {
350
0
#ifdef U_ALIASING_BARRIER
351
0
    U_ALIASING_BARRIER(p);
352
0
#endif
353
0
    return reinterpret_cast<const OldUChar *>(p);
354
0
}
355
356
/**
357
 * Converts from char16_t * to OldUChar *.
358
 * Includes an aliasing barrier if available.
359
 * @param p pointer
360
 * @return p as OldUChar *
361
 * @stable ICU 59
362
 */
363
0
inline OldUChar *toOldUCharPtr(char16_t *p) {
364
0
#ifdef U_ALIASING_BARRIER
365
0
    U_ALIASING_BARRIER(p);
366
0
#endif
367
0
    return reinterpret_cast<OldUChar *>(p);
368
0
}
369
370
}  // U_ICU_NAMESPACE_OR_INTERNAL
371
372
#endif  // U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
373
374
// ICU DLL-exported
375
#if U_SHOW_CPLUSPLUS_API
376
377
U_NAMESPACE_BEGIN
378
379
#ifndef U_FORCE_HIDE_INTERNAL_API
380
/**
381
 * Is T convertible to a std::u16string_view or some other 16-bit string view?
382
 * @internal
383
 */
384
template<typename T>
385
constexpr bool ConvertibleToU16StringView =
386
    std::is_convertible_v<T, std::u16string_view>
387
#if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
388
    || std::is_convertible_v<T, std::basic_string_view<uint16_t>>
389
#endif
390
#if U_SIZEOF_WCHAR_T==2
391
    || std::is_convertible_v<T, std::wstring_view>
392
#endif
393
    ;
394
395
namespace internal {
396
/**
397
 * Pass-through overload.
398
 * @internal
399
 */
400
0
inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; }
401
402
#if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
403
/**
404
 * Basically undefined behavior but sometimes necessary conversion
405
 * from std::basic_string_view<uint16_t> to std::u16string_view.
406
 * @internal
407
 */
408
inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) {
409
    return { ConstChar16Ptr(sv.data()), sv.length() };
410
}
411
#endif
412
413
#if U_SIZEOF_WCHAR_T==2
414
/**
415
 * Basically undefined behavior but sometimes necessary conversion
416
 * from std::wstring_view to std::u16string_view.
417
 * @internal
418
 */
419
inline std::u16string_view toU16StringView(std::wstring_view sv) {
420
    return { ConstChar16Ptr(sv.data()), sv.length() };
421
}
422
#endif
423
424
/**
425
 * Pass-through overload.
426
 * @internal
427
 */
428
template <typename T,
429
          typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>>
430
inline std::u16string_view toU16StringViewNullable(const T& text) {
431
    return toU16StringView(text);
432
}
433
434
/**
435
 * In case of nullptr, return an empty view.
436
 * @internal
437
 */
438
template <typename T,
439
          typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>,
440
          typename = void>
441
inline std::u16string_view toU16StringViewNullable(const T& text) {
442
    if (text == nullptr) return {};  // For backward compatibility.
443
    return toU16StringView(text);
444
}
445
446
}  // internal
447
#endif  // U_FORCE_HIDE_INTERNAL_API
448
449
U_NAMESPACE_END
450
451
#endif  // U_SHOW_CPLUSPLUS_API
452
453
#endif  // __CHAR16PTR_H__