Home | History | Annotate | Download | only in unicode
      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