String.Format.tlh 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  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. #pragma warning (disable : 4996)
  19. //warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
  20. // To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
  21. namespace ECOM
  22. {
  23. namespace Utility
  24. {
  25. static const char __MsgOfNull_ [] = "null";
  26. static const int __LenOfNull_ = sizeof (__MsgOfNull_) - 1;
  27. template <typename tDeriveClass>
  28. class __declspec(novtable) _string_format_detail
  29. {
  30. protected:
  31. char * m_BufferOrg;
  32. char * m_Buffer;
  33. int m_NbOfChar;
  34. protected:
  35. inline int NbOfRemain () const
  36. {
  37. return m_NbOfChar - int (m_Buffer - m_BufferOrg);
  38. }
  39. private:
  40. template <typename arg>
  41. int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
  42. {
  43. assert (false);
  44. return 22;
  45. }
  46. public:
  47. inline _string_format_detail (char * buf, int NbOfChar) // 缓冲区指针, 缓冲区长度 (字节计数)
  48. {
  49. assert (buf);
  50. m_BufferOrg = m_Buffer = buf;
  51. m_NbOfChar = NbOfChar;
  52. }
  53. protected:
  54. inline void CharFormatArg (char ch)
  55. {
  56. *m_Buffer = ch;
  57. m_Buffer ++;
  58. }
  59. // 有符号
  60. template <typename T>
  61. inline void sDigitFormatArg (T i)
  62. {
  63. _ltoa (i, m_Buffer, 10);
  64. m_Buffer += strlen (m_Buffer);
  65. }
  66. // 无符号
  67. template <typename T>
  68. inline void uDigitFormatArg (T i)
  69. {
  70. _ultoa (i, m_Buffer, 10);
  71. m_Buffer += strlen (m_Buffer);
  72. }
  73. //< 64 位偏特化
  74. template <>
  75. inline void sDigitFormatArg (__int64 i)
  76. {
  77. _i64toa (i, m_Buffer, 10);
  78. m_Buffer += strlen (m_Buffer);
  79. }
  80. template <>
  81. inline void uDigitFormatArg (unsigned __int64 i)
  82. {
  83. _ui64toa (i, m_Buffer, 10);
  84. m_Buffer += strlen (m_Buffer);
  85. }
  86. //>
  87. template <typename T>
  88. // fmt: D,X, D3,X4,d3,x4, D03,X04
  89. // D - 用 10 进制, X - 用 16 进制
  90. // D3 - 转换成 3 个数字, 如果不足, 填充空格
  91. // D03 - 转换成 3 个数字, 如果不足, 用 0 填充
  92. inline void DigitFormatArg (T i, const char * fmt)
  93. {
  94. assert (fmt);
  95. assert (fmt [0]);
  96. auto chfmt = fmt [0];
  97. if (chfmt == 'c' || chfmt == 'C')
  98. {
  99. CharFormatArg ((char) i);
  100. return;
  101. }
  102. if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
  103. if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
  104. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  105. if (! rc) // 尝试浮点数, 万一使用者搞错了
  106. {
  107. rc = (chfmt == 'f' || chfmt == 'F');
  108. if (rc)
  109. {
  110. FormatArg ((double) i, fmt);
  111. return;
  112. }
  113. }
  114. assert (rc);
  115. if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
  116. char tofmt [8] = { '%', };
  117. // D023, X093 - 1 个格式字母带 3 个数字, tofmt 将成为 "%023d" 或 "%093x"
  118. // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
  119. // d1, d3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%1d" 或 "%3d"
  120. if (std::isdigit (fmt [1]))
  121. {
  122. int iFmtChar = 2;
  123. for (int Index = 1; Index <= 3; Index ++)
  124. {
  125. if (std::isdigit (fmt [Index]))
  126. {
  127. tofmt [Index] = fmt [Index];
  128. iFmtChar = Index + 1;
  129. }
  130. else
  131. break;
  132. }
  133. tofmt [iFmtChar] = chfmt;
  134. }
  135. else // 只有 1 个 d, 比如写成 {$:d}
  136. {
  137. tofmt [1] = chfmt;
  138. tofmt [2] = 0;
  139. }
  140. auto pT = static_cast <tDeriveClass *> (this);
  141. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
  142. m_Buffer += r;
  143. }
  144. //< 64 位偏特化
  145. template <>
  146. // fmt: D,X, D3,X4,d3,x4, D03,X04
  147. // __int64 只支持 d, x, 不支持前导/后导, 因此下面的代码只用了 D 或 X
  148. inline void DigitFormatArg (__int64 i, const char * fmt)
  149. {
  150. assert (fmt);
  151. assert (fmt [0]);
  152. auto chfmt = fmt [0];
  153. if (chfmt == 'c' || chfmt == 'C')
  154. {
  155. CharFormatArg ((char) i);
  156. return;
  157. }
  158. if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
  159. if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
  160. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  161. assert (rc);
  162. if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
  163. char tofmt [8] = { '%', 'I', 'I', chfmt };
  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 (unsigned __int64 i, const char * fmt)
  173. {
  174. DigitFormatArg <__int64> ((__int64) i, fmt);
  175. }
  176. //>
  177. // 字符,不带格式, 就认为是字符
  178. inline void FormatArg (char ch) { CharFormatArg (ch); }
  179. // 字符,带格式, 就认为是整数
  180. inline void FormatArg (char ch, const char * fmt) { DigitFormatArg <int> (ch, fmt); }
  181. //< 各种整数
  182. inline void FormatArg (int i) { sDigitFormatArg <int> (i); }
  183. inline void FormatArg (long i) { sDigitFormatArg <long> (i); }
  184. inline void FormatArg (short i) { sDigitFormatArg <short> (i); }
  185. inline void FormatArg (unsigned int i) { uDigitFormatArg <unsigned int> (i); }
  186. inline void FormatArg (unsigned long i) { uDigitFormatArg <unsigned long> (i); }
  187. inline void FormatArg (unsigned short i) { uDigitFormatArg <unsigned short> (i); }
  188. inline void FormatArg (int i , const char * fmt) { DigitFormatArg <int> (i, fmt); }
  189. inline void FormatArg (unsigned int i , const char * fmt) { DigitFormatArg <unsigned int> (i, fmt); }
  190. inline void FormatArg (long i , const char * fmt) { DigitFormatArg <long> (i, fmt); }
  191. inline void FormatArg (unsigned long i , const char * fmt) { DigitFormatArg <unsigned long> (i, fmt); }
  192. inline void FormatArg (short i , const char * fmt) { DigitFormatArg <short> (i, fmt); }
  193. inline void FormatArg (unsigned short i, const char * fmt) { DigitFormatArg <unsigned short> (i, fmt); }
  194. // int64
  195. inline void FormatArg (__int64 i) { sDigitFormatArg <__int64> (i); }
  196. inline void FormatArg (unsigned __int64 i) { uDigitFormatArg <unsigned __int64> (i); }
  197. // int64, 带参数
  198. inline void FormatArg (__int64 i , const char * fmt) { DigitFormatArg <__int64> (i, fmt); }
  199. inline void FormatArg (unsigned __int64 i , const char * fmt) { DigitFormatArg <unsigned __int64> (i, fmt); }
  200. //>
  201. //< 浮点数, 默认精度由 printf 决定
  202. inline void FormatArg (double i)
  203. {
  204. auto pT = static_cast <tDeriveClass *> (this);
  205. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%f", i);
  206. m_Buffer += r;
  207. }
  208. // fmt: F3, 精确到小数点后面3位
  209. // fmt: F, 默认精度由 printf 决定
  210. // fmt : f} --> tofmt : %f
  211. // fmt : f3} --> tofmt : %.3f
  212. // fmt : f23} --> tofmt : %.23f
  213. inline void FormatArg (double i, const char * fmt)
  214. {
  215. assert (fmt);
  216. assert (fmt [0]);
  217. char tofmt [8] = { '%', '.', };
  218. auto chfmt = fmt [0];
  219. // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
  220. // f1, f3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%.1f" 或 "%.3f"
  221. if (std::isdigit (fmt [1]))
  222. {
  223. int iFmtChar = 2;
  224. for (int Index = 1; Index <= 3; Index ++)
  225. {
  226. if (std::isdigit (fmt [Index]))
  227. {
  228. tofmt [Index+1] = fmt [Index];
  229. iFmtChar = Index + 2;
  230. }
  231. else
  232. break;
  233. }
  234. tofmt [iFmtChar] = chfmt;
  235. }
  236. else // 只有 1 个 f, 比如写成 {$:f}
  237. {
  238. tofmt [1] = chfmt;
  239. tofmt [2] = 0;
  240. }
  241. auto pT = static_cast <tDeriveClass *> (this);
  242. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
  243. m_Buffer += r;
  244. }
  245. //>
  246. // 字符串, 无格式
  247. inline void FormatArg (const char * p)
  248. {
  249. if (p == nullptr)
  250. {
  251. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  252. m_Buffer += __LenOfNull_;
  253. return;
  254. }
  255. int len = (int) strlen (p);
  256. memcpy (m_Buffer, p, len);
  257. m_Buffer += len;
  258. }
  259. //< 字符串, 带格式, 格式:
  260. // 6 : 最长 6 个字符, 右对齐, 左边填空
  261. // +6 : 最长 6 个字符, 右对齐, 左边填空
  262. // -6 : 最长 6 个字符, 左对齐, 右边填空
  263. inline void FormatArg (const char * p, const char * fmt)
  264. {
  265. if (p == nullptr)
  266. {
  267. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  268. m_Buffer += __LenOfNull_;
  269. return;
  270. }
  271. int len = (int) strlen (p);
  272. _StringFormatArg (p, len, fmt);
  273. }
  274. inline void _StringFormatArg (const char * p, int len, const char * fmt)
  275. {
  276. if (p == nullptr)
  277. {
  278. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  279. m_Buffer += __LenOfNull_;
  280. return;
  281. }
  282. if (fmt [0] == '-') // 左对齐
  283. {
  284. fmt ++;
  285. auto i = atoi (fmt);
  286. if (i > len)
  287. {
  288. memcpy (m_Buffer, p, len);
  289. m_Buffer += len;
  290. memset (m_Buffer, ' ', i - len);
  291. m_Buffer += i - len;
  292. }
  293. else
  294. {
  295. memcpy (m_Buffer, p, len);
  296. m_Buffer += len;
  297. }
  298. }
  299. else // 右对齐
  300. {
  301. if (fmt [0] == '+') fmt ++;
  302. auto i = atoi (fmt);
  303. if (i > len)
  304. {
  305. memset (m_Buffer, ' ', i - len);
  306. m_Buffer += i - len;
  307. memcpy (m_Buffer, p, len);
  308. m_Buffer += len;
  309. }
  310. else
  311. {
  312. memcpy (m_Buffer, p, len);
  313. m_Buffer += len;
  314. }
  315. }
  316. }
  317. //>
  318. // bool
  319. void FormatArg (bool b)
  320. {
  321. if (b)
  322. {
  323. *m_Buffer = 't'; m_Buffer ++;
  324. *m_Buffer = 'r'; m_Buffer ++;
  325. *m_Buffer = 'u'; m_Buffer ++;
  326. *m_Buffer = 'e'; m_Buffer ++;
  327. }
  328. else
  329. {
  330. *m_Buffer = 'f'; m_Buffer ++;
  331. *m_Buffer = 'a'; m_Buffer ++;
  332. *m_Buffer = 'l'; m_Buffer ++;
  333. *m_Buffer = 's'; m_Buffer ++;
  334. *m_Buffer = 'e'; m_Buffer ++;
  335. }
  336. }
  337. // 任意指针类型
  338. template <typename UNP>
  339. inline void FormatArg (const UNP * ptr)
  340. {
  341. auto pT = static_cast <tDeriveClass *> (this);
  342. auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%p", ptr);
  343. m_Buffer += r;
  344. }
  345. // 任意指针类型, 带格式 -- 转化成整数来格式化
  346. template <typename UNP>
  347. inline void FormatArg (const UNP * ptr, const char * fmt)
  348. {
  349. DigitFormatArg <uintptr_t> ((uintptr_t) ptr, fmt);
  350. }
  351. // 偏特化 - 字符串指针
  352. template <> inline void FormatArg (const char * p)
  353. {
  354. if (p == nullptr)
  355. {
  356. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  357. m_Buffer += __LenOfNull_;
  358. return;
  359. }
  360. int len = (int) strlen (p);
  361. memcpy (m_Buffer, p, len);
  362. m_Buffer += len;
  363. }
  364. // 偏特化 - 字符串指针
  365. template <> inline void FormatArg (const char * p, const char *)
  366. {
  367. if (p == nullptr)
  368. {
  369. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  370. m_Buffer += __LenOfNull_;
  371. return;
  372. }
  373. int len = (int) strlen (p);
  374. memcpy (m_Buffer, p, len);
  375. m_Buffer += len;
  376. }
  377. #ifdef DSTRING_API
  378. inline void FormatArg (const DString & s)
  379. {
  380. memcpy (m_Buffer, s.constBuffer (), s.GetLength ());
  381. m_Buffer += s.GetLength ();
  382. }
  383. inline void FormatArg (const DString & s, const char * fmt)
  384. {
  385. _StringFormatArg (s.constBuffer (), s.GetLength (), fmt);
  386. }
  387. #endif
  388. inline void FormatArg (const std::string & s)
  389. {
  390. memcpy (m_Buffer, s.data (), s.size ());
  391. m_Buffer += s.size ();
  392. }
  393. inline void FormatArg (const std::string & s, const char * fmt)
  394. {
  395. _StringFormatArg (s.data (), (int) s.size (), fmt);
  396. }
  397. #ifdef WSTRING_API
  398. //#if 1
  399. inline void FormatArg (const wchar_t * p)
  400. {
  401. if (p == nullptr)
  402. {
  403. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  404. m_Buffer += __LenOfNull_;
  405. return;
  406. }
  407. auto dp = WString (p).ToDString ();
  408. FormatArg (dp);
  409. }
  410. inline void FormatArg (const wchar_t * p, const char * fmt)
  411. {
  412. if (p == nullptr)
  413. {
  414. memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
  415. m_Buffer += __LenOfNull_;
  416. return;
  417. }
  418. auto dp = WString (p).ToDString ();
  419. FormatArg (dp, fmt);
  420. }
  421. inline void FormatArg (const WString & s)
  422. {
  423. auto dp = s.ToDString ();
  424. FormatArg (dp);
  425. }
  426. inline void FormatArg (const WString & s, const char * fmt)
  427. {
  428. auto dp = s.ToDString ();
  429. FormatArg (dp, fmt);
  430. }
  431. inline void FormatArg (const std::wstring & s)
  432. {
  433. auto dp = WString (s.c_str ()).ToDString ();
  434. FormatArg (dp);
  435. }
  436. inline void FormatArg (const std::wstring & s, const char * fmt)
  437. {
  438. auto dp = WString (s.c_str ()).ToDString ();
  439. FormatArg (dp, fmt);
  440. }
  441. #endif
  442. template <size_t k, typename Tuple>
  443. typename std::enable_if <(k == std::tuple_size<Tuple>::value)>::type
  444. inline GetArgByIndex (size_t, Tuple &)
  445. {
  446. // 忽略那些误写的位置参数, 比如忽略下面的 {99}
  447. // eLog::Log ("{99}, {0}", 123456
  448. #ifdef _DEBUG
  449. // throw std::invalid_argument ("arg index out of range");
  450. #endif
  451. }
  452. template <size_t k = 0, typename Tuple>
  453. typename std::enable_if <(k < std::tuple_size<Tuple>::value)>::type
  454. inline GetArgByIndex (size_t index, Tuple & tp)
  455. {
  456. if (k == index)
  457. {
  458. FormatArg (std::get<k> (tp));
  459. }
  460. else
  461. {
  462. GetArgByIndex <k + 1> (index, tp);
  463. }
  464. }
  465. template <size_t k, typename Tuple>
  466. typename std::enable_if <(k == std::tuple_size<Tuple>::value)>::type
  467. inline GetArgByIndex (size_t, Tuple &, const char * fmt)
  468. {
  469. #ifdef _DEBUG
  470. // throw std::invalid_argument ("arg index out of range");
  471. #endif
  472. }
  473. template <size_t k = 0, typename Tuple>
  474. typename std::enable_if <(k < std::tuple_size<Tuple>::value)>::type
  475. inline GetArgByIndex (size_t index, Tuple & tp, const char * fmt)
  476. {
  477. if (k == index)
  478. {
  479. FormatArg (std::get <k> (tp), fmt);
  480. }
  481. else
  482. {
  483. GetArgByIndex <k + 1> (index, tp, fmt);
  484. }
  485. }
  486. static inline const char * FirstDollar (const char *& p)
  487. {
  488. while (*p != '}' && *p != '\0')
  489. {
  490. if ('$' == (*p))
  491. return p;
  492. p ++;
  493. }
  494. return nullptr;
  495. }
  496. static inline const char * FirstDigit (const char *& p)
  497. {
  498. while (*p != '}' && *p != '\0')
  499. {
  500. if (std::isdigit (*p))
  501. return p;
  502. p ++;
  503. }
  504. return nullptr;
  505. }
  506. static inline const char * LastDigit (const char *& p)
  507. {
  508. while (*p != '}' && *p != '\0')
  509. {
  510. if (! std::isdigit (*p))
  511. return p - 1;
  512. p ++;
  513. }
  514. return p - 1;
  515. }
  516. static inline const char * FindColon (const char *& p)
  517. {
  518. while (*p != '}' && *p != '\0')
  519. {
  520. if (*p == ':')
  521. return p;
  522. p++;
  523. }
  524. return nullptr;
  525. }
  526. static inline const char * FindRightBrace (const char *& p)
  527. {
  528. while (*p != '\0')
  529. {
  530. if (*p == '}')
  531. return p;
  532. p++;
  533. }
  534. return nullptr;
  535. }
  536. static inline int GetIndex (const char *& p, const char *& fmt, int prevIndex)
  537. {
  538. auto bp = p; // 备份一下, 因为后面跟的可能是 $, 也可能是数字
  539. auto pDollar = FirstDollar (p);
  540. if (pDollar)
  541. {
  542. auto pc = FindColon (p);
  543. auto _ = FindRightBrace (p);
  544. if (pc)
  545. fmt = pc + 1;
  546. return prevIndex + 1;
  547. }
  548. p = bp;
  549. auto pd = FirstDigit (p);
  550. auto pl = LastDigit (p);
  551. auto pc = FindColon (p);
  552. auto _ = FindRightBrace (p);
  553. if (pd == nullptr) return -1;
  554. auto ii = pl + 1 - pd;
  555. assert (ii <= 2);
  556. if (ii <= 0) return -1;
  557. char temp [3] = {};
  558. temp [0] = *pd; pd ++;
  559. temp [1] = *pd;
  560. auto index = std::atoi (temp);
  561. if (pc)
  562. fmt = pc + 1;
  563. return index;
  564. }
  565. public:
  566. // 返回: 格式化后的字符串长度
  567. template <typename... Args>
  568. inline int Format (const char * fmt, Args... args)
  569. {
  570. assert (fmt);
  571. if (fmt == nullptr)
  572. {
  573. m_Buffer [0] = 0;
  574. return 0;
  575. }
  576. // 最好在上层判断, 以避免在这里重复计算 strlen
  577. if (sizeof...(args) == 0)
  578. {
  579. strcpy (m_Buffer, fmt);
  580. int len = (int) strlen (m_Buffer);
  581. return len;
  582. }
  583. m_Buffer = m_BufferOrg;
  584. auto tp = std::tuple <Args...> (args...);
  585. const char * p = fmt;
  586. const char * original = p;
  587. int len = (int) strlen (fmt) + 1;
  588. int last = 0;
  589. int Index = -1;
  590. while (true)
  591. {
  592. if (*p == '{')
  593. {
  594. //copy content befor {
  595. last = int (p - original);
  596. if (last)
  597. {
  598. memcpy (m_Buffer, original, last);
  599. m_Buffer += last;
  600. }
  601. //format args
  602. const char * tmp = nullptr;
  603. Index = GetIndex (p, tmp, Index);
  604. if (Index >= 0)
  605. {
  606. if (tmp)
  607. GetArgByIndex <0> (Index, tp, tmp);
  608. else
  609. GetArgByIndex <0> (Index, tp);
  610. }
  611. //skip }
  612. original = p + 1;
  613. }
  614. else
  615. if (*p == '\0')
  616. {
  617. last = int (p - original);
  618. if (last == 0)
  619. *m_Buffer = 0;
  620. else
  621. {
  622. memcpy (m_Buffer, original, last + 1); // +1 的目的是, 包括尾部的 \0
  623. m_Buffer += last;
  624. }
  625. break;
  626. }
  627. p++;
  628. }
  629. auto delta = m_Buffer - m_BufferOrg;
  630. #ifdef _DEBUG
  631. len = (int) strlen (m_BufferOrg);
  632. assert ((delta - len) == 0);
  633. #endif
  634. return (int) delta;
  635. // return buf_org;
  636. }
  637. };
  638. class StringFormat : public _string_format_detail <StringFormat>
  639. {
  640. public:
  641. inline StringFormat (char * buf, int NbOfChar) : _string_format_detail (buf, NbOfChar) { }
  642. public:
  643. template <typename arg>
  644. inline int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
  645. {
  646. return sprintf_s (buf, NbOfChar, fmt, a);
  647. }
  648. };
  649. }
  650. }
  651. //-----------------------------------------------------------------------------
  652. // 设计说明 (2021-06-18):
  653. // 1. 为什么只能支持 3 个数字 (即 最大只能是 {$:d999} 或 {$:f999})
  654. // 1) 预留的 Buffer 一般大小是 8192, 见 DString::_XFormat 及 TLSLog
  655. // 2) 最终会调用 _vsprintf_s_l (buffer, len, ...)
  656. // 3) 当 buffer 不足时, 上述函数会调用 无效参数错误处理函数,
  657. // 4) 无效参数错误处理函数 : 在 Debug 模式时, 弹出断言错误. 在 Release 模式时, 直接终止程序.
  658. //
  659. //-----------------------------------------------------------------------------