util.h 5.2 KB

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