Format.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #pragma once
  2. #include <string>
  3. #include <vector>
  4. #include <stdlib.h>
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <sstream>
  8. #include <iomanip>
  9. namespace util
  10. {
  11. class ArgBase
  12. {
  13. public:
  14. ArgBase() {}
  15. virtual ~ArgBase() {}
  16. virtual void Format(std::ostringstream &ss, const std::string &fmt) = 0;
  17. };
  18. template <class T>
  19. class Arg : public ArgBase
  20. {
  21. public:
  22. Arg(T arg) : m_arg(arg) {}
  23. virtual ~Arg() {}
  24. virtual void Format(std::ostringstream &ss, const std::string &fmt)
  25. {
  26. ss << m_arg;
  27. }
  28. private:
  29. T m_arg;
  30. };
  31. class ArgArray : public std::vector<ArgBase *>
  32. {
  33. public:
  34. ArgArray() {}
  35. ~ArgArray()
  36. {
  37. std::for_each(begin(), end(), [](ArgBase *p)
  38. { delete p; });
  39. }
  40. };
  41. static void FormatItem(std::ostringstream &ss, const std::string &item, const ArgArray &args)
  42. {
  43. int index = 0;
  44. int alignment = 0;
  45. std::string fmt;
  46. char *endptr = nullptr;
  47. index = strtol(&item[0], &endptr, 10);
  48. if (index < 0 || index >= args.size())
  49. {
  50. return;
  51. }
  52. if (*endptr == ',')
  53. {
  54. alignment = strtol(endptr + 1, &endptr, 10);
  55. if (alignment > 0)
  56. {
  57. ss << std::right << std::setw(alignment);
  58. }
  59. else if (alignment < 0)
  60. {
  61. ss << std::left << std::setw(-alignment);
  62. }
  63. }
  64. if (*endptr == ':')
  65. {
  66. fmt = endptr + 1;
  67. }
  68. args[index]->Format(ss, fmt);
  69. return;
  70. }
  71. template <class T>
  72. static void Transfer(ArgArray &argArray, T t)
  73. {
  74. argArray.push_back(new Arg<T>(t));
  75. }
  76. template <class T, typename... Args>
  77. static void Transfer(ArgArray &argArray, T t, Args &&...args)
  78. {
  79. Transfer(argArray, t);
  80. Transfer(argArray, args...);
  81. }
  82. template <typename... Args>
  83. std::string Format(const std::string &format, Args &&...args)
  84. {
  85. if (sizeof...(args) == 0)
  86. {
  87. return format;
  88. }
  89. ArgArray argArray;
  90. Transfer(argArray, args...);
  91. size_t start = 0;
  92. size_t pos = 0;
  93. std::ostringstream ss;
  94. while (true)
  95. {
  96. pos = format.find('{', start);
  97. if (pos == std::string::npos)
  98. {
  99. ss << format.substr(start);
  100. break;
  101. }
  102. ss << format.substr(start, pos - start);
  103. if (format[pos + 1] == '{')
  104. {
  105. ss << '{';
  106. start = pos + 2;
  107. continue;
  108. }
  109. start = pos + 1;
  110. pos = format.find('}', start);
  111. if (pos == std::string::npos)
  112. {
  113. ss << format.substr(start - 1);
  114. break;
  115. }
  116. FormatItem(ss, format.substr(start, pos - start), argArray);
  117. start = pos + 1;
  118. }
  119. return ss.str();
  120. }
  121. }