mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 22:30:13 +00:00
[reland][NFC][libc] standardize string_view
This commit is contained in:
parent
13cb1a9249
commit
df99774ef7
@ -33,30 +33,41 @@ private:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static constexpr size_t length(const char *Str) {
|
||||
for (const char *End = Str;; ++End)
|
||||
if (*End == '\0')
|
||||
return End - Str;
|
||||
}
|
||||
|
||||
bool equals(string_view Other) const {
|
||||
return (Len == Other.Len &&
|
||||
compareMemory(Data, Other.Data, Other.Len) == 0);
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = char;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using pointer = char *;
|
||||
using const_pointer = const char *;
|
||||
using reference = char &;
|
||||
using const_reference = const char &;
|
||||
using const_iterator = char *;
|
||||
using iterator = const_iterator;
|
||||
|
||||
// special value equal to the maximum value representable by the type
|
||||
// size_type.
|
||||
static constexpr size_t npos = -1;
|
||||
inline static constexpr size_t npos = -1;
|
||||
|
||||
constexpr string_view() : Data(nullptr), Len(0) {}
|
||||
|
||||
// Assumes Str is a null-terminated string. The length of the string does
|
||||
// not include the terminating null character.
|
||||
explicit constexpr string_view(const char *Str) : Data(Str), Len(0) {
|
||||
if (Str == nullptr)
|
||||
return;
|
||||
for (const char *D = Data; *D != '\0'; ++D, ++Len)
|
||||
;
|
||||
if (Len == 0)
|
||||
Data = nullptr;
|
||||
}
|
||||
// Preconditions: [Str, Str + length(Str)) is a valid range.
|
||||
constexpr string_view(const char *Str) : Data(Str), Len(length(Str)) {}
|
||||
|
||||
explicit constexpr string_view(const char *Str, size_t N)
|
||||
: Data(N ? Str : nullptr), Len(Str == nullptr ? 0 : N) {}
|
||||
|
||||
// Ctor for raw literal.
|
||||
template <size_t N>
|
||||
constexpr string_view(const char (&Str)[N]) : string_view(Str, N - 1) {}
|
||||
// Preconditions: [Str, Str + N) is a valid range.
|
||||
constexpr string_view(const char *Str, size_t N) : Data(Str), Len(N) {}
|
||||
|
||||
constexpr const char *data() const { return Data; }
|
||||
|
||||
@ -90,16 +101,14 @@ public:
|
||||
return Len < Other.Len ? -1 : 1;
|
||||
}
|
||||
|
||||
// An equivalent method is not available in std::string_view.
|
||||
bool equals(string_view Other) const {
|
||||
return (Len == Other.Len &&
|
||||
compareMemory(Data, Other.Data, Other.Len) == 0);
|
||||
}
|
||||
|
||||
inline bool operator==(string_view Other) const { return equals(Other); }
|
||||
inline bool operator!=(string_view Other) const { return !(*this == Other); }
|
||||
inline bool operator<(string_view Other) const { return compare(Other) == -1; }
|
||||
inline bool operator<=(string_view Other) const { return compare(Other) != 1; }
|
||||
inline bool operator<(string_view Other) const {
|
||||
return compare(Other) == -1;
|
||||
}
|
||||
inline bool operator<=(string_view Other) const {
|
||||
return compare(Other) != 1;
|
||||
}
|
||||
inline bool operator>(string_view Other) const { return compare(Other) == 1; }
|
||||
inline bool operator>=(string_view Other) const {
|
||||
return compare(Other) != -1;
|
||||
@ -116,16 +125,6 @@ public:
|
||||
// The behavior is undefined if n > size().
|
||||
void remove_suffix(size_t N) { Len -= N; }
|
||||
|
||||
// An equivalent method is not available in std::string_view.
|
||||
string_view trim(const char C) const {
|
||||
string_view Copy = *this;
|
||||
while (Copy.starts_with(C))
|
||||
Copy = Copy.drop_front();
|
||||
while (Copy.ends_with(C))
|
||||
Copy = Copy.drop_back();
|
||||
return Copy;
|
||||
}
|
||||
|
||||
// Check if this string starts with the given Prefix.
|
||||
bool starts_with(string_view Prefix) const {
|
||||
return Len >= Prefix.Len &&
|
||||
@ -162,129 +161,27 @@ public:
|
||||
return string_view(Data + Start, min(N, Len - Start));
|
||||
}
|
||||
|
||||
// Search for the first character matching the character
|
||||
//
|
||||
// Returns The index of the first character satisfying the character starting
|
||||
// from From, or npos if not found.
|
||||
size_t find_first_of(const char c, size_t From = 0) const noexcept {
|
||||
string_view S = drop_front(From);
|
||||
while (!S.empty()) {
|
||||
if (S.front() == c)
|
||||
return size() - S.size();
|
||||
S = S.drop_front();
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Search for the last character matching the character
|
||||
//
|
||||
// Return the index of the last character equal to the |c| before End.
|
||||
size_t find_last_of(const char c, size_t End = npos) const {
|
||||
End = End > size() ? size() : End + 1;
|
||||
string_view S = drop_back(size() - End);
|
||||
while (!S.empty()) {
|
||||
if (S.back() == c)
|
||||
return S.size() - 1;
|
||||
S = S.drop_back();
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Search for the first character satisfying the predicate Function
|
||||
//
|
||||
// Returns The index of the first character satisfying Function starting from
|
||||
// From, or npos if not found.
|
||||
template <typename F> size_t find_if(F Function, size_t From = 0) const {
|
||||
string_view S = drop_front(From);
|
||||
while (!S.empty()) {
|
||||
if (Function(S.front()))
|
||||
return size() - S.size();
|
||||
S = S.drop_front();
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Search for the first character not satisfying the predicate Function
|
||||
// Returns The index of the first character not satisfying Function starting
|
||||
// from From, or npos if not found.
|
||||
template <typename F> size_t find_if_not(F Function, size_t From = 0) const {
|
||||
return find_if([Function](char c) { return !Function(c); }, From);
|
||||
}
|
||||
|
||||
// front - Get the first character in the string.
|
||||
char front() const { return Data[0]; }
|
||||
|
||||
// back - Get the last character in the string.
|
||||
char back() const { return Data[Len - 1]; }
|
||||
|
||||
// Return a string_view equal to 'this' but with the first N elements
|
||||
// dropped.
|
||||
string_view drop_front(size_t N = 1) const { return substr(N); }
|
||||
|
||||
// Return a string_view equal to 'this' but with the last N elements
|
||||
// dropped.
|
||||
string_view drop_back(size_t N = 1) const { return substr(0, size() - N); }
|
||||
|
||||
// Return a string_view equal to 'this' but with only the first N
|
||||
// elements remaining. If N is greater than the length of the
|
||||
// string, the entire string is returned.
|
||||
string_view take_front(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
return *this;
|
||||
return drop_back(size() - N);
|
||||
// Finds the first occurence of c in this view, starting at position From.
|
||||
size_t find_first_of(const char c, size_t From = 0) const {
|
||||
for (size_t Pos = From; Pos < size(); ++Pos)
|
||||
if ((*this)[Pos] == c)
|
||||
return Pos;
|
||||
return npos;
|
||||
}
|
||||
|
||||
// Return a string_view equal to 'this' but with only the last N
|
||||
// elements remaining. If N is greater than the length of the
|
||||
// string, the entire string is returned.
|
||||
string_view take_back(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
return *this;
|
||||
return drop_front(size() - N);
|
||||
}
|
||||
|
||||
// Return the longest prefix of 'this' such that every character
|
||||
// in the prefix satisfies the given predicate.
|
||||
template <typename F> string_view take_while(F Function) const {
|
||||
return substr(0, find_if_not(Function));
|
||||
}
|
||||
|
||||
// Return the longest prefix of 'this' such that no character in
|
||||
// the prefix satisfies the given predicate.
|
||||
template <typename F> string_view take_until(F Function) const {
|
||||
return substr(0, find_if(Function));
|
||||
}
|
||||
|
||||
// Return a string_view equal to 'this', but with all characters satisfying
|
||||
// the given predicate dropped from the beginning of the string.
|
||||
template <typename F> string_view drop_while(F Function) const {
|
||||
return substr(find_if_not(Function));
|
||||
}
|
||||
|
||||
// Return a string_view equal to 'this', but with all characters not
|
||||
// satisfying the given predicate dropped from the beginning of the string.
|
||||
template <typename F> string_view drop_until(F Function) const {
|
||||
return substr(find_if(Function));
|
||||
}
|
||||
|
||||
// Returns true if this string_view has the given prefix and removes that
|
||||
// prefix.
|
||||
bool consume_front(string_view Prefix) {
|
||||
if (!starts_with(Prefix))
|
||||
return false;
|
||||
|
||||
*this = drop_front(Prefix.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if this string_view has the given suffix and removes that
|
||||
// suffix.
|
||||
bool consume_back(string_view Suffix) {
|
||||
if (!ends_with(Suffix))
|
||||
return false;
|
||||
|
||||
*this = drop_back(Suffix.size());
|
||||
return true;
|
||||
// Finds the last occurence of c in this view, ending at position End.
|
||||
size_t find_last_of(const char c, size_t End = npos) const {
|
||||
End = End >= size() ? size() : End + 1;
|
||||
for (; End > 0; --End)
|
||||
if ((*this)[End - 1] == c)
|
||||
return End - 1;
|
||||
return npos;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,8 +58,8 @@ struct FormatSection {
|
||||
if (has_conv != other.has_conv)
|
||||
return false;
|
||||
|
||||
if (!cpp::string_view(raw_string, raw_len)
|
||||
.equals(cpp::string_view(other.raw_string, other.raw_len)))
|
||||
if (cpp::string_view(raw_string, raw_len) !=
|
||||
cpp::string_view(other.raw_string, other.raw_len))
|
||||
return false;
|
||||
|
||||
if (has_conv) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
//===-- Unittests for string_view ------------------------------------------===//
|
||||
//===-- Unittests for string_view
|
||||
//------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
@ -18,19 +19,11 @@ TEST(LlvmLibcStringViewTest, InitializeCheck) {
|
||||
|
||||
v = string_view("");
|
||||
ASSERT_EQ(v.size(), size_t(0));
|
||||
ASSERT_TRUE(v.data() == nullptr);
|
||||
|
||||
v = string_view(nullptr);
|
||||
ASSERT_EQ(v.size(), size_t(0));
|
||||
ASSERT_TRUE(v.data() == nullptr);
|
||||
|
||||
v = string_view(nullptr, 10);
|
||||
ASSERT_EQ(v.size(), size_t(0));
|
||||
ASSERT_TRUE(v.data() == nullptr);
|
||||
ASSERT_TRUE(v.data() != nullptr);
|
||||
|
||||
v = string_view("abc", 0);
|
||||
ASSERT_EQ(v.size(), size_t(0));
|
||||
ASSERT_TRUE(v.data() == nullptr);
|
||||
ASSERT_TRUE(v.data() != nullptr);
|
||||
|
||||
v = string_view("123456789");
|
||||
ASSERT_EQ(v.size(), size_t(9));
|
||||
@ -38,13 +31,13 @@ TEST(LlvmLibcStringViewTest, InitializeCheck) {
|
||||
|
||||
TEST(LlvmLibcStringViewTest, Equals) {
|
||||
string_view v("abc");
|
||||
ASSERT_TRUE(v.equals(string_view("abc")));
|
||||
ASSERT_FALSE(v.equals(string_view()));
|
||||
ASSERT_FALSE(v.equals(string_view("")));
|
||||
ASSERT_FALSE(v.equals(string_view("123")));
|
||||
ASSERT_FALSE(v.equals(string_view("abd")));
|
||||
ASSERT_FALSE(v.equals(string_view("aaa")));
|
||||
ASSERT_FALSE(v.equals(string_view("abcde")));
|
||||
ASSERT_EQ(v, string_view("abc"));
|
||||
ASSERT_NE(v, string_view());
|
||||
ASSERT_NE(v, string_view(""));
|
||||
ASSERT_NE(v, string_view("123"));
|
||||
ASSERT_NE(v, string_view("abd"));
|
||||
ASSERT_NE(v, string_view("aaa"));
|
||||
ASSERT_NE(v, string_view("abcde"));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, startsWith) {
|
||||
@ -81,12 +74,12 @@ TEST(LlvmLibcStringViewTest, RemovePrefix) {
|
||||
string_view a("123456789");
|
||||
a.remove_prefix(0);
|
||||
ASSERT_EQ(a.size(), size_t(9));
|
||||
ASSERT_TRUE(a.equals(string_view("123456789")));
|
||||
ASSERT_TRUE(a == "123456789");
|
||||
|
||||
string_view b("123456789");
|
||||
b.remove_prefix(4);
|
||||
ASSERT_EQ(b.size(), size_t(5));
|
||||
ASSERT_TRUE(b.equals(string_view("56789")));
|
||||
ASSERT_TRUE(b == "56789");
|
||||
|
||||
string_view c("123456789");
|
||||
c.remove_prefix(9);
|
||||
@ -97,59 +90,18 @@ TEST(LlvmLibcStringViewTest, RemoveSuffix) {
|
||||
string_view a("123456789");
|
||||
a.remove_suffix(0);
|
||||
ASSERT_EQ(a.size(), size_t(9));
|
||||
ASSERT_TRUE(a.equals(string_view("123456789")));
|
||||
ASSERT_TRUE(a == "123456789");
|
||||
|
||||
string_view b("123456789");
|
||||
b.remove_suffix(4);
|
||||
ASSERT_EQ(b.size(), size_t(5));
|
||||
ASSERT_TRUE(b.equals(string_view("12345")));
|
||||
ASSERT_TRUE(b == "12345");
|
||||
|
||||
string_view c("123456789");
|
||||
c.remove_suffix(9);
|
||||
ASSERT_EQ(c.size(), size_t(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, TrimSingleChar) {
|
||||
string_view v(" 123456789 ");
|
||||
auto t = v.trim(' ');
|
||||
ASSERT_EQ(t.size(), size_t(9));
|
||||
ASSERT_TRUE(t.equals(string_view("123456789")));
|
||||
|
||||
v = string_view("====12345==");
|
||||
t = v.trim(' ');
|
||||
ASSERT_EQ(v.size(), size_t(11));
|
||||
ASSERT_TRUE(t.equals(string_view("====12345==")));
|
||||
|
||||
t = v.trim('=');
|
||||
ASSERT_EQ(t.size(), size_t(5));
|
||||
ASSERT_TRUE(t.equals(string_view("12345")));
|
||||
|
||||
v = string_view("12345===");
|
||||
t = v.trim('=');
|
||||
ASSERT_EQ(t.size(), size_t(5));
|
||||
ASSERT_TRUE(t.equals(string_view("12345")));
|
||||
|
||||
v = string_view("===========12345");
|
||||
t = v.trim('=');
|
||||
ASSERT_EQ(t.size(), size_t(5));
|
||||
ASSERT_TRUE(t.equals(string_view("12345")));
|
||||
|
||||
v = string_view("============");
|
||||
t = v.trim('=');
|
||||
ASSERT_EQ(t.size(), size_t(0));
|
||||
ASSERT_TRUE(t.data() == nullptr);
|
||||
|
||||
v = string_view();
|
||||
t = v.trim(' ');
|
||||
ASSERT_EQ(t.size(), size_t(0));
|
||||
ASSERT_TRUE(t.data() == nullptr);
|
||||
|
||||
v = string_view("");
|
||||
t = v.trim(' ');
|
||||
ASSERT_EQ(t.size(), size_t(0));
|
||||
ASSERT_TRUE(t.data() == nullptr);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, Observer) {
|
||||
string_view ABC("abc");
|
||||
ASSERT_EQ(ABC.size(), size_t(3));
|
||||
@ -160,32 +112,6 @@ TEST(LlvmLibcStringViewTest, Observer) {
|
||||
|
||||
bool isDigit(char c) { return c >= '0' && c <= '9'; }
|
||||
|
||||
TEST(LlvmLibcStringViewTest, Transform) {
|
||||
ASSERT_TRUE(string_view("123abc").drop_back(3).equals("123"));
|
||||
ASSERT_TRUE(string_view("123abc").drop_front(3).equals("abc"));
|
||||
ASSERT_TRUE(string_view("123abc").take_back(3).equals("abc"));
|
||||
ASSERT_TRUE(string_view("123abc").take_front(3).equals("123"));
|
||||
|
||||
ASSERT_TRUE(string_view("123abc").take_while(&isDigit).equals("123"));
|
||||
ASSERT_TRUE(string_view("abc123").take_until(&isDigit).equals("abc"));
|
||||
ASSERT_TRUE(string_view("123abc").drop_while(&isDigit).equals("abc"));
|
||||
ASSERT_TRUE(string_view("abc123").drop_until(&isDigit).equals("123"));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, ConsumeFront) {
|
||||
string_view Tmp("abc");
|
||||
ASSERT_FALSE(Tmp.consume_front("###"));
|
||||
ASSERT_TRUE(Tmp.consume_front("ab"));
|
||||
ASSERT_TRUE(Tmp.equals("c"));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, ConsumeBack) {
|
||||
string_view Tmp("abc");
|
||||
ASSERT_FALSE(Tmp.consume_back("###"));
|
||||
ASSERT_TRUE(Tmp.consume_back("bc"));
|
||||
ASSERT_TRUE(Tmp.equals("a"));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStringViewTest, FindFirstOf) {
|
||||
string_view Tmp("abca");
|
||||
ASSERT_TRUE(Tmp.find_first_of('a') == 0);
|
||||
|
@ -33,13 +33,13 @@ TEST(LlvmLibcDirentTest, SimpleOpenAndRead) {
|
||||
struct ::dirent *d = __llvm_libc::readdir(dir);
|
||||
if (d == nullptr)
|
||||
break;
|
||||
if (string_view(&d->d_name[0]).equals("file1.txt"))
|
||||
if (string_view(&d->d_name[0]) == "file1.txt")
|
||||
file1 = d;
|
||||
if (string_view(&d->d_name[0]).equals("file2.txt"))
|
||||
if (string_view(&d->d_name[0]) == "file2.txt")
|
||||
file2 = d;
|
||||
if (string_view(&d->d_name[0]).equals("dir1"))
|
||||
if (string_view(&d->d_name[0]) == "dir1")
|
||||
dir1 = d;
|
||||
if (string_view(&d->d_name[0]).equals("dir2"))
|
||||
if (string_view(&d->d_name[0]) == "dir2")
|
||||
dir2 = d;
|
||||
}
|
||||
|
||||
|
@ -380,7 +380,12 @@ public:
|
||||
char buffer[printBufSize];
|
||||
mpfr_snprintf(buffer, printBufSize, "%100.50Rf", value);
|
||||
cpp::string_view view(buffer);
|
||||
view = view.trim(' ');
|
||||
// Trim whitespaces
|
||||
const char whitespace = ' ';
|
||||
while (!view.empty() && view.front() == whitespace)
|
||||
view.remove_prefix(1);
|
||||
while (!view.empty() && view.back() == whitespace)
|
||||
view.remove_suffix(1);
|
||||
return std::string(view.data());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user