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 LIBICU_U_SHOW_CPLUSPLUS_API
13
14 #include <cstddef>
15 #include <string_view>
16
17 /**
18 * @addtogroup icu4c ICU4C
19 * @{
20 * \file
21 * \brief C++ API: char16_t pointer wrappers with
22 * implicit conversion from bit-compatible raw pointer types.
23 * Also conversion functions from char16_t * to UChar * and OldUChar *.
24 */
25
26 U_NAMESPACE_BEGIN
27
28 /**
29 * \def U_ALIASING_BARRIER
30 * Barrier for pointer anti-aliasing optimizations even across function boundaries.
31 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
32 */
33 #ifdef U_ALIASING_BARRIER
34 // Use the predefined value.
35 #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
36 # define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
37 #elif defined(U_IN_DOXYGEN)
38 # define U_ALIASING_BARRIER(ptr)
39 #endif
40
41 /**
42 * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
43 * \xrefitem stable "Stable" "Stable List" ICU 59
44 */
45 class U_COMMON_API Char16Ptr final {
46 public:
47 /**
48 * Copies the pointer.
49 * @param p pointer
50 * \xrefitem stable "Stable" "Stable List" ICU 59
51 */
52 inline Char16Ptr(char16_t *p);
53 #if !U_CHAR16_IS_TYPEDEF
54 /**
55 * Converts the pointer to char16_t *.
56 * @param p pointer to be converted
57 * \xrefitem stable "Stable" "Stable List" ICU 59
58 */
59 inline Char16Ptr(uint16_t *p);
60 #endif
61 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
62 /**
63 * Converts the pointer to char16_t *.
64 * (Only defined if U_SIZEOF_WCHAR_T==2.)
65 * @param p pointer to be converted
66 * \xrefitem stable "Stable" "Stable List" ICU 59
67 */
68 inline Char16Ptr(wchar_t *p);
69 #endif
70 /**
71 * nullptr constructor.
72 * @param p nullptr
73 * \xrefitem stable "Stable" "Stable List" ICU 59
74 */
75 inline Char16Ptr(std::nullptr_t p);
76 /**
77 * Destructor.
78 * \xrefitem stable "Stable" "Stable List" ICU 59
79 */
80 inline ~Char16Ptr();
81
82 /**
83 * Pointer access.
84 * @return the wrapped pointer
85 * \xrefitem stable "Stable" "Stable List" ICU 59
86 */
87 inline char16_t *get() const;
88 /**
89 * char16_t pointer access via type conversion (e.g., static_cast).
90 * @return the wrapped pointer
91 * \xrefitem stable "Stable" "Stable List" ICU 59
92 */
93 inline operator char16_t *() const { return get(); }
94
95 private:
96 Char16Ptr() = delete;
97
98 #ifdef U_ALIASING_BARRIER
cast(T * t)99 template<typename T> static char16_t *cast(T *t) {
100 U_ALIASING_BARRIER(t);
101 return reinterpret_cast<char16_t *>(t);
102 }
103
104 char16_t *p_;
105 #else
106 union {
107 char16_t *cp;
108 uint16_t *up;
109 wchar_t *wp;
110 } u_;
111 #endif
112 };
113
114 /// \cond
115 #ifdef U_ALIASING_BARRIER
116
Char16Ptr(char16_t * p)117 Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
118 #if !U_CHAR16_IS_TYPEDEF
Char16Ptr(uint16_t * p)119 Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
120 #endif
121 #if U_SIZEOF_WCHAR_T==2
Char16Ptr(wchar_t * p)122 Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
123 #endif
Char16Ptr(std::nullptr_t p)124 Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
~Char16Ptr()125 Char16Ptr::~Char16Ptr() {
126 U_ALIASING_BARRIER(p_);
127 }
128
get()129 char16_t *Char16Ptr::get() const { return p_; }
130
131 #else
132
Char16Ptr(char16_t * p)133 Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
134 #if !U_CHAR16_IS_TYPEDEF
Char16Ptr(uint16_t * p)135 Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
136 #endif
137 #if U_SIZEOF_WCHAR_T==2
Char16Ptr(wchar_t * p)138 Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
139 #endif
Char16Ptr(std::nullptr_t p)140 Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
~Char16Ptr()141 Char16Ptr::~Char16Ptr() {}
142
get()143 char16_t *Char16Ptr::get() const { return u_.cp; }
144
145 #endif
146 /// \endcond
147
148 /**
149 * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
150 * \xrefitem stable "Stable" "Stable List" ICU 59
151 */
152 class U_COMMON_API ConstChar16Ptr final {
153 public:
154 /**
155 * Copies the pointer.
156 * @param p pointer
157 * \xrefitem stable "Stable" "Stable List" ICU 59
158 */
159 inline ConstChar16Ptr(const char16_t *p);
160 #if !U_CHAR16_IS_TYPEDEF
161 /**
162 * Converts the pointer to char16_t *.
163 * @param p pointer to be converted
164 * \xrefitem stable "Stable" "Stable List" ICU 59
165 */
166 inline ConstChar16Ptr(const uint16_t *p);
167 #endif
168 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
169 /**
170 * Converts the pointer to char16_t *.
171 * (Only defined if U_SIZEOF_WCHAR_T==2.)
172 * @param p pointer to be converted
173 * \xrefitem stable "Stable" "Stable List" ICU 59
174 */
175 inline ConstChar16Ptr(const wchar_t *p);
176 #endif
177 /**
178 * nullptr constructor.
179 * @param p nullptr
180 * \xrefitem stable "Stable" "Stable List" ICU 59
181 */
182 inline ConstChar16Ptr(const std::nullptr_t p);
183
184 /**
185 * Destructor.
186 * \xrefitem stable "Stable" "Stable List" ICU 59
187 */
188 inline ~ConstChar16Ptr();
189
190 /**
191 * Pointer access.
192 * @return the wrapped pointer
193 * \xrefitem stable "Stable" "Stable List" ICU 59
194 */
195 inline const char16_t *get() const;
196 /**
197 * char16_t pointer access via type conversion (e.g., static_cast).
198 * @return the wrapped pointer
199 * \xrefitem stable "Stable" "Stable List" ICU 59
200 */
201 inline operator const char16_t *() const { return get(); }
202
203 private:
204 ConstChar16Ptr() = delete;
205
206 #ifdef U_ALIASING_BARRIER
cast(const T * t)207 template<typename T> static const char16_t *cast(const T *t) {
208 U_ALIASING_BARRIER(t);
209 return reinterpret_cast<const char16_t *>(t);
210 }
211
212 const char16_t *p_;
213 #else
214 union {
215 const char16_t *cp;
216 const uint16_t *up;
217 const wchar_t *wp;
218 } u_;
219 #endif
220 };
221
222 /// \cond
223 #ifdef U_ALIASING_BARRIER
224
ConstChar16Ptr(const char16_t * p)225 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
226 #if !U_CHAR16_IS_TYPEDEF
ConstChar16Ptr(const uint16_t * p)227 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
228 #endif
229 #if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr(const wchar_t * p)230 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
231 #endif
ConstChar16Ptr(const std::nullptr_t p)232 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
~ConstChar16Ptr()233 ConstChar16Ptr::~ConstChar16Ptr() {
234 U_ALIASING_BARRIER(p_);
235 }
236
get()237 const char16_t *ConstChar16Ptr::get() const { return p_; }
238
239 #else
240
ConstChar16Ptr(const char16_t * p)241 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
242 #if !U_CHAR16_IS_TYPEDEF
ConstChar16Ptr(const uint16_t * p)243 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
244 #endif
245 #if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr(const wchar_t * p)246 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
247 #endif
ConstChar16Ptr(const std::nullptr_t p)248 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
~ConstChar16Ptr()249 ConstChar16Ptr::~ConstChar16Ptr() {}
250
get()251 const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
252
253 #endif
254 /// \endcond
255
256 /**
257 * Converts from const char16_t * to const UChar *.
258 * Includes an aliasing barrier if available.
259 * @param p pointer
260 * @return p as const UChar *
261 * \xrefitem stable "Stable" "Stable List" ICU 59
262 */
toUCharPtr(const char16_t * p)263 inline const UChar *toUCharPtr(const char16_t *p) {
264 #ifdef U_ALIASING_BARRIER
265 U_ALIASING_BARRIER(p);
266 #endif
267 return reinterpret_cast<const UChar *>(p);
268 }
269
270 /**
271 * Converts from char16_t * to UChar *.
272 * Includes an aliasing barrier if available.
273 * @param p pointer
274 * @return p as UChar *
275 * \xrefitem stable "Stable" "Stable List" ICU 59
276 */
toUCharPtr(char16_t * p)277 inline UChar *toUCharPtr(char16_t *p) {
278 #ifdef U_ALIASING_BARRIER
279 U_ALIASING_BARRIER(p);
280 #endif
281 return reinterpret_cast<UChar *>(p);
282 }
283
284 /**
285 * Converts from const char16_t * to const OldUChar *.
286 * Includes an aliasing barrier if available.
287 * @param p pointer
288 * @return p as const OldUChar *
289 * \xrefitem stable "Stable" "Stable List" ICU 59
290 */
toOldUCharPtr(const char16_t * p)291 inline const OldUChar *toOldUCharPtr(const char16_t *p) {
292 #ifdef U_ALIASING_BARRIER
293 U_ALIASING_BARRIER(p);
294 #endif
295 return reinterpret_cast<const OldUChar *>(p);
296 }
297
298 /**
299 * Converts from char16_t * to OldUChar *.
300 * Includes an aliasing barrier if available.
301 * @param p pointer
302 * @return p as OldUChar *
303 * \xrefitem stable "Stable" "Stable List" ICU 59
304 */
toOldUCharPtr(char16_t * p)305 inline OldUChar *toOldUCharPtr(char16_t *p) {
306 #ifdef U_ALIASING_BARRIER
307 U_ALIASING_BARRIER(p);
308 #endif
309 return reinterpret_cast<OldUChar *>(p);
310 }
311
312 #ifndef U_FORCE_HIDE_INTERNAL_API
313 /**
314 * Is T convertible to a std::u16string_view or some other 16-bit string view?
315 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
316 */
317 template<typename T>
318 constexpr bool ConvertibleToU16StringView =
319 std::is_convertible_v<T, std::u16string_view>
320 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
321 || std::is_convertible_v<T, std::basic_string_view<uint16_t>>
322 #endif
323 #if U_SIZEOF_WCHAR_T==2
324 || std::is_convertible_v<T, std::wstring_view>
325 #endif
326 ;
327
328 namespace internal {
329 /**
330 * Pass-through overload.
331 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
332 */
toU16StringView(std::u16string_view sv)333 inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; }
334
335 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
336 /**
337 * Basically undefined behavior but sometimes necessary conversion
338 * from std::basic_string_view<uint16_t> to std::u16string_view.
339 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
340 */
toU16StringView(std::basic_string_view<uint16_t> sv)341 inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) {
342 return { ConstChar16Ptr(sv.data()), sv.length() };
343 }
344 #endif
345
346 #if U_SIZEOF_WCHAR_T==2
347 /**
348 * Basically undefined behavior but sometimes necessary conversion
349 * from std::wstring_view to std::u16string_view.
350 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
351 */
toU16StringView(std::wstring_view sv)352 inline std::u16string_view toU16StringView(std::wstring_view sv) {
353 return { ConstChar16Ptr(sv.data()), sv.length() };
354 }
355 #endif
356
357 /**
358 * Pass-through overload.
359 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
360 */
361 template <typename T,
362 typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>>
toU16StringViewNullable(const T & text)363 inline std::u16string_view toU16StringViewNullable(const T& text) {
364 return toU16StringView(text);
365 }
366
367 /**
368 * In case of nullptr, return an empty view.
369 * \xrefitem internal "Internal" "Internal List" Do not use. This API is for internal use only.
370 */
371 template <typename T,
372 typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>,
373 typename = void>
toU16StringViewNullable(const T & text)374 inline std::u16string_view toU16StringViewNullable(const T& text) {
375 if (text == nullptr) return {}; // For backward compatibility.
376 return toU16StringView(text);
377 }
378
379 } // internal
380 #endif // U_FORCE_HIDE_INTERNAL_API
381
382 U_NAMESPACE_END
383
384 #endif /* LIBICU_U_SHOW_CPLUSPLUS_API */
385
386 #endif // __CHAR16PTR_H__
387
388 /** @} */ // addtogroup
389