StringUtil.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. #ifndef C10_UTIL_STRINGUTIL_H_
  3. #define C10_UTIL_STRINGUTIL_H_
  4. #include <c10/macros/Macros.h>
  5. #include <c10/util/string_utils.h>
  6. #include <cstddef>
  7. #include <optional>
  8. #include <ostream>
  9. #include <sstream>
  10. #include <string>
  11. #include <string_view>
  12. #include <type_traits>
  13. #include <vector>
  14. C10_CLANG_DIAGNOSTIC_PUSH()
  15. #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
  16. C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
  17. #endif
  18. namespace c10 {
  19. namespace detail {
  20. // Obtains the base name from a full path.
  21. C10_API std::string StripBasename(const std::string& full_path);
  22. C10_API std::string ExcludeFileExtension(const std::string& full_path);
  23. struct CompileTimeEmptyString {
  24. operator const std::string&() const {
  25. static const std::string empty_string_literal;
  26. return empty_string_literal;
  27. }
  28. operator const char*() const {
  29. return "";
  30. }
  31. };
  32. template <typename T>
  33. struct CanonicalizeStrTypes {
  34. using type = const T&;
  35. };
  36. template <size_t N>
  37. // NOLINTNEXTLINE(*c-arrays*)
  38. struct CanonicalizeStrTypes<char[N]> {
  39. using type = const char*;
  40. };
  41. inline std::ostream& _str(std::ostream& ss) {
  42. return ss;
  43. }
  44. template <class T, class = std::ostream&>
  45. struct Streamable : std::false_type {};
  46. template <class T>
  47. struct Streamable<T, decltype(std::declval<std::ostream&>() << T{})>
  48. : std::true_type {};
  49. template <typename T>
  50. inline std::ostream& _str(std::ostream& ss, const T& t) {
  51. if constexpr (std::is_enum_v<T> && !Streamable<T>::value) {
  52. // NOLINTNEXTLINE(modernize-type-traits)
  53. return _str(ss, static_cast<typename std::underlying_type<T>::type>(t));
  54. } else {
  55. // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage)
  56. ss << t;
  57. return ss;
  58. }
  59. }
  60. template <typename T>
  61. inline std::ostream& _str(std::ostream& ss, const std::optional<T>& t) {
  62. if (t.has_value()) {
  63. return _str(ss, t.value());
  64. }
  65. ss << "std::nullopt";
  66. return ss;
  67. }
  68. // Overloads of _str for wide types; forces narrowing.
  69. C10_API std::ostream& _str(std::ostream& ss, const wchar_t* wCStr);
  70. C10_API std::ostream& _str(std::ostream& ss, const wchar_t& wChar);
  71. C10_API std::ostream& _str(std::ostream& ss, const std::wstring& wString);
  72. template <>
  73. inline std::ostream& _str<CompileTimeEmptyString>(
  74. std::ostream& ss,
  75. const CompileTimeEmptyString& /*unused*/) {
  76. return ss;
  77. }
  78. template <typename T, typename... Args>
  79. inline std::ostream& _str(std::ostream& ss, const T& t, const Args&... args) {
  80. return _str(_str(ss, t), args...);
  81. }
  82. template <typename... Args>
  83. struct _str_wrapper final {
  84. static std::string call(const Args&... args) {
  85. std::ostringstream ss;
  86. _str(ss, args...);
  87. return ss.str();
  88. }
  89. };
  90. // Specializations for already-a-string types.
  91. template <>
  92. struct _str_wrapper<std::string> final {
  93. // return by reference to avoid the binary size of a string copy
  94. static const std::string& call(const std::string& str) {
  95. return str;
  96. }
  97. };
  98. template <>
  99. struct _str_wrapper<const char*> final {
  100. static const char* call(const char* str) {
  101. return str;
  102. }
  103. };
  104. // For c10::str() with an empty argument list (which is common in our assert
  105. // macros), we don't want to pay the binary size for constructing and
  106. // destructing a stringstream or even constructing a string.
  107. template <>
  108. struct _str_wrapper<> final {
  109. static CompileTimeEmptyString call() {
  110. return CompileTimeEmptyString();
  111. }
  112. };
  113. } // namespace detail
  114. // Convert a list of string-like arguments into a single string.
  115. template <typename... Args>
  116. inline auto str(const Args&... args) {
  117. return detail::_str_wrapper<
  118. typename detail::CanonicalizeStrTypes<Args>::type...>::call(args...);
  119. }
  120. template <class Container>
  121. inline std::string Join(const std::string& delimiter, const Container& v) {
  122. std::stringstream s;
  123. int cnt = static_cast<int64_t>(v.size()) - 1;
  124. for (auto i = v.begin(); i != v.end(); ++i, --cnt) {
  125. s << (*i) << (cnt ? delimiter : "");
  126. }
  127. return std::move(s).str();
  128. }
  129. // Replace all occurrences of "from" substring to "to" string.
  130. // Returns number of replacements
  131. size_t C10_API
  132. ReplaceAll(std::string& s, std::string_view from, std::string_view to);
  133. /// Represents a location in source code (for debugging).
  134. struct C10_API SourceLocation {
  135. const char* function;
  136. const char* file;
  137. uint32_t line;
  138. static constexpr SourceLocation current(
  139. const char* file = __builtin_FILE(),
  140. const char* function = __builtin_FUNCTION(),
  141. const std::uint_least32_t line = __builtin_LINE()) noexcept {
  142. return {function, file, line};
  143. }
  144. };
  145. std::ostream& operator<<(std::ostream& out, const SourceLocation& loc);
  146. // unix isprint but insensitive to locale
  147. inline bool isPrint(char s) {
  148. return s > 0x1f && s < 0x7f;
  149. }
  150. inline void printQuotedString(std::ostream& stmt, const std::string_view str) {
  151. stmt << '"';
  152. for (auto s : str) {
  153. switch (s) {
  154. case '\\':
  155. stmt << "\\\\";
  156. break;
  157. case '\'':
  158. stmt << "\\'";
  159. break;
  160. case '\"':
  161. stmt << "\\\"";
  162. break;
  163. case '\a':
  164. stmt << "\\a";
  165. break;
  166. case '\b':
  167. stmt << "\\b";
  168. break;
  169. case '\f':
  170. stmt << "\\f";
  171. break;
  172. case '\n':
  173. stmt << "\\n";
  174. break;
  175. case '\r':
  176. stmt << "\\r";
  177. break;
  178. case '\t':
  179. stmt << "\\t";
  180. break;
  181. case '\v':
  182. stmt << "\\v";
  183. break;
  184. default:
  185. if (isPrint(s)) {
  186. stmt << s;
  187. } else {
  188. // C++ io has stateful formatting settings. Messing with
  189. // them is probably worse than doing this manually.
  190. // NOLINTNEXTLINE(*c-arrays*)
  191. char buf[4] = "000";
  192. // NOLINTNEXTLINE(*narrowing-conversions)
  193. buf[2] += s % 8;
  194. s /= 8;
  195. // NOLINTNEXTLINE(*narrowing-conversions)
  196. buf[1] += s % 8;
  197. s /= 8;
  198. // NOLINTNEXTLINE(*narrowing-conversions)
  199. buf[0] += s;
  200. stmt << "\\" << buf;
  201. }
  202. break;
  203. }
  204. }
  205. stmt << '"';
  206. }
  207. template <typename T>
  208. std::optional<T> tryToNumber(const char* symbol) = delete;
  209. template <typename T>
  210. std::optional<T> tryToNumber(const std::string& symbol) = delete;
  211. /*
  212. * Convert a string to a 64 bit integer. Trailing whitespaces are not supported.
  213. * Similarly, integer string with trailing characters like "123abc" will be
  214. * rejected.
  215. */
  216. template <>
  217. C10_API std::optional<int64_t> tryToNumber<int64_t>(const char* symbol);
  218. template <>
  219. C10_API std::optional<int64_t> tryToNumber<int64_t>(const std::string& symbol);
  220. /*
  221. * Convert a string to a double. Trailing whitespaces are not supported.
  222. * Similarly, integer string with trailing characters like "123abc" will
  223. * be rejected.
  224. */
  225. template <>
  226. C10_API std::optional<double> tryToNumber<double>(const char* symbol);
  227. template <>
  228. C10_API std::optional<double> tryToNumber<double>(const std::string& symbol);
  229. C10_API std::vector<std::string_view> split(
  230. std::string_view target,
  231. char delimiter);
  232. } // namespace c10
  233. C10_CLANG_DIAGNOSTIC_POP()
  234. #endif // C10_UTIL_STRINGUTIL_H_
  235. #else
  236. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  237. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)