]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_RGW_STRING_H | |
5 | #define CEPH_RGW_STRING_H | |
6 | ||
31f18b77 | 7 | #include <errno.h> |
7c673cae FG |
8 | #include <stdlib.h> |
9 | #include <limits.h> | |
10 | ||
31f18b77 FG |
11 | #include <boost/container/small_vector.hpp> |
12 | #include <boost/utility/string_view.hpp> | |
13 | ||
7c673cae FG |
14 | struct ltstr_nocase |
15 | { | |
31f18b77 | 16 | bool operator()(const std::string& s1, const std::string& s2) const |
7c673cae FG |
17 | { |
18 | return strcasecmp(s1.c_str(), s2.c_str()) < 0; | |
19 | } | |
20 | }; | |
21 | ||
31f18b77 | 22 | static inline int stringcasecmp(const std::string& s1, const std::string& s2) |
7c673cae FG |
23 | { |
24 | return strcasecmp(s1.c_str(), s2.c_str()); | |
25 | } | |
26 | ||
31f18b77 | 27 | static inline int stringcasecmp(const std::string& s1, const char *s2) |
7c673cae FG |
28 | { |
29 | return strcasecmp(s1.c_str(), s2); | |
30 | } | |
31 | ||
31f18b77 | 32 | static inline int stringcasecmp(const std::string& s1, int ofs, int size, const std::string& s2) |
7c673cae FG |
33 | { |
34 | return strncasecmp(s1.c_str() + ofs, s2.c_str(), size); | |
35 | } | |
36 | ||
31f18b77 | 37 | static inline int stringtoll(const std::string& s, int64_t *val) |
7c673cae FG |
38 | { |
39 | char *end; | |
40 | ||
41 | long long result = strtoll(s.c_str(), &end, 10); | |
42 | if (result == LLONG_MAX) | |
43 | return -EINVAL; | |
44 | ||
45 | if (*end) | |
46 | return -EINVAL; | |
47 | ||
48 | *val = (int64_t)result; | |
49 | ||
50 | return 0; | |
51 | } | |
52 | ||
31f18b77 | 53 | static inline int stringtoull(const std::string& s, uint64_t *val) |
7c673cae FG |
54 | { |
55 | char *end; | |
56 | ||
57 | unsigned long long result = strtoull(s.c_str(), &end, 10); | |
58 | if (result == ULLONG_MAX) | |
59 | return -EINVAL; | |
60 | ||
61 | if (*end) | |
62 | return -EINVAL; | |
63 | ||
64 | *val = (uint64_t)result; | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
31f18b77 | 69 | static inline int stringtol(const std::string& s, int32_t *val) |
7c673cae FG |
70 | { |
71 | char *end; | |
72 | ||
73 | long result = strtol(s.c_str(), &end, 10); | |
74 | if (result == LONG_MAX) | |
75 | return -EINVAL; | |
76 | ||
77 | if (*end) | |
78 | return -EINVAL; | |
79 | ||
80 | *val = (int32_t)result; | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
31f18b77 | 85 | static inline int stringtoul(const std::string& s, uint32_t *val) |
7c673cae FG |
86 | { |
87 | char *end; | |
88 | ||
89 | unsigned long result = strtoul(s.c_str(), &end, 10); | |
90 | if (result == ULONG_MAX) | |
91 | return -EINVAL; | |
92 | ||
93 | if (*end) | |
94 | return -EINVAL; | |
95 | ||
96 | *val = (uint32_t)result; | |
97 | ||
98 | return 0; | |
99 | } | |
100 | ||
31f18b77 FG |
101 | /* A converter between boost::string_view and null-terminated C-strings. |
102 | * It copies memory while trying to utilize the local memory instead of | |
103 | * issuing dynamic allocations. */ | |
104 | template<std::size_t N = 128> | |
105 | static inline boost::container::small_vector<char, N> | |
106 | sview2cstr(const boost::string_view& sv) | |
107 | { | |
108 | boost::container::small_vector<char, N> cstr; | |
109 | cstr.reserve(sv.size() + sizeof('\0')); | |
110 | ||
111 | cstr.assign(std::begin(sv), std::end(sv)); | |
112 | cstr.push_back('\0'); | |
113 | ||
114 | return cstr; | |
115 | } | |
116 | ||
117 | /* std::strlen() isn't guaranteed to be computable at compile-time. Although | |
118 | * newer GCCs actually do that, Clang doesn't. Please be aware this function | |
119 | * IS NOT A DROP-IN REPLACEMENT FOR STRLEN -- it returns a different result | |
120 | * for strings having \0 in the middle. */ | |
121 | template<size_t N> | |
122 | static inline constexpr size_t sarrlen(const char (&arr)[N]) { | |
123 | return N - 1; | |
124 | } | |
125 | ||
126 | namespace detail { | |
127 | ||
128 | // variadic sum() to add up string lengths for reserve() | |
129 | static inline constexpr size_t sum() { return 0; } | |
130 | template <typename... Args> | |
131 | constexpr size_t sum(size_t v, Args... args) { return v + sum(args...); } | |
132 | ||
133 | // traits for string_size() | |
134 | template <typename T> | |
135 | struct string_traits { | |
136 | static constexpr size_t size(const T& s) { return s.size(); } | |
137 | }; | |
138 | // specializations for char*/const char* use strlen() | |
139 | template <> | |
140 | struct string_traits<const char*> { | |
141 | static size_t size(const char* s) { return std::strlen(s); } | |
142 | }; | |
143 | template <> | |
144 | struct string_traits<char*> : string_traits<const char*> {}; | |
145 | // constexpr specializations for char[]/const char[] | |
146 | template <std::size_t N> | |
147 | struct string_traits<const char[N]> { | |
148 | static constexpr size_t size_(const char* s, size_t i) { | |
149 | return i < N ? (*(s + i) == '\0' ? i : size_(s, i + 1)) | |
150 | : throw std::invalid_argument("Unterminated string constant."); | |
151 | } | |
152 | static constexpr size_t size(const char(&s)[N]) { return size_(s, 0); } | |
153 | }; | |
154 | template <std::size_t N> | |
155 | struct string_traits<char[N]> : string_traits<const char[N]> {}; | |
156 | ||
157 | // helpers for string_cat_reserve() | |
158 | static inline void append_to(std::string& s) {} | |
159 | template <typename... Args> | |
160 | void append_to(std::string& s, const boost::string_view& v, const Args&... args) | |
161 | { | |
162 | s.append(v.begin(), v.end()); | |
163 | append_to(s, args...); | |
164 | } | |
165 | ||
166 | // helpers for string_join_reserve() | |
167 | static inline void join_next(std::string& s, const boost::string_view& d) {} | |
168 | template <typename... Args> | |
169 | void join_next(std::string& s, const boost::string_view& d, | |
170 | const boost::string_view& v, const Args&... args) | |
171 | { | |
172 | s.append(d.begin(), d.end()); | |
173 | s.append(v.begin(), v.end()); | |
174 | join_next(s, d, args...); | |
175 | } | |
176 | ||
177 | static inline void join(std::string& s, const boost::string_view& d) {} | |
178 | template <typename... Args> | |
179 | void join(std::string& s, const boost::string_view& d, | |
180 | const boost::string_view& v, const Args&... args) | |
181 | { | |
182 | s.append(v.begin(), v.end()); | |
183 | join_next(s, d, args...); | |
184 | } | |
185 | ||
186 | } // namespace detail | |
187 | ||
188 | /// return the length of a c string, string literal, or string type | |
189 | template <typename T> | |
190 | constexpr size_t string_size(const T& s) | |
191 | { | |
192 | return detail::string_traits<T>::size(s); | |
193 | } | |
194 | ||
195 | /// concatenates the given string arguments, returning as a std::string that | |
196 | /// gets preallocated with reserve() | |
197 | template <typename... Args> | |
198 | std::string string_cat_reserve(const Args&... args) | |
199 | { | |
200 | size_t total_size = detail::sum(string_size(args)...); | |
201 | std::string result; | |
202 | result.reserve(total_size); | |
203 | detail::append_to(result, args...); | |
204 | return result; | |
205 | } | |
206 | ||
207 | /// joins the given string arguments with a delimiter, returning as a | |
208 | /// std::string that gets preallocated with reserve() | |
209 | template <typename... Args> | |
210 | std::string string_join_reserve(const boost::string_view& delim, | |
211 | const Args&... args) | |
212 | { | |
213 | size_t delim_size = delim.size() * std::max<ssize_t>(0, sizeof...(args) - 1); | |
214 | size_t total_size = detail::sum(string_size(args)...) + delim_size; | |
215 | std::string result; | |
216 | result.reserve(total_size); | |
217 | detail::join(result, delim, args...); | |
218 | return result; | |
219 | } | |
220 | template <typename... Args> | |
221 | std::string string_join_reserve(char delim, const Args&... args) | |
222 | { | |
223 | return string_join_reserve(boost::string_view{&delim, 1}, args...); | |
224 | } | |
225 | ||
d2e6a577 FG |
226 | |
227 | /// use case-insensitive comparison in match_wildcards() | |
228 | static constexpr uint32_t MATCH_CASE_INSENSITIVE = 0x01; | |
229 | ||
230 | /// attempt to match the given input string with the pattern, which may contain | |
231 | /// the wildcard characters * and ? | |
232 | extern bool match_wildcards(boost::string_view pattern, | |
233 | boost::string_view input, | |
234 | uint32_t flags = 0); | |
235 | ||
7c673cae | 236 | #endif |