Skip to content

Commit 35c5437

Browse files
committed
StringSplitter: recreate State after copy
commit_hash:75f3a4a20b797f07c51c63b96f0f1e1374707f33
1 parent d979792 commit 35c5437

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

util/string/split.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,15 @@ namespace NStringSplitPrivate {
660660
using TIterator = TIteratorOf<String>;
661661
friend class TStringSplitter<String>;
662662

663+
template <typename S = String, std::enable_if_t<THasData<S>::value, int> = 0>
664+
TIterState(const String& string) noexcept
665+
: TStringBufType()
666+
, DelimiterEnd_(string.data())
667+
, OriginEnd_(string.data() + string.size())
668+
{
669+
}
670+
671+
template <typename S = String, std::enable_if_t<!THasData<S>::value, int> = 0>
663672
TIterState(const String& string) noexcept
664673
: TStringBufType()
665674
, DelimiterEnd_(std::begin(string))
@@ -700,6 +709,11 @@ namespace NStringSplitPrivate {
700709
return TokenDelim() == DelimiterEnd_;
701710
}
702711

712+
void MarkExhausted() noexcept {
713+
UpdateParentBuf(OriginEnd_, OriginEnd_);
714+
DelimiterEnd_ = OriginEnd_;
715+
}
716+
703717
private:
704718
TIterator DelimiterEnd_;
705719
const TIterator OriginEnd_;
@@ -845,6 +859,24 @@ namespace NStringSplitPrivate {
845859
{
846860
}
847861

862+
TSplitRangeBase(const TSplitRangeBase& other)
863+
: String_(other.String_)
864+
, State_(String_)
865+
, Delimiter_(other.Delimiter_)
866+
{
867+
}
868+
869+
TSplitRangeBase(TSplitRangeBase&& other)
870+
: String_(std::move(other.String_))
871+
, State_(String_)
872+
, Delimiter_(std::move(other.Delimiter_))
873+
{
874+
other.State_.MarkExhausted();
875+
}
876+
877+
TSplitRangeBase& operator=(const TSplitRangeBase& other) = delete;
878+
TSplitRangeBase& operator=(TSplitRangeBase&& other) = delete;
879+
848880
inline TIteratorState* Next() {
849881
if (State_.DelimiterIsEmpty()) {
850882
return nullptr;

util/string/split_ut.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,13 @@ Y_UNIT_TEST_SUITE(StringSplitter) {
443443
sum += FromString<int>(it.Token());
444444
}
445445
UNIT_ASSERT_VALUES_EQUAL(sum, 6);
446+
447+
TString ssum;
448+
for (const auto& it : StringSplitter(" 1 2 3 " + std::string(100, ' ')).Split(' ').SkipEmpty()) {
449+
ssum += FromString<TString>(it.Token());
450+
ssum += ';';
451+
}
452+
UNIT_ASSERT_VALUES_EQUAL(ssum, "1;2;3;");
446453
}
447454

448455
Y_UNIT_TEST(TestTake) {
@@ -746,6 +753,25 @@ Y_UNIT_TEST_SUITE(StringSplitter) {
746753
UNIT_ASSERT_VALUES_EQUAL(expected1, actual3);
747754
}
748755

756+
Y_UNIT_TEST(TesIterationAfterMove) {
757+
const TString src = TString::Join(
758+
"aaa",
759+
TString(250, 'c'),
760+
"bbb",
761+
"aaa",
762+
TString(250, 'c'),
763+
"bbb");
764+
auto s1 = StringSplitter(std::string(src)).SplitByString("c").SkipEmpty();
765+
{
766+
auto s2 = std::move(s1);
767+
const TVector<TString> expected2 = {"aaa", "bbbaaa", "bbb"};
768+
const auto result2 = s2.ToList<TString>();
769+
UNIT_ASSERT_VALUES_EQUAL(result2, expected2);
770+
}
771+
const auto result1 = s1.ToList<TString>();
772+
Y_UNUSED(result1); // valid but unspecified value
773+
}
774+
749775
Y_UNIT_TEST(TestConstCString) {
750776
const char* b = "a;b";
751777
const char* e = b + 3;

0 commit comments

Comments
 (0)