case_insensitive_char_traits.h 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #pragma once
  2. #include <contrib/libs/libc_compat/string.h>
  3. #include <util/string/ascii.h>
  4. #include <string>
  5. namespace NPrivate {
  6. template <typename TImpl>
  7. struct TCommonCaseInsensitiveCharTraits : private std::char_traits<char> {
  8. static bool eq(char c1, char c2) {
  9. return TImpl::ToCommonCase(c1) == TImpl::ToCommonCase(c2);
  10. }
  11. static bool lt(char c1, char c2) {
  12. return TImpl::ToCommonCase(c1) < TImpl::ToCommonCase(c2);
  13. }
  14. static const char* find(const char* s, std::size_t n, char a);
  15. using std::char_traits<char>::assign;
  16. using std::char_traits<char>::char_type;
  17. using std::char_traits<char>::copy;
  18. using std::char_traits<char>::length;
  19. using std::char_traits<char>::move;
  20. };
  21. } // namespace NPrivate
  22. struct TCaseInsensitiveCharTraits : public ::NPrivate::TCommonCaseInsensitiveCharTraits<TCaseInsensitiveCharTraits> {
  23. static int compare(const char* s1, const char* s2, std::size_t n);
  24. private:
  25. friend ::NPrivate::TCommonCaseInsensitiveCharTraits<TCaseInsensitiveCharTraits>;
  26. // XXX return unsigned char. Current impl depends on char signedness, and if char is signed,
  27. // TCaseInsensitiveCharTraits::compare returns different result from std::char_traits<char>::compare for non-ascii strings.
  28. static char ToCommonCase(char ch) {
  29. return std::toupper((unsigned char)ch);
  30. }
  31. };
  32. struct TCaseInsensitiveAsciiCharTraits : public ::NPrivate::TCommonCaseInsensitiveCharTraits<TCaseInsensitiveCharTraits> {
  33. // WARN: does not work with null bytes (`compare("ab\0c", "ab\0d", 4)` returns 0).
  34. static int compare(const char* s1, const char* s2, std::size_t n) {
  35. return ::strncasecmp(s1, s2, n);
  36. }
  37. private:
  38. friend ::NPrivate::TCommonCaseInsensitiveCharTraits<TCaseInsensitiveAsciiCharTraits>;
  39. static unsigned char ToCommonCase(char ch) {
  40. return AsciiToLower(ch);
  41. }
  42. };