aboutsummaryrefslogtreecommitdiffstats
path: root/util/string/strip.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/string/strip.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/string/strip.h')
-rw-r--r--util/string/strip.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/util/string/strip.h b/util/string/strip.h
new file mode 100644
index 0000000000..d5ef6da96d
--- /dev/null
+++ b/util/string/strip.h
@@ -0,0 +1,257 @@
+#pragma once
+
+#include "ascii.h"
+
+#include <util/generic/string.h>
+#include <util/generic/strbuf.h>
+#include <utility>
+
+template <class It>
+struct TIsAsciiSpaceAdapter {
+ bool operator()(const It& it) const noexcept {
+ return IsAsciiSpace(*it);
+ }
+};
+
+template <class It>
+TIsAsciiSpaceAdapter<It> IsAsciiSpaceAdapter(It) {
+ return {};
+}
+
+template <class TChar>
+struct TEqualsStripAdapter {
+ TEqualsStripAdapter(TChar ch)
+ : Ch(ch)
+ {
+ }
+
+ template <class It>
+ bool operator()(const It& it) const noexcept {
+ return *it == Ch;
+ }
+
+ const TChar Ch;
+};
+
+template <class TChar>
+TEqualsStripAdapter<TChar> EqualsStripAdapter(TChar ch) {
+ return {ch};
+}
+
+template <class It, class TStripCriterion>
+inline void StripRangeBegin(It& b, const It& e, TStripCriterion&& criterion) noexcept {
+ while (b < e && criterion(b)) {
+ ++b;
+ }
+}
+
+template <class It>
+inline void StripRangeBegin(It& b, const It& e) noexcept {
+ StripRangeBegin(b, e, IsAsciiSpaceAdapter(b));
+}
+
+template <class It, class TStripCriterion>
+inline void StripRangeEnd(const It& b, It& e, TStripCriterion&& criterion) noexcept {
+ while (b < e && criterion(e - 1)) {
+ --e;
+ }
+}
+
+template <class It>
+inline void StripRangeEnd(const It& b, It& e) noexcept {
+ StripRangeEnd(b, e, IsAsciiSpaceAdapter(b));
+}
+
+template <bool stripBeg, bool stripEnd>
+struct TStripImpl {
+ template <class It, class TStripCriterion>
+ static inline bool StripRange(It& b, It& e, TStripCriterion&& criterion) noexcept {
+ const size_t oldLen = e - b;
+
+ if (stripBeg) {
+ StripRangeBegin(b, e, criterion);
+ }
+
+ if (stripEnd) {
+ StripRangeEnd(b, e, criterion);
+ }
+
+ const size_t newLen = e - b;
+ return newLen != oldLen;
+ }
+
+ template <class T, class TStripCriterion>
+ static inline bool StripString(const T& from, T& to, TStripCriterion&& criterion) {
+ auto b = from.begin();
+ auto e = from.end();
+
+ if (StripRange(b, e, criterion)) {
+ to = T(b, e - b);
+
+ return true;
+ }
+
+ to = from;
+
+ return false;
+ }
+
+ template <class T, class TStripCriterion>
+ static inline T StripString(const T& from, TStripCriterion&& criterion) {
+ T ret;
+ StripString(from, ret, criterion);
+ return ret;
+ }
+
+ template <class T>
+ static inline T StripString(const T& from) {
+ return StripString(from, IsAsciiSpaceAdapter(from.begin()));
+ }
+};
+
+template <class It, class TStripCriterion>
+inline bool StripRange(It& b, It& e, TStripCriterion&& criterion) noexcept {
+ return TStripImpl<true, true>::StripRange(b, e, criterion);
+}
+
+template <class It>
+inline bool StripRange(It& b, It& e) noexcept {
+ return StripRange(b, e, IsAsciiSpaceAdapter(b));
+}
+
+template <class It, class TStripCriterion>
+inline bool Strip(It& b, size_t& len, TStripCriterion&& criterion) noexcept {
+ It e = b + len;
+
+ if (StripRange(b, e, criterion)) {
+ len = e - b;
+
+ return true;
+ }
+
+ return false;
+}
+
+template <class It>
+inline bool Strip(It& b, size_t& len) noexcept {
+ return Strip(b, len, IsAsciiSpaceAdapter(b));
+}
+
+template <class T, class TStripCriterion>
+static inline bool StripString(const T& from, T& to, TStripCriterion&& criterion) {
+ return TStripImpl<true, true>::StripString(from, to, criterion);
+}
+
+template <class T>
+static inline bool StripString(const T& from, T& to) {
+ return StripString(from, to, IsAsciiSpaceAdapter(from.begin()));
+}
+
+template <class T, class TStripCriterion>
+static inline T StripString(const T& from, TStripCriterion&& criterion) {
+ return TStripImpl<true, true>::StripString(from, criterion);
+}
+
+template <class T>
+static inline T StripString(const T& from) {
+ return TStripImpl<true, true>::StripString(from);
+}
+
+template <class T>
+static inline T StripStringLeft(const T& from) {
+ return TStripImpl<true, false>::StripString(from);
+}
+
+template <class T>
+static inline T StripStringRight(const T& from) {
+ return TStripImpl<false, true>::StripString(from);
+}
+
+template <class T, class TStripCriterion>
+static inline T StripStringLeft(const T& from, TStripCriterion&& criterion) {
+ return TStripImpl<true, false>::StripString(from, criterion);
+}
+
+template <class T, class TStripCriterion>
+static inline T StripStringRight(const T& from, 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);
+}
+
+/// Removes leading and trailing spaces from the string.
+inline TString& StripInPlace(TString& s) {
+ Strip(s, s);
+ return s;
+}
+
+/// Returns a copy of the given string with removed leading and trailing spaces.
+inline TString Strip(const TString& s) Y_WARN_UNUSED_RESULT;
+inline TString Strip(const TString& s) {
+ TString ret = s;
+ Strip(ret, ret);
+ return ret;
+}
+
+template <class TChar, class TWhitespaceFunc>
+size_t CollapseImpl(TChar* s, size_t n, const TWhitespaceFunc& isWhitespace) {
+ size_t newLen = 0;
+ for (size_t i = 0; i < n; ++i, ++newLen) {
+ size_t nextNonSpace = i;
+ while (nextNonSpace < n && isWhitespace(s[nextNonSpace])) {
+ ++nextNonSpace;
+ }
+ size_t numSpaces = nextNonSpace - i;
+ if (numSpaces > 1 || (numSpaces == 1 && s[i] != ' ')) {
+ s[newLen] = ' ';
+ i = nextNonSpace - 1;
+ } else {
+ s[newLen] = s[i];
+ }
+ }
+ return newLen;
+}
+
+template <class TStringType, class TWhitespaceFunc>
+bool CollapseImpl(const TStringType& from, TStringType& to, size_t maxLen, const TWhitespaceFunc& isWhitespace) {
+ to = from;
+ maxLen = maxLen ? Min(maxLen, to.size()) : to.size();
+ for (size_t i = 0; i < maxLen; ++i) {
+ if (isWhitespace(to[i]) && (to[i] != ' ' || isWhitespace(to[i + 1]))) {
+ size_t tailSize = maxLen - i;
+ size_t newTailSize = CollapseImpl(to.begin() + i, tailSize, isWhitespace);
+ to.remove(i + newTailSize, tailSize - newTailSize);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Collapse(const TString& from, TString& to, size_t maxLen = 0);
+
+/// Replaces several consequtive space symbols with one (processing is limited to maxLen bytes)
+inline TString& CollapseInPlace(TString& s, size_t maxLen = 0) {
+ Collapse(s, s, maxLen);
+ return s;
+}
+
+/// Replaces several consequtive space symbols with one (processing is limited to maxLen bytes)
+inline TString Collapse(const TString& s, size_t maxLen = 0) Y_WARN_UNUSED_RESULT;
+inline TString Collapse(const TString& s, size_t maxLen) {
+ TString ret;
+ Collapse(s, ret, maxLen);
+ return ret;
+}
+
+void CollapseText(const TString& from, TString& to, size_t maxLen);
+
+/// The same as Collapse() + truncates the string to maxLen.
+/// @details An ellipsis is inserted at the end of the truncated line.
+inline void CollapseText(TString& s, size_t maxLen) {
+ TString to;
+ CollapseText(s, to, maxLen);
+ s = to;
+}