summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorswarmer <[email protected]>2025-03-08 00:16:40 +0300
committerswarmer <[email protected]>2025-03-08 00:29:30 +0300
commitc9f8def64215301bd8809a93f792277cbcacd9fe (patch)
tree2758f9b8c54463284b34720eb0c696ce12c90cda
parent732794c096f3c49d5f8c830c3b0c66514248025e (diff)
[util] track the lifetime of strings passed through the StripString function family
Specialize StripString functions for the std::string_view and TStringBuf types. An example of erroneous code in which the compiler will be able to detect a problem with the lifetime of temporary string: ``` TStringBuf sb = StripString(TStringBuf{" abc "s}); Use(sb); // segfault ``` commit_hash:ad47648de30fd1a7e59d39a8ec3918fd1484a0ba
-rw-r--r--util/string/strip.h60
-rw-r--r--util/string/strip_ut.cpp22
2 files changed, 82 insertions, 0 deletions
diff --git a/util/string/strip.h b/util/string/strip.h
index 809a047cd87..f4aecd4703f 100644
--- a/util/string/strip.h
+++ b/util/string/strip.h
@@ -157,31 +157,91 @@ template <class T, class TStripCriterion>
return TStripImpl<true, true>::StripString(from, criterion);
}
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename TBasicStringBuf<TChar, TTraits>::iterator>, TBasicStringBuf<TChar, TTraits>> StripString(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<true, true>::StripString(from, criterion);
+}
+
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename std::basic_string_view<TChar, TTraits>::iterator>, std::basic_string_view<TChar, TTraits>> StripString(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<true, true>::StripString(from, criterion);
+}
+
template <class T>
[[nodiscard]] static inline T StripString(const T& from) {
return TStripImpl<true, true>::StripString(from);
}
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline TBasicStringBuf<TChar, TTraits> StripString(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<true, true>::StripString(from);
+}
+
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline std::basic_string_view<TChar, TTraits> StripString(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<true, true>::StripString(from);
+}
+
template <class T>
[[nodiscard]] static inline T StripStringLeft(const T& from) {
return TStripImpl<true, false>::StripString(from);
}
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline TBasicStringBuf<TChar, TTraits> StripStringLeft(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<true, false>::StripString(from);
+}
+
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline std::basic_string_view<TChar, TTraits> StripStringLeft(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<true, false>::StripString(from);
+}
+
template <class T>
[[nodiscard]] static inline T StripStringRight(const T& from) {
return TStripImpl<false, true>::StripString(from);
}
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline TBasicStringBuf<TChar, TTraits> StripStringRight(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<false, true>::StripString(from);
+}
+
+template <typename TChar, typename TTraits>
+[[nodiscard]] static inline std::basic_string_view<TChar, TTraits> StripStringRight(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND) {
+ return TStripImpl<false, true>::StripString(from);
+}
+
template <class T, class TStripCriterion>
[[nodiscard]] static inline T StripStringLeft(const T& from, TStripCriterion&& criterion) {
return TStripImpl<true, false>::StripString(from, criterion);
}
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename TBasicStringBuf<TChar, TTraits>::iterator>, TBasicStringBuf<TChar, TTraits>> StripStringLeft(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<true, false>::StripString(from, criterion);
+}
+
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename std::basic_string_view<TChar, TTraits>::iterator>, std::basic_string_view<TChar, TTraits>> StripStringLeft(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<true, false>::StripString(from, criterion);
+}
+
template <class T, class TStripCriterion>
[[nodiscard]] static inline T StripStringRight(const T& from, TStripCriterion&& criterion) {
return TStripImpl<false, true>::StripString(from, criterion);
}
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename TBasicStringBuf<TChar, TTraits>::iterator>, TBasicStringBuf<TChar, TTraits>> StripStringRight(const TBasicStringBuf<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<false, true>::StripString(from, criterion);
+}
+
+template <typename TChar, typename TTraits, class TStripCriterion>
+[[nodiscard]] static inline std::enable_if_t<std::is_invocable_v<TStripCriterion, typename std::basic_string_view<TChar, TTraits>::iterator>, std::basic_string_view<TChar, TTraits>> StripStringRight(const std::basic_string_view<TChar, TTraits> from Y_LIFETIME_BOUND, TStripCriterion&& criterion) {
+ return TStripImpl<false, true>::StripString(from, criterion);
+}
+
/// Copies the given string removing leading and trailing spaces.
static inline bool Strip(const TString& from, TString& to) {
return StripString(from, to);
diff --git a/util/string/strip_ut.cpp b/util/string/strip_ut.cpp
index d5598ce866b..37e5a4f04a0 100644
--- a/util/string/strip_ut.cpp
+++ b/util/string/strip_ut.cpp
@@ -103,8 +103,20 @@ Y_UNIT_TEST_SUITE(TStripStringTest) {
StripStringLeft(TString(test.Str), EqualsStripAdapter('/')),
test.ResultLeft);
UNIT_ASSERT_EQUAL(
+ StripStringLeft(TStringBuf(test.Str), EqualsStripAdapter('/')),
+ test.ResultLeft);
+ UNIT_ASSERT_EQUAL(
+ StripStringLeft(std::string_view(test.Str), EqualsStripAdapter('/')),
+ test.ResultLeft);
+ UNIT_ASSERT_EQUAL(
StripStringRight(TString(test.Str), EqualsStripAdapter('/')),
test.ResultRight);
+ UNIT_ASSERT_EQUAL(
+ StripStringRight(TStringBuf(test.Str), EqualsStripAdapter('/')),
+ test.ResultRight);
+ UNIT_ASSERT_EQUAL(
+ StripStringRight(std::string_view(test.Str), EqualsStripAdapter('/')),
+ test.ResultRight);
};
}
@@ -129,6 +141,16 @@ Y_UNIT_TEST_SUITE(TStripStringTest) {
u"abc");
}
+ Y_UNIT_TEST(TestSelfRefStringStrip) {
+ TStringBuf sb = " abc ";
+ StripString(sb, sb);
+ UNIT_ASSERT_EQUAL(sb, "abc");
+
+ TString str = " abc ";
+ StripString(str, str);
+ UNIT_ASSERT_EQUAL(str, "abc");
+ }
+
Y_UNIT_TEST(TestCollapseUtf32) {
TUtf32String s;
Collapse(UTF8ToUTF32<true>(" 123 456 "), s, IsWhitespace);