-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathstring.hpp
131 lines (118 loc) · 3.1 KB
/
string.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#pragma once
#include <cstring>
#include <cctype>
#include <string>
#include <algorithm>
#include <string_view>
#include <span>
#include <cstddef>
namespace ws_client
{
using std::string;
using std::string_view;
using std::byte;
using std::span;
/**
* Case-insensitive single ASCII character comparison (less than).
*/
inline bool less_ci_char(const char a, const char b) noexcept
{
return std::tolower(static_cast<unsigned char>(a)) <
std::tolower(static_cast<unsigned char>(b));
}
/**
* Case-insensitive single ASCII character equality comparison.
*/
inline bool equals_ci_char(const char a, const char b) noexcept
{
return std::tolower(static_cast<unsigned char>(a)) ==
std::tolower(static_cast<unsigned char>(b));
}
/**
* Case-insensitive string equality comparison.
*/
inline bool equals_ci(const string& a, const string& b) noexcept
{
return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), equals_ci_char);
}
/**
* Case-insensitive string equality comparison.
*/
inline bool equals_ci(const string_view lhs, const string_view rhs) noexcept
{
return lhs.size() == rhs.size() &&
std::equal(lhs.begin(), lhs.end(), rhs.begin(), equals_ci_char);
}
/**
* Case-insensitive "less than" string comparison operator.
* E.g. useful for case-insensitive map keys.
*
* Examples:
* ```c++
* std::map<string, int, CaseInsensitiveLess> my_map;
* std::multimap<string, int, CaseInsensitiveLess> my_multimap;
* ```
*/
struct CaseInsensitiveLess
{
bool operator()(const string_view s1, const string_view s2) const noexcept
{
if (s1.size() != s2.size())
return s1.size() < s2.size();
return std::lexicographical_compare(
s1.begin(), s1.end(), s2.begin(), s2.end(), less_ci_char
);
}
};
/**
* Trim whitespace-like characters from beginning of string in-place.
*/
inline void trim_left(string& s) noexcept
{
s.erase(
s.begin(),
std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); })
);
}
/**
* Trim whitespace-like characters from end of string in-place.
*/
inline void trim_right(string& s) noexcept
{
s.erase(
std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); }).base(),
s.end()
);
}
/**
* Trim whitespace-like characters from beginning and end of string in-place.
*/
inline void trim(string& s) noexcept
{
trim_left(s);
trim_right(s);
}
/**
* Creates a string from a span of bytes.
*/
inline string string_from_bytes(span<byte> data) noexcept
{
return string(reinterpret_cast<const char*>(data.data()), data.size());
}
struct string_like_hash
{
using is_transparent = void;
[[nodiscard]] inline size_t operator()(const char* txt) const
{
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] inline size_t operator()(std::string_view txt) const
{
return std::hash<std::string_view>{}(txt);
}
[[nodiscard]] inline size_t operator()(const std::string& txt) const
{
return std::hash<std::string>{}(txt);
}
};
} // namespace ws_client