StringUtil.h 5.1 KB

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