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