• 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 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