Skip to content

Commit dbb131d

Browse files
author
Siva Chandra Reddy
committed
[libc] Add a standalone flavor of an equivalent of std::string_view.
This class is to serve as a replacement for llvm::StringRef as part of the plans to limit dependency on other parts of LLVM. One use of llvm::StringRef in MPFRWrapper has been replaced with the new class. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D97330
1 parent b79507a commit dbb131d

File tree

6 files changed

+241
-7
lines changed

6 files changed

+241
-7
lines changed

libc/test/utils/CPP/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,13 @@ add_libc_unittest(
99
DEPENDS
1010
libc.utils.CPP.standalone_cpp
1111
)
12+
13+
add_libc_unittest(
14+
stringview_test
15+
SUITE
16+
libc_cpp_utils_unittests
17+
SRCS
18+
stringview_test.cpp
19+
DEPENDS
20+
libc.utils.CPP.standalone_cpp
21+
)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===-- Unittests for StringView ------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "utils/CPP/StringView.h"
10+
#include "utils/UnitTest/Test.h"
11+
12+
TEST(LlvmLibcStringViewTest, InitializeCheck) {
13+
__llvm_libc::cpp::StringView v;
14+
ASSERT_EQ(v.size(), size_t(0));
15+
ASSERT_TRUE(v.data() == nullptr);
16+
17+
v = __llvm_libc::cpp::StringView("");
18+
ASSERT_EQ(v.size(), size_t(0));
19+
ASSERT_TRUE(v.data() == nullptr);
20+
21+
v = __llvm_libc::cpp::StringView(nullptr);
22+
ASSERT_EQ(v.size(), size_t(0));
23+
ASSERT_TRUE(v.data() == nullptr);
24+
25+
v = __llvm_libc::cpp::StringView(nullptr, 10);
26+
ASSERT_EQ(v.size(), size_t(0));
27+
ASSERT_TRUE(v.data() == nullptr);
28+
29+
v = __llvm_libc::cpp::StringView("abc", 0);
30+
ASSERT_EQ(v.size(), size_t(0));
31+
ASSERT_TRUE(v.data() == nullptr);
32+
33+
v = __llvm_libc::cpp::StringView("123456789");
34+
ASSERT_EQ(v.size(), size_t(9));
35+
}
36+
37+
TEST(LlvmLibcStringViewTest, Equals) {
38+
__llvm_libc::cpp::StringView v("abc");
39+
ASSERT_TRUE(v.equals(__llvm_libc::cpp::StringView("abc")));
40+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView()));
41+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("")));
42+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("123")));
43+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("abd")));
44+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("aaa")));
45+
ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("abcde")));
46+
}
47+
48+
TEST(LlvmLibcStringViewTest, RemovePrefix) {
49+
__llvm_libc::cpp::StringView v("123456789");
50+
51+
auto p = v.remove_prefix(0);
52+
ASSERT_EQ(p.size(), size_t(9));
53+
ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("123456789")));
54+
55+
p = v.remove_prefix(4);
56+
ASSERT_EQ(p.size(), size_t(5));
57+
ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("56789")));
58+
59+
p = v.remove_prefix(9);
60+
ASSERT_EQ(p.size(), size_t(0));
61+
ASSERT_TRUE(p.data() == nullptr);
62+
63+
p = v.remove_prefix(10);
64+
ASSERT_EQ(p.size(), size_t(0));
65+
ASSERT_TRUE(p.data() == nullptr);
66+
}
67+
68+
TEST(LlvmLibcStringViewTest, RemoveSuffix) {
69+
__llvm_libc::cpp::StringView v("123456789");
70+
71+
auto p = v.remove_suffix(0);
72+
ASSERT_EQ(p.size(), size_t(9));
73+
ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("123456789")));
74+
75+
p = v.remove_suffix(4);
76+
ASSERT_EQ(p.size(), size_t(5));
77+
ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("12345")));
78+
79+
p = v.remove_suffix(9);
80+
ASSERT_EQ(p.size(), size_t(0));
81+
ASSERT_TRUE(p.data() == nullptr);
82+
83+
p = v.remove_suffix(10);
84+
ASSERT_EQ(p.size(), size_t(0));
85+
ASSERT_TRUE(p.data() == nullptr);
86+
}
87+
88+
TEST(LlvmLibcStringViewTest, TrimSingleChar) {
89+
__llvm_libc::cpp::StringView v(" 123456789 ");
90+
auto t = v.trim(' ');
91+
ASSERT_EQ(t.size(), size_t(9));
92+
ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("123456789")));
93+
94+
v = __llvm_libc::cpp::StringView("====12345==");
95+
t = v.trim(' ');
96+
ASSERT_EQ(v.size(), size_t(11));
97+
ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("====12345==")));
98+
99+
t = v.trim('=');
100+
ASSERT_EQ(t.size(), size_t(5));
101+
ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
102+
103+
v = __llvm_libc::cpp::StringView("12345===");
104+
t = v.trim('=');
105+
ASSERT_EQ(t.size(), size_t(5));
106+
ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
107+
108+
v = __llvm_libc::cpp::StringView("===========12345");
109+
t = v.trim('=');
110+
ASSERT_EQ(t.size(), size_t(5));
111+
ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
112+
113+
v = __llvm_libc::cpp::StringView("============");
114+
t = v.trim('=');
115+
ASSERT_EQ(t.size(), size_t(0));
116+
ASSERT_TRUE(t.data() == nullptr);
117+
118+
v = __llvm_libc::cpp::StringView();
119+
t = v.trim(' ');
120+
ASSERT_EQ(t.size(), size_t(0));
121+
ASSERT_TRUE(t.data() == nullptr);
122+
123+
v = __llvm_libc::cpp::StringView("");
124+
t = v.trim(' ');
125+
ASSERT_EQ(t.size(), size_t(0));
126+
ASSERT_TRUE(t.data() == nullptr);
127+
}

