String.Format.tlh 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  1. #pragma once
  2. #ifndef ASSERT
  3. #include <assert.h>
  4. #define ASSERT assert
  5. #endif
  6. //-----------------------------------------------------------------------------
  7. // 字符串格式化
  8. // 思路主要来自祈宇的文章:
  9. // <实现一个简单的字符串格式化方法>
  10. // https://www.cnblogs.com/qicosmos/p/3825612.html
  11. //-----------------------------------------------------------------------------
  12. #include <tuple>
  13. #include <type_traits>
  14. #include <string>
  15. #include <inttypes.h>
  16. #include <cctype>
  17. #include <stdexcept>
  18. #include <codecvt>
  19. #include <chrono>
  20. #pragma warning (disable : 4996)
  21. //warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
  22. // To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
  23. namespace ECOM::Utility::String
  24. {
  25. template <typename> constexpr bool dependent_false = false;
  26. template <typename T>
  27. inline std::string ToString (const T & value)
  28. {
  29. static_assert (dependent_false <T>, "You must implement ToString for type T with Partial template specialization !");
  30. return std::string ();
  31. }
  32. }
  33. // 针对 bool 的模板偏特化, 编译要求定义这些函数, 但是实际上不会执行
  34. namespace ECOM::Utility::String
  35. {
  36. template <> inline std::string ToString (const bool & value)
  37. {
  38. static const auto strTrue = std::string ("true");
  39. static const auto strFalse = std::string ("false");
  40. if (value) return strTrue;
  41. else return strFalse;
  42. }
  43. }
  44. namespace ECOM::Utility::String
  45. {
  46. static const char __MsgOfNull_ [] = "null";
  47. static const int __LenOfNull_ = sizeof (__MsgOfNull_) - 1;
  48. template <typename tDeriveClass>
  49. class __declspec(novtable) _string_format_detail
  50. {
  51. protected:
  52. char * m_BufferOrg;
  53. char * m_Buffer;
  54. int m_NbOfChar;
  55. protected:
  56. inline int NbOfRemain () const
  57. {
  58. return m_NbOfChar - int (m_Buffer - m_BufferOrg);
  59. }
  60. private:
  61. template <typename arg>
  62. int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
  63. {
  64. assert (false);
  65. return 22;
  66. }
  67. public:
  68. inline _string_format_detail (char * buf, int NbOfChar) // 缓冲区指针, 缓冲区长度 (字节计数)
  69. {
  70. assert (buf);
  71. m_BufferOrg = m_Buffer = buf;
  72. m_NbOfChar = NbOfChar;
  73. }
  74. protected:
  75. inline void CharFormatArg (char ch)
  76. {
  77. // ch 不能是控制字符, 否则不知道显示成什么
  78. // assert (0 < ch);
  79. assert (9 <= ch); assert (ch <= 127);
  80. *m_Buffer = ch;
  81. m_Buffer ++;
  82. }
  83. // 有符号
  84. template <typename T>
  85. inline void sDigitFormatArg (T i)
  86. {
  87. _ltoa (i, m_Buffer, 10);
  88. m_Buffer += strlen (m_Buffer);
  89. }
  90. // 无符号
  91. template <typename T>
  92. inline void uDigitFormatArg (T i)
  93. {
  94. _ultoa (i, m_Buffer, 10);
  95. m_Buffer += strlen (m_Buffer);
  96. }
  97. //< 64 位偏特化
  98. template <>
  99. inline void sDigitFormatArg (__int64 i)
  100. {
  101. _i64toa (i, m_Buffer, 10);
  102. m_Buffer += strlen (m_Buffer);
  103. }
  104. template <>
  105. inline void uDigitFormatArg (unsigned __int64 i)
  106. {
  107. _ui64toa (i, m_Buffer, 10);
  108. m_Buffer += strlen (m_Buffer);
  109. }
  110. //>
  111. template <typename T>
  112. // fmt: D,X, D3,X4,d3,x4, D03,X04
  113. // D - 用 10 进制, X - 用 16 进制
  114. // D3 - 转换成 3 个数字, 如果不足, 填充空格
  115. // D03 - 转换成 3 个数字, 如果不足, 用 0 填充
  116. inline void DigitFormatArg (T i, const char * fmt)
  117. {
  118. assert (fmt);
  119. assert (fmt [0]);
  120. auto chfmt = fmt [0];
  121. if (chfmt == 'c' || chfmt == 'C')
  122. {
  123. CharFormatArg ((char) i);
  124. return;
  125. }
  126. if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
  127. if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
  128. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  129. if (! rc) // 尝试浮点数, 万一使用者搞错了
  130. {
  131. rc = (chfmt == 'f' || chfmt == 'F');
  132. if (rc)
  133. {
  134. FormatArg ((double) i, fmt);
  135. return;
  136. }
  137. }
  138. assert (rc);
  139. if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
  140. char tofmt [8] = { '%', };
  141. // D023, X093 - 1 个格式字母带 3 个数字, tofmt 将成为 "%023d" 或 "%093x"
  142. // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
  143. // d1, d3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%1d" 或 "%3d"
  144. if (std::isdigit (fmt [1]))
  145. {
  146. int iFmtChar = 2;
  147. for (int Index = 1; Index <= 3; Index ++)
  148. {
  149. if (std::isdigit (fmt [Index]))
  150. {
  151. tofmt [Index] = fmt [Index];
  152. iFmtChar = Index + 1;
  153. }
  154. else
  155. break;
  156. }
  157. tofmt [iFmtChar] = chfmt;
  158. }
  159. else // 只有 1 个 d, 比如写成 {$:d}
  160. {
  161. tofmt [1] = chfmt;
  162. tofmt [2] = 0;
  163. }
  164. auto pT = static_cast <tDeriveClass *> (this);
  165. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
  166. m_Buffer += r;
  167. }
  168. //< 64 位偏特化
  169. template <>
  170. // fmt: D,X, D3,X4,d3,x4, D03,X04
  171. // __int64 只支持 d, x, 不支持前导/后导, 因此下面的代码只用了 D 或 X
  172. inline void DigitFormatArg (__int64 i, const char * fmt)
  173. {
  174. assert (fmt);
  175. assert (fmt [0]);
  176. auto chfmt = fmt [0];
  177. if (chfmt == 'c' || chfmt == 'C')
  178. {
  179. CharFormatArg ((char) i);
  180. return;
  181. }
  182. if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
  183. if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
  184. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  185. assert (rc);
  186. if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
  187. char tofmt [8] = { '%', 'I', 'I', chfmt };
  188. auto pT = static_cast <tDeriveClass *> (this);
  189. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
  190. m_Buffer += r;
  191. }
  192. // 64 位偏特化
  193. template <>
  194. // fmt: D,X, D3,X4,d3,x4, D03,X04
  195. // __int64 只支持 d, x, 不支持前导/后导, 因此下面的代码只用了 D 或 X
  196. inline void DigitFormatArg (unsigned __int64 i, const char * fmt)
  197. {
  198. DigitFormatArg <__int64> ((__int64) i, fmt);
  199. }
  200. //>
  201. // 字符,不带格式, 就认为是字符
  202. inline void FormatArg (char ch) { CharFormatArg (ch); }
  203. // inline void FormatArg (unsigned char ch) { CharFormatArg (ch); }
  204. inline void FormatArg (unsigned char ch) { uDigitFormatArg <unsigned short> (ch); }
  205. // 字符,带格式, 就认为是整数
  206. inline void FormatArg (char ch, const char * fmt) { DigitFormatArg <int> (ch, fmt); }
  207. inline void FormatArg (unsigned char ch, const char * fmt) { DigitFormatArg <int> (ch, fmt); }
  208. //< 各种整数
  209. inline void FormatArg (int i) { sDigitFormatArg <int> (i); }
  210. inline void FormatArg (long i) { sDigitFormatArg <long> (i); }
  211. inline void FormatArg (short i) { sDigitFormatArg <short> (i); }
  212. inline void FormatArg (unsigned int i) { uDigitFormatArg <unsigned int> (i); }
  213. inline void FormatArg (unsigned long i) { uDigitFormatArg <unsigned long> (i); }
  214. inline void FormatArg (unsigned short i) { uDigitFormatArg <unsigned short> (i); }
  215. inline void FormatArg (int i , const char * fmt) { DigitFormatArg <int> (i, fmt); }
  216. inline void FormatArg (unsigned int i , const char * fmt) { DigitFormatArg <unsigned int> (i, fmt); }
  217. inline void FormatArg (long i , const char * fmt) { DigitFormatArg <long> (i, fmt); }
  218. inline void FormatArg (unsigned long i , const char * fmt) { DigitFormatArg <unsigned long> (i, fmt); }
  219. inline void FormatArg (short i , const char * fmt) { DigitFormatArg <short> (i, fmt); }
  220. inline void FormatArg (unsigned short i, const char * fmt) { DigitFormatArg <unsigned short> (i, fmt); }
  221. // int64
  222. inline void FormatArg (__int64 i) { sDigitFormatArg <__int64> (i); }
  223. inline void FormatArg (unsigned __int64 i) { uDigitFormatArg <unsigned __int64> (i); }
  224. // int64, 带参数
  225. inline void FormatArg (__int64 i , const char * fmt) { DigitFormatArg <__int64> (i, fmt); }
  226. inline void FormatArg (unsigned __int64 i , const char * fmt) { DigitFormatArg <unsigned __int64> (i, fmt); }
  227. //>
  228. //< 浮点数, 默认精度由 printf 决定
  229. inline void FormatArg (double i)
  230. {
  231. auto pT = static_cast <tDeriveClass *> (this);
  232. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%f", i);
  233. m_Buffer += r;
  234. }
  235. // fmt: F3, 精确到小数点后面3位
  236. // fmt: F, 默认精度由 printf 决定
  237. // fmt : f} --> tofmt : %f
  238. // fmt : f3} --> tofmt : %.3f
  239. // fmt : f23} --> tofmt : %.23f
  240. inline void FormatArg (double i, const char * fmt)
  241. {
  242. assert (fmt);
  243. assert (fmt [0]);
  244. char tofmt [8] = { '%', '.', };
  245. auto chfmt = fmt [0];
  246. // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
  247. // f1, f3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%.1f" 或 "%.3f"
  248. if (std::isdigit (fmt [1]))
  249. {
  250. int iFmtChar = 2;
  251. for (int Index = 1; Index <= 3; Index ++)
  252. {
  253. if (std::isdigit (fmt [Index]))
  254. {
  255. tofmt [Index+1] = fmt [Index];
  256. iFmtChar = Index + 2;
  257. }
  258. else
  259. break;
  260. }
  261. tofmt [iFmtChar] = chfmt;
  262. }
  263. else // 只有 1 个 f, 比如写成 {$:f}
  264. {
  265. tofmt [1] = chfmt;
  266. tofmt [2] = 0;
  267. }
  268. auto pT = static_cast <tDeriveClass *> (this);
  269. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
  270. m_Buffer += r;
  271. }
  272. inline void FormatArg (float f)
  273. {
  274. double d = f;
  275. FormatArg (d);
  276. }
  277. inline void FormatArg (float f, const char * fmt)
  278. {
  279. double d = f;
  280. FormatArg (d, fmt);
  281. }
  282. //>
  283. // 字符串, 无格式
  284. inline void FormatArg (const char * p)
  285. {
  286. if (p == nullptr)
  287. {
  288. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  289. m_Buffer += __LenOfNull_;
  290. return;
  291. }
  292. int len = (int) strlen (p);
  293. memcpy (m_Buffer, p, len);
  294. m_Buffer += len;
  295. }
  296. //< 字符串, 带格式, 格式:
  297. // 6 : 最长 6 个字符, 右对齐, 左边填空
  298. // +6 : 最长 6 个字符, 右对齐, 左边填空
  299. // -6 : 最长 6 个字符, 左对齐, 右边填空
  300. inline void FormatArg (const char * p, const char * fmt)
  301. {
  302. if (p == nullptr)
  303. {
  304. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  305. m_Buffer += __LenOfNull_;
  306. return;
  307. }
  308. int len = (int) strlen (p);
  309. _StringFormatArg (p, len, fmt);
  310. }
  311. inline void FormatArg (char * p)
  312. {
  313. FormatArg ((const char *) p);
  314. }
  315. inline void FormatArg (char * p, const char * fmt)
  316. {
  317. FormatArg ((const char *)p, fmt);
  318. }
  319. inline void _StringFormatArg (const char * p, int len, const char * fmt)
  320. {
  321. if (p == nullptr)
  322. {
  323. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  324. m_Buffer += __LenOfNull_;
  325. return;
  326. }
  327. if (fmt [0] == '-') // 左对齐
  328. {
  329. fmt ++;
  330. auto i = atoi (fmt);
  331. if (i > len)
  332. {
  333. memcpy (m_Buffer, p, len);
  334. m_Buffer += len;
  335. memset (m_Buffer, ' ', i - len);
  336. m_Buffer += i - len;
  337. }
  338. else
  339. {
  340. memcpy (m_Buffer, p, len);
  341. m_Buffer += len;
  342. }
  343. }
  344. else // 右对齐
  345. {
  346. if (fmt [0] == '+') fmt ++;
  347. auto i = atoi (fmt);
  348. if (i > len)
  349. {
  350. memset (m_Buffer, ' ', i - len);
  351. m_Buffer += i - len;
  352. memcpy (m_Buffer, p, len);
  353. m_Buffer += len;
  354. }
  355. else
  356. {
  357. memcpy (m_Buffer, p, len);
  358. m_Buffer += len;
  359. }
  360. }
  361. }
  362. //>
  363. // bool
  364. void FormatArg (bool b)
  365. {
  366. if (b)
  367. {
  368. *m_Buffer = 't'; m_Buffer ++;
  369. *m_Buffer = 'r'; m_Buffer ++;
  370. *m_Buffer = 'u'; m_Buffer ++;
  371. *m_Buffer = 'e'; m_Buffer ++;
  372. }
  373. else
  374. {
  375. *m_Buffer = 'f'; m_Buffer ++;
  376. *m_Buffer = 'a'; m_Buffer ++;
  377. *m_Buffer = 'l'; m_Buffer ++;
  378. *m_Buffer = 's'; m_Buffer ++;
  379. *m_Buffer = 'e'; m_Buffer ++;
  380. }
  381. }
  382. // 任意指针类型 - const
  383. template <typename UNP>
  384. inline void FormatArg (const UNP * ptr)
  385. {
  386. auto pT = static_cast <tDeriveClass *> (this);
  387. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%p", ptr);
  388. m_Buffer += r;
  389. }
  390. // 任意指针类型, 带格式 -- 转化成整数来格式化
  391. template <typename UNP>
  392. inline void FormatArg (const UNP * ptr, const char * fmt)
  393. {
  394. DigitFormatArg <uintptr_t> ((uintptr_t) ptr, fmt);
  395. }
  396. // 任意指针类型 - 非 const
  397. template <typename UNP>
  398. inline void FormatArg (UNP * ptr)
  399. {
  400. auto pT = static_cast <tDeriveClass *> (this);
  401. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%p", ptr);
  402. m_Buffer += r;
  403. }
  404. // 任意指针类型, 带格式 -- 转化成整数来格式化
  405. template <typename UNP>
  406. inline void FormatArg (UNP * ptr, const char * fmt)
  407. {
  408. DigitFormatArg <uintptr_t> ((uintptr_t)ptr, fmt);
  409. }
  410. // 偏特化 - 字符串指针
  411. template <> inline void FormatArg (const char * p)
  412. {
  413. if (p == nullptr)
  414. {
  415. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  416. m_Buffer += __LenOfNull_;
  417. return;
  418. }
  419. int len = (int) strlen (p);
  420. memcpy (m_Buffer, p, len);
  421. m_Buffer += len;
  422. }
  423. // 偏特化 - 字符串指针
  424. template <> inline void FormatArg (const char * p, const char *)
  425. {
  426. if (p == nullptr)
  427. {
  428. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  429. m_Buffer += __LenOfNull_;
  430. return;
  431. }
  432. int len = (int) strlen (p);
  433. memcpy (m_Buffer, p, len);
  434. m_Buffer += len;
  435. }
  436. protected:
  437. //< string_view
  438. inline void FormatArg (const std::string_view & s)
  439. {
  440. memcpy (m_Buffer, s.data (), s.size ());
  441. m_Buffer += s.size ();
  442. }
  443. inline void FormatArg (const std::string_view & s, const char * fmt)
  444. {
  445. _StringFormatArg (s.data (), static_cast <int> (s.size ()), fmt);
  446. }
  447. inline void FormatArg (const std::wstring_view & s)
  448. {
  449. std::wstring_convert <std::codecvt <wchar_t, char, mbstate_t>> converter;
  450. auto str = converter.to_bytes (s.data (), s.data () + s.size ());
  451. FormatArg (str);
  452. }
  453. inline void FormatArg (const std::wstring_view & s, const char * fmt)
  454. {
  455. std::wstring_convert <std::codecvt <wchar_t, char, mbstate_t>> converter;
  456. auto str = converter.to_bytes (s.data (), s.data () + s.size ());
  457. FormatArg (str, fmt);
  458. }
  459. //>
  460. #ifdef __Utility_String_StringView__
  461. inline void FormatArg (const DStringView & s)
  462. {
  463. memcpy (m_Buffer, s.constBuffer (), s.Length ());
  464. m_Buffer += s.Length ();
  465. }
  466. inline void FormatArg (const DStringView & s, const char * fmt)
  467. {
  468. _StringFormatArg (s.constBuffer (), s.Length (), fmt);
  469. }
  470. #endif
  471. #ifdef DSTRING_API
  472. inline void FormatArg (const DString & s)
  473. {
  474. memcpy (m_Buffer, s.constBuffer (), s.GetLength ());
  475. m_Buffer += s.GetLength ();
  476. }
  477. inline void FormatArg (const DString & s, const char * fmt)
  478. {
  479. _StringFormatArg (s.constBuffer (), s.GetLength (), fmt);
  480. }
  481. #endif
  482. //< std::string
  483. inline void FormatArg (const std::string & s)
  484. {
  485. memcpy (m_Buffer, s.data (), s.size ());
  486. m_Buffer += s.size ();
  487. }
  488. inline void FormatArg (const std::string & s, const char * fmt)
  489. {
  490. _StringFormatArg (s.data (), (int) s.size (), fmt);
  491. }
  492. //>
  493. #ifdef WSTRING_API
  494. //#if 1
  495. inline void FormatArg (const wchar_t * p)
  496. {
  497. if (p == nullptr)
  498. {
  499. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  500. m_Buffer += __LenOfNull_;
  501. return;
  502. }
  503. auto dp = WString (WStringView (p)).ToDString ();
  504. FormatArg (dp);
  505. }
  506. inline void FormatArg (const wchar_t * p, const char * fmt)
  507. {
  508. if (p == nullptr)
  509. {
  510. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  511. m_Buffer += __LenOfNull_;
  512. return;
  513. }
  514. auto dp = WString (WStringView (p)).ToDString ();
  515. FormatArg (dp, fmt);
  516. }
  517. inline void FormatArg (const WString & s)
  518. {
  519. auto dp = s.ToDString ();
  520. FormatArg (dp);
  521. }
  522. inline void FormatArg (const WString & s, const char * fmt)
  523. {
  524. auto dp = s.ToDString ();
  525. FormatArg (dp, fmt);
  526. }
  527. inline void FormatArg (const std::wstring & s)
  528. {
  529. auto dp = WString (s.c_str ()).ToDString ();
  530. FormatArg (dp);
  531. }
  532. inline void FormatArg (const std::wstring & s, const char * fmt)
  533. {
  534. auto dp = WString (s.c_str ()).ToDString ();
  535. FormatArg (dp, fmt);
  536. }
  537. inline void FormatArg (const WStringView & ws)
  538. {
  539. auto ds = WString (ws).ToDString ();
  540. FormatArg (ds);
  541. }
  542. inline void FormatArg (const WStringView & ws, const char * fmt)
  543. {
  544. auto ds = WString (ws).ToDString ();
  545. FormatArg (ds, fmt);
  546. }
  547. #endif
  548. #if 1
  549. template <typename TO>
  550. inline void FormatArg (const TO & _val)
  551. {
  552. auto dp = ECOM::Utility::String::ToString <TO> (_val);
  553. FormatArg (dp);
  554. }
  555. template <typename TO>
  556. inline void FormatArg (const TO & _val, const char * fmt)
  557. {
  558. auto dp = ECOM::Utility::String::ToString <TO> (_val);
  559. FormatArg (dp, fmt);
  560. }
  561. #endif
  562. protected:
  563. template <size_t k, typename Tuple>
  564. typename std::enable_if <(k == std::tuple_size <Tuple>::value)>::type
  565. inline GetArgByIndex (size_t, Tuple &)
  566. {
  567. // 忽略那些误写的位置参数, 比如忽略下面的 {99}
  568. // mLog::Info ("{99}, {0}", 123456
  569. #ifdef _DEBUG
  570. // throw std::invalid_argument ("arg index out of range");
  571. #endif
  572. }
  573. template <size_t k = 0, typename Tuple>
  574. typename std::enable_if <(k < std::tuple_size <Tuple>::value)>::type
  575. inline GetArgByIndex (size_t index, Tuple & tp)
  576. {
  577. if (k == index)
  578. {
  579. FormatArg (std::get<k> (tp));
  580. }
  581. else
  582. {
  583. GetArgByIndex <k + 1> (index, tp);
  584. }
  585. }
  586. template <size_t k, typename Tuple>
  587. typename std::enable_if <(k == std::tuple_size <Tuple>::value)>::type
  588. inline GetArgByIndex (size_t, Tuple &, const char * fmt)
  589. {
  590. #ifdef _DEBUG
  591. // throw std::invalid_argument ("arg index out of range");
  592. #endif
  593. }
  594. template <size_t k = 0, typename Tuple>
  595. typename std::enable_if <(k < std::tuple_size <Tuple>::value)>::type
  596. inline GetArgByIndex (size_t index, Tuple & tp, const char * fmt)
  597. {
  598. if (k == index)
  599. {
  600. FormatArg (std::get <k> (tp), fmt);
  601. }
  602. else
  603. {
  604. GetArgByIndex <k + 1> (index, tp, fmt);
  605. }
  606. }
  607. static inline const char * FirstDollar (const char *& p)
  608. {
  609. while (*p != '}' && *p != '\0')
  610. {
  611. if ('$' == (*p))
  612. return p;
  613. p ++;
  614. }
  615. return nullptr;
  616. }
  617. static inline const char * FirstDigit (const char *& p)
  618. {
  619. while (*p != '}' && *p != '\0')
  620. {
  621. if (std::isdigit (*p))
  622. return p;
  623. p ++;
  624. }
  625. return nullptr;
  626. }
  627. static inline const char * LastDigit (const char *& p)
  628. {
  629. while (*p != '}' && *p != '\0')
  630. {
  631. if (! std::isdigit (*p))
  632. return p - 1;
  633. p ++;
  634. }
  635. return p - 1;
  636. }
  637. static inline const char * FindColon (const char *& p)
  638. {
  639. while (*p != '}' && *p != '\0')
  640. {
  641. if (*p == ':')
  642. return p;
  643. p++;
  644. }
  645. return nullptr;
  646. }
  647. static inline const char * FindRightBrace (const char *& p)
  648. {
  649. while (*p != '\0')
  650. {
  651. if (*p == '}')
  652. return p;
  653. p++;
  654. }
  655. return nullptr;
  656. }
  657. static inline int GetIndex (const char *& p, const char *& fmt, int prevIndex)
  658. {
  659. auto bp = p; // 备份一下, 因为后面跟的可能是 $, 也可能是数字
  660. auto pDollar = FirstDollar (p);
  661. if (pDollar)
  662. {
  663. auto pc = FindColon (p);
  664. auto _ = FindRightBrace (p);
  665. if (pc)
  666. fmt = pc + 1;
  667. return prevIndex + 1;
  668. }
  669. p = bp;
  670. auto pd = FirstDigit (p);
  671. auto pl = LastDigit (p);
  672. auto pc = FindColon (p);
  673. auto _ = FindRightBrace (p);
  674. if (pd == nullptr) return -1;
  675. auto ii = pl + 1 - pd;
  676. assert (ii <= 2);
  677. if (ii <= 0) return -1;
  678. char temp [3] = {};
  679. temp [0] = *pd; pd ++;
  680. temp [1] = *pd;
  681. auto index = std::atoi (temp);
  682. if (pc)
  683. fmt = pc + 1;
  684. return index;
  685. }
  686. public:
  687. // 返回: 格式化后的字符串长度
  688. template <typename... Args>
  689. inline int Format (const char * fmt, Args && ... args)
  690. {
  691. int fmtlen = (int) strlen (fmt);
  692. return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
  693. }
  694. #ifdef __Utility_String_StringView__
  695. template <typename... Args>
  696. inline int Format (const eSTR::StringView & fmt, Args && ... args)
  697. {
  698. int fmtlen = fmt.GetLength ();
  699. return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
  700. }
  701. #endif
  702. template <typename... Args>
  703. inline int Format (const std::string_view & fmt, Args && ... args)
  704. {
  705. int fmtlen = static_cast <int> (fmt.size ());
  706. return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
  707. }
  708. protected:
  709. template <typename... Args>
  710. inline int DoFormat (int fmtlen, const char * fmt, Args && ... args)
  711. {
  712. assert (fmt);
  713. if (fmt == nullptr)
  714. {
  715. m_Buffer [0] = 0;
  716. return 0;
  717. }
  718. // 最好在上层判断, 以避免在这里重复计算 strlen
  719. if (sizeof...(args) == 0)
  720. {
  721. strcpy (m_Buffer, fmt);
  722. return fmtlen;
  723. }
  724. auto tp = std::tuple <Args...> (std::forward <Args> (args)...);
  725. return DoFormat (fmtlen, fmt, std::move (tp));
  726. }
  727. template <typename... Args>
  728. inline int DoFormat (int fmtlen, const char * fmt, std::tuple <Args ...> && tp)
  729. {
  730. assert (fmt);
  731. if (fmt == nullptr)
  732. {
  733. m_Buffer [0] = 0;
  734. return 0;
  735. }
  736. m_Buffer = m_BufferOrg;
  737. const char * p = fmt;
  738. const char * original = p;
  739. int len = fmtlen + 1;
  740. int last = 0;
  741. int Index = -1;
  742. while (true)
  743. {
  744. if (*p == '{')
  745. {
  746. //copy content befor {
  747. last = int (p - original);
  748. if (last)
  749. {
  750. memcpy (m_Buffer, original, last);
  751. m_Buffer += last;
  752. }
  753. //format args
  754. const char * tmp = nullptr;
  755. Index = GetIndex (p, tmp, Index);
  756. if (Index >= 0)
  757. {
  758. if (tmp)
  759. GetArgByIndex <0> (Index, tp, tmp);
  760. else
  761. GetArgByIndex <0> (Index, tp);
  762. }
  763. //skip }
  764. original = p + 1;
  765. }
  766. else
  767. if (*p == '\0')
  768. {
  769. last = int (p - original);
  770. if (last == 0)
  771. *m_Buffer = 0;
  772. else
  773. {
  774. memcpy (m_Buffer, original, last + 1); // +1 的目的是, 包括尾部的 \0
  775. m_Buffer += last;
  776. }
  777. break;
  778. }
  779. p++;
  780. }
  781. auto delta = m_Buffer - m_BufferOrg;
  782. #ifdef _DEBUG
  783. len = (int) strlen (m_BufferOrg);
  784. assert ((delta - len) == 0);
  785. // ! 此断言对以下语句不成立:
  786. // char ch = 0; mLog::Info ("{$}", ch);
  787. // 应改成以下语句, 即强制作为数字
  788. // char ch = 0; mLog::Info ("{$:d2}", ch);
  789. #endif
  790. return (int) delta;
  791. // return buf_org;
  792. }
  793. };
  794. class StringFormat : public _string_format_detail <StringFormat>
  795. {
  796. public:
  797. inline StringFormat (char * buf, int NbOfChar) : _string_format_detail (buf, NbOfChar) { }
  798. public:
  799. template <typename arg>
  800. inline int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
  801. {
  802. return sprintf_s (buf, NbOfChar, fmt, a);
  803. }
  804. };
  805. }
  806. //-----------------------------------------------------------------------------
  807. // 设计说明 (2021-06-18):
  808. // 1. 为什么只能支持 3 个数字 (即 最大只能是 {$:d999} 或 {$:f999})
  809. // 1) 预留的 Buffer 一般大小是 8192, 见 DString::Format 及 TLSLog
  810. // 2) 最终会调用 _vsprintf_s_l (buffer, len, ...)
  811. // 3) 当 buffer 不足时, 上述函数会调用 无效参数错误处理函数,
  812. // 4) 无效参数错误处理函数 : 在 Debug 模式时, 弹出断言错误. 在 Release 模式时, 直接终止程序.
  813. //
  814. //-----------------------------------------------------------------------------
  815. //-----------------------------------------------------------------------------
  816. // 自定义类型的格式化 (2023-05-15)
  817. /*
  818. class TestMyClass
  819. {
  820. public:
  821. TestMyClass () = default;
  822. };
  823. namespace ECOM::Utility::String
  824. {
  825. template <> inline std::string ToString (const TestMyClass & value)
  826. {
  827. return std::string ("it is TestMyClass !");
  828. }
  829. }
  830. */
  831. // assert (eSTR::DString::FromFormat ("{$}{$}-{$}"_sv, 11, 22, TestMyClass ()) == eSTR::DString ("1122-it is TestMyClass !"));
  832. //-----------------------------------------------------------------------------