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