|  | #ifndef C10_UTIL_STRINGUTIL_H_ | 
|  | #define C10_UTIL_STRINGUTIL_H_ | 
|  |  | 
|  | #include <c10/macros/Macros.h> | 
|  | #include <c10/util/string_utils.h> | 
|  | #include <c10/util/string_view.h> | 
|  |  | 
|  | #include <cstddef> | 
|  | #include <ostream> | 
|  | #include <sstream> | 
|  | #include <string> | 
|  | #include <vector> | 
|  |  | 
|  | C10_CLANG_DIAGNOSTIC_PUSH() | 
|  | #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32") | 
|  | C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32") | 
|  | #endif | 
|  |  | 
|  | namespace c10 { | 
|  |  | 
|  | namespace detail { | 
|  |  | 
|  | // Obtains the base name from a full path. | 
|  | C10_API std::string StripBasename(const std::string& full_path); | 
|  |  | 
|  | C10_API std::string ExcludeFileExtension(const std::string& full_path); | 
|  |  | 
|  | struct CompileTimeEmptyString { | 
|  | operator const std::string&() const { | 
|  | static const std::string empty_string_literal; | 
|  | return empty_string_literal; | 
|  | } | 
|  | operator const char*() const { | 
|  | return ""; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | struct CanonicalizeStrTypes { | 
|  | using type = const T&; | 
|  | }; | 
|  |  | 
|  | template <size_t N> | 
|  | struct CanonicalizeStrTypes<char[N]> { | 
|  | using type = const char*; | 
|  | }; | 
|  |  | 
|  | inline std::ostream& _str(std::ostream& ss) { | 
|  | return ss; | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | inline std::ostream& _str(std::ostream& ss, const T& t) { | 
|  | // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) | 
|  | ss << t; | 
|  | return ss; | 
|  | } | 
|  |  | 
|  | template <> | 
|  | inline std::ostream& _str<CompileTimeEmptyString>( | 
|  | std::ostream& ss, | 
|  | const CompileTimeEmptyString&) { | 
|  | return ss; | 
|  | } | 
|  |  | 
|  | template <typename T, typename... Args> | 
|  | inline std::ostream& _str(std::ostream& ss, const T& t, const Args&... args) { | 
|  | return _str(_str(ss, t), args...); | 
|  | } | 
|  |  | 
|  | template <typename... Args> | 
|  | struct _str_wrapper final { | 
|  | static std::string call(const Args&... args) { | 
|  | std::ostringstream ss; | 
|  | _str(ss, args...); | 
|  | return ss.str(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | // Specializations for already-a-string types. | 
|  | template <> | 
|  | struct _str_wrapper<std::string> final { | 
|  | // return by reference to avoid the binary size of a string copy | 
|  | static const std::string& call(const std::string& str) { | 
|  | return str; | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct _str_wrapper<const char*> final { | 
|  | static const char* call(const char* str) { | 
|  | return str; | 
|  | } | 
|  | }; | 
|  |  | 
|  | // For c10::str() with an empty argument list (which is common in our assert | 
|  | // macros), we don't want to pay the binary size for constructing and | 
|  | // destructing a stringstream or even constructing a string. | 
|  | template <> | 
|  | struct _str_wrapper<> final { | 
|  | static CompileTimeEmptyString call() { | 
|  | return CompileTimeEmptyString(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // namespace detail | 
|  |  | 
|  | // Convert a list of string-like arguments into a single string. | 
|  | template <typename... Args> | 
|  | inline decltype(auto) str(const Args&... args) { | 
|  | return detail::_str_wrapper< | 
|  | typename detail::CanonicalizeStrTypes<Args>::type...>::call(args...); | 
|  | } | 
|  |  | 
|  | template <class Container> | 
|  | inline std::string Join(const std::string& delimiter, const Container& v) { | 
|  | std::stringstream s; | 
|  | int cnt = static_cast<int64_t>(v.size()) - 1; | 
|  | for (auto i = v.begin(); i != v.end(); ++i, --cnt) { | 
|  | s << (*i) << (cnt ? delimiter : ""); | 
|  | } | 
|  | return s.str(); | 
|  | } | 
|  |  | 
|  | // Replace all occurrences of "from" substring to "to" string. | 
|  | // Returns number of replacements | 
|  | size_t C10_API | 
|  | ReplaceAll(std::string& s, c10::string_view from, c10::string_view to); | 
|  |  | 
|  | /// Represents a location in source code (for debugging). | 
|  | struct C10_API SourceLocation { | 
|  | const char* function; | 
|  | const char* file; | 
|  | uint32_t line; | 
|  | }; | 
|  |  | 
|  | std::ostream& operator<<(std::ostream& out, const SourceLocation& loc); | 
|  |  | 
|  | // unix isprint but insensitive to locale | 
|  | inline static bool isPrint(char s) { | 
|  | return s > 0x1f && s < 0x7f; | 
|  | } | 
|  |  | 
|  | inline void printQuotedString(std::ostream& stmt, const string_view str) { | 
|  | stmt << "\""; | 
|  | for (auto s : str) { | 
|  | switch (s) { | 
|  | case '\\': | 
|  | stmt << "\\\\"; | 
|  | break; | 
|  | case '\'': | 
|  | stmt << "\\'"; | 
|  | break; | 
|  | case '\"': | 
|  | stmt << "\\\""; | 
|  | break; | 
|  | case '\a': | 
|  | stmt << "\\a"; | 
|  | break; | 
|  | case '\b': | 
|  | stmt << "\\b"; | 
|  | break; | 
|  | case '\f': | 
|  | stmt << "\\f"; | 
|  | break; | 
|  | case '\n': | 
|  | stmt << "\\n"; | 
|  | break; | 
|  | case '\r': | 
|  | stmt << "\\r"; | 
|  | break; | 
|  | case '\t': | 
|  | stmt << "\\t"; | 
|  | break; | 
|  | case '\v': | 
|  | stmt << "\\v"; | 
|  | break; | 
|  | default: | 
|  | if (isPrint(s)) { | 
|  | stmt << s; | 
|  | } else { | 
|  | // C++ io has stateful formatting settings. Messing with | 
|  | // them is probably worse than doing this manually. | 
|  | char buf[4] = "000"; | 
|  | buf[2] += s % 8; | 
|  | s /= 8; | 
|  | buf[1] += s % 8; | 
|  | s /= 8; | 
|  | buf[0] += s; | 
|  | stmt << "\\" << buf; | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | stmt << "\""; | 
|  | } | 
|  |  | 
|  | } // namespace c10 | 
|  |  | 
|  | C10_CLANG_DIAGNOSTIC_POP() | 
|  |  | 
|  | #endif // C10_UTIL_STRINGUTIL_H_ |