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