strip.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #pragma once
  2. #include "ascii.h"
  3. #include <util/generic/string.h>
  4. #include <util/generic/strbuf.h>
  5. #include <utility>
  6. template <class It>
  7. struct TIsAsciiSpaceAdapter {
  8. bool operator()(const It& it) const noexcept {
  9. return IsAsciiSpace(*it);
  10. }
  11. };
  12. template <class It>
  13. TIsAsciiSpaceAdapter<It> IsAsciiSpaceAdapter(It) {
  14. return {};
  15. }
  16. template <class TChar>
  17. struct TEqualsStripAdapter {
  18. TEqualsStripAdapter(TChar ch)
  19. : Ch(ch)
  20. {
  21. }
  22. template <class It>
  23. bool operator()(const It& it) const noexcept {
  24. return *it == Ch;
  25. }
  26. const TChar Ch;
  27. };
  28. template <class TChar>
  29. TEqualsStripAdapter<TChar> EqualsStripAdapter(TChar ch) {
  30. return {ch};
  31. }
  32. template <class It, class TStripCriterion>
  33. inline void StripRangeBegin(It& b, const It& e, TStripCriterion&& criterion) noexcept {
  34. while (b < e && criterion(b)) {
  35. ++b;
  36. }
  37. }
  38. template <class It>
  39. inline void StripRangeBegin(It& b, const It& e) noexcept {
  40. StripRangeBegin(b, e, IsAsciiSpaceAdapter(b));
  41. }
  42. template <class It, class TStripCriterion>
  43. inline void StripRangeEnd(const It& b, It& e, TStripCriterion&& criterion) noexcept {
  44. while (b < e && criterion(e - 1)) {
  45. --e;
  46. }
  47. }
  48. template <class It>
  49. inline void StripRangeEnd(const It& b, It& e) noexcept {
  50. StripRangeEnd(b, e, IsAsciiSpaceAdapter(b));
  51. }
  52. template <bool stripBeg, bool stripEnd>
  53. struct TStripImpl {
  54. template <class It, class TStripCriterion>
  55. static inline bool StripRange(It& b, It& e, TStripCriterion&& criterion) noexcept {
  56. const size_t oldLen = e - b;
  57. if (stripBeg) {
  58. StripRangeBegin(b, e, criterion);
  59. }
  60. if (stripEnd) {
  61. StripRangeEnd(b, e, criterion);
  62. }
  63. const size_t newLen = e - b;
  64. return newLen != oldLen;
  65. }
  66. template <class T, class TStripCriterion>
  67. static inline bool StripString(const T& from, T& to, TStripCriterion&& criterion) {
  68. auto b = from.begin();
  69. auto e = from.end();
  70. if (StripRange(b, e, criterion)) {
  71. to = T(b, e - b);
  72. return true;
  73. }
  74. to = from;
  75. return false;
  76. }
  77. template <class T, class TStripCriterion>
  78. static inline T StripString(const T& from, TStripCriterion&& criterion) {
  79. T ret;
  80. StripString(from, ret, criterion);
  81. return ret;
  82. }
  83. template <class T>
  84. static inline T StripString(const T& from) {
  85. return StripString(from, IsAsciiSpaceAdapter(from.begin()));
  86. }
  87. };
  88. template <class It, class TStripCriterion>
  89. inline bool StripRange(It& b, It& e, TStripCriterion&& criterion) noexcept {
  90. return TStripImpl<true, true>::StripRange(b, e, criterion);
  91. }
  92. template <class It>
  93. inline bool StripRange(It& b, It& e) noexcept {
  94. return StripRange(b, e, IsAsciiSpaceAdapter(b));
  95. }
  96. template <class It, class TStripCriterion>
  97. inline bool Strip(It& b, size_t& len, TStripCriterion&& criterion) noexcept {
  98. It e = b + len;
  99. if (StripRange(b, e, criterion)) {
  100. len = e - b;
  101. return true;
  102. }
  103. return false;
  104. }
  105. template <class It>
  106. inline bool Strip(It& b, size_t& len) noexcept {
  107. return Strip(b, len, IsAsciiSpaceAdapter(b));
  108. }
  109. template <class T, class TStripCriterion>
  110. static inline bool StripString(const T& from, T& to, TStripCriterion&& criterion) {
  111. return TStripImpl<true, true>::StripString(from, to, criterion);
  112. }
  113. template <class T>
  114. static inline bool StripString(const T& from, T& to) {
  115. return StripString(from, to, IsAsciiSpaceAdapter(from.begin()));
  116. }
  117. template <class T, class TStripCriterion>
  118. static inline T StripString(const T& from, TStripCriterion&& criterion) {
  119. return TStripImpl<true, true>::StripString(from, criterion);
  120. }
  121. template <class T>
  122. static inline T StripString(const T& from) {
  123. return TStripImpl<true, true>::StripString(from);
  124. }
  125. template <class T>
  126. static inline T StripStringLeft(const T& from) {
  127. return TStripImpl<true, false>::StripString(from);
  128. }
  129. template <class T>
  130. static inline T StripStringRight(const T& from) {
  131. return TStripImpl<false, true>::StripString(from);
  132. }
  133. template <class T, class TStripCriterion>
  134. static inline T StripStringLeft(const T& from, TStripCriterion&& criterion) {
  135. return TStripImpl<true, false>::StripString(from, criterion);
  136. }
  137. template <class T, class TStripCriterion>
  138. static inline T StripStringRight(const T& from, TStripCriterion&& criterion) {
  139. return TStripImpl<false, true>::StripString(from, criterion);
  140. }
  141. /// Copies the given string removing leading and trailing spaces.
  142. static inline bool Strip(const TString& from, TString& to) {
  143. return StripString(from, to);
  144. }
  145. /// Removes leading and trailing spaces from the string.
  146. inline TString& StripInPlace(TString& s) {
  147. Strip(s, s);
  148. return s;
  149. }
  150. /// Returns a copy of the given string with removed leading and trailing spaces.
  151. inline TString Strip(const TString& s) Y_WARN_UNUSED_RESULT;
  152. inline TString Strip(const TString& s) {
  153. TString ret = s;
  154. Strip(ret, ret);
  155. return ret;
  156. }
  157. template <class TChar, class TWhitespaceFunc>
  158. size_t CollapseImpl(TChar* s, size_t n, const TWhitespaceFunc& isWhitespace) {
  159. size_t newLen = 0;
  160. for (size_t i = 0; i < n; ++i, ++newLen) {
  161. size_t nextNonSpace = i;
  162. while (nextNonSpace < n && isWhitespace(s[nextNonSpace])) {
  163. ++nextNonSpace;
  164. }
  165. size_t numSpaces = nextNonSpace - i;
  166. if (numSpaces > 1 || (numSpaces == 1 && s[i] != ' ')) {
  167. s[newLen] = ' ';
  168. i = nextNonSpace - 1;
  169. } else {
  170. s[newLen] = s[i];
  171. }
  172. }
  173. return newLen;
  174. }
  175. template <class TStringType, class TWhitespaceFunc>
  176. bool CollapseImpl(const TStringType& from, TStringType& to, size_t maxLen, const TWhitespaceFunc& isWhitespace) {
  177. to = from;
  178. maxLen = maxLen ? Min(maxLen, to.size()) : to.size();
  179. for (size_t i = 0; i < maxLen; ++i) {
  180. if (isWhitespace(to[i]) && (to[i] != ' ' || isWhitespace(to[i + 1]))) {
  181. size_t tailSize = maxLen - i;
  182. size_t newTailSize = CollapseImpl(to.begin() + i, tailSize, isWhitespace);
  183. to.remove(i + newTailSize, tailSize - newTailSize);
  184. return true;
  185. }
  186. }
  187. return false;
  188. }
  189. bool Collapse(const TString& from, TString& to, size_t maxLen = 0);
  190. /// Replaces several consequtive space symbols with one (processing is limited to maxLen bytes)
  191. inline TString& CollapseInPlace(TString& s, size_t maxLen = 0) {
  192. Collapse(s, s, maxLen);
  193. return s;
  194. }
  195. /// Replaces several consequtive space symbols with one (processing is limited to maxLen bytes)
  196. inline TString Collapse(const TString& s, size_t maxLen = 0) Y_WARN_UNUSED_RESULT;
  197. inline TString Collapse(const TString& s, size_t maxLen) {
  198. TString ret;
  199. Collapse(s, ret, maxLen);
  200. return ret;
  201. }
  202. void CollapseText(const TString& from, TString& to, size_t maxLen);
  203. /// The same as Collapse() + truncates the string to maxLen.
  204. /// @details An ellipsis is inserted at the end of the truncated line.
  205. inline void CollapseText(TString& s, size_t maxLen) {
  206. TString to;
  207. CollapseText(s, to, maxLen);
  208. s = to;
  209. }