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)114Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {} 115 #if !U_CHAR16_IS_TYPEDEF Char16Ptr(uint16_t * p)116Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {} 117 #endif 118 #if U_SIZEOF_WCHAR_T==2 Char16Ptr(wchar_t * p)119Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {} 120 #endif Char16Ptr(std::nullptr_t p)121Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {} ~Char16Ptr()122Char16Ptr::~Char16Ptr() { 123 U_ALIASING_BARRIER(p_); 124 } 125 get()126char16_t *Char16Ptr::get() const { return p_; } 127 128 #else 129 Char16Ptr(char16_t * p)130Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; } 131 #if !U_CHAR16_IS_TYPEDEF Char16Ptr(uint16_t * p)132Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; } 133 #endif 134 #if U_SIZEOF_WCHAR_T==2 Char16Ptr(wchar_t * p)135Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; } 136 #endif Char16Ptr(std::nullptr_t p)137Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; } ~Char16Ptr()138Char16Ptr::~Char16Ptr() {} 139 get()140char16_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)222ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {} 223 #if !U_CHAR16_IS_TYPEDEF ConstChar16Ptr(const uint16_t * p)224ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {} 225 #endif 226 #if U_SIZEOF_WCHAR_T==2 ConstChar16Ptr(const wchar_t * p)227ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {} 228 #endif ConstChar16Ptr(const std::nullptr_t p)229ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {} ~ConstChar16Ptr()230ConstChar16Ptr::~ConstChar16Ptr() { 231 U_ALIASING_BARRIER(p_); 232 } 233 get()234const char16_t *ConstChar16Ptr::get() const { return p_; } 235 236 #else 237 ConstChar16Ptr(const char16_t * p)238ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; } 239 #if !U_CHAR16_IS_TYPEDEF ConstChar16Ptr(const uint16_t * p)240ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; } 241 #endif 242 #if U_SIZEOF_WCHAR_T==2 ConstChar16Ptr(const wchar_t * p)243ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; } 244 #endif ConstChar16Ptr(const std::nullptr_t p)245ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; } ~ConstChar16Ptr()246ConstChar16Ptr::~ConstChar16Ptr() {} 247 get()248const 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)260inline 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)274inline 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)288inline 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)302inline 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