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
13 
14 #include <cstddef>
15 
16 /**
17  * \file
18  * \brief C++ API: char16_t pointer wrappers with
19  *        implicit conversion from bit-compatible raw pointer types.
20  *        Also conversion functions from char16_t * to UChar * and OldUChar *.
21  */
22 
23 U_NAMESPACE_BEGIN
24 
25 /**
26  * \def U_ALIASING_BARRIER
27  * Barrier for pointer anti-aliasing optimizations even across function boundaries.
28  * @internal
29  */
30 #ifdef U_ALIASING_BARRIER
31     // Use the predefined value.
32 #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
33 #   define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
34 #elif defined(U_IN_DOXYGEN)
35 #   define U_ALIASING_BARRIER(ptr)
36 #endif
37 
38 /**
39  * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
40  * @stable ICU 59
41  */
42 class U_COMMON_API Char16Ptr U_FINAL {
43 public:
44     /**
45      * Copies the pointer.
46      * @param p pointer
47      * @stable ICU 59
48      */
49     inline Char16Ptr(char16_t *p);
50 #if !U_CHAR16_IS_TYPEDEF
51     /**
52      * Converts the pointer to char16_t *.
53      * @param p pointer to be converted
54      * @stable ICU 59
55      */
56     inline Char16Ptr(uint16_t *p);
57 #endif
58 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
59     /**
60      * Converts the pointer to char16_t *.
61      * (Only defined if U_SIZEOF_WCHAR_T==2.)
62      * @param p pointer to be converted
63      * @stable ICU 59
64      */
65     inline Char16Ptr(wchar_t *p);
66 #endif
67     /**
68      * nullptr constructor.
69      * @param p nullptr
70      * @stable ICU 59
71      */
72     inline Char16Ptr(std::nullptr_t p);
73     /**
74      * Destructor.
75      * @stable ICU 59
76      */
77     inline ~Char16Ptr();
78 
79     /**
80      * Pointer access.
81      * @return the wrapped pointer
82      * @stable ICU 59
83      */
84     inline char16_t *get() const;
85     /**
86      * char16_t pointer access via type conversion (e.g., static_cast).
87      * @return the wrapped pointer
88      * @stable ICU 59
89      */
90     inline operator char16_t *() const { return get(); }
91 
92 private:
93     Char16Ptr() = delete;
94 
95 #ifdef U_ALIASING_BARRIER
cast(T * t)96     template<typename T> static char16_t *cast(T *t) {
97         U_ALIASING_BARRIER(t);
98         return reinterpret_cast<char16_t *>(t);
99     }
100 
101     char16_t *p_;
102 #else
103     union {
104         char16_t *cp;
105         uint16_t *up;
106         wchar_t *wp;
107     } u_;
108 #endif
109 };
110 
111 /// \cond
112 #ifdef U_ALIASING_BARRIER
113 
Char16Ptr(char16_t * p)114 Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
115 #if !U_CHAR16_IS_TYPEDEF
Char16Ptr(uint16_t * p)116 Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
117 #endif
118 #if U_SIZEOF_WCHAR_T==2
Char16Ptr(wchar_t * p)119 Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
120 #endif
Char16Ptr(std::nullptr_t p)121 Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
~Char16Ptr()122 Char16Ptr::~Char16Ptr() {
123     U_ALIASING_BARRIER(p_);
124 }
125 
get()126 char16_t *Char16Ptr::get() const { return p_; }
127 
128 #else
129 
Char16Ptr(char16_t * p)130 Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
131 #if !U_CHAR16_IS_TYPEDEF
Char16Ptr(uint16_t * p)132 Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
133 #endif
134 #if U_SIZEOF_WCHAR_T==2
Char16Ptr(wchar_t * p)135 Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
136 #endif
Char16Ptr(std::nullptr_t p)137 Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
~Char16Ptr()138 Char16Ptr::~Char16Ptr() {}
139 
get()140 char16_t *Char16Ptr::get() const { return u_.cp; }
141 
142 #endif
143 /// \endcond
144 
145 /**
146  * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
147  * @stable ICU 59
148  */
149 class U_COMMON_API ConstChar16Ptr U_FINAL {
150 public:
151     /**
152      * Copies the pointer.
153      * @param p pointer
154      * @stable ICU 59
155      */
156     inline ConstChar16Ptr(const char16_t *p);
157 #if !U_CHAR16_IS_TYPEDEF
158     /**
159      * Converts the pointer to char16_t *.
160      * @param p pointer to be converted
161      * @stable ICU 59
162      */
163     inline ConstChar16Ptr(const uint16_t *p);
164 #endif
165 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
166     /**
167      * Converts the pointer to char16_t *.
168      * (Only defined if U_SIZEOF_WCHAR_T==2.)
169      * @param p pointer to be converted
170      * @stable ICU 59
171      */
172     inline ConstChar16Ptr(const wchar_t *p);
173 #endif
174     /**
175      * nullptr constructor.
176      * @param p nullptr
177      * @stable ICU 59
178      */
179     inline ConstChar16Ptr(const std::nullptr_t p);
180 
181     /**
182      * Destructor.
183      * @stable ICU 59
184      */
185     inline ~ConstChar16Ptr();
186 
187     /**
188      * Pointer access.
189      * @return the wrapped pointer
190      * @stable ICU 59
191      */
192     inline const char16_t *get() const;
193     /**
194      * char16_t pointer access via type conversion (e.g., static_cast).
195      * @return the wrapped pointer
196      * @stable ICU 59
197      */
198     inline operator const char16_t *() const { return get(); }
199 
200 private:
201     ConstChar16Ptr() = delete;
202 
203 #ifdef U_ALIASING_BARRIER
cast(const T * t)204     template<typename T> static const char16_t *cast(const T *t) {
205         U_ALIASING_BARRIER(t);
206         return reinterpret_cast<const char16_t *>(t);
207     }
208 
209     const char16_t *p_;
210 #else
211     union {
212         const char16_t *cp;
213         const uint16_t *up;
214         const wchar_t *wp;
215     } u_;
216 #endif
217 };
218 
219 /// \cond
220 #ifdef U_ALIASING_BARRIER
221 
ConstChar16Ptr(const char16_t * p)222 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
223 #if !U_CHAR16_IS_TYPEDEF
ConstChar16Ptr(const uint16_t * p)224 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
225 #endif
226 #if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr(const wchar_t * p)227 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
228 #endif
ConstChar16Ptr(const std::nullptr_t p)229 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
~ConstChar16Ptr()230 ConstChar16Ptr::~ConstChar16Ptr() {
231     U_ALIASING_BARRIER(p_);
232 }
233 
get()234 const char16_t *ConstChar16Ptr::get() const { return p_; }
235 
236 #else
237 
ConstChar16Ptr(const char16_t * p)238 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
239 #if !U_CHAR16_IS_TYPEDEF
ConstChar16Ptr(const uint16_t * p)240 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
241 #endif
242 #if U_SIZEOF_WCHAR_T==2
ConstChar16Ptr(const wchar_t * p)243 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
244 #endif
ConstChar16Ptr(const std::nullptr_t p)245 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
~ConstChar16Ptr()246 ConstChar16Ptr::~ConstChar16Ptr() {}
247 
get()248 const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
249 
250 #endif
251 /// \endcond
252 
253 /**
254  * Converts from const char16_t * to const UChar *.
255  * Includes an aliasing barrier if available.
256  * @param p pointer
257  * @return p as const UChar *
258  * @stable ICU 59
259  */
toUCharPtr(const char16_t * p)260 inline const UChar *toUCharPtr(const char16_t *p) {
261 #ifdef U_ALIASING_BARRIER
262     U_ALIASING_BARRIER(p);
263 #endif
264     return reinterpret_cast<const UChar *>(p);
265 }
266 
267 /**
268  * Converts from char16_t * to UChar *.
269  * Includes an aliasing barrier if available.
270  * @param p pointer
271  * @return p as UChar *
272  * @stable ICU 59
273  */
toUCharPtr(char16_t * p)274 inline UChar *toUCharPtr(char16_t *p) {
275 #ifdef U_ALIASING_BARRIER
276     U_ALIASING_BARRIER(p);
277 #endif
278     return reinterpret_cast<UChar *>(p);
279 }
280 
281 /**
282  * Converts from const char16_t * to const OldUChar *.
283  * Includes an aliasing barrier if available.
284  * @param p pointer
285  * @return p as const OldUChar *
286  * @stable ICU 59
287  */
toOldUCharPtr(const char16_t * p)288 inline const OldUChar *toOldUCharPtr(const char16_t *p) {
289 #ifdef U_ALIASING_BARRIER
290     U_ALIASING_BARRIER(p);
291 #endif
292     return reinterpret_cast<const OldUChar *>(p);
293 }
294 
295 /**
296  * Converts from char16_t * to OldUChar *.
297  * Includes an aliasing barrier if available.
298  * @param p pointer
299  * @return p as OldUChar *
300  * @stable ICU 59
301  */
toOldUCharPtr(char16_t * p)302 inline OldUChar *toOldUCharPtr(char16_t *p) {
303 #ifdef U_ALIASING_BARRIER
304     U_ALIASING_BARRIER(p);
305 #endif
306     return reinterpret_cast<OldUChar *>(p);
307 }
308 
309 U_NAMESPACE_END
310 
311 #endif /* U_SHOW_CPLUSPLUS_API */
312 
313 #endif  // __CHAR16PTR_H__
314