[libc-commits] [libc] dbb131d - [libc] Add a standalone flavor of an equivalent of std::string_view.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Tue Feb 23 15:40:36 PST 2021
Author: Siva Chandra Reddy
Date: 2021-02-23T15:40:26-08:00
New Revision: dbb131d53aacabdf5d85299e447a970a0280b127
URL: https://github.com/llvm/llvm-project/commit/dbb131d53aacabdf5d85299e447a970a0280b127
DIFF: https://github.com/llvm/llvm-project/commit/dbb131d53aacabdf5d85299e447a970a0280b127.diff
LOG: [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
Added:
libc/test/utils/CPP/stringview_test.cpp
libc/utils/CPP/StringView.h
Modified:
libc/test/utils/CPP/CMakeLists.txt
libc/utils/CPP/CMakeLists.txt
libc/utils/MPFRWrapper/CMakeLists.txt
libc/utils/MPFRWrapper/MPFRUtils.cpp
Removed:
################################################################################
diff --git a/libc/test/utils/CPP/CMakeLists.txt b/libc/test/utils/CPP/CMakeLists.txt
index f770334dfed7..13a22c79a9e8 100644
--- a/libc/test/utils/CPP/CMakeLists.txt
+++ b/libc/test/utils/CPP/CMakeLists.txt
@@ -9,3 +9,13 @@ add_libc_unittest(
DEPENDS
libc.utils.CPP.standalone_cpp
)
+
+add_libc_unittest(
+ stringview_test
+ SUITE
+ libc_cpp_utils_unittests
+ SRCS
+ stringview_test.cpp
+ DEPENDS
+ libc.utils.CPP.standalone_cpp
+)
diff --git a/libc/test/utils/CPP/stringview_test.cpp b/libc/test/utils/CPP/stringview_test.cpp
new file mode 100644
index 000000000000..b88bcc38a1ef
--- /dev/null
+++ b/libc/test/utils/CPP/stringview_test.cpp
@@ -0,0 +1,127 @@
+//===-- Unittests for StringView ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "utils/CPP/StringView.h"
+#include "utils/UnitTest/Test.h"
+
+TEST(LlvmLibcStringViewTest, InitializeCheck) {
+ __llvm_libc::cpp::StringView v;
+ ASSERT_EQ(v.size(), size_t(0));
+ ASSERT_TRUE(v.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView("");
+ ASSERT_EQ(v.size(), size_t(0));
+ ASSERT_TRUE(v.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView(nullptr);
+ ASSERT_EQ(v.size(), size_t(0));
+ ASSERT_TRUE(v.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView(nullptr, 10);
+ ASSERT_EQ(v.size(), size_t(0));
+ ASSERT_TRUE(v.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView("abc", 0);
+ ASSERT_EQ(v.size(), size_t(0));
+ ASSERT_TRUE(v.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView("123456789");
+ ASSERT_EQ(v.size(), size_t(9));
+}
+
+TEST(LlvmLibcStringViewTest, Equals) {
+ __llvm_libc::cpp::StringView v("abc");
+ ASSERT_TRUE(v.equals(__llvm_libc::cpp::StringView("abc")));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView()));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("")));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("123")));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("abd")));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("aaa")));
+ ASSERT_FALSE(v.equals(__llvm_libc::cpp::StringView("abcde")));
+}
+
+TEST(LlvmLibcStringViewTest, RemovePrefix) {
+ __llvm_libc::cpp::StringView v("123456789");
+
+ auto p = v.remove_prefix(0);
+ ASSERT_EQ(p.size(), size_t(9));
+ ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("123456789")));
+
+ p = v.remove_prefix(4);
+ ASSERT_EQ(p.size(), size_t(5));
+ ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("56789")));
+
+ p = v.remove_prefix(9);
+ ASSERT_EQ(p.size(), size_t(0));
+ ASSERT_TRUE(p.data() == nullptr);
+
+ p = v.remove_prefix(10);
+ ASSERT_EQ(p.size(), size_t(0));
+ ASSERT_TRUE(p.data() == nullptr);
+}
+
+TEST(LlvmLibcStringViewTest, RemoveSuffix) {
+ __llvm_libc::cpp::StringView v("123456789");
+
+ auto p = v.remove_suffix(0);
+ ASSERT_EQ(p.size(), size_t(9));
+ ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("123456789")));
+
+ p = v.remove_suffix(4);
+ ASSERT_EQ(p.size(), size_t(5));
+ ASSERT_TRUE(p.equals(__llvm_libc::cpp::StringView("12345")));
+
+ p = v.remove_suffix(9);
+ ASSERT_EQ(p.size(), size_t(0));
+ ASSERT_TRUE(p.data() == nullptr);
+
+ p = v.remove_suffix(10);
+ ASSERT_EQ(p.size(), size_t(0));
+ ASSERT_TRUE(p.data() == nullptr);
+}
+
+TEST(LlvmLibcStringViewTest, TrimSingleChar) {
+ __llvm_libc::cpp::StringView v(" 123456789 ");
+ auto t = v.trim(' ');
+ ASSERT_EQ(t.size(), size_t(9));
+ ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("123456789")));
+
+ v = __llvm_libc::cpp::StringView("====12345==");
+ t = v.trim(' ');
+ ASSERT_EQ(v.size(), size_t(11));
+ ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("====12345==")));
+
+ t = v.trim('=');
+ ASSERT_EQ(t.size(), size_t(5));
+ ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
+
+ v = __llvm_libc::cpp::StringView("12345===");
+ t = v.trim('=');
+ ASSERT_EQ(t.size(), size_t(5));
+ ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
+
+ v = __llvm_libc::cpp::StringView("===========12345");
+ t = v.trim('=');
+ ASSERT_EQ(t.size(), size_t(5));
+ ASSERT_TRUE(t.equals(__llvm_libc::cpp::StringView("12345")));
+
+ v = __llvm_libc::cpp::StringView("============");
+ t = v.trim('=');
+ ASSERT_EQ(t.size(), size_t(0));
+ ASSERT_TRUE(t.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView();
+ t = v.trim(' ');
+ ASSERT_EQ(t.size(), size_t(0));
+ ASSERT_TRUE(t.data() == nullptr);
+
+ v = __llvm_libc::cpp::StringView("");
+ t = v.trim(' ');
+ ASSERT_EQ(t.size(), size_t(0));
+ ASSERT_TRUE(t.data() == nullptr);
+}
diff --git a/libc/utils/CPP/CMakeLists.txt b/libc/utils/CPP/CMakeLists.txt
index e321150a7f49..67483ab97d26 100644
--- a/libc/utils/CPP/CMakeLists.txt
+++ b/libc/utils/CPP/CMakeLists.txt
@@ -5,5 +5,6 @@ add_header_library(
ArrayRef.h
Bitset.h
Functional.h
+ StringView.h
TypeTraits.h
)
diff --git a/libc/utils/CPP/StringView.h b/libc/utils/CPP/StringView.h
new file mode 100644
index 000000000000..2e7b3a07b3dc
--- /dev/null
+++ b/libc/utils/CPP/StringView.h
@@ -0,0 +1,97 @@
+//===-- Standalone implementation std::string_view --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_UTILS_CPP_STRINGVIEW_H
+#define LLVM_LIBC_UTILS_CPP_STRINGVIEW_H
+
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace cpp {
+
+// This is very simple alternate of the std::string_view class. There is no
+// bounds check performed in any of the methods. The callers are expected to
+// do the checks before invoking the methods.
+//
+// This class will be extended as needed in future.
+class StringView {
+private:
+ const char *Data;
+ size_t Len;
+
+public:
+ StringView() : Data(nullptr), Len(0) {}
+
+ // Assumes Str is a null-terminated string. The length of the string does
+ // not include the terminating null character.
+ explicit StringView(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;
+ }
+
+ explicit StringView(const char *Str, size_t N)
+ : Data(N ? Str : nullptr), Len(Str == nullptr ? 0 : N) {}
+
+ const char *data() const { return Data; }
+
+ size_t size() { return Len; }
+
+ StringView remove_prefix(size_t N) const {
+ if (N >= Len)
+ return StringView();
+ return StringView(Data + N, Len - N);
+ }
+
+ StringView remove_suffix(size_t N) const {
+ if (N >= Len)
+ return StringView();
+ return StringView(Data, Len - N);
+ }
+
+ // An equivalent method is not available in std::string_view.
+ StringView trim(char C) const {
+ if (Len == 0)
+ return StringView();
+
+ const char *NewStart = Data;
+ size_t PrefixLen = 0;
+ for (; PrefixLen < Len; ++NewStart, ++PrefixLen) {
+ if (*NewStart != C)
+ break;
+ }
+
+ size_t SuffixLen = 0;
+ const char *NewEnd = Data + Len - 1;
+ for (; SuffixLen < Len; --NewEnd, ++SuffixLen) {
+ if (*NewEnd != C)
+ break;
+ }
+
+ return remove_prefix(PrefixLen).remove_suffix(SuffixLen);
+ }
+
+ // An equivalent method is not available in std::string_view.
+ bool equals(StringView Other) const {
+ if (Len != Other.Len)
+ return false;
+ for (size_t I = 0; I < Len; ++I) {
+ if (Data[I] != Other.Data[I])
+ return false;
+ }
+ return true;
+ }
+};
+
+} // namespace cpp
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_UTILS_CPP_STRINGVIEW_H
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index cc66d1c47d62..6f1bb76da7e8 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -12,8 +12,8 @@ if(LIBC_TESTS_CAN_USE_MPFR)
MPFRUtils.cpp
MPFRUtils.h
)
- add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp libc.utils.FPUtil.fputil LibcUnitTest LLVMSupport)
- target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcFPTestHelpers LibcUnitTest LLVMSupport)
+ add_dependencies(libcMPFRWrapper libc.utils.CPP.standalone_cpp libc.utils.FPUtil.fputil LibcUnitTest)
+ target_link_libraries(libcMPFRWrapper -lmpfr -lgmp LibcFPTestHelpers LibcUnitTest)
else()
message(WARNING "Math tests using MPFR will be skipped.")
endif()
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 79e7379133e2..314bece8df55 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -8,11 +8,10 @@
#include "MPFRUtils.h"
+#include "utils/CPP/StringView.h"
#include "utils/FPUtil/FPBits.h"
#include "utils/FPUtil/TestHelpers.h"
-#include "llvm/ADT/StringRef.h"
-
#include <memory>
#include <stdint.h>
#include <string>
@@ -226,9 +225,9 @@ class MPFRNumber {
constexpr size_t printBufSize = 200;
char buffer[printBufSize];
mpfr_snprintf(buffer, printBufSize, "%100.50Rf", value);
- llvm::StringRef ref(buffer);
- ref = ref.trim();
- return ref.str();
+ cpp::StringView view(buffer);
+ view = view.trim(' ');
+ return std::string(view.data());
}
// These functions are useful for debugging.
More information about the libc-commits
mailing list