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