diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/deprecated/split/delim_string_iter.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/deprecated/split/delim_string_iter.h')
-rw-r--r-- | library/cpp/deprecated/split/delim_string_iter.h | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/library/cpp/deprecated/split/delim_string_iter.h b/library/cpp/deprecated/split/delim_string_iter.h new file mode 100644 index 0000000000..8e4ca171a0 --- /dev/null +++ b/library/cpp/deprecated/split/delim_string_iter.h @@ -0,0 +1,185 @@ +#pragma once + +#include <util/generic/algorithm.h> +#include <util/generic/strbuf.h> +#include <util/generic/yexception.h> +#include <util/string/cast.h> +#include <util/system/yassert.h> + +#include <iterator> + +class TDelimStringIter { +public: + using value_type = TStringBuf; + using difference_type = ptrdiff_t; + using pointer = const TStringBuf*; + using reference = const TStringBuf&; + using iterator_category = std::forward_iterator_tag; + + inline TDelimStringIter(const char* begin, const char* strEnd, TStringBuf delim) + : TDelimStringIter(TStringBuf(begin, strEnd), delim) + { + } + + inline TDelimStringIter(TStringBuf str, TStringBuf delim) + : IsValid(true) + , Str(str) + , Delim(delim) + { + UpdateCurrent(); + } + + inline TDelimStringIter() + : IsValid(false) + { + } + + inline explicit operator bool() const { + return IsValid; + } + + // NOTE: this is a potentially unsafe operation (no overrun check) + inline TDelimStringIter& operator++() { + if (Current.end() != Str.end()) { + Str.Skip(Current.length() + Delim.length()); + UpdateCurrent(); + } else { + Str.Clear(); + Current.Clear(); + IsValid = false; + } + return *this; + } + + inline void operator+=(size_t n) { + for (; n > 0; --n) { + ++(*this); + } + } + + inline bool operator==(const TDelimStringIter& rhs) const { + return (IsValid == rhs.IsValid) && (!IsValid || (Current.begin() == rhs.Current.begin())); + } + + inline bool operator!=(const TDelimStringIter& rhs) const { + return !(*this == rhs); + } + + inline TStringBuf operator*() const { + return Current; + } + + inline const TStringBuf* operator->() const { + return &Current; + } + + // Get & advance + template <class T> + inline bool TryNext(T& t) { + if (IsValid) { + t = FromString<T>(Current); + operator++(); + return true; + } else { + return false; + } + } + + template <class T> + inline TDelimStringIter& Next(T& t) // Get & advance + { + if (!TryNext(t)) + ythrow yexception() << "No valid field"; + return *this; + } + + template <class T> + inline T GetNext() { + T res; + Next(res); + return res; + } + + inline const char* GetBegin() const { + return Current.begin(); + } + + inline const char* GetEnd() const { + return Current.end(); + } + + inline bool Valid() const { + return IsValid; + } + + // contents from next token to the end of string + inline TStringBuf Cdr() const { + return Str.SubStr(Current.length() + Delim.length()); + } + + inline TDelimStringIter IterEnd() const { + return TDelimStringIter(); + } + +private: + inline void UpdateCurrent() { + // it is much faster than TStringBuf::find + size_t pos = std::search(Str.begin(), Str.end(), Delim.begin(), Delim.end()) - Str.begin(); + Current = Str.Head(pos); + } + +private: + bool IsValid; + + TStringBuf Str; + TStringBuf Current; + TStringBuf Delim; +}; + +//example: for (TStringBuf field: TDelimStroka(line, "@@")) { ... } +struct TDelimStroka { + TStringBuf S; + TStringBuf Delim; + + inline TDelimStroka(TStringBuf s, TStringBuf delim) + : S(s) + , Delim(delim) + { + } + + inline TDelimStringIter begin() const { + return TDelimStringIter(S, Delim); + } + + inline TDelimStringIter end() const { + return TDelimStringIter(); + } +}; + +inline TDelimStringIter begin_delim(const TString& str, TStringBuf delim) { + return TDelimStringIter(str, delim); +} + +inline TDelimStringIter begin_delim(TStringBuf str, TStringBuf delim) { + return TDelimStringIter(str.begin(), str.end(), delim); +} + +inline TDelimStringIter end_delim(const TString& /*str*/, TStringBuf /*delim*/) { + return TDelimStringIter(); +} + +class TKeyValueDelimStringIter { +public: + TKeyValueDelimStringIter(const TStringBuf str, const TStringBuf delim); + bool Valid() const; + TKeyValueDelimStringIter& operator++(); + const TStringBuf& Key() const; + const TStringBuf& Value() const; + +private: + TDelimStringIter DelimIter; + TStringBuf ChunkKey, ChunkValue; + +private: + void ReadKeyAndValue(); +}; |