ci_string.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #pragma once
  2. #include "codepage.h"
  3. #include <util/generic/string.h>
  4. #include <util/str_stl.h>
  5. // Same as TString but uses CASE INSENSITIVE comparator and hash. Use with care.
  6. class TCiString: public TString {
  7. public:
  8. TCiString() {
  9. }
  10. TCiString(const TString& s)
  11. : TString(s)
  12. {
  13. }
  14. TCiString(const TString& s, size_t pos, size_t n)
  15. : TString(s, pos, n)
  16. {
  17. }
  18. TCiString(const char* pc)
  19. : TString(pc)
  20. {
  21. }
  22. TCiString(const char* pc, size_t n)
  23. : TString(pc, n)
  24. {
  25. }
  26. TCiString(const char* pc, size_t pos, size_t n)
  27. : TString(pc, pos, n)
  28. {
  29. }
  30. TCiString(size_t n, char c)
  31. : TString(n, c)
  32. {
  33. }
  34. TCiString(const TUninitialized& uninitialized)
  35. : TString(uninitialized)
  36. {
  37. }
  38. TCiString(const char* b, const char* e)
  39. : TString(b, e)
  40. {
  41. }
  42. explicit TCiString(const TStringBuf& s)
  43. : TString(s)
  44. {
  45. }
  46. // ~~~ Comparison ~~~ : FAMILY0(int, compare)
  47. static int compare(const TCiString& s1, const TCiString& s2, const CodePage& cp = csYandex);
  48. static int compare(const char* p, const TCiString& s2, const CodePage& cp = csYandex);
  49. static int compare(const TCiString& s1, const char* p, const CodePage& cp = csYandex);
  50. static int compare(const TStringBuf& p1, const TStringBuf& p2, const CodePage& cp = csYandex);
  51. // TODO: implement properly in TString via enum ECaseSensitivity
  52. static bool is_prefix(const TStringBuf& what, const TStringBuf& of, const CodePage& cp = csYandex);
  53. static bool is_suffix(const TStringBuf& what, const TStringBuf& of, const CodePage& cp = csYandex);
  54. bool StartsWith(const TStringBuf& s, const CodePage& cp = csYandex) const {
  55. return is_prefix(s, *this, cp);
  56. }
  57. bool EndsWith(const TStringBuf& s, const CodePage& cp = csYandex) const {
  58. return is_suffix(s, *this, cp);
  59. }
  60. friend bool operator==(const TCiString& s1, const TCiString& s2) {
  61. return TCiString::compare(s1, s2) == 0;
  62. }
  63. friend bool operator==(const TCiString& s, const char* pc) {
  64. return TCiString::compare(s, pc) == 0;
  65. }
  66. friend bool operator==(const char* pc, const TCiString& s) {
  67. return TCiString::compare(pc, s) == 0;
  68. }
  69. template <typename TDerived2, typename TTraits2>
  70. friend bool operator==(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) {
  71. return TCiString::compare(s, pc) == 0;
  72. }
  73. template <typename TDerived2, typename TTraits2>
  74. friend bool operator==(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) {
  75. return TCiString::compare(pc, s) == 0;
  76. }
  77. friend bool operator!=(const TCiString& s1, const TCiString& s2) {
  78. return TCiString::compare(s1, s2) != 0;
  79. }
  80. friend bool operator!=(const TCiString& s, const char* pc) {
  81. return TCiString::compare(s, pc) != 0;
  82. }
  83. friend bool operator!=(const char* pc, const TCiString& s) {
  84. return TCiString::compare(pc, s) != 0;
  85. }
  86. template <typename TDerived2, typename TTraits2>
  87. friend bool operator!=(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) {
  88. return TCiString::compare(s, pc) != 0;
  89. }
  90. template <typename TDerived2, typename TTraits2>
  91. friend bool operator!=(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) {
  92. return TCiString::compare(pc, s) != 0;
  93. }
  94. friend bool operator<(const TCiString& s1, const TCiString& s2) {
  95. return TCiString::compare(s1, s2) < 0;
  96. }
  97. friend bool operator<(const TCiString& s, const char* pc) {
  98. return TCiString::compare(s, pc) < 0;
  99. }
  100. friend bool operator<(const char* pc, const TCiString& s) {
  101. return TCiString::compare(pc, s) < 0;
  102. }
  103. template <typename TDerived2, typename TTraits2>
  104. friend bool operator<(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) {
  105. return TCiString::compare(s, pc) < 0;
  106. }
  107. template <typename TDerived2, typename TTraits2>
  108. friend bool operator<(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) {
  109. return TCiString::compare(pc, s) < 0;
  110. }
  111. friend bool operator<=(const TCiString& s1, const TCiString& s2) {
  112. return TCiString::compare(s1, s2) <= 0;
  113. }
  114. friend bool operator<=(const TCiString& s, const char* pc) {
  115. return TCiString::compare(s, pc) <= 0;
  116. }
  117. friend bool operator<=(const char* pc, const TCiString& s) {
  118. return TCiString::compare(pc, s) <= 0;
  119. }
  120. template <typename TDerived2, typename TTraits2>
  121. friend bool operator<=(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) {
  122. return TCiString::compare(s, pc) <= 0;
  123. }
  124. template <typename TDerived2, typename TTraits2>
  125. friend bool operator<=(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) {
  126. return TCiString::compare(pc, s) <= 0;
  127. }
  128. friend bool operator>(const TCiString& s1, const TCiString& s2) {
  129. return TCiString::compare(s1, s2) > 0;
  130. }
  131. friend bool operator>(const TCiString& s, const char* pc) {
  132. return TCiString::compare(s, pc) > 0;
  133. }
  134. friend bool operator>(const char* pc, const TCiString& s) {
  135. return TCiString::compare(pc, s) > 0;
  136. }
  137. template <typename TDerived2, typename TTraits2>
  138. friend bool operator>(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) noexcept {
  139. return TCiString::compare(s, pc) > 0;
  140. }
  141. template <typename TDerived2, typename TTraits2>
  142. friend bool operator>(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) noexcept {
  143. return TCiString::compare(pc, s) > 0;
  144. }
  145. friend bool operator>=(const TCiString& s1, const TCiString& s2) {
  146. return TCiString::compare(s1, s2) >= 0;
  147. }
  148. friend bool operator>=(const TCiString& s, const char* pc) {
  149. return TCiString::compare(s, pc) >= 0;
  150. }
  151. friend bool operator>=(const char* pc, const TCiString& s) {
  152. return TCiString::compare(pc, s) >= 0;
  153. }
  154. template <typename TDerived2, typename TTraits2>
  155. friend bool operator>=(const TCiString& s, const TStringBase<TDerived2, TChar, TTraits2>& pc) {
  156. return TCiString::compare(s, pc) >= 0;
  157. }
  158. template <typename TDerived2, typename TTraits2>
  159. friend bool operator>=(const TStringBase<TDerived2, TChar, TTraits2>& pc, const TCiString& s) {
  160. return TCiString::compare(pc, s) >= 0;
  161. }
  162. static size_t hashVal(const char* pc, size_t len, const CodePage& cp = csYandex);
  163. size_t hash() const {
  164. return TCiString::hashVal(data(), length());
  165. }
  166. };
  167. struct ci_hash {
  168. inline size_t operator()(const char* s) const {
  169. return TCiString::hashVal(s, strlen(s));
  170. }
  171. inline size_t operator()(const TStringBuf& s) const {
  172. return TCiString::hashVal(s.data(), s.size());
  173. }
  174. };
  175. struct ci_hash32 { // not the same as ci_hash under 64-bit
  176. inline ui32 operator()(const char* s) const {
  177. return (ui32)TCiString::hashVal(s, strlen(s));
  178. }
  179. };
  180. //template <class T> struct hash;
  181. template <>
  182. struct hash<TCiString>: public ci_hash {
  183. };
  184. template <class T>
  185. struct TCIHash {
  186. };
  187. template <>
  188. struct TCIHash<const char*> {
  189. inline size_t operator()(const TStringBuf& s) const {
  190. return TCiString::hashVal(s.data(), s.size());
  191. }
  192. };
  193. template <>
  194. struct TCIHash<TStringBuf> {
  195. inline size_t operator()(const TStringBuf& s) const {
  196. return TCiString::hashVal(s.data(), s.size());
  197. }
  198. };
  199. template <>
  200. struct TCIHash<TString> {
  201. inline size_t operator()(const TString& s) const {
  202. return TCiString::hashVal(s.data(), s.size());
  203. }
  204. };
  205. struct ci_less {
  206. inline bool operator()(const char* x, const char* y) const {
  207. return csYandex.stricmp(x, y) < 0;
  208. }
  209. };
  210. struct ci_equal_to {
  211. inline bool operator()(const char* x, const char* y) const {
  212. return csYandex.stricmp(x, y) == 0;
  213. }
  214. // this implementation is not suitable for strings with zero characters inside, sorry
  215. bool operator()(const TStringBuf& x, const TStringBuf& y) const {
  216. return x.size() == y.size() && csYandex.strnicmp(x.data(), y.data(), y.size()) == 0;
  217. }
  218. };
  219. template <>
  220. struct TEqualTo<TCiString>: public ci_equal_to {
  221. };