String.DString.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. #pragma once
  2. #include <stdlib.h>
  3. #include <string>
  4. #include <functional>
  5. #include <list>
  6. #include <vector>
  7. #include "String.StringView.hpp"
  8. #ifdef DSTRING_EXPORTS
  9. #define DSTRING_API _declspec(dllexport)
  10. #else
  11. #define DSTRING_API _declspec(dllimport)
  12. #endif
  13. #ifdef _DSTRING_STATIC_
  14. #undef DSTRING_API
  15. #define DSTRING_API
  16. #endif
  17. #ifndef DSTRING_EXPORTS
  18. #ifdef _WIN64
  19. #ifdef _DEBUG
  20. #pragma comment (lib, "ECOM.Utility.DString64D.lib")
  21. #else
  22. #pragma comment (lib, "ECOM.Utility.DString64.lib")
  23. #endif
  24. #else // X86
  25. #endif
  26. #endif // DSTRING_EXPORTS
  27. namespace ECOM::Utility::String
  28. {
  29. class WString;
  30. // using size_type = unsigned int; // 用 unsigned int 比较好, 但是会造成很多编译警告
  31. using size_type = int;
  32. //-----------------------------------------------------------------------------
  33. // DStringData
  34. //-----------------------------------------------------------------------------
  35. namespace
  36. {
  37. struct DStringData
  38. {
  39. long nRefs; // reference count
  40. size_type nDataLength; // length of data (including terminator)
  41. size_type nAllocLength; // length of allocation
  42. // char data[nAllocLength]
  43. char * data () // char* to managed data
  44. {
  45. return (char *) (this + 1);
  46. }
  47. };
  48. }
  49. //-----------------------------------------------------------------------------
  50. // DString
  51. //-----------------------------------------------------------------------------
  52. class DSTRING_API DString
  53. {
  54. public:
  55. using value_type = DString;
  56. using reference = value_type &;
  57. using const_reference = const value_type &;
  58. public:
  59. // Constructors
  60. DString ();
  61. // DString (const char * lpsz);
  62. DString (const char * lpsz, int nLength);
  63. // DString (const unsigned char * lpsz) { Init(); *this = (const char *) lpsz; }
  64. // std::string 支持 std::string (char * p), 即支持隐式从 char * 构造,
  65. // 因此这里变成显示的构造, 以避免 DString (const char *) 的默认构造
  66. explicit DString (const std::string & Src);
  67. DString (const DString & Src);
  68. DString (DString && Src);
  69. public:
  70. ~DString ();
  71. public:
  72. // get data length
  73. size_type GetLength () const;
  74. size_type GetByteLength () const { return GetLength (); }
  75. size_type GetAllocLength () const { return GetData ()->nAllocLength; }
  76. size_type size () const { return GetLength (); };
  77. public:
  78. bool empty () const { return IsEmpty (); }
  79. bool IsEmpty () const { return GetLength () <= 0; }
  80. void Clear ();
  81. void Release ();
  82. public:
  83. char GetAt (int nIndex) const
  84. {
  85. // ASSERT(nIndex >= 0);
  86. // ASSERT(nIndex < GetData()->nDataLength);
  87. return m_pchData [nIndex];
  88. }
  89. char operator [] (int nIndex) const { return GetAt (nIndex); }
  90. void SetAt (int nIndex, char ch);
  91. int Count (char ch) const;
  92. int Count (const StringView & Sub) const;
  93. public:
  94. DString & operator = (const char *) = delete;
  95. DString & operator = (const DString & S);
  96. DString & operator = (DString && S);
  97. DString & operator = (char ch);
  98. DString & operator = (const std::string & S) { AssignCopy (static_cast <int> (S.size ()), S.c_str ()); return (*this); }
  99. DString & operator = (const StringView & S) { return Assign (S); }
  100. DString & operator = (std::initializer_list <StringView> lst) { return Assign (lst); }
  101. DString & operator = (std::initializer_list <const char *> lst) { return Assign (lst); }
  102. public:
  103. //< 这些函数被声明为废除, 避免误写误用. 如果不废除, 编译器将认为/转化为 Append (char)
  104. // 当然可以设计成自动转换 { return Append (From (v)); }
  105. // 但是万一用户真是写错了, 自动转换就变成帮倒忙了
  106. // 2022-12-26
  107. DString & Append (const char * v) = delete; // 改用 "..."_sv 代替
  108. DString & Append (int v) = delete;
  109. DString & Append (unsigned int v) = delete;
  110. DString & Append (short v) = delete;
  111. DString & Append (unsigned short v) = delete;
  112. DString & Append (long v) = delete;
  113. DString & Append (unsigned long v) = delete;
  114. DString & Append (float v) = delete;
  115. DString & Append (double v) = delete;
  116. //>
  117. DString & Append (unsigned char ch)
  118. {
  119. return Append (static_cast <char> (ch));
  120. }
  121. DString & Append (char ch)
  122. {
  123. ConcatInPlace (1, &ch);
  124. return *this;
  125. }
  126. DString & Append (const DString & S)
  127. {
  128. ConcatInPlace (S.GetData ()->nDataLength, S.m_pchData);
  129. return *this;
  130. }
  131. DString & Append (const StringView & S);
  132. DString & Append (const std::string_view & S);
  133. DString & Append (const std::string & S)
  134. {
  135. ConcatInPlace (static_cast <int> (S.length ()), S.c_str());
  136. return *this;
  137. }
  138. // DString & operator += (const char * lpsz) = delete; // 改用 "..."_sv 代替
  139. DString & operator += (const DString & S) { return Append (S); }
  140. DString & operator += (char ch) { return Append (ch); }
  141. DString & operator += (const StringView & S) { return Append (S); }
  142. // DString & operator += (const std::string & S) { return Append (S); }
  143. DString & operator += (std::initializer_list <StringView> lst) { return Append (lst); }
  144. //< DString & operator << (const char * lpsz) = delete; // 改用 "..."_sv 代替
  145. // 不废除了, 某些强制赋值还是需要的.
  146. // 如果不做提前声明, 编译时发生 C2678: 无法找到匹配的运算符
  147. // 2023-11-14
  148. //>
  149. DString & operator << (const DString & S) { return Append (S); }
  150. DString & operator << (char ch) { return Append (ch); }
  151. DString & operator << (const StringView & S) { return Append (S); }
  152. DString & operator << (short v) { return Append (From (v)); }
  153. DString & operator << (int v) { return Append (From (v)); }
  154. DString & operator << (long v) { return Append (From (v)); }
  155. DString & operator << (UINT16 v) { return Append (From (v)); }
  156. DString & operator << (UINT32 v) { return Append (From (v)); }
  157. DString & operator << (unsigned long v) { return Append (From (v)); }
  158. // DString & operator << (const std::string & S) { return Append (S); }
  159. DString & operator << (std::initializer_list <StringView> lst) { return Append (lst); }
  160. public:
  161. int Compare (const char * With) const;
  162. int CompareNoCase (const char * With) const;
  163. int Compare (const DStringView & With) const;
  164. int Compare (const DString & With) const;
  165. //< 增加命名空间后, std::map <DString, ...> 就需要如下内置比较函数
  166. bool operator == (const DString & with) const { return Compare (with) == 0; }
  167. bool operator != (const DString & with) const { return Compare (with) != 0; }
  168. bool operator < (const DString & with) const { return Compare (with) < 0; }
  169. bool operator > (const DString & with) const { return Compare (with) > 0; }
  170. bool operator <= (const DString & with) const { return Compare (with) <= 0; }
  171. bool operator >= (const DString & with) const { return Compare (with) >= 0; }
  172. //>
  173. public:
  174. DString Mid (int nFirst, int nCount) const;
  175. DString Mid (int nFirst) const;
  176. DString Left (int nCount) const;
  177. DString Right (int nCount) const;
  178. // characters from beginning that are also in passed string
  179. DString SpanIncluding (const char * lpszCharSet) const;
  180. // characters from beginning that are not also in passed string
  181. DString SpanExcluding (const char * lpszCharSet) const;
  182. public:
  183. void MakeUpper ();
  184. void MakeLower ();
  185. void MakeReverse ();
  186. public:
  187. int TrimLeft (); // 返回去除的字符数
  188. int TrimRight (); // 返回去除的字符数
  189. void TrimLeft (char chTarget);
  190. void TrimLeft (const StringView & szTargets);
  191. void TrimRight (char chTarget);
  192. void TrimRight (const StringView & szTargets);
  193. DString Trim () const { DString copy = *this; copy.TrimRight (); copy.TrimLeft (); return copy; }
  194. public:
  195. // 用指定的字符填充左边/右边/中间, 直到总长度达到指定值为止
  196. void JustLeft (int ToLength, char ch = ' ');
  197. void JustRight (int ToLength, char ch = ' ');
  198. void JustCenter (int ToLength, char ch = ' ');
  199. public:
  200. int Replace (char chOld, char chNew);
  201. int Replace (const DString & Old, const StringView & New);
  202. int Replace (const StringView & Old, const StringView & New);
  203. int NCReplace (const StringView & Old, const StringView & New);
  204. int ReplaceTabs (int abstand);
  205. int Remove (const StringView & Sub);
  206. int Remove (char chRemove);
  207. int RemoveSpace ();
  208. int RemovePunctuation ();
  209. int RemoveControl ();
  210. // 用谓词函数来判断单个字符是否应该删除, 如果返回 true 就删除
  211. int Remove (std::function <bool (int)> pred);
  212. int NCRemove (const StringView & Sub);
  213. int NCRemove (char chRemove);
  214. public:
  215. int Insert (int nIndex, char ch);
  216. int Insert (int nIndex, const StringView & Sub);
  217. int Delete (int nIndex, int nCount = 1);
  218. void Repeat (char ch, int n);
  219. void Repeat (const StringView & S, int n);
  220. public:
  221. // Pred 返回 true, 表明找到, 否则下一个字符
  222. using tPred = std::function <bool (char ch)>;
  223. public:
  224. int Find (char ch, int nStart = 0) const;
  225. int Find (tPred && pred, int nStart = 0) const;
  226. int Find (const StringView & Sub, int nStart = 0) const;
  227. int Find (const DString & Sub, int nStart = 0) const;
  228. int ReverseFind (char ch, int nStart = 0) const;
  229. int ReverseFind (const StringView & Sub, int nStart = 0) const;
  230. bool StartWith (const StringView & Sub, int iStart = 0) const;
  231. bool EndWith (const StringView & Sub, int iStart = 0) const;
  232. bool StartWith (const DString & Sub, int iStart = 0) const { return StartWith (Sub.To <StringView> (), iStart); }
  233. bool EndWith (const DString & Sub, int iStart = 0) const { return EndWith (Sub.To <StringView> (), iStart); }
  234. bool StartWith (char ch, int iStart = 0) const;
  235. bool EndWith (char ch, int iStart = 0) const;
  236. int NCFind (char ch) const;
  237. int NCFind (const StringView & Sub) const;
  238. public:
  239. // start 是起始位置
  240. using tvCallback = std::function <void (CV_String & sub)>;
  241. // 如果回调返回 true, 则继续, 否则停止. Index=第几次回调
  242. using tbCallback = std::function <bool (int Index, CV_String & sub)>;
  243. int Split (char ch , tvCallback && onFound, int start = 0) const;
  244. int Split (tPred && pred, tvCallback && onFound, int start = 0) const;
  245. int SplitIf (char ch , tbCallback && onFound, int start = 0) const;
  246. int SplitIf (tPred && pred, tbCallback && onFound, int start = 0) const;
  247. // 分割成列表
  248. auto SplitTo (char ch , int start = 0) const -> std::list <DString>;
  249. auto SplitTo (tPred && pred, int start = 0) const -> std::list <DString>;
  250. // 分割成数组, 最多 Max 个
  251. auto SplitMax (int Max, char ch , int start = 0) const -> std::vector <DString>;
  252. auto SplitMax (int Max, tPred && pred, int start = 0) const -> std::vector <DString>;
  253. // 返回指定 Index 的某一个, 如果找不到: 当 Index=0 时返回本串, 否则返回空串
  254. auto SplitOne (int atIndex, char ch , int start = 0) const -> DString;
  255. auto SplitOne (int atIndex, tPred && pred, int start = 0) const -> DString;
  256. // Cast
  257. public:
  258. // return pointer to const string
  259. operator const char * () const { return m_pchData; }
  260. const char * constBuffer () const { return m_pchData; }
  261. char * data () const { return m_pchData; }
  262. const char * c_str () const { return m_pchData; }
  263. operator bool () const = delete;
  264. // 用于自动判别类型
  265. public:
  266. template <typename T> bool Is () const { return false; }
  267. template <> bool Is <DString> () const { return true; }
  268. template <> bool Is <WString> () const { return false; }
  269. public:
  270. static DString From (const int i);
  271. static DString From (const long i);
  272. static DString From (const unsigned int u);
  273. static DString From (const unsigned long u);
  274. static DString From (const __int64 i);
  275. static DString From (const unsigned __int64 u);
  276. static DString From (const double d);
  277. static DString From (const std::string_view & Src);
  278. static DString From (CV_String & Src) { return DString (Src); }
  279. static DString From (const DString & Src) { return DString (Src); }
  280. // repeat a single character
  281. [[nodiscard]]
  282. static DString FromRepeat (char ch, int nRepeat);
  283. public: // 为了支持部分组件能与 8.0 一致, 加入如下功能
  284. template <typename... Args>
  285. [[nodiscard]]
  286. static inline DString FromFormat (const StringView & szFormat, Args && ... args);
  287. template <typename... Args>
  288. inline void Format (const StringView & szFormat, Args && ... args);
  289. // append with the formatted string
  290. template <typename... Args>
  291. void AppendFormat (const StringView & szFormat, Args && ... args);
  292. [[nodiscard]]
  293. static DString FromErrorCode (DWORD errorCode); // 通过调用 FormtMessage, 把 Win32 错误码转换成字符串
  294. public:
  295. // Access to string implementation buffer as "C" character array
  296. // get pointer to modifiable buffer at least as long as nMinBufLength
  297. char * GetBuffer (int nMinBufLength);
  298. // release buffer, setting length to nNewLength (or to first nul if -1)
  299. void ReleaseBuffer (int nNewLength = -1);
  300. // get pointer to modifiable buffer exactly as long as nNewLength
  301. char * GetBufferSetLength (int nNewLength);
  302. void Reserve (int nMinBufLength) { GetBuffer (nMinBufLength); }
  303. void reserve (int nMinBufLength) { GetBuffer (nMinBufLength); }
  304. public:
  305. // 转换函数
  306. double Double () const { return atof (m_pchData); }
  307. int Int () const { int i = atoi (m_pchData); if (i) return i; return strtol (m_pchData, nullptr, 16); }
  308. long Long () const { long l = atol (m_pchData); if (l) return l; return strtol (m_pchData, nullptr, 16); }
  309. char Char () const { return m_pchData[0]; }
  310. bool Bool () const;
  311. __int64 Int64 () const { __int64 i = _atoi64 (m_pchData); if (i) return i; return _strtoi64 (m_pchData, nullptr, 16); }
  312. template <typename T> T To () const = delete;
  313. template <> int To () const { return Int (); }
  314. template <> double To () const { return Double (); }
  315. template <> float To () const { return (float) Double (); }
  316. template <> long To () const { return Long (); }
  317. template <> bool To () const { return Bool (); }
  318. template <> __int64 To () const { return Int64 (); }
  319. template <> unsigned int To () const { return Int (); }
  320. template <> unsigned __int64 To () const { return Int64 (); }
  321. template <> unsigned long To () const { return Long (); }
  322. template <> DString To () const { return *this; }
  323. template <> std::string To () const { return std::string { m_pchData, static_cast <std::string::size_type> (GetLength ())}; }
  324. template <> std::string_view To () const { return std::string_view { m_pchData, static_cast <std::string_view::size_type> (GetLength ()) }; }
  325. public: // 与 StringView 的转换,构造,赋值等
  326. DString (const StringView & Src);
  327. //DString (const std::string_view & Src); // 不能定义这个构造函数, 否则, 编译 eSTR::DString Path (szPath) 时, 编译器会发生警告: 重载函数的调用不明确
  328. public:
  329. operator StringView () const noexcept;
  330. operator std::string_view () const noexcept;
  331. // ? 不能定义这个强制转换函数, 否则, 编译 Hash (DString) 时, 编译器会发生警告: 重载函数的调用不明确
  332. public:
  333. template <> StringView To () const;
  334. template <> const StringView To () const;
  335. DString & Assign (const StringView & _Right);
  336. DString & Assign (const std::string_view & _Right);
  337. DString & Append (std::initializer_list <StringView> lst);
  338. DString & Append (std::initializer_list <std::string_view> lst);
  339. DString & Append (std::initializer_list <const char *> lst);
  340. DString & Assign (std::initializer_list <StringView> lst);
  341. DString & Assign (std::initializer_list <std::string_view> lst);
  342. DString & Assign (std::initializer_list <const char *> lst);
  343. // 万一编译器警告: 调用不明确, 就用模板函数显式告诉编译器
  344. template <typename T> static DString From (std::initializer_list <T> lst) { DString rc; rc.Assign (lst); return rc; }
  345. static DString From (std::initializer_list <StringView> lst) { DString rc; rc.Assign (lst); return rc; }
  346. static DString From (std::initializer_list <std::string_view> lst) { DString rc; rc.Assign (lst); return rc; }
  347. static DString From (std::initializer_list <const char *> lst) { DString rc; rc.Assign (lst); return rc; }
  348. public:
  349. // 判断整个字符串是否是某一类字符组成
  350. bool IsDigit () const;
  351. bool IsAlNum () const;
  352. bool IsAlpha () const;
  353. bool IsUpper () const;
  354. bool IsLower () const;
  355. bool IsSpace () const;
  356. // 判断某个字符是否是某一类字符组成
  357. bool IsDigit (int nPos) const;
  358. bool IsAlNum (int nPos) const;
  359. bool IsAlpha (int nPos) const;
  360. bool IsUpper (int nPos) const;
  361. bool IsLower (int nPos) const;
  362. bool IsSpace (int nPos) const;
  363. public:
  364. bool ToCharacterSet (unsigned int CodePage);
  365. bool FromCharacterSet (unsigned int CodePage);
  366. public:
  367. // release memory allocated to but unused by string
  368. void FreeExtra ();
  369. protected:
  370. char * m_pchData; // pointer to ref counted string data
  371. // implementation helpers
  372. DStringData * GetData () const
  373. {
  374. return ((DStringData *) m_pchData)-1;
  375. }
  376. bool IsNil () const; // 用来判断 m_pchData 是否等于 DStringPchNil
  377. void Init ();
  378. void AllocCopy (DString & dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
  379. void AllocBuffer (int nLen);
  380. void AssignCopy (int Len, const char * S);
  381. void ConcatCopy (int L1, const char * S1, int L2, const char * S2);
  382. void ConcatInPlace (int Len, const char * S);
  383. void CopyBeforeWrite ();
  384. void AllocBeforeWrite (int nLen);
  385. DString & Assign (const DString & Src); // 拷贝赋值
  386. void MoveAssign (DString & Src);
  387. void MoveAssign (DString && Src);
  388. protected:
  389. static void Release (DStringData * pData);
  390. static void FreeData (DStringData * pData);
  391. //-----------------------------------------------------------------------------
  392. // Token类用来对字符串进行标识符切分
  393. //-----------------------------------------------------------------------------
  394. public:
  395. class DSTRING_API Token
  396. {
  397. public:
  398. Token (const DString & str, bool bSkipPunctuation = false) :
  399. m_Str (str),
  400. m_bSkipPunctuation (bSkipPunctuation)
  401. {
  402. // 在Restart之前先初始化这个变量,因为Restart之后需要立即调用Next,
  403. // 而Next函数需要这个变量
  404. Restart ();
  405. }
  406. public:
  407. operator bool () const { return m_bContinue; };
  408. operator DString () const { return Current (); };
  409. public:
  410. // 定位到下一个标识符
  411. bool Next (void);
  412. // 定位到下一个标识符,但是以出作为分割符
  413. bool Next (char sep);
  414. // 定位到行尾,Current返回直到行尾的所有字符,但是不包括行尾的回车或换行
  415. bool NextLine (void);
  416. DString Current (void) const; // 获得当前标识符,或者当前行
  417. bool IsValid () const { return (m_nL <= m_nR); };
  418. void Clear (void)
  419. {
  420. m_nL = 0;
  421. m_nR = -1;
  422. m_nNext = 0;
  423. m_bContinue = true;
  424. m_nStrLength = 0;
  425. }
  426. void Restart (void) // 重新开始
  427. {
  428. m_szDoc = m_Str;
  429. Clear ();
  430. m_nStrLength = (int) strlen (m_szDoc);
  431. Next ();
  432. }
  433. bool SkipPunctuation (bool bSkipPunctuation)
  434. {
  435. bool tmp = m_bSkipPunctuation;
  436. m_bSkipPunctuation =bSkipPunctuation;
  437. return tmp;
  438. }
  439. void operator ++ () // ++Token; prevfix
  440. {
  441. Next ();
  442. }
  443. void operator ++ (int) // Token++; postfix
  444. {
  445. Next ();
  446. }
  447. DString operator () (void) const
  448. {
  449. return Current ();
  450. }
  451. protected:
  452. int FindWhitespace (int nChar) const; // 从nChar开始,定位到下一个非空字符,并返回这个位置的索引,如果找不到,返回-1
  453. int FindChar (int nChar, char ch) const; // 从nChar开始,在字符串中寻找与ch相同的下一个ch,并返回这个位置的索引,如果找不到,返回-1
  454. protected:
  455. const DString & m_Str;
  456. const char * m_szDoc;
  457. int m_nL; // 当前标识符的左边界
  458. int m_nR; // 当前标识符的右边界
  459. int m_nNext; // 下一个标识符的初始位置
  460. bool m_bContinue; // 可用继续迭代吗?
  461. int m_nStrLength; // 字符串长度;
  462. bool m_bSkipPunctuation; // Next()时跳过标点符号,即Current()不会返回遇到的标点符号
  463. };
  464. };
  465. }
  466. namespace eSTR = ECOM::Utility::String;
  467. DSTRING_API eSTR::DString operator + (const eSTR::DString & S1, const eSTR::DString & S2);
  468. DSTRING_API eSTR::DString operator + (const eSTR::DString & S, char ch);
  469. DSTRING_API eSTR::DString operator + (const eSTR::DString & S1, const eSTR::StringView & S2);
  470. DSTRING_API eSTR::DString operator + (const eSTR::StringView & S1, const eSTR::DString & S2);
  471. DSTRING_API eSTR::DString operator + (const eSTR::StringView & S1, char ch);
  472. DSTRING_API eSTR::DString operator + (char ch, const eSTR::DString & S);
  473. DSTRING_API eSTR::DString operator + (const eSTR::DString & S1, const std::string_view & S2);
  474. DSTRING_API eSTR::DString operator + (const std::string_view & S1, const eSTR::DString & S2);
  475. DSTRING_API eSTR::DString operator + (const std::string_view & S1, char ch);
  476. DSTRING_API eSTR::DString operator + (const eSTR::DString & S1, const std::string & S2);
  477. DSTRING_API eSTR::DString operator + (const std::string & S1, const eSTR::DString & S2);
  478. DSTRING_API eSTR::DString operator + (const eSTR::StringView & S1, const eSTR::StringView & S2);
  479. // Compare helpers
  480. #if 0 // 如下比较重载将导致编译器无法选择, 因此注释掉
  481. DSTRING_API inline bool operator == (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) == 0; }
  482. DSTRING_API inline bool operator != (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) != 0; }
  483. DSTRING_API inline bool operator < (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) < 0; }
  484. DSTRING_API inline bool operator > (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) > 0; }
  485. DSTRING_API inline bool operator <= (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) <= 0; }
  486. DSTRING_API inline bool operator >= (const eSTR::DString & s1, const eSTR::DString & s2) { return s1.Compare (s2) >= 0; }
  487. #endif
  488. DSTRING_API inline bool operator == (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) == 0; }
  489. DSTRING_API inline bool operator != (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) != 0; }
  490. DSTRING_API inline bool operator < (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) < 0; }
  491. DSTRING_API inline bool operator > (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) > 0; }
  492. DSTRING_API inline bool operator <= (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) <= 0; }
  493. DSTRING_API inline bool operator >= (const eSTR::DString & s1, const eSTR::StringView s2) { return s1.Compare (s2) >= 0; }
  494. #if 1
  495. inline bool operator == (const eSTR::DString & s1, const char * s2) = delete;
  496. inline bool operator != (const eSTR::DString & s1, const char * s2) = delete;
  497. inline bool operator < (const eSTR::DString & s1, const char * s2) = delete;
  498. inline bool operator > (const eSTR::DString & s1, const char * s2) = delete;
  499. inline bool operator <= (const eSTR::DString & s1, const char * s2) = delete;
  500. inline bool operator >= (const eSTR::DString & s1, const char * s2) = delete;
  501. #else
  502. DSTRING_API inline bool operator == (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) == 0; }
  503. DSTRING_API inline bool operator != (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) != 0; }
  504. DSTRING_API inline bool operator < (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) < 0; }
  505. DSTRING_API inline bool operator > (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) > 0; }
  506. DSTRING_API inline bool operator <= (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) <= 0; }
  507. DSTRING_API inline bool operator >= (const eSTR::DString & s1, const char * s2) { return s1.Compare (s2) >= 0; }
  508. #endif
  509. DSTRING_API inline bool operator == (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) == 0; }
  510. DSTRING_API inline bool operator != (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) != 0; }
  511. DSTRING_API inline bool operator < (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) > 0; }
  512. DSTRING_API inline bool operator > (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) < 0; }
  513. DSTRING_API inline bool operator <= (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) >= 0; }
  514. DSTRING_API inline bool operator >= (const eSTR::StringView & s1, const eSTR::DString & s2) { return s2.Compare (s1) <= 0; }
  515. #if 1
  516. inline bool operator == (const char * s1, const eSTR::DString & s2) = delete;
  517. inline bool operator != (const char * s1, const eSTR::DString & s2) = delete;
  518. inline bool operator < (const char * s1, const eSTR::DString & s2) = delete;
  519. inline bool operator > (const char * s1, const eSTR::DString & s2) = delete;
  520. inline bool operator <= (const char * s1, const eSTR::DString & s2) = delete;
  521. inline bool operator >= (const char * s1, const eSTR::DString & s2) = delete;
  522. #else
  523. DSTRING_API inline bool operator == (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) == 0; }
  524. DSTRING_API inline bool operator != (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) != 0; }
  525. DSTRING_API inline bool operator < (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) > 0; }
  526. DSTRING_API inline bool operator > (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) < 0; }
  527. DSTRING_API inline bool operator <= (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) >= 0; }
  528. DSTRING_API inline bool operator >= (const char * s1, const eSTR::DString & s2) { return s2.Compare (s1) <= 0; }
  529. #endif
  530. #include "String.Format.tlh"
  531. template <typename... Args>
  532. inline void eSTR::DString::Format (const StringView & szFormat, Args && ... args)
  533. {
  534. char * DString_TLSBuffer_Get ();
  535. int DString_TLSBuffer_Size ();
  536. auto pb = DString_TLSBuffer_Get ();
  537. auto sz = DString_TLSBuffer_Size ();
  538. if (! pb)
  539. {
  540. this->Init ();
  541. return;
  542. }
  543. auto len = StringFormat (pb, sz).Format (szFormat, std::forward <Args> (args)...);
  544. auto pc = GetBufferSetLength (len);
  545. memcpy_s (pc, len, pb, len);
  546. }
  547. template <typename... Args>
  548. static inline eSTR::DString eSTR::DString::FromFormat (const StringView & szFormat, Args && ... args)
  549. {
  550. DString rc;
  551. rc.Format (szFormat, std::forward <Args> (args)...);
  552. return std::move (rc);
  553. }
  554. template <typename... Args>
  555. inline void eSTR::DString::AppendFormat (const StringView & szFormat, Args && ... args)
  556. {
  557. DString rc;
  558. rc.Format (szFormat, std::forward <Args> (args)...);
  559. Append (rc);
  560. }
  561. template <>
  562. struct std::hash <eSTR::DString>
  563. {
  564. size_t operator() (const char * pc) const noexcept
  565. {
  566. auto len = strlen (pc);
  567. return std::_Hash_array_representation (pc, len);
  568. }
  569. size_t operator () (const eSTR::DString & from) const noexcept
  570. {
  571. auto pc = from.constBuffer ();
  572. auto len = from.GetLength ();
  573. return std::_Hash_array_representation (pc, len);
  574. }
  575. };
  576. #include "Hash.String.hpp"
  577. //< 针对 DString 的 Hash. 目的是避免编译器的错误: 重载函数调用不明确
  578. namespace ECOM::Utility
  579. {
  580. inline constexpr size_t Hash (const String::DString & SV)
  581. {
  582. return (Hash (SV.To <String::DStringView> ()));
  583. }
  584. }