1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#ifndef C10_UTIL_STRINGUTIL_H_
#define C10_UTIL_STRINGUTIL_H_
#include <c10/macros/Macros.h>
#include <c10/util/string_utils.h>
#include <cstddef>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
namespace c10 {
namespace detail {
// Obtains the base name from a full path.
C10_API std::string StripBasename(const std::string& full_path);
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) {
ss << t;
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 std::string 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. Let's just return a reference to an empty string.
template<>
struct _str_wrapper<> final {
static const std::string& call() {
thread_local const std::string empty_string_literal;
return empty_string_literal;
}
};
} // 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, const char* from, const char* 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 std::string& 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
#endif // C10_UTIL_STRINGUTIL_H_
|