Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_string.h
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
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <limits.h>
10
11 #include <boost/container/small_vector.hpp>
12 #include <boost/utility/string_view.hpp>
13
14 struct ltstr_nocase
15 {
16   bool operator()(const std::string& s1, const std::string& s2) const
17   {
18     return strcasecmp(s1.c_str(), s2.c_str()) < 0;
19   }
20 };
21
22 static inline int stringcasecmp(const std::string& s1, const std::string& s2)
23 {
24   return strcasecmp(s1.c_str(), s2.c_str());
25 }
26
27 static inline int stringcasecmp(const std::string& s1, const char *s2)
28 {
29   return strcasecmp(s1.c_str(), s2);
30 }
31
32 static inline int stringcasecmp(const std::string& s1, int ofs, int size, const std::string& s2)
33 {
34   return strncasecmp(s1.c_str() + ofs, s2.c_str(), size);
35 }
36
37 static inline int stringtoll(const std::string& s, int64_t *val)
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
53 static inline int stringtoull(const std::string& s, uint64_t *val)
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
69 static inline int stringtol(const std::string& s, int32_t *val)
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
85 static inline int stringtoul(const std::string& s, uint32_t *val)
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
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
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
236 #endif