StringUtil.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #ifndef C10_UTIL_STRINGUTIL_H_
  2. #define C10_UTIL_STRINGUTIL_H_
  3. #include <c10/macros/Macros.h>
  4. #include <c10/util/string_utils.h>
  5. #include <c10/util/string_view.h>
  6. #include <cstddef>
  7. #include <ostream>
  8. #include <sstream>
  9. #include <string>
  10. #include <vector>
  11. C10_CLANG_DIAGNOSTIC_PUSH()
  12. #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
  13. C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
  14. #endif
  15. namespace c10 {
  16. namespace detail {
  17. // Obtains the base name from a full path.
  18. C10_API std::string StripBasename(const std::string& full_path);
  19. C10_API std::string ExcludeFileExtension(const std::string& full_path);
  20. struct CompileTimeEmptyString {
  21. operator const std::string&() const {
  22. static const std::string empty_string_literal;
  23. return empty_string_literal;
  24. }
  25. operator const char*() const {
  26. return "";
  27. }
  28. };
  29. template <typename T>
  30. struct CanonicalizeStrTypes {
  31. using type = const T&;
  32. };
  33. template <size_t N>
  34. struct CanonicalizeStrTypes<char[N]> {
  35. using type = const char*;
  36. };
  37. inline std::ostream& _str(std::ostream& ss) {
  38. return ss;
  39. }
  40. template <typename T>
  41. inline std::ostream& _str(std::ostream& ss, const T& t) {
  42. // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
  43. ss << t;
  44. return ss;
  45. }
  46. template <>
  47. inline std::ostream& _str<CompileTimeEmptyString>(
  48. std::ostream& ss,
  49. const CompileTimeEmptyString&) {
  50. return ss;
  51. }
  52. template <typename T, typename... Args>
  53. inline std::ostream& _str(std::ostream& ss, const T& t, const Args&... args) {
  54. return _str(_str(ss, t), args...);
  55. }
  56. template <typename... Args>
  57. struct _str_wrapper final {
  58. static std::string call(const Args&... args) {
  59. std::ostringstream ss;
  60. _str(ss, args...);
  61. return ss.str();
  62. }
  63. };
  64. // Specializations for already-a-string types.
  65. template <>
  66. struct _str_wrapper<std::string> final {
  67. // return by reference to avoid the binary size of a string copy
  68. static const std::string& call(const std::string& str) {
  69. return str;
  70. }
  71. };
  72. template <>
  73. struct _str_wrapper<const char*> final {
  74. static const char* call(const char* str) {
  75. return str;
  76. }
  77. };
  78. // For c10::str() with an empty argument list (which is common in our assert
  79. // macros), we don't want to pay the binary size for constructing and
  80. // destructing a stringstream or even constructing a string.
  81. template <>
  82. struct _str_wrapper<> final {
  83. static CompileTimeEmptyString call() {
  84. return CompileTimeEmptyString();
  85. }
  86. };
  87. } // namespace detail
  88. // Convert a list of string-like arguments into a single string.
  89. template <typename... Args>
  90. inline decltype(auto) str(const Args&... args) {
  91. return detail::_str_wrapper<
  92. typename detail::CanonicalizeStrTypes<Args>::type...>::call(args...);
  93. }
  94. template <class Container>
  95. inline std::string Join(const std::string& delimiter, const Container& v) {
  96. std::stringstream s;
  97. int cnt = static_cast<int64_t>(v.size()) - 1;
  98. for (auto i = v.begin(); i != v.end(); ++i, --cnt) {
  99. s << (*i) << (cnt ? delimiter : "");
  100. }
  101. return s.str();
  102. }
  103. // Replace all occurrences of "from" substring to "to" string.
  104. // Returns number of replacements
  105. size_t C10_API
  106. ReplaceAll(std::string& s, c10::string_view from, c10::string_view to);
  107. /// Represents a location in source code (for debugging).
  108. struct C10_API SourceLocation {
  109. const char* function;
  110. const char* file;
  111. uint32_t line;
  112. };
  113. std::ostream& operator<<(std::ostream& out, const SourceLocation& loc);
  114. // unix isprint but insensitive to locale
  115. inline static bool isPrint(char s) {
  116. return s > 0x1f && s < 0x7f;
  117. }
  118. inline void printQuotedString(std::ostream& stmt, const string_view str) {
  119. stmt << "\"";
  120. for (auto s : str) {
  121. switch (s) {
  122. case '\\':
  123. stmt << "\\\\";
  124. break;
  125. case '\'':
  126. stmt << "\\'";
  127. break;
  128. case '\"':
  129. stmt << "\\\"";
  130. break;
  131. case '\a':
  132. stmt << "\\a";
  133. break;
  134. case '\b':
  135. stmt << "\\b";
  136. break;
  137. case '\f':
  138. stmt << "\\f";
  139. break;
  140. case '\n':
  141. stmt << "\\n";
  142. break;
  143. case '\r':
  144. stmt << "\\r";
  145. break;
  146. case '\t':
  147. stmt << "\\t";
  148. break;
  149. case '\v':
  150. stmt << "\\v";
  151. break;
  152. default:
  153. if (isPrint(s)) {
  154. stmt << s;
  155. } else {
  156. // C++ io has stateful formatting settings. Messing with
  157. // them is probably worse than doing this manually.
  158. char buf[4] = "000";
  159. buf[2] += s % 8;
  160. s /= 8;
  161. buf[1] += s % 8;
  162. s /= 8;
  163. buf[0] += s;
  164. stmt << "\\" << buf;
  165. }
  166. break;
  167. }
  168. }
  169. stmt << "\"";
  170. }
  171. } // namespace c10
  172. C10_CLANG_DIAGNOSTIC_POP()
  173. #endif // C10_UTIL_STRINGUTIL_H_