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