123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002 |
- #pragma once
- #ifndef ASSERT
- #include <assert.h>
- #define ASSERT assert
- #endif
- //-----------------------------------------------------------------------------
- // 字符串格式化
- // 思路主要来自祈宇的文章:
- // <实现一个简单的字符串格式化方法>
- // https://www.cnblogs.com/qicosmos/p/3825612.html
- //-----------------------------------------------------------------------------
- #include <tuple>
- #include <type_traits>
- #include <string>
- #include <inttypes.h>
- #include <cctype>
- #include <stdexcept>
- #include <codecvt>
- #include <chrono>
- #pragma warning (disable : 4996)
- //warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
- // To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
- namespace ECOM::Utility::String
- {
- template <typename> constexpr bool dependent_false = false;
- template <typename T>
- inline std::string ToString (const T & value)
- {
- static_assert (dependent_false <T>, "You must implement ToString for type T with Partial template specialization !");
- return std::string ();
- }
- }
- // 针对 bool 的模板偏特化, 编译要求定义这些函数, 但是实际上不会执行
- namespace ECOM::Utility::String
- {
- template <> inline std::string ToString (const bool & value)
- {
- static const auto strTrue = std::string ("true");
- static const auto strFalse = std::string ("false");
- if (value) return strTrue;
- else return strFalse;
- }
- }
- namespace ECOM::Utility::String
- {
- static const char __MsgOfNull_ [] = "null";
- static const int __LenOfNull_ = sizeof (__MsgOfNull_) - 1;
- template <typename tDeriveClass>
- class __declspec(novtable) _string_format_detail
- {
- protected:
- char * m_BufferOrg;
- char * m_Buffer;
- int m_NbOfChar;
- protected:
- inline int NbOfRemain () const
- {
- return m_NbOfChar - int (m_Buffer - m_BufferOrg);
- }
- private:
- template <typename arg>
- int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
- {
- assert (false);
- return 22;
- }
- public:
- inline _string_format_detail (char * buf, int NbOfChar) // 缓冲区指针, 缓冲区长度 (字节计数)
- {
- assert (buf);
- m_BufferOrg = m_Buffer = buf;
- m_NbOfChar = NbOfChar;
- }
- protected:
- inline void CharFormatArg (char ch)
- {
- // ch 不能是控制字符, 否则不知道显示成什么
- // assert (0 < ch);
- assert (9 <= ch); assert (ch <= 127);
- *m_Buffer = ch;
- m_Buffer ++;
- }
- // 有符号
- template <typename T>
- inline void sDigitFormatArg (T i)
- {
- _ltoa (i, m_Buffer, 10);
- m_Buffer += strlen (m_Buffer);
- }
- // 无符号
- template <typename T>
- inline void uDigitFormatArg (T i)
- {
- _ultoa (i, m_Buffer, 10);
- m_Buffer += strlen (m_Buffer);
- }
- //< 64 位偏特化
- template <>
- inline void sDigitFormatArg (__int64 i)
- {
- _i64toa (i, m_Buffer, 10);
- m_Buffer += strlen (m_Buffer);
- }
- template <>
- inline void uDigitFormatArg (unsigned __int64 i)
- {
- _ui64toa (i, m_Buffer, 10);
- m_Buffer += strlen (m_Buffer);
- }
- //>
- template <typename T>
- // fmt: D,X, D3,X4,d3,x4, D03,X04
- // D - 用 10 进制, X - 用 16 进制
- // D3 - 转换成 3 个数字, 如果不足, 填充空格
- // D03 - 转换成 3 个数字, 如果不足, 用 0 填充
- inline void DigitFormatArg (T i, const char * fmt)
- {
- assert (fmt);
- assert (fmt [0]);
- auto chfmt = fmt [0];
- if (chfmt == 'c' || chfmt == 'C')
- {
- CharFormatArg ((char) i);
- return;
- }
- if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
- if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
- auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
- if (! rc) // 尝试浮点数, 万一使用者搞错了
- {
- rc = (chfmt == 'f' || chfmt == 'F');
- if (rc)
- {
- FormatArg ((double) i, fmt);
- return;
- }
- }
- assert (rc);
- if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
- char tofmt [8] = { '%', };
- // D023, X093 - 1 个格式字母带 3 个数字, tofmt 将成为 "%023d" 或 "%093x"
- // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
- // d1, d3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%1d" 或 "%3d"
- if (std::isdigit (fmt [1]))
- {
- int iFmtChar = 2;
- for (int Index = 1; Index <= 3; Index ++)
- {
- if (std::isdigit (fmt [Index]))
- {
- tofmt [Index] = fmt [Index];
- iFmtChar = Index + 1;
- }
- else
- break;
- }
- tofmt [iFmtChar] = chfmt;
- }
- else // 只有 1 个 d, 比如写成 {$:d}
- {
- tofmt [1] = chfmt;
- tofmt [2] = 0;
- }
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
- m_Buffer += r;
- }
- //< 64 位偏特化
- template <>
- // fmt: D,X, D3,X4,d3,x4, D03,X04
- // __int64 只支持 d, x, 不支持前导/后导, 因此下面的代码只用了 D 或 X
- inline void DigitFormatArg (__int64 i, const char * fmt)
- {
- assert (fmt);
- assert (fmt [0]);
- auto chfmt = fmt [0];
- if (chfmt == 'c' || chfmt == 'C')
- {
- CharFormatArg ((char) i);
- return;
- }
- if (chfmt == 'D') chfmt = 'd'; // 把大写的 D 改成小写的 d, 因为 sprintf 不支持大写 D
- if (chfmt == 'U') chfmt = 'u'; // 把大写的 U 改成小写的 u, 因为 sprintf 不支持大写 U
- auto rc = (chfmt == 'd' || chfmt == 'u' || chfmt == 'X' || chfmt == 'x');
- assert (rc);
- if (! rc) return; // 既不是 d, 也不是 u, 也不是 x, 也不是 c
- char tofmt [8] = { '%', 'I', 'I', chfmt };
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
- m_Buffer += r;
- }
- // 64 位偏特化
- template <>
- // fmt: D,X, D3,X4,d3,x4, D03,X04
- // __int64 只支持 d, x, 不支持前导/后导, 因此下面的代码只用了 D 或 X
- inline void DigitFormatArg (unsigned __int64 i, const char * fmt)
- {
- DigitFormatArg <__int64> ((__int64) i, fmt);
- }
- //>
- // 字符,不带格式, 就认为是字符
- inline void FormatArg (char ch) { CharFormatArg (ch); }
- // inline void FormatArg (unsigned char ch) { CharFormatArg (ch); }
- inline void FormatArg (unsigned char ch) { uDigitFormatArg <unsigned short> (ch); }
- // 字符,带格式, 就认为是整数
- inline void FormatArg (char ch, const char * fmt) { DigitFormatArg <int> (ch, fmt); }
- inline void FormatArg (unsigned char ch, const char * fmt) { DigitFormatArg <int> (ch, fmt); }
- //< 各种整数
- inline void FormatArg (int i) { sDigitFormatArg <int> (i); }
- inline void FormatArg (long i) { sDigitFormatArg <long> (i); }
- inline void FormatArg (short i) { sDigitFormatArg <short> (i); }
- inline void FormatArg (unsigned int i) { uDigitFormatArg <unsigned int> (i); }
- inline void FormatArg (unsigned long i) { uDigitFormatArg <unsigned long> (i); }
- inline void FormatArg (unsigned short i) { uDigitFormatArg <unsigned short> (i); }
- inline void FormatArg (int i , const char * fmt) { DigitFormatArg <int> (i, fmt); }
- inline void FormatArg (unsigned int i , const char * fmt) { DigitFormatArg <unsigned int> (i, fmt); }
- inline void FormatArg (long i , const char * fmt) { DigitFormatArg <long> (i, fmt); }
- inline void FormatArg (unsigned long i , const char * fmt) { DigitFormatArg <unsigned long> (i, fmt); }
- inline void FormatArg (short i , const char * fmt) { DigitFormatArg <short> (i, fmt); }
- inline void FormatArg (unsigned short i, const char * fmt) { DigitFormatArg <unsigned short> (i, fmt); }
- // int64
- inline void FormatArg (__int64 i) { sDigitFormatArg <__int64> (i); }
- inline void FormatArg (unsigned __int64 i) { uDigitFormatArg <unsigned __int64> (i); }
- // int64, 带参数
- inline void FormatArg (__int64 i , const char * fmt) { DigitFormatArg <__int64> (i, fmt); }
- inline void FormatArg (unsigned __int64 i , const char * fmt) { DigitFormatArg <unsigned __int64> (i, fmt); }
- //>
- //< 浮点数, 默认精度由 printf 决定
- inline void FormatArg (double i)
- {
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%f", i);
- m_Buffer += r;
- }
- // fmt: F3, 精确到小数点后面3位
- // fmt: F, 默认精度由 printf 决定
- // fmt : f} --> tofmt : %f
- // fmt : f3} --> tofmt : %.3f
- // fmt : f23} --> tofmt : %.23f
- inline void FormatArg (double i, const char * fmt)
- {
- assert (fmt);
- assert (fmt [0]);
- char tofmt [8] = { '%', '.', };
- auto chfmt = fmt [0];
- // 最多支持 3 个数字. 注意, 如果判断到 \0 也不怕
- // f1, f3 - 1 个格式字母带 1 个数字, tofmt 将成为 "%.1f" 或 "%.3f"
- if (std::isdigit (fmt [1]))
- {
- int iFmtChar = 2;
- for (int Index = 1; Index <= 3; Index ++)
- {
- if (std::isdigit (fmt [Index]))
- {
- tofmt [Index+1] = fmt [Index];
- iFmtChar = Index + 2;
- }
- else
- break;
- }
- tofmt [iFmtChar] = chfmt;
- }
- else // 只有 1 个 f, 比如写成 {$:f}
- {
- tofmt [1] = chfmt;
- tofmt [2] = 0;
- }
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), tofmt, i);
- m_Buffer += r;
- }
- inline void FormatArg (float f)
- {
- double d = f;
- FormatArg (d);
- }
- inline void FormatArg (float f, const char * fmt)
- {
- double d = f;
- FormatArg (d, fmt);
- }
- //>
- // 字符串, 无格式
- inline void FormatArg (const char * p)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- int len = (int) strlen (p);
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- //< 字符串, 带格式, 格式:
- // 6 : 最长 6 个字符, 右对齐, 左边填空
- // +6 : 最长 6 个字符, 右对齐, 左边填空
- // -6 : 最长 6 个字符, 左对齐, 右边填空
- inline void FormatArg (const char * p, const char * fmt)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- int len = (int) strlen (p);
- _StringFormatArg (p, len, fmt);
- }
- inline void FormatArg (char * p)
- {
- FormatArg ((const char *) p);
- }
- inline void FormatArg (char * p, const char * fmt)
- {
- FormatArg ((const char *)p, fmt);
- }
- inline void _StringFormatArg (const char * p, int len, const char * fmt)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- if (fmt [0] == '-') // 左对齐
- {
- fmt ++;
- auto i = atoi (fmt);
- if (i > len)
- {
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- memset (m_Buffer, ' ', i - len);
- m_Buffer += i - len;
- }
- else
- {
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- }
- else // 右对齐
- {
- if (fmt [0] == '+') fmt ++;
- auto i = atoi (fmt);
- if (i > len)
- {
- memset (m_Buffer, ' ', i - len);
- m_Buffer += i - len;
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- else
- {
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- }
- }
- //>
- // bool
- void FormatArg (bool b)
- {
- if (b)
- {
- *m_Buffer = 't'; m_Buffer ++;
- *m_Buffer = 'r'; m_Buffer ++;
- *m_Buffer = 'u'; m_Buffer ++;
- *m_Buffer = 'e'; m_Buffer ++;
- }
- else
- {
- *m_Buffer = 'f'; m_Buffer ++;
- *m_Buffer = 'a'; m_Buffer ++;
- *m_Buffer = 'l'; m_Buffer ++;
- *m_Buffer = 's'; m_Buffer ++;
- *m_Buffer = 'e'; m_Buffer ++;
- }
- }
- // 任意指针类型 - const
- template <typename UNP>
- inline void FormatArg (const UNP * ptr)
- {
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%p", ptr);
- m_Buffer += r;
- }
- // 任意指针类型, 带格式 -- 转化成整数来格式化
- template <typename UNP>
- inline void FormatArg (const UNP * ptr, const char * fmt)
- {
- DigitFormatArg <uintptr_t> ((uintptr_t) ptr, fmt);
- }
- // 任意指针类型 - 非 const
- template <typename UNP>
- inline void FormatArg (UNP * ptr)
- {
- auto pT = static_cast <tDeriveClass *> (this);
- auto r = pT->_my_sprintf (m_Buffer, NbOfRemain (), "%p", ptr);
- m_Buffer += r;
- }
- // 任意指针类型, 带格式 -- 转化成整数来格式化
- template <typename UNP>
- inline void FormatArg (UNP * ptr, const char * fmt)
- {
- DigitFormatArg <uintptr_t> ((uintptr_t)ptr, fmt);
- }
- // 偏特化 - 字符串指针
- template <> inline void FormatArg (const char * p)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- int len = (int) strlen (p);
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- // 偏特化 - 字符串指针
- template <> inline void FormatArg (const char * p, const char *)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- int len = (int) strlen (p);
- memcpy (m_Buffer, p, len);
- m_Buffer += len;
- }
- protected:
- //< string_view
- inline void FormatArg (const std::string_view & s)
- {
- memcpy (m_Buffer, s.data (), s.size ());
- m_Buffer += s.size ();
- }
- inline void FormatArg (const std::string_view & s, const char * fmt)
- {
- _StringFormatArg (s.data (), static_cast <int> (s.size ()), fmt);
- }
- inline void FormatArg (const std::wstring_view & s)
- {
- std::wstring_convert <std::codecvt <wchar_t, char, mbstate_t>> converter;
- auto str = converter.to_bytes (s.data (), s.data () + s.size ());
- FormatArg (str);
- }
- inline void FormatArg (const std::wstring_view & s, const char * fmt)
- {
- std::wstring_convert <std::codecvt <wchar_t, char, mbstate_t>> converter;
- auto str = converter.to_bytes (s.data (), s.data () + s.size ());
- FormatArg (str, fmt);
- }
- //>
- #ifdef __Utility_String_StringView__
- inline void FormatArg (const DStringView & s)
- {
- memcpy (m_Buffer, s.constBuffer (), s.Length ());
- m_Buffer += s.Length ();
- }
- inline void FormatArg (const DStringView & s, const char * fmt)
- {
- _StringFormatArg (s.constBuffer (), s.Length (), fmt);
- }
- #endif
- #ifdef DSTRING_API
- inline void FormatArg (const DString & s)
- {
- memcpy (m_Buffer, s.constBuffer (), s.GetLength ());
- m_Buffer += s.GetLength ();
- }
- inline void FormatArg (const DString & s, const char * fmt)
- {
- _StringFormatArg (s.constBuffer (), s.GetLength (), fmt);
- }
- #endif
- //< std::string
- inline void FormatArg (const std::string & s)
- {
- memcpy (m_Buffer, s.data (), s.size ());
- m_Buffer += s.size ();
- }
- inline void FormatArg (const std::string & s, const char * fmt)
- {
- _StringFormatArg (s.data (), (int) s.size (), fmt);
- }
- //>
- #ifdef WSTRING_API
- //#if 1
- inline void FormatArg (const wchar_t * p)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- auto dp = WString (WStringView (p)).ToDString ();
- FormatArg (dp);
- }
- inline void FormatArg (const wchar_t * p, const char * fmt)
- {
- if (p == nullptr)
- {
- memcpy (m_Buffer, __MsgOfNull_, __LenOfNull_);
- m_Buffer += __LenOfNull_;
- return;
- }
- auto dp = WString (WStringView (p)).ToDString ();
- FormatArg (dp, fmt);
- }
- inline void FormatArg (const WString & s)
- {
- auto dp = s.ToDString ();
- FormatArg (dp);
- }
- inline void FormatArg (const WString & s, const char * fmt)
- {
- auto dp = s.ToDString ();
- FormatArg (dp, fmt);
- }
- inline void FormatArg (const std::wstring & s)
- {
- auto dp = WString (s.c_str ()).ToDString ();
- FormatArg (dp);
- }
- inline void FormatArg (const std::wstring & s, const char * fmt)
- {
- auto dp = WString (s.c_str ()).ToDString ();
- FormatArg (dp, fmt);
- }
- inline void FormatArg (const WStringView & ws)
- {
- auto ds = WString (ws).ToDString ();
- FormatArg (ds);
- }
- inline void FormatArg (const WStringView & ws, const char * fmt)
- {
- auto ds = WString (ws).ToDString ();
- FormatArg (ds, fmt);
- }
- #endif
- #if 1
- template <typename TO>
- inline void FormatArg (const TO & _val)
- {
- auto dp = ECOM::Utility::String::ToString <TO> (_val);
- FormatArg (dp);
- }
- template <typename TO>
- inline void FormatArg (const TO & _val, const char * fmt)
- {
- auto dp = ECOM::Utility::String::ToString <TO> (_val);
- FormatArg (dp, fmt);
- }
- #endif
- protected:
- template <size_t k, typename Tuple>
- typename std::enable_if <(k == std::tuple_size <Tuple>::value)>::type
- inline GetArgByIndex (size_t, Tuple &)
- {
- // 忽略那些误写的位置参数, 比如忽略下面的 {99}
- // mLog::Info ("{99}, {0}", 123456
- #ifdef _DEBUG
- // throw std::invalid_argument ("arg index out of range");
- #endif
- }
- template <size_t k = 0, typename Tuple>
- typename std::enable_if <(k < std::tuple_size <Tuple>::value)>::type
- inline GetArgByIndex (size_t index, Tuple & tp)
- {
- if (k == index)
- {
- FormatArg (std::get<k> (tp));
- }
- else
- {
- GetArgByIndex <k + 1> (index, tp);
- }
- }
- template <size_t k, typename Tuple>
- typename std::enable_if <(k == std::tuple_size <Tuple>::value)>::type
- inline GetArgByIndex (size_t, Tuple &, const char * fmt)
- {
- #ifdef _DEBUG
- // throw std::invalid_argument ("arg index out of range");
- #endif
- }
- template <size_t k = 0, typename Tuple>
- typename std::enable_if <(k < std::tuple_size <Tuple>::value)>::type
- inline GetArgByIndex (size_t index, Tuple & tp, const char * fmt)
- {
- if (k == index)
- {
- FormatArg (std::get <k> (tp), fmt);
- }
- else
- {
- GetArgByIndex <k + 1> (index, tp, fmt);
- }
- }
- static inline const char * FirstDollar (const char *& p)
- {
- while (*p != '}' && *p != '\0')
- {
- if ('$' == (*p))
- return p;
- p ++;
- }
- return nullptr;
- }
- static inline const char * FirstDigit (const char *& p)
- {
- while (*p != '}' && *p != '\0')
- {
- if (std::isdigit (*p))
- return p;
- p ++;
- }
- return nullptr;
- }
- static inline const char * LastDigit (const char *& p)
- {
- while (*p != '}' && *p != '\0')
- {
- if (! std::isdigit (*p))
- return p - 1;
- p ++;
- }
- return p - 1;
- }
- static inline const char * FindColon (const char *& p)
- {
- while (*p != '}' && *p != '\0')
- {
- if (*p == ':')
- return p;
- p++;
- }
- return nullptr;
- }
- static inline const char * FindRightBrace (const char *& p)
- {
- while (*p != '\0')
- {
- if (*p == '}')
- return p;
- p++;
- }
- return nullptr;
- }
- static inline int GetIndex (const char *& p, const char *& fmt, int prevIndex)
- {
- auto bp = p; // 备份一下, 因为后面跟的可能是 $, 也可能是数字
- auto pDollar = FirstDollar (p);
- if (pDollar)
- {
- auto pc = FindColon (p);
- auto _ = FindRightBrace (p);
- if (pc)
- fmt = pc + 1;
- return prevIndex + 1;
- }
- p = bp;
- auto pd = FirstDigit (p);
- auto pl = LastDigit (p);
- auto pc = FindColon (p);
- auto _ = FindRightBrace (p);
- if (pd == nullptr) return -1;
- auto ii = pl + 1 - pd;
- assert (ii <= 2);
- if (ii <= 0) return -1;
- char temp [3] = {};
- temp [0] = *pd; pd ++;
- temp [1] = *pd;
- auto index = std::atoi (temp);
- if (pc)
- fmt = pc + 1;
- return index;
- }
- public:
- // 返回: 格式化后的字符串长度
- template <typename... Args>
- inline int Format (const char * fmt, Args && ... args)
- {
- int fmtlen = (int) strlen (fmt);
- return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
- }
- #ifdef __Utility_String_StringView__
- template <typename... Args>
- inline int Format (const eSTR::StringView & fmt, Args && ... args)
- {
- int fmtlen = fmt.GetLength ();
- return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
- }
- #endif
- template <typename... Args>
- inline int Format (const std::string_view & fmt, Args && ... args)
- {
- int fmtlen = static_cast <int> (fmt.size ());
- return DoFormat (fmtlen, fmt, std::forward <Args> (args)...);
- }
- protected:
- template <typename... Args>
- inline int DoFormat (int fmtlen, const char * fmt, Args && ... args)
- {
- assert (fmt);
- if (fmt == nullptr)
- {
- m_Buffer [0] = 0;
- return 0;
- }
- // 最好在上层判断, 以避免在这里重复计算 strlen
- if (sizeof...(args) == 0)
- {
- strcpy (m_Buffer, fmt);
- return fmtlen;
- }
- auto tp = std::tuple <Args...> (std::forward <Args> (args)...);
- return DoFormat (fmtlen, fmt, std::move (tp));
- }
- template <typename... Args>
- inline int DoFormat (int fmtlen, const char * fmt, std::tuple <Args ...> && tp)
- {
- assert (fmt);
- if (fmt == nullptr)
- {
- m_Buffer [0] = 0;
- return 0;
- }
- m_Buffer = m_BufferOrg;
- const char * p = fmt;
- const char * original = p;
- int len = fmtlen + 1;
- int last = 0;
- int Index = -1;
- while (true)
- {
- if (*p == '{')
- {
- //copy content befor {
- last = int (p - original);
- if (last)
- {
- memcpy (m_Buffer, original, last);
- m_Buffer += last;
- }
- //format args
- const char * tmp = nullptr;
- Index = GetIndex (p, tmp, Index);
- if (Index >= 0)
- {
- if (tmp)
- GetArgByIndex <0> (Index, tp, tmp);
- else
- GetArgByIndex <0> (Index, tp);
- }
- //skip }
- original = p + 1;
- }
- else
- if (*p == '\0')
- {
- last = int (p - original);
- if (last == 0)
- *m_Buffer = 0;
- else
- {
- memcpy (m_Buffer, original, last + 1); // +1 的目的是, 包括尾部的 \0
- m_Buffer += last;
- }
- break;
- }
- p++;
- }
- auto delta = m_Buffer - m_BufferOrg;
- #ifdef _DEBUG
- len = (int) strlen (m_BufferOrg);
- assert ((delta - len) == 0);
- // ! 此断言对以下语句不成立:
- // char ch = 0; mLog::Info ("{$}", ch);
- // 应改成以下语句, 即强制作为数字
- // char ch = 0; mLog::Info ("{$:d2}", ch);
- #endif
- return (int) delta;
- // return buf_org;
- }
- };
- class StringFormat : public _string_format_detail <StringFormat>
- {
- public:
- inline StringFormat (char * buf, int NbOfChar) : _string_format_detail (buf, NbOfChar) { }
- public:
- template <typename arg>
- inline int _my_sprintf (char * buf, int NbOfChar, const char * fmt, arg a)
- {
- return sprintf_s (buf, NbOfChar, fmt, a);
- }
- };
- }
- //-----------------------------------------------------------------------------
- // 设计说明 (2021-06-18):
- // 1. 为什么只能支持 3 个数字 (即 最大只能是 {$:d999} 或 {$:f999})
- // 1) 预留的 Buffer 一般大小是 8192, 见 DString::Format 及 TLSLog
- // 2) 最终会调用 _vsprintf_s_l (buffer, len, ...)
- // 3) 当 buffer 不足时, 上述函数会调用 无效参数错误处理函数,
- // 4) 无效参数错误处理函数 : 在 Debug 模式时, 弹出断言错误. 在 Release 模式时, 直接终止程序.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // 自定义类型的格式化 (2023-05-15)
- /*
- class TestMyClass
- {
- public:
- TestMyClass () = default;
- };
- namespace ECOM::Utility::String
- {
- template <> inline std::string ToString (const TestMyClass & value)
- {
- return std::string ("it is TestMyClass !");
- }
- }
- */
- // assert (eSTR::DString::FromFormat ("{$}{$}-{$}"_sv, 11, 22, TestMyClass ()) == eSTR::DString ("1122-it is TestMyClass !"));
- //-----------------------------------------------------------------------------
|