String.Format.tlh 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. #pragma once
  2. #ifndef ASSERT
  3. #include <cassert>
  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. #include <cstdint> // 标准整数类型
  21. #include <cstdio> // snprintf函数
  22. #include <cstring> // 字符串操作函数
  23. #include <locale>
  24. // Linux下移除Windows特有警告禁用,替换为GCC兼容的警告处理(如需)
  25. #ifdef __GNUC__
  26. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  27. #endif
  28. namespace ZSKK::Utility::String
  29. {
  30. template <typename> constexpr bool dependent_false = false;
  31. template <typename T>
  32. inline std::string ToString(const T& value)
  33. {
  34. static_assert(dependent_false<T>, "You must implement ToString for type T with Partial template specialization !");
  35. return std::string();
  36. }
  37. }
  38. // 针对 bool 的模板偏特化
  39. namespace ZSKK::Utility::String
  40. {
  41. template <> inline std::string ToString(const bool& value)
  42. {
  43. static const auto strTrue = std::string("true");
  44. static const auto strFalse = std::string("false");
  45. return value ? strTrue : strFalse;
  46. }
  47. }
  48. namespace ZSKK::Utility::String
  49. {
  50. static const char __MsgOfNull_[] = "null";
  51. static const int __LenOfNull_ = sizeof(__MsgOfNull_) - 1;
  52. template <typename tDeriveClass>
  53. class _string_format_detail
  54. {
  55. protected:
  56. char* m_BufferOrg;
  57. char* m_Buffer;
  58. int m_NbOfChar;
  59. protected:
  60. inline int NbOfRemain() const
  61. {
  62. return m_NbOfChar - int(m_Buffer - m_BufferOrg);
  63. }
  64. private:
  65. template <typename arg>
  66. int _my_sprintf(char* buf, int NbOfChar, const char* fmt, arg a)
  67. {
  68. assert(false);
  69. return 22;
  70. }
  71. public:
  72. inline _string_format_detail(char* buf, int NbOfChar) // 缓冲区指针, 缓冲区长度 (字节计数)
  73. {
  74. assert(buf);
  75. m_BufferOrg = m_Buffer = buf;
  76. m_NbOfChar = NbOfChar;
  77. }
  78. protected:
  79. inline void CharFormatArg(char ch)
  80. {
  81. assert(9 <= ch && ch <= 127); // 确保非控制字符
  82. *m_Buffer = ch;
  83. m_Buffer++;
  84. }
  85. // 有符号整数格式化 - 使用重载而非特化
  86. inline void sDigitFormatArg(int i)
  87. {
  88. int len = std::snprintf(m_Buffer, NbOfRemain(), "%d", i);
  89. if (len > 0)
  90. m_Buffer += len;
  91. }
  92. inline void sDigitFormatArg(short i)
  93. {
  94. int len = std::snprintf(m_Buffer, NbOfRemain(), "%hd", i);
  95. if (len > 0)
  96. m_Buffer += len;
  97. }
  98. inline void sDigitFormatArg(int64_t i)
  99. {
  100. int len = std::snprintf(m_Buffer, NbOfRemain(), "%lld", i);
  101. if (len > 0)
  102. m_Buffer += len;
  103. }
  104. // 无符号整数格式化 - 使用重载而非特化
  105. inline void uDigitFormatArg(unsigned int i)
  106. {
  107. int len = std::snprintf(m_Buffer, NbOfRemain(), "%u", i);
  108. if (len > 0)
  109. m_Buffer += len;
  110. }
  111. /* inline void uDigitFormatArg(unsigned long i)
  112. {
  113. int len = std::snprintf(m_Buffer, NbOfRemain(), "%lu", i);
  114. if (len > 0)
  115. m_Buffer += len;
  116. }*/
  117. inline void uDigitFormatArg(unsigned short i)
  118. {
  119. int len = std::snprintf(m_Buffer, NbOfRemain(), "%hu", i);
  120. if (len > 0)
  121. m_Buffer += len;
  122. }
  123. inline void uDigitFormatArg(uint64_t i)
  124. {
  125. int len = std::snprintf(m_Buffer, NbOfRemain(), "%llu", i);
  126. if (len > 0)
  127. m_Buffer += len;
  128. }
  129. // 带格式的整数格式化 - 使用重载而非特化
  130. inline void DigitFormatArg(int i, const char* fmt)
  131. {
  132. // 实现代码保持不变
  133. assert(fmt && fmt[0]);
  134. auto chfmt = fmt[0];
  135. if (chfmt == 'c' || chfmt == 'C')
  136. {
  137. CharFormatArg(static_cast<char>(i));
  138. return;
  139. }
  140. if (chfmt == 'D') chfmt = 'd'; // 统一为小写格式符
  141. if (chfmt == 'U') chfmt = 'u';
  142. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  143. if (!rc)
  144. {
  145. rc = (chfmt == 'f' || chfmt == 'F');
  146. if (rc)
  147. {
  148. FormatArg(static_cast<double>(i), fmt);
  149. return;
  150. }
  151. }
  152. assert(rc);
  153. if (!rc) return;
  154. char tofmt[8] = { '%', };
  155. // 处理格式数字(如D023 -> %023d)
  156. if (std::isdigit(fmt[1]))
  157. {
  158. int iFmtChar = 2;
  159. for (int Index = 1; Index <= 3; ++Index)
  160. {
  161. if (std::isdigit(fmt[Index]))
  162. {
  163. tofmt[Index] = fmt[Index];
  164. iFmtChar = Index + 1;
  165. }
  166. else
  167. break;
  168. }
  169. tofmt[iFmtChar] = chfmt;
  170. }
  171. else
  172. {
  173. tofmt[1] = chfmt;
  174. tofmt[2] = 0;
  175. }
  176. auto pT = static_cast<tDeriveClass*>(this);
  177. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), tofmt, i);
  178. m_Buffer += r;
  179. }
  180. // 64位有符号整数带格式重载
  181. inline void DigitFormatArg(int64_t i, const char* fmt)
  182. {
  183. // 实现代码保持不变
  184. assert(fmt && fmt[0]);
  185. auto chfmt = fmt[0];
  186. if (chfmt == 'c' || chfmt == 'C')
  187. {
  188. CharFormatArg(static_cast<char>(i));
  189. return;
  190. }
  191. if (chfmt == 'D') chfmt = 'd';
  192. if (chfmt == 'U') chfmt = 'u';
  193. auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
  194. assert(rc);
  195. if (!rc) return;
  196. // Linux下64位整数格式符为%lld/%llx,无需Windows的%I64d
  197. char tofmt[8] = { '%', };
  198. if (chfmt == 'd' || chfmt == 'i')
  199. std::strcpy(tofmt, "%lld");
  200. else if (chfmt == 'x')
  201. std::strcpy(tofmt, "%llx");
  202. else if (chfmt == 'X')
  203. std::strcpy(tofmt, "%llX");
  204. else if (chfmt == 'u')
  205. std::strcpy(tofmt, "%llu");
  206. auto pT = static_cast<tDeriveClass*>(this);
  207. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), tofmt, i);
  208. m_Buffer += r;
  209. }
  210. // 64位无符号整数带格式重载
  211. inline void DigitFormatArg(uint64_t i, const char* fmt)
  212. {
  213. DigitFormatArg(static_cast<int64_t>(i), fmt);
  214. }
  215. // 字符格式化(无格式)
  216. inline void FormatArg(char ch) { CharFormatArg(ch); }
  217. inline void FormatArg(unsigned char ch) { uDigitFormatArg(static_cast<unsigned short>(ch)); }
  218. // 字符格式化(带格式,按整数处理)
  219. inline void FormatArg(char ch, const char* fmt) { DigitFormatArg(static_cast<int>(ch), fmt); }
  220. inline void FormatArg(unsigned char ch, const char* fmt) { DigitFormatArg(static_cast<int>(ch), fmt); }
  221. // 各种整数类型格式化
  222. inline void FormatArg(int i) { sDigitFormatArg(i); }
  223. //inline void FormatArg(long i) { sDigitFormatArg(i); }
  224. inline void FormatArg(short i) { sDigitFormatArg(i); }
  225. inline void FormatArg(unsigned int i) { uDigitFormatArg(i); }
  226. //inline void FormatArg(unsigned long i) { uDigitFormatArg(i); }
  227. inline void FormatArg(unsigned short i) { uDigitFormatArg(i); }
  228. // 整数带格式格式化
  229. inline void FormatArg(int i, const char* fmt) { DigitFormatArg(i, fmt); }
  230. inline void FormatArg(unsigned int i, const char* fmt) { DigitFormatArg(i, fmt); }
  231. //inline void FormatArg(long i, const char* fmt) { DigitFormatArg(i, fmt); }
  232. //inline void FormatArg(unsigned long i, const char* fmt) { DigitFormatArg(i, fmt); }
  233. inline void FormatArg(short i, const char* fmt) { DigitFormatArg(i, fmt); }
  234. inline void FormatArg(unsigned short i, const char* fmt) { DigitFormatArg(i, fmt); }
  235. // 64位整数格式化
  236. inline void FormatArg(int64_t i) { sDigitFormatArg(i); }
  237. inline void FormatArg(uint64_t i) { uDigitFormatArg(i); }
  238. inline void FormatArg(int64_t i, const char* fmt) { DigitFormatArg(i, fmt); }
  239. inline void FormatArg(uint64_t i, const char* fmt) { DigitFormatArg(i, fmt); }
  240. // 浮点数格式化(默认精度)
  241. inline void FormatArg(double i)
  242. {
  243. auto pT = static_cast<tDeriveClass*>(this);
  244. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), "%f", i);
  245. m_Buffer += r;
  246. }
  247. // 浮点数带格式格式化(如F3 -> 保留3位小数)
  248. inline void FormatArg(double i, const char* fmt)
  249. {
  250. assert(fmt && fmt[0]);
  251. char tofmt[8] = { '%', '.', };
  252. auto chfmt = fmt[0];
  253. if (std::isdigit(fmt[1]))
  254. {
  255. int iFmtChar = 2;
  256. for (int Index = 1; Index <= 3; ++Index)
  257. {
  258. if (std::isdigit(fmt[Index]))
  259. {
  260. tofmt[Index + 1] = fmt[Index];
  261. iFmtChar = Index + 2;
  262. }
  263. else
  264. break;
  265. }
  266. tofmt[iFmtChar] = chfmt;
  267. }
  268. else
  269. {
  270. tofmt[1] = chfmt;
  271. tofmt[2] = 0;
  272. }
  273. auto pT = static_cast<tDeriveClass*>(this);
  274. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), tofmt, i);
  275. m_Buffer += r;
  276. }
  277. // 浮点数(float)格式化
  278. inline void FormatArg(float f) { FormatArg(static_cast<double>(f)); }
  279. inline void FormatArg(float f, const char* fmt) { FormatArg(static_cast<double>(f), fmt); }
  280. // 字符串格式化(无格式)
  281. inline void FormatArg(const char* p)
  282. {
  283. if (!p)
  284. {
  285. std::memcpy(m_Buffer, __MsgOfNull_, __LenOfNull_);
  286. m_Buffer += __LenOfNull_;
  287. return;
  288. }
  289. int len = static_cast<int>(std::strlen(p));
  290. std::memcpy(m_Buffer, p, len);
  291. m_Buffer += len;
  292. }
  293. // 字符串带格式格式化(对齐处理)
  294. inline void FormatArg(const char* p, const char* fmt)
  295. {
  296. if (!p)
  297. {
  298. std::memcpy(m_Buffer, __MsgOfNull_, __LenOfNull_);
  299. m_Buffer += __LenOfNull_;
  300. return;
  301. }
  302. int len = static_cast<int>(std::strlen(p));
  303. _StringFormatArg(p, len, fmt);
  304. }
  305. inline void FormatArg(char* p) { FormatArg(static_cast<const char*>(p)); }
  306. inline void FormatArg(char* p, const char* fmt) { FormatArg(static_cast<const char*>(p), fmt); }
  307. // 字符串格式处理实现(对齐)
  308. inline void _StringFormatArg(const char* p, int len, const char* fmt)
  309. {
  310. if (!p)
  311. {
  312. std::memcpy(m_Buffer, __MsgOfNull_, __LenOfNull_);
  313. m_Buffer += __LenOfNull_;
  314. return;
  315. }
  316. if (fmt[0] == '-') // 左对齐
  317. {
  318. fmt++;
  319. auto i = std::atoi(fmt);
  320. if (i > len)
  321. {
  322. std::memcpy(m_Buffer, p, len);
  323. m_Buffer += len;
  324. std::memset(m_Buffer, ' ', i - len);
  325. m_Buffer += i - len;
  326. }
  327. else
  328. {
  329. std::memcpy(m_Buffer, p, len);
  330. m_Buffer += len;
  331. }
  332. }
  333. else // 右对齐
  334. {
  335. if (fmt[0] == '+') fmt++;
  336. auto i = std::atoi(fmt);
  337. if (i > len)
  338. {
  339. std::memset(m_Buffer, ' ', i - len);
  340. m_Buffer += i - len;
  341. std::memcpy(m_Buffer, p, len);
  342. m_Buffer += len;
  343. }
  344. else
  345. {
  346. std::memcpy(m_Buffer, p, len);
  347. m_Buffer += len;
  348. }
  349. }
  350. }
  351. // bool类型格式化
  352. void FormatArg(bool b)
  353. {
  354. if (b)
  355. {
  356. *m_Buffer++ = 't';
  357. *m_Buffer++ = 'r';
  358. *m_Buffer++ = 'u';
  359. *m_Buffer++ = 'e';
  360. }
  361. else
  362. {
  363. *m_Buffer++ = 'f';
  364. *m_Buffer++ = 'a';
  365. *m_Buffer++ = 'l';
  366. *m_Buffer++ = 's';
  367. *m_Buffer++ = 'e';
  368. }
  369. }
  370. // 指针类型格式化
  371. template <typename UNP>
  372. inline void FormatArg(const UNP* ptr)
  373. {
  374. auto pT = static_cast<tDeriveClass*>(this);
  375. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), "%p", ptr);
  376. m_Buffer += r;
  377. }
  378. // 指针带格式格式化(按整数处理)
  379. template <typename UNP>
  380. inline void FormatArg(const UNP* ptr, const char* fmt)
  381. {
  382. DigitFormatArg(static_cast<uintptr_t>(ptr), fmt);
  383. }
  384. // 非const指针格式化
  385. template <typename UNP>
  386. inline void FormatArg(UNP* ptr)
  387. {
  388. auto pT = static_cast<tDeriveClass*>(this);
  389. auto r = pT->_my_sprintf(m_Buffer, NbOfRemain(), "%p", ptr);
  390. m_Buffer += r;
  391. }
  392. // 非const指针带格式格式化
  393. template <typename UNP>
  394. inline void FormatArg(UNP* ptr, const char* fmt)
  395. {
  396. DigitFormatArg(static_cast<uintptr_t>(ptr), fmt);
  397. }
  398. protected:
  399. // string_view格式化
  400. inline void FormatArg(const std::string_view& s)
  401. {
  402. std::memcpy(m_Buffer, s.data(), s.size());
  403. m_Buffer += s.size();
  404. }
  405. inline void FormatArg(const std::string_view& s, const char* fmt)
  406. {
  407. _StringFormatArg(s.data(), static_cast<int>(s.size()), fmt);
  408. }
  409. // wstring_view格式化(Linux下宽字符转多字节)
  410. inline void FormatArg(const std::wstring_view& s)
  411. {
  412. std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter;
  413. auto str = converter.to_bytes(s.data(), s.data() + s.size());
  414. FormatArg(str);
  415. }
  416. inline void FormatArg(const std::wstring_view& s, const char* fmt)
  417. {
  418. std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter;
  419. auto str = converter.to_bytes(s.data(), s.data() + s.size());
  420. FormatArg(str, fmt);
  421. }
  422. #ifdef __Utility_String_StringView__
  423. inline void FormatArg(const DStringView& s)
  424. {
  425. std::memcpy(m_Buffer, s.constBuffer(), s.Length());
  426. m_Buffer += s.Length();
  427. }
  428. inline void FormatArg(const DStringView& s, const char* fmt)
  429. {
  430. _StringFormatArg(s.constBuffer(), s.Length(), fmt);
  431. }
  432. #endif
  433. #ifdef DSTRING_API
  434. inline void FormatArg(const DString& s)
  435. {
  436. std::memcpy(m_Buffer, s.constBuffer(), s.GetLength());
  437. m_Buffer += s.GetLength();
  438. }
  439. inline void FormatArg(const DString& s, const char* fmt)
  440. {
  441. _StringFormatArg(s.constBuffer(), s.GetLength(), fmt);
  442. }
  443. #endif
  444. // std::string格式化
  445. inline void FormatArg(const std::string& s)
  446. {
  447. std::memcpy(m_Buffer, s.data(), s.size());
  448. m_Buffer += s.size();
  449. }
  450. inline void FormatArg(const std::string& s, const char* fmt)
  451. {
  452. _StringFormatArg(s.data(), static_cast<int>(s.size()), fmt);
  453. }
  454. #ifdef WSTRING_API
  455. inline void FormatArg(const wchar_t* p)
  456. {
  457. if (!p)
  458. {
  459. std::memcpy(m_Buffer, __MsgOfNull_, __LenOfNull_);
  460. m_Buffer += __LenOfNull_;
  461. return;
  462. }
  463. auto dp = WString(WStringView(p)).ToDString();
  464. FormatArg(dp);
  465. }
  466. inline void FormatArg(const wchar_t* p, const char* fmt)
  467. {
  468. if (!p)
  469. {
  470. std::memcpy(m_Buffer, __MsgOfNull_, __LenOfNull_);
  471. m_Buffer += __LenOfNull_;
  472. return;
  473. }
  474. auto dp = WString(WStringView(p)).ToDString();
  475. FormatArg(dp, fmt);
  476. }
  477. inline void FormatArg(const WString& s)
  478. {
  479. auto dp = s.ToDString();
  480. FormatArg(dp);
  481. }
  482. inline void FormatArg(const WString& s, const char* fmt)
  483. {
  484. auto dp = s.ToDString();
  485. FormatArg(dp, fmt);
  486. }
  487. inline void FormatArg(const std::wstring& s)
  488. {
  489. auto dp = WString(s.c_str()).ToDString();
  490. FormatArg(dp);
  491. }
  492. inline void FormatArg(const std::wstring& s, const char* fmt)
  493. {
  494. auto dp = WString(s.c_str()).ToDString();
  495. FormatArg(dp, fmt);
  496. }
  497. inline void FormatArg(const WStringView& ws)
  498. {
  499. auto ds = WString(ws).ToDString();
  500. FormatArg(ds);
  501. }
  502. inline void FormatArg(const WStringView& ws, const char* fmt)
  503. {
  504. auto ds = WString(ws).ToDString();
  505. FormatArg(ds, fmt);
  506. }
  507. #endif
  508. #if 1
  509. template <typename TO>
  510. inline void FormatArg(const TO& _val)
  511. {
  512. auto dp = ZSKK::Utility::String::ToString<TO>(_val);
  513. FormatArg(dp);
  514. }
  515. template <typename TO>
  516. inline void FormatArg(const TO& _val, const char* fmt)
  517. {
  518. auto dp = ZSKK::Utility::String::ToString<TO>(_val);
  519. FormatArg(dp, fmt);
  520. }
  521. #endif
  522. protected:
  523. // 元组参数索引访问(无格式)
  524. template <size_t k, typename Tuple>
  525. typename std::enable_if<(k == std::tuple_size<Tuple>::value)>::type
  526. inline GetArgByIndex(size_t, Tuple&)
  527. {
  528. #ifdef _DEBUG
  529. // throw std::invalid_argument("arg index out of range");
  530. #endif
  531. }
  532. template <size_t k = 0, typename Tuple>
  533. typename std::enable_if<(k < std::tuple_size<Tuple>::value)>::type
  534. inline GetArgByIndex(size_t index, Tuple& tp)
  535. {
  536. if (k == index)
  537. {
  538. FormatArg(std::get<k>(tp));
  539. }
  540. else
  541. {
  542. GetArgByIndex<k + 1>(index, tp);
  543. }
  544. }
  545. // 元组参数索引访问(带格式)
  546. template <size_t k, typename Tuple>
  547. typename std::enable_if<(k == std::tuple_size<Tuple>::value)>::type
  548. inline GetArgByIndex(size_t, Tuple&, const char* fmt)
  549. {
  550. #ifdef _DEBUG
  551. // throw std::invalid_argument("arg index out of range");
  552. #endif
  553. }
  554. template <size_t k = 0, typename Tuple>
  555. typename std::enable_if<(k < std::tuple_size<Tuple>::value)>::type
  556. inline GetArgByIndex(size_t index, Tuple& tp, const char* fmt)
  557. {
  558. if (k == index)
  559. {
  560. FormatArg(std::get<k>(tp), fmt);
  561. }
  562. else
  563. {
  564. GetArgByIndex<k + 1>(index, tp, fmt);
  565. }
  566. }
  567. // 格式解析辅助函数:查找$符号
  568. static inline const char* FirstDollar(const char*& p)
  569. {
  570. while (*p != '}' && *p != '\0')
  571. {
  572. if ('$' == (*p))
  573. return p;
  574. p++;
  575. }
  576. return nullptr;
  577. }
  578. // 格式解析辅助函数:查找数字
  579. static inline const char* FirstDigit(const char*& p)
  580. {
  581. while (*p != '}' && *p != '\0')
  582. {
  583. if (std::isdigit(*p))
  584. return p;
  585. p++;
  586. }
  587. return nullptr;
  588. }
  589. // 格式解析辅助函数:查找最后一个数字
  590. static inline const char* LastDigit(const char*& p)
  591. {
  592. while (*p != '}' && *p != '\0')
  593. {
  594. if (!std::isdigit(*p))
  595. return p - 1;
  596. p++;
  597. }
  598. return p - 1;
  599. }
  600. // 格式解析辅助函数:查找冒号
  601. static inline const char* FindColon(const char*& p)
  602. {
  603. while (*p != '}' && *p != '\0')
  604. {
  605. if (*p == ':')
  606. return p;
  607. p++;
  608. }
  609. return nullptr;
  610. }
  611. // 格式解析辅助函数:查找右括号
  612. static inline const char* FindRightBrace(const char*& p)
  613. {
  614. while (*p != '\0')
  615. {
  616. if (*p == '}')
  617. return p;
  618. p++;
  619. }
  620. return nullptr;
  621. }
  622. // 解析参数索引
  623. static inline int GetIndex(const char*& p, const char*& fmt, int prevIndex)
  624. {
  625. auto bp = p; // 备份当前位置
  626. auto pDollar = FirstDollar(p);
  627. if (pDollar)
  628. {
  629. auto pc = FindColon(p);
  630. auto _ = FindRightBrace(p);
  631. if (pc)
  632. fmt = pc + 1;
  633. return prevIndex + 1;
  634. }
  635. p = bp;
  636. auto pd = FirstDigit(p);
  637. auto pl = LastDigit(p);
  638. auto pc = FindColon(p);
  639. auto _ = FindRightBrace(p);
  640. if (!pd) return -1;
  641. auto ii = pl + 1 - pd;
  642. assert(ii <= 2);
  643. if (ii <= 0) return -1;
  644. char temp[3] = {};
  645. temp[0] = *pd; pd++;
  646. temp[1] = *pd;
  647. auto index = std::atoi(temp);
  648. if (pc)
  649. fmt = pc + 1;
  650. return index;
  651. }
  652. public:
  653. // 格式化入口(const char*)
  654. template <typename... Args>
  655. inline int Format(const char* fmt, Args&&... args)
  656. {
  657. int fmtlen = static_cast<int>(std::strlen(fmt));
  658. return DoFormat(fmtlen, fmt, std::forward<Args>(args)...);
  659. }
  660. #ifdef __Utility_String_StringView__
  661. // 格式化入口(DStringView)
  662. template <typename... Args>
  663. inline int Format(const eSTR::StringView& fmt, Args&&... args)
  664. {
  665. int fmtlen = fmt.GetLength();
  666. return DoFormat(fmtlen, fmt, std::forward<Args>(args)...);
  667. }
  668. #endif
  669. // 格式化入口(std::string_view)
  670. template <typename... Args>
  671. inline int Format(const std::string_view& fmt, Args&&... args)
  672. {
  673. int fmtlen = static_cast<int>(fmt.size());
  674. return DoFormat(fmtlen, fmt, std::forward<Args>(args)...);
  675. }
  676. protected:
  677. // 格式化实现(const char*)
  678. template <typename... Args>
  679. inline int DoFormat(int fmtlen, const char* fmt, Args&&... args)
  680. {
  681. assert(fmt);
  682. if (!fmt)
  683. {
  684. m_Buffer[0] = 0;
  685. return 0;
  686. }
  687. if (sizeof...(args) == 0)
  688. {
  689. std::strcpy(m_Buffer, fmt);
  690. return fmtlen;
  691. }
  692. auto tp = std::tuple<Args...>(std::forward<Args>(args)...);
  693. return DoFormat(fmtlen, fmt, std::move(tp));
  694. }
  695. // 格式化实现(元组参数)
  696. template <typename... Args>
  697. inline int DoFormat(int fmtlen, const char* fmt, std::tuple<Args...>&& tp)
  698. {
  699. assert(fmt);
  700. if (!fmt)
  701. {
  702. m_Buffer[0] = 0;
  703. return 0;
  704. }
  705. m_Buffer = m_BufferOrg;
  706. const char* p = fmt;
  707. const char* original = p;
  708. int last = 0;
  709. int Index = -1;
  710. while (true)
  711. {
  712. if (*p == '{')
  713. {
  714. // 复制{之前的内容
  715. last = static_cast<int>(p - original);
  716. if (last)
  717. {
  718. std::memcpy(m_Buffer, original, last);
  719. m_Buffer += last;
  720. }
  721. // 解析参数索引和格式
  722. const char* tmpfmt = nullptr;
  723. Index = GetIndex(p, tmpfmt, Index);
  724. if (Index >= 0)
  725. {
  726. if (tmpfmt)
  727. GetArgByIndex<0>(Index, tp, tmpfmt);
  728. else
  729. GetArgByIndex<0>(Index, tp);
  730. }
  731. // 跳过}
  732. original = p + 1;
  733. }
  734. else if (*p == '\0')
  735. {
  736. // 复制剩余内容
  737. last = static_cast<int>(p - original);
  738. if (last == 0)
  739. *m_Buffer = 0;
  740. else
  741. {
  742. std::memcpy(m_Buffer, original, last + 1); // 包含终止符
  743. m_Buffer += last;
  744. }
  745. break;
  746. }
  747. p++;
  748. }
  749. auto delta = m_Buffer - m_BufferOrg;
  750. #ifdef _DEBUG
  751. int len = static_cast<int>(std::strlen(m_BufferOrg));
  752. assert((delta - len) == 0);
  753. #endif
  754. return static_cast<int>(delta);
  755. }
  756. };
  757. // 字符串格式化实现类(替换Windows的sprintf_s为Linux的snprintf)
  758. class StringFormat : public _string_format_detail<StringFormat>
  759. {
  760. public:
  761. inline StringFormat(char* buf, int NbOfChar) : _string_format_detail(buf, NbOfChar) {}
  762. public:
  763. template <typename arg>
  764. inline int _my_sprintf(char* buf, int NbOfChar, const char* fmt, arg a)
  765. {
  766. // Linux下用snprintf替换Windows的sprintf_s
  767. return std::snprintf(buf, NbOfChar, fmt, a);
  768. }
  769. };
  770. }
  771. //-----------------------------------------------------------------------------
  772. // 设计说明 (2021-06-18):
  773. // 1. 为什么只能支持 3 个数字 (即 最大只能是 {$:d999} 或 {$:f999})
  774. // 1) 预留的 Buffer 一般大小是 8192, 见 DString::Format 及 TLSLog
  775. // 2) 最终会调用 snprintf (buffer, len, ...)
  776. // 3) 当 buffer 不足时, 上述函数会截断输出, 避免程序崩溃
  777. //-----------------------------------------------------------------------------
  778. //-----------------------------------------------------------------------------
  779. // 自定义类型的格式化 (2023-05-15)
  780. /*
  781. class TestMyClass
  782. {
  783. public:
  784. TestMyClass() = default;
  785. };
  786. namespace ZSKK::Utility::String
  787. {
  788. template <> inline std::string ToString(const TestMyClass& value)
  789. {
  790. return std::string("it is TestMyClass !");
  791. }
  792. }
  793. */
  794. // assert(eSTR::DString::FromFormat("{$}{$}-{$}"_sv, 11, 22, TestMyClass()) == eSTR::DString("1122-it is TestMyClass !"));
  795. //-----------------------------------------------------------------------------