diff options
| author | swarmer <[email protected]> | 2025-03-08 00:16:40 +0300 |
|---|---|---|
| committer | swarmer <[email protected]> | 2025-03-08 00:29:30 +0300 |
| commit | c9f8def64215301bd8809a93f792277cbcacd9fe (patch) | |
| tree | 2758f9b8c54463284b34720eb0c696ce12c90cda | |
| parent | 732794c096f3c49d5f8c830c3b0c66514248025e (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.h | 60 | ||||
| -rw-r--r-- | util/string/strip_ut.cpp | 22 |
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); |