libc/utils/CPP/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ add_header_library(
55
ArrayRef.h
66
Bitset.h
77
Functional.h
8+
StringView.h
89
TypeTraits.h
910
)

libc/utils/CPP/StringView.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//===-- Standalone implementation std::string_view --------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_UTILS_CPP_STRINGVIEW_H
10+
#define LLVM_LIBC_UTILS_CPP_STRINGVIEW_H
11+
12+
#include <stddef.h>
13+
14+
namespace __llvm_libc {
15+
namespace cpp {
16+
17+
// This is very simple alternate of the std::string_view class. There is no
18+
// bounds check performed in any of the methods. The callers are expected to
19+
// do the checks before invoking the methods.
20+
//
21+
// This class will be extended as needed in future.
22+
class StringView {
23+
private:
24+
const char *Data;
25+
size_t Len;
26+
27+
public:
28+
StringView() : Data(nullptr), Len(0) {}
29+
30+
// Assumes Str is a null-terminated string. The length of the string does
31+
// not include the terminating null character.
32+
explicit StringView(const char *Str) : Data(Str), Len(0) {
33+
if (Str == nullptr)
34+
return;
35+
for (const char *D = Data; *D != '\0'; ++D, ++Len)
36+
;
37+
if (Len == 0)
38+
Data = nullptr;
39+
}
40+
41+
explicit StringView(const char *Str, size_t N)
42+
: Data(N ? Str : nullptr), Len(Str == nullptr ? 0 : N) {}
43+
44+
const char *data() const { return Data; }
45+
46+
size_t size() { return Len; }
47+
48+
StringView remove_prefix(size_t N) const {
49+
if (N >= Len)
50+
return StringView();
51+
return StringView(Data + N, Len - N);
52+
}
53+
54+
StringView remove_suffix(size_t N) const {
55+
if (N >= Len)
56+
return StringView();
57+
return StringView(Data, Len - N);
58+
}
59+
60+
// An equivalent method is not available in std::string_view.
61+
StringView trim(char C) const {
62+
if (Len == 0)
63+
return StringView();
64+
65+
const char *NewStart = Data;
66+
size_t PrefixLen = 0;
67+
for (; PrefixLen < Len; ++NewStart, ++PrefixLen) {
68+
if (*NewStart != C)
69+
break;
70+
}
71+
72+
size_t SuffixLen = 0;
73+
const char *NewEnd = Data + Len - 1;
74+
for (; SuffixLen < Len; --NewEnd, ++SuffixLen) {
75+
if (*NewEnd != C)
76+
break;
77+
}
78+
79+
return remove_prefix(PrefixLen).remove_suffix(SuffixLen);
80+
}
81+
82+
// An equivalent method is not available in std::string_view.
83+
bool equals(StringView Other) const {
84+
if (Len != Other.Len)
85+
return false;
86+
for (size_t I = 0; I < Len; ++I) {
87+
if (Data[I] != Other.Data[I])
88+
return false;
89+
}
90+
return true;
91+
}
92+
};
93+
94+
} // namespace cpp
95+
} // namespace __llvm_libc
96+
97+
#endif // LLVM_LIBC_UTILS_CPP_STRINGVIEW_H

libc/utils/MPFRWrapper/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ if(LIBC_TESTS_CAN_USE_MPFR)
1212
MPFRUtils.cpp
1313
MPFRUtils.h
1414
)
15-
add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp libc.utils.FPUtil.fputil LibcUnitTest LLVMSupport)
16-
target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcFPTestHelpers LibcUnitTest LLVMSupport)
15+
add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp libc.utils.FPUtil.fputil LibcUnitTest)
16+
target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcFPTestHelpers LibcUnitTest)
1717
else()
1818
message(WARNING "Math tests using MPFR will be skipped.")
1919
endif()

libc/utils/MPFRWrapper/MPFRUtils.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88

99
#include "MPFRUtils.h"
1010

11+
#include "utils/CPP/StringView.h"
1112
#include "utils/FPUtil/FPBits.h"
1213
#include "utils/FPUtil/TestHelpers.h"
1314

14-
#include "llvm/ADT/StringRef.h"
15-
1615
#include <memory>
1716
#include <stdint.h>
1817
#include <string>
@@ -226,9 +225,9 @@ class MPFRNumber {
226225
constexpr size_t printBufSize = 200;
227226
char buffer[printBufSize];
228227
mpfr_snprintf(buffer, printBufSize, "%100.50Rf", value);
229-
llvm::StringRef ref(buffer);
230-
ref = ref.trim();
231-
return ref.str();
228+
cpp::StringView view(buffer);
229+
view = view.trim(' ');
230+
return std::string(view.data());
232231
}
233232

234233
// These functions are useful for debugging.

0 commit comments

Comments
 (0)