tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

char16ptr.h (11045B)


      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 "unicode/utypes.h"
     11 
     12 #if U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
     13 
     14 #include <cstddef>
     15 #include <string_view>
     16 #include <type_traits>
     17 
     18 #endif
     19 
     20 /**
     21 * \file
     22 * \brief C++ API: char16_t pointer wrappers with
     23 *        implicit conversion from bit-compatible raw pointer types.
     24 *        Also conversion functions from char16_t * to UChar * and OldUChar *.
     25 */
     26 
     27 /**
     28 * \def U_ALIASING_BARRIER
     29 * Barrier for pointer anti-aliasing optimizations even across function boundaries.
     30 * @internal
     31 */
     32 #ifdef U_ALIASING_BARRIER
     33    // Use the predefined value.
     34 #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
     35 #   define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
     36 #elif defined(U_IN_DOXYGEN)
     37 #   define U_ALIASING_BARRIER(ptr)
     38 #endif
     39 
     40 // ICU DLL-exported
     41 #if U_SHOW_CPLUSPLUS_API
     42 
     43 U_NAMESPACE_BEGIN
     44 
     45 /**
     46 * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
     47 * @stable ICU 59
     48 */
     49 class U_COMMON_API Char16Ptr final {
     50 public:
     51    /**
     52     * Copies the pointer.
     53     * @param p pointer
     54     * @stable ICU 59
     55     */
     56    inline Char16Ptr(char16_t *p);
     57 #if !U_CHAR16_IS_TYPEDEF
     58    /**
     59     * Converts the pointer to char16_t *.
     60     * @param p pointer to be converted
     61     * @stable ICU 59
     62     */
     63    inline Char16Ptr(uint16_t *p);
     64 #endif
     65 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
     66    /**
     67     * Converts the pointer to char16_t *.
     68     * (Only defined if U_SIZEOF_WCHAR_T==2.)
     69     * @param p pointer to be converted
     70     * @stable ICU 59
     71     */
     72    inline Char16Ptr(wchar_t *p);
     73 #endif
     74    /**
     75     * nullptr constructor.
     76     * @param p nullptr
     77     * @stable ICU 59
     78     */
     79    inline Char16Ptr(std::nullptr_t p);
     80    /**
     81     * Destructor.
     82     * @stable ICU 59
     83     */
     84    inline ~Char16Ptr();
     85 
     86    /**
     87     * Pointer access.
     88     * @return the wrapped pointer
     89     * @stable ICU 59
     90     */
     91    inline char16_t *get() const;
     92    /**
     93     * char16_t pointer access via type conversion (e.g., static_cast).
     94     * @return the wrapped pointer
     95     * @stable ICU 59
     96     */
     97    inline operator char16_t *() const { return get(); }
     98 
     99 private:
    100    Char16Ptr() = delete;
    101 
    102 #ifdef U_ALIASING_BARRIER
    103    template<typename T> static char16_t *cast(T *t) {
    104        U_ALIASING_BARRIER(t);
    105        return reinterpret_cast<char16_t *>(t);
    106    }
    107 
    108    char16_t *p_;
    109 #else
    110    union {
    111        char16_t *cp;
    112        uint16_t *up;
    113        wchar_t *wp;
    114    } u_;
    115 #endif
    116 };
    117 
    118 /// \cond
    119 #ifdef U_ALIASING_BARRIER
    120 
    121 Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
    122 #if !U_CHAR16_IS_TYPEDEF
    123 Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
    124 #endif
    125 #if U_SIZEOF_WCHAR_T==2
    126 Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
    127 #endif
    128 Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
    129 Char16Ptr::~Char16Ptr() {
    130    U_ALIASING_BARRIER(p_);
    131 }
    132 
    133 char16_t *Char16Ptr::get() const { return p_; }
    134 
    135 #else
    136 
    137 Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
    138 #if !U_CHAR16_IS_TYPEDEF
    139 Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
    140 #endif
    141 #if U_SIZEOF_WCHAR_T==2
    142 Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
    143 #endif
    144 Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
    145 Char16Ptr::~Char16Ptr() {}
    146 
    147 char16_t *Char16Ptr::get() const { return u_.cp; }
    148 
    149 #endif
    150 /// \endcond
    151 
    152 /**
    153 * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
    154 * @stable ICU 59
    155 */
    156 class U_COMMON_API ConstChar16Ptr final {
    157 public:
    158    /**
    159     * Copies the pointer.
    160     * @param p pointer
    161     * @stable ICU 59
    162     */
    163    inline ConstChar16Ptr(const char16_t *p);
    164 #if !U_CHAR16_IS_TYPEDEF
    165    /**
    166     * Converts the pointer to char16_t *.
    167     * @param p pointer to be converted
    168     * @stable ICU 59
    169     */
    170    inline ConstChar16Ptr(const uint16_t *p);
    171 #endif
    172 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
    173    /**
    174     * Converts the pointer to char16_t *.
    175     * (Only defined if U_SIZEOF_WCHAR_T==2.)
    176     * @param p pointer to be converted
    177     * @stable ICU 59
    178     */
    179    inline ConstChar16Ptr(const wchar_t *p);
    180 #endif
    181    /**
    182     * nullptr constructor.
    183     * @param p nullptr
    184     * @stable ICU 59
    185     */
    186    inline ConstChar16Ptr(const std::nullptr_t p);
    187 
    188    /**
    189     * Destructor.
    190     * @stable ICU 59
    191     */
    192    inline ~ConstChar16Ptr();
    193 
    194    /**
    195     * Pointer access.
    196     * @return the wrapped pointer
    197     * @stable ICU 59
    198     */
    199    inline const char16_t *get() const;
    200    /**
    201     * char16_t pointer access via type conversion (e.g., static_cast).
    202     * @return the wrapped pointer
    203     * @stable ICU 59
    204     */
    205    inline operator const char16_t *() const { return get(); }
    206 
    207 private:
    208    ConstChar16Ptr() = delete;
    209 
    210 #ifdef U_ALIASING_BARRIER
    211    template<typename T> static const char16_t *cast(const T *t) {
    212        U_ALIASING_BARRIER(t);
    213        return reinterpret_cast<const char16_t *>(t);
    214    }
    215 
    216    const char16_t *p_;
    217 #else
    218    union {
    219        const char16_t *cp;
    220        const uint16_t *up;
    221        const wchar_t *wp;
    222    } u_;
    223 #endif
    224 };
    225 
    226 /// \cond
    227 #ifdef U_ALIASING_BARRIER
    228 
    229 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
    230 #if !U_CHAR16_IS_TYPEDEF
    231 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
    232 #endif
    233 #if U_SIZEOF_WCHAR_T==2
    234 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
    235 #endif
    236 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
    237 ConstChar16Ptr::~ConstChar16Ptr() {
    238    U_ALIASING_BARRIER(p_);
    239 }
    240 
    241 const char16_t *ConstChar16Ptr::get() const { return p_; }
    242 
    243 #else
    244 
    245 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
    246 #if !U_CHAR16_IS_TYPEDEF
    247 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
    248 #endif
    249 #if U_SIZEOF_WCHAR_T==2
    250 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
    251 #endif
    252 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
    253 ConstChar16Ptr::~ConstChar16Ptr() {}
    254 
    255 const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
    256 
    257 #endif
    258 /// \endcond
    259 
    260 U_NAMESPACE_END
    261 
    262 #endif  // U_SHOW_CPLUSPLUS_API
    263 
    264 // Usable in header-only definitions
    265 #if U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
    266 
    267 namespace U_ICU_NAMESPACE_OR_INTERNAL {
    268 
    269 #ifndef U_FORCE_HIDE_INTERNAL_API
    270 /** @internal */
    271 template<typename T, typename = std::enable_if_t<std::is_same_v<T, UChar>>>
    272 inline const char16_t *uprv_char16PtrFromUChar(const T *p) {
    273    if constexpr (std::is_same_v<UChar, char16_t>) {
    274        return p;
    275    } else {
    276 #if U_SHOW_CPLUSPLUS_API
    277        return ConstChar16Ptr(p).get();
    278 #else
    279 #ifdef U_ALIASING_BARRIER
    280        U_ALIASING_BARRIER(p);
    281 #endif
    282        return reinterpret_cast<const char16_t *>(p);
    283 #endif
    284    }
    285 }
    286 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
    287 /** @internal */
    288 inline const char16_t *uprv_char16PtrFromUint16(const uint16_t *p) {
    289 #if U_SHOW_CPLUSPLUS_API
    290    return ConstChar16Ptr(p).get();
    291 #else
    292 #ifdef U_ALIASING_BARRIER
    293    U_ALIASING_BARRIER(p);
    294 #endif
    295    return reinterpret_cast<const char16_t *>(p);
    296 #endif
    297 }
    298 #endif
    299 #if U_SIZEOF_WCHAR_T==2
    300 /** @internal */
    301 inline const char16_t *uprv_char16PtrFromWchar(const wchar_t *p) {
    302 #if U_SHOW_CPLUSPLUS_API
    303    return ConstChar16Ptr(p).get();
    304 #else
    305 #ifdef U_ALIASING_BARRIER
    306    U_ALIASING_BARRIER(p);
    307 #endif
    308    return reinterpret_cast<const char16_t *>(p);
    309 #endif
    310 }
    311 #endif
    312 #endif
    313 
    314 /**
    315 * Converts from const char16_t * to const UChar *.
    316 * Includes an aliasing barrier if available.
    317 * @param p pointer
    318 * @return p as const UChar *
    319 * @stable ICU 59
    320 */
    321 inline const UChar *toUCharPtr(const char16_t *p) {
    322 #ifdef U_ALIASING_BARRIER
    323    U_ALIASING_BARRIER(p);
    324 #endif
    325    return reinterpret_cast<const UChar *>(p);
    326 }
    327 
    328 /**
    329 * Converts from char16_t * to UChar *.
    330 * Includes an aliasing barrier if available.
    331 * @param p pointer
    332 * @return p as UChar *
    333 * @stable ICU 59
    334 */
    335 inline UChar *toUCharPtr(char16_t *p) {
    336 #ifdef U_ALIASING_BARRIER
    337    U_ALIASING_BARRIER(p);
    338 #endif
    339    return reinterpret_cast<UChar *>(p);
    340 }
    341 
    342 /**
    343 * Converts from const char16_t * to const OldUChar *.
    344 * Includes an aliasing barrier if available.
    345 * @param p pointer
    346 * @return p as const OldUChar *
    347 * @stable ICU 59
    348 */
    349 inline const OldUChar *toOldUCharPtr(const char16_t *p) {
    350 #ifdef U_ALIASING_BARRIER
    351    U_ALIASING_BARRIER(p);
    352 #endif
    353    return reinterpret_cast<const OldUChar *>(p);
    354 }
    355 
    356 /**
    357 * Converts from char16_t * to OldUChar *.
    358 * Includes an aliasing barrier if available.
    359 * @param p pointer
    360 * @return p as OldUChar *
    361 * @stable ICU 59
    362 */
    363 inline OldUChar *toOldUCharPtr(char16_t *p) {
    364 #ifdef U_ALIASING_BARRIER
    365    U_ALIASING_BARRIER(p);
    366 #endif
    367    return reinterpret_cast<OldUChar *>(p);
    368 }
    369 
    370 }  // U_ICU_NAMESPACE_OR_INTERNAL
    371 
    372 #endif  // U_SHOW_CPLUSPLUS_API || U_SHOW_CPLUSPLUS_HEADER_API
    373 
    374 // ICU DLL-exported
    375 #if U_SHOW_CPLUSPLUS_API
    376 
    377 U_NAMESPACE_BEGIN
    378 
    379 #ifndef U_FORCE_HIDE_INTERNAL_API
    380 /**
    381 * Is T convertible to a std::u16string_view or some other 16-bit string view?
    382 * @internal
    383 */
    384 template<typename T>
    385 constexpr bool ConvertibleToU16StringView =
    386    std::is_convertible_v<T, std::u16string_view>
    387 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
    388    || std::is_convertible_v<T, std::basic_string_view<uint16_t>>
    389 #endif
    390 #if U_SIZEOF_WCHAR_T==2
    391    || std::is_convertible_v<T, std::wstring_view>
    392 #endif
    393    ;
    394 
    395 namespace internal {
    396 /**
    397 * Pass-through overload.
    398 * @internal
    399 */
    400 inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; }
    401 
    402 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
    403 /**
    404 * Basically undefined behavior but sometimes necessary conversion
    405 * from std::basic_string_view<uint16_t> to std::u16string_view.
    406 * @internal
    407 */
    408 inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) {
    409    return { ConstChar16Ptr(sv.data()), sv.length() };
    410 }
    411 #endif
    412 
    413 #if U_SIZEOF_WCHAR_T==2
    414 /**
    415 * Basically undefined behavior but sometimes necessary conversion
    416 * from std::wstring_view to std::u16string_view.
    417 * @internal
    418 */
    419 inline std::u16string_view toU16StringView(std::wstring_view sv) {
    420    return { ConstChar16Ptr(sv.data()), sv.length() };
    421 }
    422 #endif
    423 
    424 /**
    425 * Pass-through overload.
    426 * @internal
    427 */
    428 template <typename T,
    429          typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>>
    430 inline std::u16string_view toU16StringViewNullable(const T& text) {
    431    return toU16StringView(text);
    432 }
    433 
    434 /**
    435 * In case of nullptr, return an empty view.
    436 * @internal
    437 */
    438 template <typename T,
    439          typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>,
    440          typename = void>
    441 inline std::u16string_view toU16StringViewNullable(const T& text) {
    442    if (text == nullptr) return {};  // For backward compatibility.
    443    return toU16StringView(text);
    444 }
    445 
    446 }  // internal
    447 #endif  // U_FORCE_HIDE_INTERNAL_API
    448 
    449 U_NAMESPACE_END
    450 
    451 #endif  // U_SHOW_CPLUSPLUS_API
    452 
    453 #endif  // __CHAR16PTR_H__