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 20 U_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 */ 39 class U_COMMON_API Char16Ptr U_FINAL { 40 public: 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 89 private: 90 Char16Ptr() = delete; 91 92 #ifdef U_ALIASING_BARRIER cast(T * t)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 Char16Ptr(char16_t * p)111Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {} 112 #if !U_CHAR16_IS_TYPEDEF Char16Ptr(uint16_t * p)113Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {} 114 #endif 115 #if U_SIZEOF_WCHAR_T==2 Char16Ptr(wchar_t * p)116Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {} 117 #endif Char16Ptr(std::nullptr_t p)118Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {} ~Char16Ptr()119Char16Ptr::~Char16Ptr() { 120 U_ALIASING_BARRIER(p_); 121 } 122 get()123char16_t *Char16Ptr::get() const { return p_; } 124 125 #else 126 Char16Ptr(char16_t * p)127Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; } 128 #if !U_CHAR16_IS_TYPEDEF Char16Ptr(uint16_t * p)129Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; } 130 #endif 131 #if U_SIZEOF_WCHAR_T==2 Char16Ptr(wchar_t * p)132Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; } 133 #endif Char16Ptr(std::nullptr_t p)134Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; } ~Char16Ptr()135Char16Ptr::~Char16Ptr() {} 136 get()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 */ 146 class U_COMMON_API ConstChar16Ptr U_FINAL { 147 public: 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 197 private: 198 ConstChar16Ptr() = delete; 199 200 #ifdef U_ALIASING_BARRIER cast(const T * t)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 ConstChar16Ptr(const char16_t * p)219ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {} 220 #if !U_CHAR16_IS_TYPEDEF ConstChar16Ptr(const uint16_t * p)221ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {} 222 #endif 223 #if U_SIZEOF_WCHAR_T==2 ConstChar16Ptr(const wchar_t * p)224ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {} 225 #endif ConstChar16Ptr(const std::nullptr_t p)226ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {} ~ConstChar16Ptr()227ConstChar16Ptr::~ConstChar16Ptr() { 228 U_ALIASING_BARRIER(p_); 229 } 230 get()231const char16_t *ConstChar16Ptr::get() const { return p_; } 232 233 #else 234 ConstChar16Ptr(const char16_t * p)235ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; } 236 #if !U_CHAR16_IS_TYPEDEF ConstChar16Ptr(const uint16_t * p)237ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; } 238 #endif 239 #if U_SIZEOF_WCHAR_T==2 ConstChar16Ptr(const wchar_t * p)240ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; } 241 #endif ConstChar16Ptr(const std::nullptr_t p)242ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; } ~ConstChar16Ptr()243ConstChar16Ptr::~ConstChar16Ptr() {} 244 get()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 */ toUCharPtr(const char16_t * p)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 */ toUCharPtr(char16_t * p)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 */ toOldUCharPtr(const char16_t * p)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 */ toOldUCharPtr(char16_t * p)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 306 U_NAMESPACE_END 307 308 #endif // __CHAR16PTR_H__ 309