jpayne@69: // © 2017 and later: Unicode, Inc. and others. jpayne@69: // License & terms of use: http://www.unicode.org/copyright.html jpayne@69: jpayne@69: // char16ptr.h jpayne@69: // created: 2017feb28 Markus W. Scherer jpayne@69: jpayne@69: #ifndef __CHAR16PTR_H__ jpayne@69: #define __CHAR16PTR_H__ jpayne@69: jpayne@69: #include "unicode/utypes.h" jpayne@69: jpayne@69: #if U_SHOW_CPLUSPLUS_API jpayne@69: jpayne@69: #include jpayne@69: jpayne@69: /** jpayne@69: * \file jpayne@69: * \brief C++ API: char16_t pointer wrappers with jpayne@69: * implicit conversion from bit-compatible raw pointer types. jpayne@69: * Also conversion functions from char16_t * to UChar * and OldUChar *. jpayne@69: */ jpayne@69: jpayne@69: U_NAMESPACE_BEGIN jpayne@69: jpayne@69: /** jpayne@69: * \def U_ALIASING_BARRIER jpayne@69: * Barrier for pointer anti-aliasing optimizations even across function boundaries. jpayne@69: * @internal jpayne@69: */ jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: // Use the predefined value. jpayne@69: #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT jpayne@69: # define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory") jpayne@69: #elif defined(U_IN_DOXYGEN) jpayne@69: # define U_ALIASING_BARRIER(ptr) jpayne@69: #endif jpayne@69: jpayne@69: /** jpayne@69: * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types. jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: class U_COMMON_API Char16Ptr U_FINAL { jpayne@69: public: jpayne@69: /** jpayne@69: * Copies the pointer. jpayne@69: * @param p pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline Char16Ptr(char16_t *p); jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: /** jpayne@69: * Converts the pointer to char16_t *. jpayne@69: * @param p pointer to be converted jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline Char16Ptr(uint16_t *p); jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) jpayne@69: /** jpayne@69: * Converts the pointer to char16_t *. jpayne@69: * (Only defined if U_SIZEOF_WCHAR_T==2.) jpayne@69: * @param p pointer to be converted jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline Char16Ptr(wchar_t *p); jpayne@69: #endif jpayne@69: /** jpayne@69: * nullptr constructor. jpayne@69: * @param p nullptr jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline Char16Ptr(std::nullptr_t p); jpayne@69: /** jpayne@69: * Destructor. jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ~Char16Ptr(); jpayne@69: jpayne@69: /** jpayne@69: * Pointer access. jpayne@69: * @return the wrapped pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline char16_t *get() const; jpayne@69: /** jpayne@69: * char16_t pointer access via type conversion (e.g., static_cast). jpayne@69: * @return the wrapped pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline operator char16_t *() const { return get(); } jpayne@69: jpayne@69: private: jpayne@69: Char16Ptr() = delete; jpayne@69: jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: template static char16_t *cast(T *t) { jpayne@69: U_ALIASING_BARRIER(t); jpayne@69: return reinterpret_cast(t); jpayne@69: } jpayne@69: jpayne@69: char16_t *p_; jpayne@69: #else jpayne@69: union { jpayne@69: char16_t *cp; jpayne@69: uint16_t *up; jpayne@69: wchar_t *wp; jpayne@69: } u_; jpayne@69: #endif jpayne@69: }; jpayne@69: jpayne@69: /// \cond jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: jpayne@69: Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {} jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {} jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 jpayne@69: Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {} jpayne@69: #endif jpayne@69: Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {} jpayne@69: Char16Ptr::~Char16Ptr() { jpayne@69: U_ALIASING_BARRIER(p_); jpayne@69: } jpayne@69: jpayne@69: char16_t *Char16Ptr::get() const { return p_; } jpayne@69: jpayne@69: #else jpayne@69: jpayne@69: Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; } jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; } jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 jpayne@69: Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; } jpayne@69: #endif jpayne@69: Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; } jpayne@69: Char16Ptr::~Char16Ptr() {} jpayne@69: jpayne@69: char16_t *Char16Ptr::get() const { return u_.cp; } jpayne@69: jpayne@69: #endif jpayne@69: /// \endcond jpayne@69: jpayne@69: /** jpayne@69: * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types. jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: class U_COMMON_API ConstChar16Ptr U_FINAL { jpayne@69: public: jpayne@69: /** jpayne@69: * Copies the pointer. jpayne@69: * @param p pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ConstChar16Ptr(const char16_t *p); jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: /** jpayne@69: * Converts the pointer to char16_t *. jpayne@69: * @param p pointer to be converted jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ConstChar16Ptr(const uint16_t *p); jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN) jpayne@69: /** jpayne@69: * Converts the pointer to char16_t *. jpayne@69: * (Only defined if U_SIZEOF_WCHAR_T==2.) jpayne@69: * @param p pointer to be converted jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ConstChar16Ptr(const wchar_t *p); jpayne@69: #endif jpayne@69: /** jpayne@69: * nullptr constructor. jpayne@69: * @param p nullptr jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ConstChar16Ptr(const std::nullptr_t p); jpayne@69: jpayne@69: /** jpayne@69: * Destructor. jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline ~ConstChar16Ptr(); jpayne@69: jpayne@69: /** jpayne@69: * Pointer access. jpayne@69: * @return the wrapped pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline const char16_t *get() const; jpayne@69: /** jpayne@69: * char16_t pointer access via type conversion (e.g., static_cast). jpayne@69: * @return the wrapped pointer jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline operator const char16_t *() const { return get(); } jpayne@69: jpayne@69: private: jpayne@69: ConstChar16Ptr() = delete; jpayne@69: jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: template static const char16_t *cast(const T *t) { jpayne@69: U_ALIASING_BARRIER(t); jpayne@69: return reinterpret_cast(t); jpayne@69: } jpayne@69: jpayne@69: const char16_t *p_; jpayne@69: #else jpayne@69: union { jpayne@69: const char16_t *cp; jpayne@69: const uint16_t *up; jpayne@69: const wchar_t *wp; jpayne@69: } u_; jpayne@69: #endif jpayne@69: }; jpayne@69: jpayne@69: /// \cond jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {} jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {} jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {} jpayne@69: #endif jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {} jpayne@69: ConstChar16Ptr::~ConstChar16Ptr() { jpayne@69: U_ALIASING_BARRIER(p_); jpayne@69: } jpayne@69: jpayne@69: const char16_t *ConstChar16Ptr::get() const { return p_; } jpayne@69: jpayne@69: #else jpayne@69: jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; } jpayne@69: #if !U_CHAR16_IS_TYPEDEF jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; } jpayne@69: #endif jpayne@69: #if U_SIZEOF_WCHAR_T==2 jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; } jpayne@69: #endif jpayne@69: ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; } jpayne@69: ConstChar16Ptr::~ConstChar16Ptr() {} jpayne@69: jpayne@69: const char16_t *ConstChar16Ptr::get() const { return u_.cp; } jpayne@69: jpayne@69: #endif jpayne@69: /// \endcond jpayne@69: jpayne@69: /** jpayne@69: * Converts from const char16_t * to const UChar *. jpayne@69: * Includes an aliasing barrier if available. jpayne@69: * @param p pointer jpayne@69: * @return p as const UChar * jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline const UChar *toUCharPtr(const char16_t *p) { jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: U_ALIASING_BARRIER(p); jpayne@69: #endif jpayne@69: return reinterpret_cast(p); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Converts from char16_t * to UChar *. jpayne@69: * Includes an aliasing barrier if available. jpayne@69: * @param p pointer jpayne@69: * @return p as UChar * jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline UChar *toUCharPtr(char16_t *p) { jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: U_ALIASING_BARRIER(p); jpayne@69: #endif jpayne@69: return reinterpret_cast(p); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Converts from const char16_t * to const OldUChar *. jpayne@69: * Includes an aliasing barrier if available. jpayne@69: * @param p pointer jpayne@69: * @return p as const OldUChar * jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline const OldUChar *toOldUCharPtr(const char16_t *p) { jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: U_ALIASING_BARRIER(p); jpayne@69: #endif jpayne@69: return reinterpret_cast(p); jpayne@69: } jpayne@69: jpayne@69: /** jpayne@69: * Converts from char16_t * to OldUChar *. jpayne@69: * Includes an aliasing barrier if available. jpayne@69: * @param p pointer jpayne@69: * @return p as OldUChar * jpayne@69: * @stable ICU 59 jpayne@69: */ jpayne@69: inline OldUChar *toOldUCharPtr(char16_t *p) { jpayne@69: #ifdef U_ALIASING_BARRIER jpayne@69: U_ALIASING_BARRIER(p); jpayne@69: #endif jpayne@69: return reinterpret_cast(p); jpayne@69: } jpayne@69: jpayne@69: U_NAMESPACE_END jpayne@69: jpayne@69: #endif /* U_SHOW_CPLUSPLUS_API */ jpayne@69: jpayne@69: #endif // __CHAR16PTR_H__