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
|
#include <c10/util/StringUtil.h>
#include <string>
#ifndef _WIN32
#include <codecvt>
#include <locale>
#else
#include <c10/util/Unicode.h>
#endif
namespace c10 {
namespace detail {
std::string StripBasename(const std::string& full_path) {
#ifdef _WIN32
const std::string separators("/\\");
#else
const std::string separators("/");
#endif
size_t pos = full_path.find_last_of(separators);
if (pos != std::string::npos) {
return full_path.substr(pos + 1, std::string::npos);
} else {
return full_path;
}
}
std::string ExcludeFileExtension(const std::string& file_name) {
const char sep = '.';
auto end_index = file_name.find_last_of(sep) == std::string::npos
? -1
: file_name.find_last_of(sep);
return file_name.substr(0, end_index);
}
// Narrows the wstr argument and then passes it to _str.
// Assumes that the input (wide) text is encoded as UTF-16.
static std::ostream& _strFromWide(
std::ostream& ss,
const std::wstring& wString);
#ifndef _WIN32
C10_DIAGNOSTIC_PUSH_AND_IGNORED_IF_DEFINED("-Wdeprecated-declarations")
// TODO (huydhn) https://en.cppreference.com/w/cpp/header/codecvt has been
// deprecated in C++17 but there is no alternative yet, so I just ack it
static std::ostream& _strFromWide(
std::ostream& ss,
const std::wstring& wString) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return _str(ss, converter.to_bytes(wString));
}
C10_DIAGNOSTIC_POP()
#else // #ifndef _WIN32
// The WIN32 implementation of wstring_convert leaks memory; see
// https://github.com/microsoft/STL/issues/443
static std::ostream& _strFromWide(
std::ostream& ss,
const std::wstring& wString) {
return _str(ss, u16u8(wString));
}
#endif // _WIN32
std::ostream& _str(std::ostream& ss, const wchar_t* wCStr) {
return _strFromWide(ss, std::wstring(wCStr));
}
std::ostream& _str(std::ostream& ss, const wchar_t& wChar) {
return _strFromWide(ss, std::wstring(1, wChar));
}
std::ostream& _str(std::ostream& ss, const std::wstring& wString) {
return _strFromWide(ss, wString);
}
} // namespace detail
std::ostream& operator<<(std::ostream& out, const SourceLocation& loc) {
out << loc.function << " at " << loc.file << ":" << loc.line;
return out;
}
size_t ReplaceAll(std::string& s, std::string_view from, std::string_view to) {
if (from.empty()) {
return 0;
}
size_t numReplaced = 0;
std::string::size_type last_pos = 0u;
std::string::size_type cur_pos = 0u;
std::string::size_type write_pos = 0u;
const c10::string_view input(s);
if (from.size() >= to.size()) {
// If the replacement string is not larger than the original, we
// can do the replacement in-place without allocating new storage.
char* s_data = &s[0];
while ((cur_pos = s.find(from.data(), last_pos, from.size())) !=
std::string::npos) {
++numReplaced;
// Append input between replaced sub-strings
if (write_pos != last_pos) {
std::copy(s_data + last_pos, s_data + cur_pos, s_data + write_pos);
}
write_pos += cur_pos - last_pos;
// Append the replacement sub-string
std::copy(to.begin(), to.end(), s_data + write_pos);
write_pos += to.size();
// Start search from next character after `from`
last_pos = cur_pos + from.size();
}
// Append any remaining input after replaced sub-strings
if (write_pos != last_pos) {
std::copy(s_data + last_pos, s_data + input.size(), s_data + write_pos);
write_pos += input.size() - last_pos;
s.resize(write_pos);
}
return numReplaced;
}
// Otherwise, do an out-of-place replacement in a temporary buffer
std::string buffer;
while ((cur_pos = s.find(from.data(), last_pos, from.size())) !=
std::string::npos) {
++numReplaced;
// Append input between replaced sub-strings
buffer.append(input.begin() + last_pos, input.begin() + cur_pos);
// Append the replacement sub-string
buffer.append(to.begin(), to.end());
// Start search from next character after `from`
last_pos = cur_pos + from.size();
}
if (numReplaced == 0) {
// If nothing was replaced, don't modify the input
return 0;
}
// Append any remaining input after replaced sub-strings
buffer.append(input.begin() + last_pos, input.end());
s = std::move(buffer);
return numReplaced;
}
} // namespace c10
|