]>
git.proxmox.com Git - ceph.git/blob - 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
4 #ifndef CEPH_RGW_STRING_H
5 #define CEPH_RGW_STRING_H
11 #include <boost/container/small_vector.hpp>
12 #include <boost/utility/string_view.hpp>
16 bool operator()(const std::string
& s1
, const std::string
& s2
) const
18 return strcasecmp(s1
.c_str(), s2
.c_str()) < 0;
22 static inline int stringcasecmp(const std::string
& s1
, const std::string
& s2
)
24 return strcasecmp(s1
.c_str(), s2
.c_str());
27 static inline int stringcasecmp(const std::string
& s1
, const char *s2
)
29 return strcasecmp(s1
.c_str(), s2
);
32 static inline int stringcasecmp(const std::string
& s1
, int ofs
, int size
, const std::string
& s2
)
34 return strncasecmp(s1
.c_str() + ofs
, s2
.c_str(), size
);
37 static inline int stringtoll(const std::string
& s
, int64_t *val
)
41 long long result
= strtoll(s
.c_str(), &end
, 10);
42 if (result
== LLONG_MAX
)
48 *val
= (int64_t)result
;
53 static inline int stringtoull(const std::string
& s
, uint64_t *val
)
57 unsigned long long result
= strtoull(s
.c_str(), &end
, 10);
58 if (result
== ULLONG_MAX
)
64 *val
= (uint64_t)result
;
69 static inline int stringtol(const std::string
& s
, int32_t *val
)
73 long result
= strtol(s
.c_str(), &end
, 10);
74 if (result
== LONG_MAX
)
80 *val
= (int32_t)result
;
85 static inline int stringtoul(const std::string
& s
, uint32_t *val
)
89 unsigned long result
= strtoul(s
.c_str(), &end
, 10);
90 if (result
== ULONG_MAX
)
96 *val
= (uint32_t)result
;
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
)
108 boost::container::small_vector
<char, N
> cstr
;
109 cstr
.reserve(sv
.size() + sizeof('\0'));
111 cstr
.assign(std::begin(sv
), std::end(sv
));
112 cstr
.push_back('\0');
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. */
122 static inline constexpr size_t sarrlen(const char (&arr
)[N
]) {
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
...); }
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(); }
138 // specializations for char*/const char* use strlen()
140 struct string_traits
<const char*> {
141 static size_t size(const char* s
) { return std::strlen(s
); }
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.");
152 static constexpr size_t size(const char(&s
)[N
]) { return size_(s
, 0); }
154 template <std::size_t N
>
155 struct string_traits
<char[N
]> : string_traits
<const char[N
]> {};
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
)
162 s
.append(v
.begin(), v
.end());
163 append_to(s
, args
...);
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
)
172 s
.append(d
.begin(), d
.end());
173 s
.append(v
.begin(), v
.end());
174 join_next(s
, d
, args
...);
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
)
182 s
.append(v
.begin(), v
.end());
183 join_next(s
, d
, args
...);
186 } // namespace detail
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
)
192 return detail::string_traits
<T
>::size(s
);
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
)
200 size_t total_size
= detail::sum(string_size(args
)...);
202 result
.reserve(total_size
);
203 detail::append_to(result
, args
...);
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
,
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
;
216 result
.reserve(total_size
);
217 detail::join(result
, delim
, args
...);
220 template <typename
... Args
>
221 std::string
string_join_reserve(char delim
, const Args
&... args
)
223 return string_join_reserve(boost::string_view
{&delim
, 1}, args
...);