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#endif
32
33// Do not use #ifndef U_HIDE_DRAFT_API for the following class, it
34// is now used in place of UChar* in several stable C++ methods
35/**
36 * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
37 * @draft ICU 59
38 */
39class U_COMMON_API Char16Ptr U_FINAL {
40public:
41 /**
42 * Copies the pointer.
43 * @param p pointer
44 * @draft 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 * @draft 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 * @draft ICU 59
61 */
62 inline Char16Ptr(wchar_t *p);
63#endif
64 /**
65 * nullptr constructor.
66 * @param p nullptr
67 * @draft ICU 59
68 */
69 inline Char16Ptr(std::nullptr_t p);
70 /**
71 * Destructor.
72 * @draft ICU 59
73 */
74 inline ~Char16Ptr();
75
76 /**
77 * Pointer access.
78 * @return the wrapped pointer
79 * @draft 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 * @draft 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#ifdef U_ALIASING_BARRIER
109
110Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
111#if !U_CHAR16_IS_TYPEDEF
112Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
113#endif
114#if U_SIZEOF_WCHAR_T==2
115Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
116#endif
117Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
118Char16Ptr::~Char16Ptr() {
119 U_ALIASING_BARRIER(p_);
120}
121
122char16_t *Char16Ptr::get() const { return p_; }
123
124#else
125
126Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
127#if !U_CHAR16_IS_TYPEDEF
128Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
129#endif
130#if U_SIZEOF_WCHAR_T==2
131Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
132#endif
133Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
134Char16Ptr::~Char16Ptr() {}
135
136char16_t *Char16Ptr::get() const { return u_.cp; }
137
138#endif
139
140// Do not use #ifndef U_HIDE_DRAFT_API for the following class, it is
141// now used in place of const UChar* in several stable C++ methods
142/**
143 * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
144 * @draft ICU 59
145 */
146class U_COMMON_API ConstChar16Ptr U_FINAL {
147public:
148 /**
149 * Copies the pointer.
150 * @param p pointer
151 * @draft 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 * @draft 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 * @draft ICU 59
168 */
169 inline ConstChar16Ptr(const wchar_t *p);
170#endif
171 /**
172 * nullptr constructor.
173 * @param p nullptr
174 * @draft ICU 59
175 */
176 inline ConstChar16Ptr(const std::nullptr_t p);
177
178 /**
179 * Destructor.
180 * @draft ICU 59
181 */
182 inline ~ConstChar16Ptr();
183
184 /**
185 * Pointer access.
186 * @return the wrapped pointer
187 * @draft 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 * @draft 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#ifdef U_ALIASING_BARRIER
217
218ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
219#if !U_CHAR16_IS_TYPEDEF
220ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
221#endif
222#if U_SIZEOF_WCHAR_T==2
223ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
224#endif
225ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
226ConstChar16Ptr::~ConstChar16Ptr() {
227 U_ALIASING_BARRIER(p_);
228}
229
230const char16_t *ConstChar16Ptr::get() const { return p_; }
231
232#else
233
234ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
235#if !U_CHAR16_IS_TYPEDEF
236ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
237#endif
238#if U_SIZEOF_WCHAR_T==2
239ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
240#endif
241ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
242ConstChar16Ptr::~ConstChar16Ptr() {}
243
244const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
245
246#endif
247
248/**
249 * Converts from const char16_t * to const UChar *.
250 * Includes an aliasing barrier if available.
251 * @param p pointer
252 * @return p as const UChar *
253 * @draft ICU 59
254 */
255inline const UChar *toUCharPtr(const char16_t *p) {
256#ifdef U_ALIASING_BARRIER
257 U_ALIASING_BARRIER(p);
258#endif
259 return reinterpret_cast<const UChar *>(p);
260}
261
262/**
263 * Converts from char16_t * to UChar *.
264 * Includes an aliasing barrier if available.
265 * @param p pointer
266 * @return p as UChar *
267 * @draft ICU 59
268 */
269inline UChar *toUCharPtr(char16_t *p) {
270#ifdef U_ALIASING_BARRIER
271 U_ALIASING_BARRIER(p);
272#endif
273 return reinterpret_cast<UChar *>(p);
274}
275
276/**
277 * Converts from const char16_t * to const OldUChar *.
278 * Includes an aliasing barrier if available.
279 * @param p pointer
280 * @return p as const OldUChar *
281 * @draft ICU 59
282 */
283inline const OldUChar *toOldUCharPtr(const char16_t *p) {
284#ifdef U_ALIASING_BARRIER
285 U_ALIASING_BARRIER(p);
286#endif
287 return reinterpret_cast<const OldUChar *>(p);
288}
289
290/**
291 * Converts from char16_t * to OldUChar *.
292 * Includes an aliasing barrier if available.
293 * @param p pointer
294 * @return p as OldUChar *
295 * @draft ICU 59
296 */
297inline OldUChar *toOldUCharPtr(char16_t *p) {
298#ifdef U_ALIASING_BARRIER
299 U_ALIASING_BARRIER(p);
300#endif
301 return reinterpret_cast<OldUChar *>(p);
302}
303
304U_NAMESPACE_END
305
306#endif // __CHAR16PTR_H__
307