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