char16ptr.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. // © 2017 and later: Unicode, Inc. and others.
  2. // License & terms of use: http://www.unicode.org/copyright.html
  3. // char16ptr.h
  4. // created: 2017feb28 Markus W. Scherer
  5. #ifndef __CHAR16PTR_H__
  6. #define __CHAR16PTR_H__
  7. #include "unicode/utypes.h"
  8. #if U_SHOW_CPLUSPLUS_API
  9. #include <cstddef>
  10. #include <string_view>
  11. /**
  12. * \file
  13. * \brief C++ API: char16_t pointer wrappers with
  14. * implicit conversion from bit-compatible raw pointer types.
  15. * Also conversion functions from char16_t * to UChar * and OldUChar *.
  16. */
  17. U_NAMESPACE_BEGIN
  18. /**
  19. * \def U_ALIASING_BARRIER
  20. * Barrier for pointer anti-aliasing optimizations even across function boundaries.
  21. * @internal
  22. */
  23. #ifdef U_ALIASING_BARRIER
  24. // Use the predefined value.
  25. #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT
  26. # define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory")
  27. #elif defined(U_IN_DOXYGEN)
  28. # define U_ALIASING_BARRIER(ptr)
  29. #endif
  30. /**
  31. * char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
  32. * @stable ICU 59
  33. */
  34. class U_COMMON_API Char16Ptr final {
  35. public:
  36. /**
  37. * Copies the pointer.
  38. * @param p pointer
  39. * @stable ICU 59
  40. */
  41. inline Char16Ptr(char16_t *p);
  42. #if !U_CHAR16_IS_TYPEDEF
  43. /**
  44. * Converts the pointer to char16_t *.
  45. * @param p pointer to be converted
  46. * @stable ICU 59
  47. */
  48. inline Char16Ptr(uint16_t *p);
  49. #endif
  50. #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
  51. /**
  52. * Converts the pointer to char16_t *.
  53. * (Only defined if U_SIZEOF_WCHAR_T==2.)
  54. * @param p pointer to be converted
  55. * @stable ICU 59
  56. */
  57. inline Char16Ptr(wchar_t *p);
  58. #endif
  59. /**
  60. * nullptr constructor.
  61. * @param p nullptr
  62. * @stable ICU 59
  63. */
  64. inline Char16Ptr(std::nullptr_t p);
  65. /**
  66. * Destructor.
  67. * @stable ICU 59
  68. */
  69. inline ~Char16Ptr();
  70. /**
  71. * Pointer access.
  72. * @return the wrapped pointer
  73. * @stable ICU 59
  74. */
  75. inline char16_t *get() const;
  76. /**
  77. * char16_t pointer access via type conversion (e.g., static_cast).
  78. * @return the wrapped pointer
  79. * @stable ICU 59
  80. */
  81. inline operator char16_t *() const { return get(); }
  82. private:
  83. Char16Ptr() = delete;
  84. #ifdef U_ALIASING_BARRIER
  85. template<typename T> static char16_t *cast(T *t) {
  86. U_ALIASING_BARRIER(t);
  87. return reinterpret_cast<char16_t *>(t);
  88. }
  89. char16_t *p_;
  90. #else
  91. union {
  92. char16_t *cp;
  93. uint16_t *up;
  94. wchar_t *wp;
  95. } u_;
  96. #endif
  97. };
  98. /// \cond
  99. #ifdef U_ALIASING_BARRIER
  100. Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {}
  101. #if !U_CHAR16_IS_TYPEDEF
  102. Char16Ptr::Char16Ptr(uint16_t *p) : p_(cast(p)) {}
  103. #endif
  104. #if U_SIZEOF_WCHAR_T==2
  105. Char16Ptr::Char16Ptr(wchar_t *p) : p_(cast(p)) {}
  106. #endif
  107. Char16Ptr::Char16Ptr(std::nullptr_t p) : p_(p) {}
  108. Char16Ptr::~Char16Ptr() {
  109. U_ALIASING_BARRIER(p_);
  110. }
  111. char16_t *Char16Ptr::get() const { return p_; }
  112. #else
  113. Char16Ptr::Char16Ptr(char16_t *p) { u_.cp = p; }
  114. #if !U_CHAR16_IS_TYPEDEF
  115. Char16Ptr::Char16Ptr(uint16_t *p) { u_.up = p; }
  116. #endif
  117. #if U_SIZEOF_WCHAR_T==2
  118. Char16Ptr::Char16Ptr(wchar_t *p) { u_.wp = p; }
  119. #endif
  120. Char16Ptr::Char16Ptr(std::nullptr_t p) { u_.cp = p; }
  121. Char16Ptr::~Char16Ptr() {}
  122. char16_t *Char16Ptr::get() const { return u_.cp; }
  123. #endif
  124. /// \endcond
  125. /**
  126. * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types.
  127. * @stable ICU 59
  128. */
  129. class U_COMMON_API ConstChar16Ptr final {
  130. public:
  131. /**
  132. * Copies the pointer.
  133. * @param p pointer
  134. * @stable ICU 59
  135. */
  136. inline ConstChar16Ptr(const char16_t *p);
  137. #if !U_CHAR16_IS_TYPEDEF
  138. /**
  139. * Converts the pointer to char16_t *.
  140. * @param p pointer to be converted
  141. * @stable ICU 59
  142. */
  143. inline ConstChar16Ptr(const uint16_t *p);
  144. #endif
  145. #if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
  146. /**
  147. * Converts the pointer to char16_t *.
  148. * (Only defined if U_SIZEOF_WCHAR_T==2.)
  149. * @param p pointer to be converted
  150. * @stable ICU 59
  151. */
  152. inline ConstChar16Ptr(const wchar_t *p);
  153. #endif
  154. /**
  155. * nullptr constructor.
  156. * @param p nullptr
  157. * @stable ICU 59
  158. */
  159. inline ConstChar16Ptr(const std::nullptr_t p);
  160. /**
  161. * Destructor.
  162. * @stable ICU 59
  163. */
  164. inline ~ConstChar16Ptr();
  165. /**
  166. * Pointer access.
  167. * @return the wrapped pointer
  168. * @stable ICU 59
  169. */
  170. inline const char16_t *get() const;
  171. /**
  172. * char16_t pointer access via type conversion (e.g., static_cast).
  173. * @return the wrapped pointer
  174. * @stable ICU 59
  175. */
  176. inline operator const char16_t *() const { return get(); }
  177. private:
  178. ConstChar16Ptr() = delete;
  179. #ifdef U_ALIASING_BARRIER
  180. template<typename T> static const char16_t *cast(const T *t) {
  181. U_ALIASING_BARRIER(t);
  182. return reinterpret_cast<const char16_t *>(t);
  183. }
  184. const char16_t *p_;
  185. #else
  186. union {
  187. const char16_t *cp;
  188. const uint16_t *up;
  189. const wchar_t *wp;
  190. } u_;
  191. #endif
  192. };
  193. /// \cond
  194. #ifdef U_ALIASING_BARRIER
  195. ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {}
  196. #if !U_CHAR16_IS_TYPEDEF
  197. ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) : p_(cast(p)) {}
  198. #endif
  199. #if U_SIZEOF_WCHAR_T==2
  200. ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) : p_(cast(p)) {}
  201. #endif
  202. ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) : p_(p) {}
  203. ConstChar16Ptr::~ConstChar16Ptr() {
  204. U_ALIASING_BARRIER(p_);
  205. }
  206. const char16_t *ConstChar16Ptr::get() const { return p_; }
  207. #else
  208. ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) { u_.cp = p; }
  209. #if !U_CHAR16_IS_TYPEDEF
  210. ConstChar16Ptr::ConstChar16Ptr(const uint16_t *p) { u_.up = p; }
  211. #endif
  212. #if U_SIZEOF_WCHAR_T==2
  213. ConstChar16Ptr::ConstChar16Ptr(const wchar_t *p) { u_.wp = p; }
  214. #endif
  215. ConstChar16Ptr::ConstChar16Ptr(const std::nullptr_t p) { u_.cp = p; }
  216. ConstChar16Ptr::~ConstChar16Ptr() {}
  217. const char16_t *ConstChar16Ptr::get() const { return u_.cp; }
  218. #endif
  219. /// \endcond
  220. /**
  221. * Converts from const char16_t * to const UChar *.
  222. * Includes an aliasing barrier if available.
  223. * @param p pointer
  224. * @return p as const UChar *
  225. * @stable ICU 59
  226. */
  227. inline const UChar *toUCharPtr(const char16_t *p) {
  228. #ifdef U_ALIASING_BARRIER
  229. U_ALIASING_BARRIER(p);
  230. #endif
  231. return reinterpret_cast<const UChar *>(p);
  232. }
  233. /**
  234. * Converts from char16_t * to UChar *.
  235. * Includes an aliasing barrier if available.
  236. * @param p pointer
  237. * @return p as UChar *
  238. * @stable ICU 59
  239. */
  240. inline UChar *toUCharPtr(char16_t *p) {
  241. #ifdef U_ALIASING_BARRIER
  242. U_ALIASING_BARRIER(p);
  243. #endif
  244. return reinterpret_cast<UChar *>(p);
  245. }
  246. /**
  247. * Converts from const char16_t * to const OldUChar *.
  248. * Includes an aliasing barrier if available.
  249. * @param p pointer
  250. * @return p as const OldUChar *
  251. * @stable ICU 59
  252. */
  253. inline const OldUChar *toOldUCharPtr(const char16_t *p) {
  254. #ifdef U_ALIASING_BARRIER
  255. U_ALIASING_BARRIER(p);
  256. #endif
  257. return reinterpret_cast<const OldUChar *>(p);
  258. }
  259. /**
  260. * Converts from char16_t * to OldUChar *.
  261. * Includes an aliasing barrier if available.
  262. * @param p pointer
  263. * @return p as OldUChar *
  264. * @stable ICU 59
  265. */
  266. inline OldUChar *toOldUCharPtr(char16_t *p) {
  267. #ifdef U_ALIASING_BARRIER
  268. U_ALIASING_BARRIER(p);
  269. #endif
  270. return reinterpret_cast<OldUChar *>(p);
  271. }
  272. #ifndef U_FORCE_HIDE_INTERNAL_API
  273. /**
  274. * Is T convertible to a std::u16string_view or some other 16-bit string view?
  275. * @internal
  276. */
  277. template<typename T>
  278. constexpr bool ConvertibleToU16StringView =
  279. std::is_convertible_v<T, std::u16string_view>
  280. #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
  281. || std::is_convertible_v<T, std::basic_string_view<uint16_t>>
  282. #endif
  283. #if U_SIZEOF_WCHAR_T==2
  284. || std::is_convertible_v<T, std::wstring_view>
  285. #endif
  286. ;
  287. namespace internal {
  288. /**
  289. * Pass-through overload.
  290. * @internal
  291. */
  292. inline std::u16string_view toU16StringView(std::u16string_view sv) { return sv; }
  293. #if !U_CHAR16_IS_TYPEDEF && (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION < 180000)
  294. /**
  295. * Basically undefined behavior but sometimes necessary conversion
  296. * from std::basic_string_view<uint16_t> to std::u16string_view.
  297. * @internal
  298. */
  299. inline std::u16string_view toU16StringView(std::basic_string_view<uint16_t> sv) {
  300. return { ConstChar16Ptr(sv.data()), sv.length() };
  301. }
  302. #endif
  303. #if U_SIZEOF_WCHAR_T==2
  304. /**
  305. * Basically undefined behavior but sometimes necessary conversion
  306. * from std::wstring_view to std::u16string_view.
  307. * @internal
  308. */
  309. inline std::u16string_view toU16StringView(std::wstring_view sv) {
  310. return { ConstChar16Ptr(sv.data()), sv.length() };
  311. }
  312. #endif
  313. /**
  314. * Pass-through overload.
  315. * @internal
  316. */
  317. template <typename T,
  318. typename = typename std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>>>
  319. inline std::u16string_view toU16StringViewNullable(const T& text) {
  320. return toU16StringView(text);
  321. }
  322. /**
  323. * In case of nullptr, return an empty view.
  324. * @internal
  325. */
  326. template <typename T,
  327. typename = typename std::enable_if_t<std::is_pointer_v<std::remove_reference_t<T>>>,
  328. typename = void>
  329. inline std::u16string_view toU16StringViewNullable(const T& text) {
  330. if (text == nullptr) return {}; // For backward compatibility.
  331. return toU16StringView(text);
  332. }
  333. } // internal
  334. #endif // U_FORCE_HIDE_INTERNAL_API
  335. U_NAMESPACE_END
  336. #endif /* U_SHOW_CPLUSPLUS_API */
  337. #endif // __CHAR16PTR_H__