Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-04 10:00:20

0001 // © 2017 and later: Unicode, Inc. and others.
0002 // License & terms of use: http://www.unicode.org/copyright.html
0003 
0004 // char16ptr.h
0005 // created: 2017feb28 Markus W. Scherer
0006 
0007 #ifndef __CHAR16PTR_H__
0008 #define __CHAR16PTR_H__
0009 
0010 #include "unicode/utypes.h"
0011 
0012 #if U_SHOW_CPLUSPLUS_API
0013 
0014 #include <cstddef>
0015 #include <string_view>
0016 
0017 /**
0018  * \file
0019  * \brief C++ API: char16_t pointer wrappers with
0020  *        implicit conversion from bit-compatible raw pointer types.
0021  *        Also conversion functions from char16_t * to UChar * and OldUChar *.
0022  */
0023 
0024 U_NAMESPACE_BEGIN
0025 
0026 /**
0027  * \def U_ALIASING_BARRIER
0028  * Barrier for pointer anti-aliasing optimizations even across function boundaries.
0029  * @internal
0030  */
0031 #ifdef U_ALIASING_BARRIER
0032     // Use the predefined value.
0033 #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
0034 #   define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
0035 #elif defined(U_IN_DOXYGEN)
0036 #   define U_ALIASING_BARRIER(ptr)
0037 #endif
0038 
0039 /**
0040  * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
0041  * @stable ICU 59
0042  */
0043 class U_COMMON_API Char16Ptr final {
0044 public:
0045     /**
0046      * Copies the pointer.
0047      * @param p pointer
0048      * @stable ICU 59
0049      */
0050     inline Char16Ptr(char16_t *p);
0051 #if !U_CHAR16_IS_TYPEDEF
0052     /**
0053      * Converts the pointer to char16_t *.
0054      * @param p pointer to be converted
0055      * @stable ICU 59
0056      */
0057     inline Char16Ptr(uint16_t *p);
0058 #endif
0059 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
0060     /**
0061      * Converts the pointer to char16_t *.
0062      * (Only defined if U_SIZEOF_WCHAR_T==2.)
0063      * @param p pointer to be converted
0064      * @stable ICU 59
0065      */
0066     inline Char16Ptr(wchar_t *p);
0067 #endif
0068     /**
0069      * nullptr constructor.
0070      * @param p nullptr
0071      * @stable ICU 59
0072      */
0073     inline Char16Ptr(std::nullptr_t p);
0074     /**
0075      * Destructor.
0076      * @stable ICU 59
0077      */
0078     inline ~Char16Ptr();
0079 
0080     /**
0081      * Pointer access.
0082      * @return the wrapped pointer
0083      * @stable ICU 59
0084      */
0085     inline char16_t *get() const;
0086     /**
0087      * char16_t pointer access via type conversion (e.g., static_cast).
0088      * @return the wrapped pointer
0089      * @stable ICU 59
0090      */
0091     inline operator char16_t *() const { return get(); }
0092 
0093 private:
0094     Char16Ptr() = delete;
0095 
0096 #ifdef U_ALIASING_BARRIER
0097     template<typename T> static char16_t *cast(T *t) {
0098         U_ALIASING_BARRIER(t);
0099         return reinterpret_cast<char16_t *>(t);
0100     }
0101 
0102     char16_t *p_;
0103 #else
0104     union {
0105         char16_t *cp;
0106         uint16_t *up;
0107         wchar_t *wp;
0108     } u_;
0109 #endif
0110 };
0111 
0112 /// \cond
0113 #ifdef U_ALIASING_BARRIER
0114 
0115 Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
0116 #if !U_CHAR16_IS_TYPEDEF
0117 Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
0118 #endif
0119 #if U_SIZEOF_WCHAR_T==2
0120 Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
0121 #endif
0122 Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
0123 Char16Ptr::~Char16Ptr() {
0124     U_ALIASING_BARRIER(p_);
0125 }
0126 
0127 char16_t *Char16Ptr::get() const { return p_; }
0128 
0129 #else
0130 
0131 Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
0132 #if !U_CHAR16_IS_TYPEDEF
0133 Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
0134 #endif
0135 #if U_SIZEOF_WCHAR_T==2
0136 Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
0137 #endif
0138 Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
0139 Char16Ptr::~Char16Ptr() {}
0140 
0141 char16_t *Char16Ptr::get() const { return u_.cp; }
0142 
0143 #endif
0144 /// \endcond
0145 
0146 /**
0147  * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
0148  * @stable ICU 59
0149  */
0150 class U_COMMON_API ConstChar16Ptr final {
0151 public:
0152     /**
0153      * Copies the pointer.
0154      * @param p pointer
0155      * @stable ICU 59
0156      */
0157     inline ConstChar16Ptr(const char16_t *p);
0158 #if !U_CHAR16_IS_TYPEDEF
0159     /**
0160      * Converts the pointer to char16_t *.
0161      * @param p pointer to be converted
0162      * @stable ICU 59
0163      */
0164     inline ConstChar16Ptr(const uint16_t *p);
0165 #endif
0166 #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
0167     /**
0168      * Converts the pointer to char16_t *.
0169      * (Only defined if U_SIZEOF_WCHAR_T==2.)
0170      * @param p pointer to be converted
0171      * @stable ICU 59
0172      */
0173     inline ConstChar16Ptr(const wchar_t *p);
0174 #endif
0175     /**
0176      * nullptr constructor.
0177      * @param p nullptr
0178      * @stable ICU 59
0179      */
0180     inline ConstChar16Ptr(const std::nullptr_t p);
0181 
0182     /**
0183      * Destructor.
0184      * @stable ICU 59
0185      */
0186     inline ~ConstChar16Ptr();
0187 
0188     /**
0189      * Pointer access.
0190      * @return the wrapped pointer
0191      * @stable ICU 59
0192      */
0193     inline const char16_t *get() const;
0194     /**
0195      * char16_t pointer access via type conversion (e.g., static_cast).
0196      * @return the wrapped pointer
0197      * @stable ICU 59
0198      */
0199     inline operator const char16_t *() const { return get(); }
0200 
0201 private:
0202     ConstChar16Ptr() = delete;
0203 
0204 #ifdef U_ALIASING_BARRIER
0205     template<typename T> static const char16_t *cast(const T *t) {
0206         U_ALIASING_BARRIER(t);
0207         return reinterpret_cast<const char16_t *>(t);
0208     }
0209 
0210     const char16_t *p_;
0211 #else
0212     union {
0213         const char16_t *cp;
0214         const uint16_t *up;
0215         const wchar_t *wp;
0216     } u_;
0217 #endif
0218 };
0219 
0220 /// \cond
0221 #ifdef U_ALIASING_BARRIER
0222 
0223 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
0224 #if !U_CHAR16_IS_TYPEDEF
0225 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
0226 #endif
0227 #if U_SIZEOF_WCHAR_T==2
0228 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
0229 #endif
0230 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
0231 ConstChar16Ptr::~ConstChar16Ptr() {
0232     U_ALIASING_BARRIER(p_);
0233 }
0234 
0235 const char16_t *ConstChar16Ptr::get() const { return p_; }
0236 
0237 #else
0238 
0239 ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
0240 #if !U_CHAR16_IS_TYPEDEF
0241 ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
0242 #endif
0243 #if U_SIZEOF_WCHAR_T==2
0244 ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
0245 #endif
0246 ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
0247 ConstChar16Ptr::~ConstChar16Ptr() {}
0248 
0249 const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
0250 
0251 #endif
0252 /// \endcond
0253 
0254 /**
0255  * Converts from const char16_t * to const UChar *.
0256  * Includes an aliasing barrier if available.
0257  * @param p pointer
0258  * @return p as const UChar *
0259  * @stable ICU 59
0260  */
0261 inline const UChar *toUCharPtr(const char16_t *p) {
0262 #ifdef U_ALIASING_BARRIER
0263     U_ALIASING_BARRIER(p);
0264 #endif
0265     return reinterpret_cast<const UChar *>(p);
0266 }
0267 
0268 /**
0269  * Converts from char16_t * to UChar *.
0270  * Includes an aliasing barrier if available.
0271  * @param p pointer
0272  * @return p as UChar *
0273  * @stable ICU 59
0274  */
0275 inline UChar *toUCharPtr(char16_t *p) {
0276 #ifdef U_ALIASING_BARRIER
0277     U_ALIASING_BARRIER(p);
0278 #endif
0279     return reinterpret_cast<UChar *>(p);
0280 }
0281 
0282 /**
0283  * Converts from const char16_t * to const OldUChar *.
0284  * Includes an aliasing barrier if available.
0285  * @param p pointer
0286  * @return p as const OldUChar *
0287  * @stable ICU 59
0288  */
0289 inline const OldUChar *toOldUCharPtr(const char16_t *p) {
0290 #ifdef U_ALIASING_BARRIER
0291     U_ALIASING_BARRIER(p);
0292 #endif
0293     return reinterpret_cast<const OldUChar *>(p);
0294 }
0295 
0296 /**
0297  * Converts from char16_t * to OldUChar *.
0298  * Includes an aliasing barrier if available.
0299  * @param p pointer
0300  * @return p as OldUChar *
0301  * @stable ICU 59
0302  */
0303 inline OldUChar *toOldUCharPtr(char16_t *p) {
0304 #ifdef U_ALIASING_BARRIER
0305     U_ALIASING_BARRIER(p);
0306 #endif
0307     return reinterpret_cast<OldUChar *>(p);
0308 }
0309 
0310 #ifndef U_FORCE_HIDE_INTERNAL_API
0311 /**
0312  * Is T convertible to a std::u16string_view or some other 16-bit string view?
0313  * @internal
0314  */
0315 template<typename T>
0316 constexpr bool ConvertibleToU16StringView =
0317     std::is_convertible_v<T, std::u16string_view>
0318 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
0319     || std::is_convertible_v<T, std::basic_string_view<uint16_t>>
0320 #endif
0321 #if U_SIZEOF_WCHAR_T==2
0322     || std::is_convertible_v<T, std::wstring_view>
0323 #endif
0324     ;
0325 
0326 namespace internal {
0327 /**
0328  * Pass-through overload.
0329  * @internal
0330  */
0331 inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; }
0332 
0333 #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
0334 /**
0335  * Basically undefined behavior but sometimes necessary conversion
0336  * from std::basic_string_view<uint16_t> to std::u16string_view.
0337  * @internal
0338  */
0339 inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) {
0340     return { ConstChar16Ptr(sv.data()), sv.length() };
0341 }
0342 #endif
0343 
0344 #if U_SIZEOF_WCHAR_T==2
0345 /**
0346  * Basically undefined behavior but sometimes necessary conversion
0347  * from std::wstring_view to std::u16string_view.
0348  * @internal
0349  */
0350 inline std::u16string_view toU16StringView(std::wstring_view sv) {
0351     return { ConstChar16Ptr(sv.data()), sv.length() };
0352 }
0353 #endif
0354 
0355 /**
0356  * Pass-through overload.
0357  * @internal
0358  */
0359 template <typename T,
0360           typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>>
0361 inline std::u16string_view toU16StringViewNullable(const T& text) {
0362     return toU16StringView(text);
0363 }
0364 
0365 /**
0366  * In case of nullptr, return an empty view.
0367  * @internal
0368  */
0369 template <typename T,
0370           typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>,
0371           typename = void>
0372 inline std::u16string_view toU16StringViewNullable(const T& text) {
0373     if (text == nullptr) return {};  // For backward compatibility.
0374     return toU16StringView(text);
0375 }
0376 
0377 }  // internal
0378 #endif  // U_FORCE_HIDE_INTERNAL_API
0379 
0380 U_NAMESPACE_END
0381 
0382 #endif /* U_SHOW_CPLUSPLUS_API */
0383 
0384 #endif  // __CHAR16PTR_H__