xref: /aosp_15_r20/external/pytorch/c10/util/StringUtil.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
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