util.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #pragma once
  2. // THIS FILE A COMPAT STUB HEADER
  3. #include <cstring>
  4. #include <cstdarg>
  5. #include <algorithm>
  6. #include <util/system/defaults.h>
  7. #include <util/generic/string.h>
  8. #include <util/generic/strbuf.h>
  9. /// @addtogroup Strings_Miscellaneous
  10. /// @{
  11. int a2i(const TString& s);
  12. /// Removes the last character if it is equal to c.
  13. template <class T>
  14. inline void RemoveIfLast(T& s, int c) {
  15. const size_t length = s.length();
  16. if (length && s[length - 1] == c) {
  17. s.remove(length - 1);
  18. }
  19. }
  20. /// Adds lastCh symbol to the the of the string if it is not already there.
  21. inline void addIfNotLast(TString& s, int lastCh) {
  22. size_t len = s.length();
  23. if (!len || s[len - 1] != lastCh) {
  24. s.append(char(lastCh));
  25. }
  26. }
  27. /// @details Finishes the string with lastCh1 if lastCh2 is not present in the string and lastCh1 is not already at the end of the string.
  28. /// Else, if lastCh2 is not equal to the symbol before the last, it finishes the string with lastCh2.
  29. /// @todo ?? Define, when to apply the function. Is in use several times for URLs parsing.
  30. inline void addIfAbsent(TString& s, char lastCh1, char lastCh2) {
  31. size_t pos = s.find(lastCh2);
  32. if (pos == TString::npos) {
  33. // s.append((char)lastCh1);
  34. addIfNotLast(s, lastCh1);
  35. } else if (pos < s.length() - 1) {
  36. addIfNotLast(s, lastCh2);
  37. }
  38. }
  39. /// @}
  40. /*
  41. * ------------------------------------------------------------------
  42. *
  43. * A fast implementation of glibc's functions;
  44. * strspn, strcspn and strpbrk.
  45. *
  46. * ------------------------------------------------------------------
  47. */
  48. struct ui8_256 {
  49. // forward chars table
  50. ui8 chars_table[256];
  51. // reverse (for c* functions) chars table
  52. ui8 c_chars_table[256];
  53. };
  54. class str_spn: public ui8_256 {
  55. public:
  56. explicit str_spn(const char* charset, bool extended = false) {
  57. // exteneded: if true, treat charset string more like
  58. // interior of brackets [ ], e.g. "a-z0-9"
  59. init(charset, extended);
  60. }
  61. /// Return first character in table, like strpbrk()
  62. /// That is, skip all characters not in table
  63. /// [DIFFERENCE FOR NOT_FOUND CASE: Returns end of string, not NULL]
  64. const char* brk(const char* s) const {
  65. while (c_chars_table[(ui8)*s]) {
  66. ++s;
  67. }
  68. return s;
  69. }
  70. const char* brk(const char* s, const char* e) const {
  71. while (s < e && c_chars_table[(ui8)*s]) {
  72. ++s;
  73. }
  74. return s;
  75. }
  76. /// Return first character not in table, like strpbrk() for inverted table.
  77. /// That is, skip all characters in table
  78. const char* cbrk(const char* s) const {
  79. while (chars_table[(ui8)*s]) {
  80. ++s;
  81. }
  82. return s;
  83. }
  84. const char* cbrk(const char* s, const char* e) const {
  85. while (s < e && chars_table[(ui8)*s]) {
  86. ++s;
  87. }
  88. return s;
  89. }
  90. /// Offset of the first character not in table, like strspn().
  91. size_t spn(const char* s) const {
  92. return cbrk(s) - s;
  93. }
  94. size_t spn(const char* s, const char* e) const {
  95. return cbrk(s, e) - s;
  96. }
  97. /// Offset of the first character in table, like strcspn().
  98. size_t cspn(const char* s) const {
  99. return brk(s) - s;
  100. }
  101. size_t cspn(const char* s, const char* e) const {
  102. return brk(s, e) - s;
  103. }
  104. char* brk(char* s) const {
  105. return const_cast<char*>(brk((const char*)s));
  106. }
  107. char* cbrk(char* s) const {
  108. return const_cast<char*>(cbrk((const char*)s));
  109. }
  110. /// See strsep [BUT argument is *&, not **]
  111. char* sep(char*& s) const {
  112. char sep_char; // unused;
  113. return sep(s, sep_char);
  114. }
  115. /// strsep + remember character that was destroyed
  116. char* sep(char*& s, char& sep_char) const {
  117. if (!s) {
  118. return nullptr;
  119. }
  120. char* ret = s;
  121. char* next = brk(ret);
  122. if (*next) {
  123. sep_char = *next;
  124. *next = 0;
  125. s = next + 1;
  126. } else {
  127. sep_char = 0;
  128. s = nullptr;
  129. }
  130. return ret;
  131. }
  132. protected:
  133. void init(const char* charset, bool extended);
  134. str_spn() = default;
  135. };
  136. // an analogue of tr/$from/$to/
  137. class Tr {
  138. public:
  139. Tr(const char* from, const char* to);
  140. char ConvertChar(char ch) const {
  141. return Map[(ui8)ch];
  142. }
  143. void Do(char* s) const {
  144. for (; *s; s++) {
  145. *s = ConvertChar(*s);
  146. }
  147. }
  148. void Do(const char* src, char* dst) const {
  149. for (; *src; src++) {
  150. *dst++ = ConvertChar(*src);
  151. }
  152. *dst = 0;
  153. }
  154. void Do(char* s, size_t l) const {
  155. for (size_t i = 0; i < l && s[i]; i++) {
  156. s[i] = ConvertChar(s[i]);
  157. }
  158. }
  159. void Do(TString& str) const;
  160. private:
  161. char Map[256];
  162. size_t FindFirstChangePosition(const TString& str) const;
  163. };
  164. // Removes all occurrences of given character from string
  165. template <typename TStringType>
  166. void RemoveAll(TStringType& str, typename TStringType::char_type ch) {
  167. size_t pos = str.find(ch); // 'find' to avoid cloning of string in 'TString.begin()'
  168. if (pos == TStringType::npos) {
  169. return;
  170. }
  171. typename TStringType::iterator begin = str.begin();
  172. typename TStringType::iterator end = begin + str.length();
  173. typename TStringType::iterator it = std::remove(begin + pos, end, ch);
  174. str.erase(it, end);
  175. }