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