String.StringView.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. #pragma once
  2. #include <assert.h>
  3. #include <stdexcept>
  4. #include <type_traits>
  5. #include <string>
  6. #include <algorithm>
  7. #include "Hash.String.hpp"
  8. #define __Utility_String_StringView__
  9. //-----------------------------------------------------------------------------
  10. // 定义一个简单的 StringView, 设计思路来自 <xstring>, 但是做了很多简化
  11. //
  12. // !!! 如果构造函数中的 _sPtr 指向 nullptr, 内部的数据指针将指向内部的 Nil
  13. // 如果是无参数构造, 内部的数据指针也指向内部的 Nil
  14. //
  15. // 上述两个措施都是为了让 Data 永远不会指向 nullptr !
  16. // 2022-11-18
  17. //
  18. // 在构造函数中, m_Hash 初始化为 0, Hash () 函数体中计算真正的 Hash 值并返回
  19. //-----------------------------------------------------------------------------
  20. namespace ECOM::Utility::String
  21. {
  22. template <typename T>
  23. class StringView_Base
  24. {
  25. public:
  26. using value_type = T;
  27. using pointer = T *;
  28. using reference = T &;
  29. using size_type = unsigned int;
  30. using hash_type = size_t;
  31. using const_pointer = const T *;
  32. using const_reference = const T &;
  33. public:
  34. static constexpr auto npos { static_cast <size_type> (-1) };
  35. private:
  36. static constexpr T __nil { 0 };
  37. public:
  38. // constexpr StringView_Base () noexcept : m_Data (nullptr), m_Count (0) {}
  39. constexpr StringView_Base () noexcept : m_Data (& __nil), m_Count (0), m_Hash (0) {}
  40. constexpr StringView_Base (const StringView_Base &) noexcept = default;
  41. constexpr StringView_Base & operator= (const StringView_Base &) noexcept = default;
  42. constexpr StringView_Base (StringView_Base &&) noexcept = default;
  43. constexpr StringView_Base & operator= (StringView_Base &&) noexcept = default;
  44. // explicit : 如果只有指针, 没有长度
  45. explicit constexpr StringView_Base (const const_pointer _sPtr) noexcept
  46. : m_Data (_sPtr ? _sPtr : reinterpret_cast <const T *> (& __nil))
  47. , m_Count (_sPtr ? __count (_sPtr) : 0)
  48. , m_Hash (0) { }
  49. constexpr StringView_Base (const const_pointer _sPtr, const size_type _Count) noexcept
  50. : m_Data (_sPtr ? _sPtr : reinterpret_cast <const T *> (& __nil))
  51. , m_Count (_sPtr ? _Count : 0)
  52. , m_Hash (0) { }
  53. // explicit ? 避免如下默认行为 StringView f () { std::string rc; return rc; }
  54. // !!! 显式转换工作量太大
  55. constexpr StringView_Base (const std::basic_string <T> & str) noexcept
  56. : m_Data (str.c_str ())
  57. , m_Count (static_cast <size_type> (str.size ()))
  58. , m_Hash (0) { }
  59. constexpr StringView_Base (const const_pointer _sPtr, const size_type _Count, hash_type H) noexcept
  60. : m_Data (_sPtr ? _sPtr : reinterpret_cast <const T *> (& __nil))
  61. , m_Count (_sPtr ? _Count : 0)
  62. , m_Hash (H) { }
  63. // 从 std::string_view 构造
  64. constexpr StringView_Base (const std::basic_string_view <T> & str) noexcept
  65. : m_Data (str.data ())
  66. , m_Count (static_cast <size_type> (str.size ()))
  67. , m_Hash (0) { }
  68. public:
  69. constexpr const_pointer _Unchecked_begin () const noexcept { return m_Data; }
  70. constexpr const_pointer _Unchecked_end () const noexcept { return m_Data + m_Count; }
  71. [[nodiscard]] constexpr size_type Size () const noexcept { return m_Count; }
  72. [[nodiscard]] constexpr size_type Length () const noexcept { return m_Count; }
  73. [[nodiscard]] constexpr size_type GetLength () const noexcept { return m_Count; }
  74. [[nodiscard]] constexpr bool isEmpty () const noexcept { return m_Count == 0; }
  75. [[nodiscard]] constexpr const_pointer Data () const noexcept { return m_Data; }
  76. [[nodiscard]] constexpr hash_type Hash () const noexcept // 返回 Hash 值. 注意 !!! 返回值有可能是 0 !!!
  77. {
  78. //< 以下代码会导致 Hash 函数不再是 constexpr, 因此删除
  79. // if constexpr (m_Hash == 0)
  80. // m_Hash = ECOM::Utility::Hash (m_Data, m_Count);
  81. //>
  82. return m_Hash; // 注意 !!! 返回值有可能是 0 !!!
  83. }
  84. [[nodiscard]] hash_type Hash () noexcept // 计算真正的 Hash 值并返回. 增加了是否为 0 的判断, 因此返回值一定非 0
  85. {
  86. if (m_Hash == 0)
  87. m_Hash = ECOM::Utility::Hash (m_Data, m_Count);
  88. return m_Hash;
  89. }
  90. // 不检查 _Off 是否合理
  91. [[nodiscard]] constexpr const_reference operator [] (const size_type _Off) const noexcept
  92. {
  93. return m_Data [_Off];
  94. }
  95. // 检查 _Off 是否合理, 如果不正确就扔例外
  96. [[nodiscard]] constexpr const_reference at (const size_type _Off) const
  97. {
  98. // get the character at _Off or throw if that is out of range
  99. if (_Off >= m_Count)
  100. throw std::out_of_range ("StringView_Base.at");
  101. return m_Data [_Off];
  102. }
  103. [[nodiscard]] constexpr const_reference Front () const noexcept { return m_Data [0]; }
  104. [[nodiscard]] constexpr const_reference Back () const noexcept { return m_Data [m_Count - 1]; }
  105. public:
  106. constexpr void RemovePrefix (const size_type _Count) noexcept { m_Data += _Count; m_Count -= _Count; }
  107. constexpr void RemoveSuffix (const size_type _Count) noexcept { m_Count -= _Count; }
  108. constexpr void Swap (StringView_Base & _Other) noexcept
  109. {
  110. const StringView_Base _Tmp { _Other }; // note: std::swap is not constexpr before C++20
  111. _Other = *this;
  112. *this = _Tmp;
  113. }
  114. [[nodiscard]] constexpr StringView_Base Sub (const size_type _Off = 0, size_type _Count = npos) const
  115. {
  116. // return a new StringView_Base moved forward by _Off and trimmed to _Count elements
  117. if (_Off > m_Count)
  118. throw std::out_of_range ("StringView_Base.Sub");
  119. _Count = (std::min) (_Count, m_Count - _Off);
  120. if (m_Hash == 0) // 我不是 constexpr
  121. return StringView_Base (m_Data + _Off, _Count);
  122. else // 我是 constexpr
  123. return StringView_Base (m_Data + _Off, _Count, Hash64 (m_Data + _Off, _Count));
  124. }
  125. public:
  126. [[nodiscard]] constexpr bool isEqual (const StringView_Base _Right) const noexcept
  127. {
  128. return (m_Count == _Right.m_Count) && Compare (_Right) == 0;
  129. }
  130. [[nodiscard]] constexpr int Compare (const StringView_Base _Right) const noexcept
  131. {
  132. // if constexpr (this->Hash () == _Right.Hash ()) return 0; // 只比较 Hash, 如果 Hash 相等就认为字符串相等
  133. return __mem_compare (m_Data, m_Count, _Right.m_Data, _Right.m_Count);
  134. }
  135. [[nodiscard]] constexpr int Compare (const size_type _Off, const size_type _Nx, const StringView_Base _Right) const
  136. {
  137. // compare [_Off, _Off + _Nx) with _Right
  138. return Sub (_Off, _Nx).Compare (_Right);
  139. }
  140. [[nodiscard]] constexpr int Compare (const size_type _Off, const size_type _Nx, const StringView_Base _Right,
  141. const size_type _Roff, const size_type _Count) const
  142. {
  143. // compare [_Off, _Off + _Nx) with _Right [_Roff, _Roff + _Count)
  144. return Sub (_Off, _Nx).Compare (_Right.substr (_Roff, _Count));
  145. }
  146. [[nodiscard]] constexpr int Compare (const T * const _Ptr) const
  147. { // compare [0, m_Count) with [_Ptr, <null>)
  148. return Compare (StringView_Base (_Ptr));
  149. }
  150. [[nodiscard]] constexpr int Compare (const size_type _Off, const size_type _Nx, const T * const _Ptr) const
  151. {
  152. // compare [_Off, _Off + _Nx) with [_Ptr, <null>)
  153. return Sub (_Off, _Nx).Compare (StringView_Base (_Ptr));
  154. }
  155. [[nodiscard]] constexpr int Compare (const size_type _Off, const size_type _Nx,
  156. const T * const _Ptr, const size_type _Count) const
  157. {
  158. // compare [_Off, _Off + _Nx) with [_Ptr, _Ptr + _Count)
  159. return Sub (_Off, _Nx).Compare (StringView_Base (_Ptr, _Count));
  160. }
  161. [[nodiscard]] constexpr bool Hash_Compare (const StringView_Base & with) const
  162. {
  163. auto H1 = this->Hash ();
  164. auto H2 = with.Hash ();
  165. if ((H1 != 0) && (H2 != 0))
  166. return (H1 == H2);
  167. return isEqual (with);
  168. }
  169. public:
  170. [[nodiscard]] constexpr bool operator == (const StringView_Base & with) const { return (Hash_Compare (with)); }
  171. [[nodiscard]] constexpr bool operator != (const StringView_Base & with) const { return (! Hash_Compare (with)); }
  172. [[nodiscard]] constexpr bool operator < (const StringView_Base & with) const { return Compare (with) < 0; }
  173. [[nodiscard]] constexpr bool operator > (const StringView_Base & with) const { return Compare (with) > 0; }
  174. [[nodiscard]] constexpr bool operator <= (const StringView_Base & with) const { return Compare (with) <= 0; }
  175. [[nodiscard]] constexpr bool operator >= (const StringView_Base & with) const { return Compare (with) >= 0; }
  176. [[nodiscard]] constexpr bool operator == (const T * with) const { return Compare (with) == 0; }
  177. [[nodiscard]] constexpr bool operator != (const T * with) const { return Compare (with) != 0; }
  178. [[nodiscard]] constexpr bool operator < (const T * with) const { return Compare (with) < 0; }
  179. [[nodiscard]] constexpr bool operator > (const T * with) const { return Compare (with) > 0; }
  180. [[nodiscard]] constexpr bool operator <= (const T * with) const { return Compare (with) <= 0; }
  181. [[nodiscard]] constexpr bool operator >= (const T * with) const { return Compare (with) >= 0; }
  182. public:
  183. [[nodiscard]] constexpr bool StartWith (const StringView_Base _Right) const noexcept
  184. {
  185. if (m_Count < _Right.m_Count) return false;
  186. return __mem_compare (m_Data, _Right.m_Data, _Right.m_Count) == 0;
  187. }
  188. [[nodiscard]] constexpr bool StartWith (const T _Right) const noexcept
  189. {
  190. return !isEmpty () && (Front () == _Right);
  191. }
  192. [[nodiscard]] constexpr bool StartWith (const T * const _Right) const noexcept
  193. {
  194. return StartWith (StringView_Base (_Right));
  195. }
  196. [[nodiscard]] constexpr bool EndWith (const StringView_Base _Right) const noexcept
  197. {
  198. const auto _Rightsize = _Right.m_Count;
  199. if (m_Count < _Rightsize) return false;
  200. return __mem_compare (m_Data + (m_Count - _Rightsize), _Right.m_Data, _Rightsize) == 0;
  201. }
  202. [[nodiscard]] constexpr bool EndWith (const T _Right) const noexcept
  203. {
  204. return !isEmpty () && (Back () == _Right);
  205. }
  206. [[nodiscard]] constexpr bool EndWith (const T * const _Right) const noexcept
  207. {
  208. return EndWith (StringView_Base (_Right));
  209. }
  210. [[nodiscard]] constexpr size_type Find (const T ch, const size_type _Off = 0) const noexcept
  211. {
  212. if (_Off < m_Count)
  213. {
  214. const auto found = __mem_find (m_Data + _Off, m_Count - _Off, ch);
  215. if (found)
  216. return static_cast <size_type> (found - m_Data);
  217. }
  218. return npos;
  219. }
  220. [[nodiscard]] constexpr int Count (const T ch) const
  221. {
  222. int count = 0;
  223. for (int i = 0, l = GetLength (); i < l; i++)
  224. if (m_Data [i] == ch)
  225. count++;
  226. return count;
  227. }
  228. // Cast
  229. public:
  230. // return pointer to const string
  231. constexpr operator const T * () const { return m_Data; }
  232. constexpr const T * constBuffer (void) const { return m_Data; }
  233. constexpr operator std::basic_string_view <T> () const // 既然长度已知, 可以几乎无代价地转换成 std::string_view
  234. {
  235. return std::basic_string_view <T> { m_Data, static_cast <size_t> (GetLength ()) };
  236. }
  237. operator bool () const = delete;
  238. public:
  239. static bool isNullOrEmpty (const StringView_Base & S)
  240. {
  241. return S.m_Count == 0;
  242. }
  243. public:
  244. // 转换函数. 因为 atof 等函数不是 constexpr, 因此这里的 constexpr 其实是无效的
  245. template <typename = std::enable_if_t <std::is_same <T, char>::value>>
  246. constexpr double Double () const { return atof (m_Data); }
  247. template <typename Dummy = void, typename = std::enable_if_t <std::is_same <T, wchar_t>::value>>
  248. constexpr double Double () const { return _wtof (m_Data); }
  249. template <typename = std::enable_if_t <std::is_same <T, char>::value>>
  250. constexpr int Int () const { int i = atoi (m_Data); if (i) return i; return strtol (m_Data, nullptr, 16); }
  251. template <typename Dummy = void, typename = std::enable_if_t <std::is_same <T, wchar_t>::value>>
  252. constexpr int Int () const { int i = _wtoi (m_Data); if (i) return i; return wcstol (m_Data, nullptr, 16); }
  253. template <typename = std::enable_if_t <std::is_same <T, char>::value>>
  254. constexpr long Long () const { int i = atol (m_Data); if (i) return i; return strtol (m_Data, nullptr, 16); }
  255. template <typename Dummy = void, typename = std::enable_if_t <std::is_same <T, wchar_t>::value>>
  256. constexpr long Long () const { int i = _wtol (m_Data); if (i) return i; return wcstol (m_Data, nullptr, 16); }
  257. template <typename = std::enable_if_t <std::is_same <T, char>::value>>
  258. constexpr __int64 Int64 () const { int i = _atoi64 (m_Data); if (i) return i; return _strtoi64 (m_Data, nullptr, 16); }
  259. template <typename Dummy = void, typename = std::enable_if_t <std::is_same <T, wchar_t>::value>>
  260. constexpr __int64 Int64 () const { int i = _wtoi64 (m_Data); if (i) return i; return _wcstoi64 (m_Data, nullptr, 16); }
  261. template <typename T> constexpr T To () const = delete;
  262. template <> constexpr int To () const { return Int (); }
  263. template <> constexpr double To () const { return Double (); }
  264. template <> constexpr float To () const { return (float) Double (); }
  265. template <> constexpr long To () const { return Long (); }
  266. template <> constexpr __int64 To () const { return Int64 (); }
  267. template <> constexpr unsigned int To () const { return Int (); }
  268. template <> constexpr unsigned __int64 To () const { return Int64 (); }
  269. template <> constexpr unsigned long To () const { return Long (); }
  270. template <>
  271. constexpr std::basic_string_view <T> To () const // 与 operator 函数完全相同
  272. {
  273. return std::basic_string_view <T> { m_Data, static_cast <size_t> (GetLength ()) };
  274. }
  275. private:
  276. //< 基于内存的比较
  277. static inline constexpr int __mem_compare (const const_pointer _l, const size_type _ls, const const_pointer _r, const size_type _rs)
  278. {
  279. auto b = __mem_compare (_l, _r, (std::min) (_ls, _rs));
  280. if (b != 0) return b;
  281. if (_ls < _rs) return -1;
  282. if (_ls > _rs) return 1;
  283. return 0;
  284. }
  285. static inline constexpr int __mem_compare (const const_pointer _l, const const_pointer _r, const size_type _sz)
  286. {
  287. if constexpr (std::is_same_v <T, wchar_t>)
  288. return __builtin_wmemcmp (_l, _r, _sz);
  289. else
  290. if constexpr (std::is_same_v <T, char>)
  291. return __builtin_memcmp (_l, _r, _sz);
  292. assert (false);
  293. return 0;
  294. }
  295. //>
  296. static inline constexpr T * __mem_find (const const_pointer _f, const size_type _sz, const T & ch)
  297. {
  298. if constexpr (std::is_same_v <T, wchar_t>)
  299. return __builtin_wmemchr (_f, ch, _sz);
  300. else
  301. if constexpr (std::is_same_v <T, char>)
  302. return __builtin_char_memchr (_f, ch, _sz);
  303. assert (false);
  304. return nullptr;
  305. }
  306. // _f 中有多少个字符?
  307. static inline constexpr size_type __count (const const_pointer _f)
  308. {
  309. if constexpr (std::is_same_v <T, wchar_t>)
  310. return static_cast <size_type> (__builtin_wcslen (_f));
  311. else
  312. if constexpr (std::is_same_v <T, char>)
  313. return static_cast <size_type> (__builtin_strlen (_f));
  314. assert (false);
  315. return 0;
  316. }
  317. private:
  318. const_pointer m_Data;
  319. size_type m_Count; // 是字符个数, 不是 NbOfByte
  320. hash_type m_Hash;
  321. };
  322. using StringView = StringView_Base <char>;
  323. using DStringView = StringView_Base <char>;
  324. using WStringView = StringView_Base <wchar_t>;
  325. inline namespace Literals
  326. {
  327. inline namespace StringViewLiterals
  328. {
  329. [[nodiscard]] constexpr StringView operator"" _sv (const char * _Str, size_t _Len) noexcept
  330. {
  331. return StringView (_Str, static_cast <unsigned int> (_Len), Hash64 (_Str, static_cast <unsigned int> (_Len)));
  332. }
  333. [[nodiscard]] constexpr WStringView operator"" _sv (const wchar_t * _Str, size_t _Len) noexcept
  334. {
  335. return WStringView (_Str, static_cast <unsigned int> (_Len), Hash64 (_Str, static_cast <unsigned int> (_Len)));
  336. }
  337. }
  338. }
  339. }
  340. //namespace eSTR = ECOM::Utility::String;
  341. //using namespace eSTR::Literals;
  342. //using namespace ECOM::Utility::String::Literals;
  343. //using constView = const ECOM::Utility::String::StringView;
  344. //using wconstView = const ECOM::Utility::String::WStringView;
  345. //using conStrView = const ECOM::Utility::String::StringView;
  346. //using conWStrView = const ECOM::Utility::String::WStringView;
  347. using CV_String = const ECOM::Utility::String::StringView;
  348. using CV_DString = const ECOM::Utility::String::StringView;
  349. using CV_WString = const ECOM::Utility::String::WStringView;
  350. //using String_CV = const ECOM::Utility::String::StringView;
  351. //using WString_CV = const ECOM::Utility::String::WStringView;
  352. //< 提供 CV_String 与 std:: string 的比较
  353. template <typename T>
  354. inline bool operator == (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  355. {
  356. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) == 0;
  357. }
  358. template <typename T>
  359. inline bool operator != (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  360. {
  361. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) != 0;
  362. }
  363. template <typename T>
  364. inline bool operator > (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  365. {
  366. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) > 0;
  367. }
  368. template <typename T>
  369. inline bool operator < (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  370. {
  371. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) < 0;
  372. }
  373. template <typename T>
  374. inline bool operator >= (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  375. {
  376. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) >= 0;
  377. }
  378. template <typename T>
  379. inline bool operator <= (const ECOM::Utility::String::StringView_Base <T> & s1, const std::basic_string <T> & s2)
  380. {
  381. return s1.Compare (ECOM::Utility::String::StringView_Base <T> { s2.c_str (), static_cast <CV_String::size_type> (s2.size ()) }) <= 0;
  382. }
  383. //>
  384. //< 提供 std:: string 与 CV_String 的比较
  385. template <typename T>
  386. inline bool operator == (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  387. {
  388. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) == 0;
  389. }
  390. template <typename T>
  391. inline bool operator != (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  392. {
  393. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) != 0;
  394. }
  395. template <typename T>
  396. inline bool operator > (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  397. {
  398. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) < 0;
  399. }
  400. template <typename T>
  401. inline bool operator < (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  402. {
  403. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) > 0;
  404. }
  405. template <typename T>
  406. inline bool operator >= (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  407. {
  408. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) <= 0;
  409. }
  410. template <typename T>
  411. inline bool operator <= (const std::basic_string <T> & s1, const ECOM::Utility::String::StringView_Base <T> & s2)
  412. {
  413. return s2.Compare (ECOM::Utility::String::StringView_Base <T> { s1.c_str (), static_cast <CV_String::size_type> (s1.size ()) }) >= 0;
  414. }
  415. //>
  416. //< 针对 StringView 的 Hash
  417. namespace ECOM::Utility
  418. {
  419. inline constexpr size_t Hash64 (const String::DStringView & SV)
  420. {
  421. return Hash64 (SV.Data (), SV.GetLength ());
  422. assert (SV.Hash ());
  423. assert (SV.Hash () == Hash64 (SV.Data (), SV.GetLength ()));
  424. // return SV.Hash ();
  425. }
  426. inline constexpr size_t Hash64 (const String::WStringView & SV)
  427. {
  428. return Hash64 (SV.Data (), SV.GetLength ());
  429. assert (SV.Hash ());
  430. assert (SV.Hash () == Hash64 (SV.Data (), SV.GetLength ()));
  431. // return SV.Hash ();
  432. }
  433. inline constexpr tHash32 Hash32 (const String::DStringView & SV)
  434. {
  435. return Hash32 (SV.Data (), SV.GetLength ());
  436. assert (SV.Hash ());
  437. assert (SV.Hash () == Hash64 (SV.Data (), SV.GetLength ()));
  438. // return SV.Hash ();
  439. }
  440. inline constexpr tHash32 Hash32 (const String::WStringView & SV)
  441. {
  442. return Hash32 (SV.Data (), SV.GetLength ());
  443. assert (SV.Hash ());
  444. assert (SV.Hash () == Hash64 (SV.Data (), SV.GetLength ()));
  445. // return SV.Hash ();
  446. }
  447. #ifdef _WIN64
  448. inline constexpr size_t Hash (const String::DStringView & SV)
  449. {
  450. return Hash64 (SV);
  451. }
  452. inline constexpr size_t Hash (const String::WStringView & SV)
  453. {
  454. return Hash64 (SV);
  455. }
  456. #else
  457. inline constexpr tHash32 Hash (const String::DStringView & SV)
  458. {
  459. return Hash32 (SV);
  460. }
  461. inline constexpr tHash32 Hash (const String::WStringView & SV)
  462. {
  463. return Hash32 (SV);
  464. }
  465. #endif
  466. }