diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/string/util.h |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/string/util.h')
-rw-r--r-- | util/string/util.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/util/string/util.h b/util/string/util.h new file mode 100644 index 00000000000..0d77a5042b8 --- /dev/null +++ b/util/string/util.h @@ -0,0 +1,195 @@ +#pragma once + +//THIS FILE A COMPAT STUB HEADER + +#include <cstring> +#include <cstdarg> +#include <algorithm> + +#include <util/system/defaults.h> +#include <util/generic/string.h> +#include <util/generic/strbuf.h> + +/// @addtogroup Strings_Miscellaneous +/// @{ +int a2i(const TString& s); + +/// Removes the last character if it is equal to c. +template <class T> +inline void RemoveIfLast(T& s, int c) { + const size_t length = s.length(); + if (length && s[length - 1] == c) + s.remove(length - 1); +} + +/// Adds lastCh symbol to the the of the string if it is not already there. +inline void addIfNotLast(TString& s, int lastCh) { + size_t len = s.length(); + if (!len || s[len - 1] != lastCh) { + s.append(char(lastCh)); + } +} + +/// @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. +/// Else, if lastCh2 is not equal to the symbol before the last, it finishes the string with lastCh2. +/// @todo ?? Define, when to apply the function. Is in use several times for URLs parsing. +inline void addIfAbsent(TString& s, char lastCh1, char lastCh2) { + size_t pos = s.find(lastCh2); + if (pos == TString::npos) { + //s.append((char)lastCh1); + addIfNotLast(s, lastCh1); + } else if (pos < s.length() - 1) { + addIfNotLast(s, lastCh2); + } +} + +/// @} + +/* + * ------------------------------------------------------------------ + * + * A fast implementation of glibc's functions; + * strspn, strcspn and strpbrk. + * + * ------------------------------------------------------------------ + */ +struct ui8_256 { + // forward chars table + ui8 chars_table[256]; + // reverse (for c* functions) chars table + ui8 c_chars_table[256]; +}; + +class str_spn: public ui8_256 { +public: + explicit str_spn(const char* charset, bool extended = false) { + // exteneded: if true, treat charset string more like + // interior of brackets [ ], e.g. "a-z0-9" + init(charset, extended); + } + + /// Return first character in table, like strpbrk() + /// That is, skip all characters not in table + /// [DIFFERENCE FOR NOT_FOUND CASE: Returns end of string, not NULL] + const char* brk(const char* s) const { + while (c_chars_table[(ui8)*s]) + ++s; + return s; + } + + const char* brk(const char* s, const char* e) const { + while (s < e && c_chars_table[(ui8)*s]) + ++s; + return s; + } + + /// Return first character not in table, like strpbrk() for inverted table. + /// That is, skip all characters in table + const char* cbrk(const char* s) const { + while (chars_table[(ui8)*s]) + ++s; + return s; + } + + const char* cbrk(const char* s, const char* e) const { + while (s < e && chars_table[(ui8)*s]) + ++s; + return s; + } + + /// Offset of the first character not in table, like strspn(). + size_t spn(const char* s) const { + return cbrk(s) - s; + } + + size_t spn(const char* s, const char* e) const { + return cbrk(s, e) - s; + } + + /// Offset of the first character in table, like strcspn(). + size_t cspn(const char* s) const { + return brk(s) - s; + } + + size_t cspn(const char* s, const char* e) const { + return brk(s, e) - s; + } + + char* brk(char* s) const { + return const_cast<char*>(brk((const char*)s)); + } + + char* cbrk(char* s) const { + return const_cast<char*>(cbrk((const char*)s)); + } + + /// See strsep [BUT argument is *&, not **] + char* sep(char*& s) const { + char sep_char; // unused; + return sep(s, sep_char); + } + + /// strsep + remember character that was destroyed + char* sep(char*& s, char& sep_char) const { + if (!s) + return nullptr; + char* ret = s; + char* next = brk(ret); + if (*next) { + sep_char = *next; + *next = 0; + s = next + 1; + } else { + sep_char = 0; + s = nullptr; + } + return ret; + } + +protected: + void init(const char* charset, bool extended); + str_spn() = default; +}; + +// an analogue of tr/$from/$to/ +class Tr { +public: + Tr(const char* from, const char* to); + + char ConvertChar(char ch) const { + return Map[(ui8)ch]; + } + + void Do(char* s) const { + for (; *s; s++) + *s = ConvertChar(*s); + } + void Do(const char* src, char* dst) const { + for (; *src; src++) + *dst++ = ConvertChar(*src); + *dst = 0; + } + void Do(char* s, size_t l) const { + for (size_t i = 0; i < l && s[i]; i++) + s[i] = ConvertChar(s[i]); + } + void Do(TString& str) const; + +private: + char Map[256]; + + size_t FindFirstChangePosition(const TString& str) const; +}; + +// Removes all occurrences of given character from string +template <typename TStringType> +void RemoveAll(TStringType& str, typename TStringType::char_type ch) { + size_t pos = str.find(ch); // 'find' to avoid cloning of string in 'TString.begin()' + if (pos == TStringType::npos) + return; + + typename TStringType::iterator begin = str.begin(); + typename TStringType::iterator end = begin + str.length(); + typename TStringType::iterator it = std::remove(begin + pos, end, ch); + str.erase(it, end); +} |