summaryrefslogtreecommitdiffstats
path: root/src/template.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/template.h')
-rw-r--r--src/template.h267
1 files changed, 118 insertions, 149 deletions
diff --git a/src/template.h b/src/template.h
index 530a1d1..3ab3677 100644
--- a/src/template.h
+++ b/src/template.h
@@ -37,20 +37,11 @@
#include <algorithm>
#include <ostream>
#include <utility>
+#include <span>
+#include <string_view>
namespace nghttp2 {
-// std::forward is constexpr since C++14
-template <typename... T>
-constexpr std::array<
- typename std::decay<typename std::common_type<T...>::type>::type,
- sizeof...(T)>
-make_array(T &&...t) {
- return std::array<
- typename std::decay<typename std::common_type<T...>::type>::type,
- sizeof...(T)>{{std::forward<T>(t)...}};
-}
-
template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) {
return N;
}
@@ -67,8 +58,7 @@ template <typename F, typename... T> struct Defer {
Defer(Defer &&o) noexcept : f(std::move(o.f)) {}
~Defer() { f(); }
- using ResultType = typename std::result_of<typename std::decay<F>::type(
- typename std::decay<T>::type...)>::type;
+ using ResultType = std::invoke_result_t<F, T...>;
std::function<ResultType()> f;
};
@@ -234,27 +224,27 @@ public:
using const_iterator = const_pointer;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- ImmutableString() : len(0), base("") {}
- ImmutableString(const char *s, size_t slen)
+ constexpr ImmutableString() : len(0), base("") {}
+ constexpr ImmutableString(const char *s, size_t slen)
: len(slen), base(copystr(s, s + len)) {}
- explicit ImmutableString(const char *s)
- : len(strlen(s)), base(copystr(s, s + len)) {}
- explicit ImmutableString(const std::string &s)
+ constexpr explicit ImmutableString(const char *s)
+ : len(traits_type::length(s)), base(copystr(s, s + len)) {}
+ constexpr explicit ImmutableString(const std::string &s)
: len(s.size()), base(copystr(std::begin(s), std::end(s))) {}
template <typename InputIt>
- ImmutableString(InputIt first, InputIt last)
+ constexpr ImmutableString(InputIt first, InputIt last)
: len(std::distance(first, last)), base(copystr(first, last)) {}
- ImmutableString(const ImmutableString &other)
+ constexpr ImmutableString(const ImmutableString &other)
: len(other.len), base(copystr(std::begin(other), std::end(other))) {}
- ImmutableString(ImmutableString &&other) noexcept
+ constexpr ImmutableString(ImmutableString &&other) noexcept
: len{std::exchange(other.len, 0)}, base{std::exchange(other.base, "")} {}
- ~ImmutableString() {
+ constexpr ~ImmutableString() {
if (len) {
delete[] base;
}
}
- ImmutableString &operator=(const ImmutableString &other) {
+ constexpr ImmutableString &operator=(const ImmutableString &other) {
if (this == &other) {
return *this;
}
@@ -265,7 +255,7 @@ public:
base = copystr(std::begin(other), std::end(other));
return *this;
}
- ImmutableString &operator=(ImmutableString &&other) noexcept {
+ constexpr ImmutableString &operator=(ImmutableString &&other) noexcept {
if (this == &other) {
return *this;
}
@@ -277,33 +267,41 @@ public:
return *this;
}
- template <size_t N> static ImmutableString from_lit(const char (&s)[N]) {
+ template <size_t N>
+ static constexpr ImmutableString from_lit(const char (&s)[N]) {
return ImmutableString(s, N - 1);
}
- const_iterator begin() const { return base; };
- const_iterator cbegin() const { return base; };
+ constexpr const_iterator begin() const noexcept { return base; };
+ constexpr const_iterator cbegin() const noexcept { return base; };
- const_iterator end() const { return base + len; };
- const_iterator cend() const { return base + len; };
+ constexpr const_iterator end() const noexcept { return base + len; };
+ constexpr const_iterator cend() const noexcept { return base + len; };
- const_reverse_iterator rbegin() const {
+ constexpr const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator{base + len};
}
- const_reverse_iterator crbegin() const {
+ constexpr const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator{base + len};
}
- const_reverse_iterator rend() const { return const_reverse_iterator{base}; }
- const_reverse_iterator crend() const { return const_reverse_iterator{base}; }
+ constexpr const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator{base};
+ }
+ constexpr const_reverse_iterator crend() const noexcept {
+ return const_reverse_iterator{base};
+ }
- const char *c_str() const { return base; }
- size_type size() const { return len; }
- bool empty() const { return len == 0; }
- const_reference operator[](size_type pos) const { return *(base + pos); }
+ constexpr const char *c_str() const noexcept { return base; }
+ constexpr size_type size() const noexcept { return len; }
+ constexpr bool empty() const noexcept { return len == 0; }
+ constexpr const_reference operator[](size_type pos) const noexcept {
+ return *(base + pos);
+ }
private:
- template <typename InputIt> const char *copystr(InputIt first, InputIt last) {
+ template <typename InputIt>
+ constexpr const char *copystr(InputIt first, InputIt last) {
if (first == last) {
return "";
}
@@ -316,49 +314,23 @@ private:
const char *base;
};
-inline bool operator==(const ImmutableString &lhs, const ImmutableString &rhs) {
+inline constexpr bool operator==(const ImmutableString &lhs,
+ const ImmutableString &rhs) {
return lhs.size() == rhs.size() &&
std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}
-inline bool operator==(const ImmutableString &lhs, const std::string &rhs) {
+inline constexpr bool operator==(const ImmutableString &lhs,
+ const std::string &rhs) {
return lhs.size() == rhs.size() &&
std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}
-inline bool operator==(const std::string &lhs, const ImmutableString &rhs) {
- return rhs == lhs;
-}
-
-inline bool operator==(const ImmutableString &lhs, const char *rhs) {
- return lhs.size() == strlen(rhs) &&
+inline constexpr bool operator==(const ImmutableString &lhs, const char *rhs) {
+ return lhs.size() == std::char_traits<char>::length(rhs) &&
std::equal(std::begin(lhs), std::end(lhs), rhs);
}
-inline bool operator==(const char *lhs, const ImmutableString &rhs) {
- return rhs == lhs;
-}
-
-inline bool operator!=(const ImmutableString &lhs, const ImmutableString &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const ImmutableString &lhs, const std::string &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const std::string &lhs, const ImmutableString &rhs) {
- return !(rhs == lhs);
-}
-
-inline bool operator!=(const ImmutableString &lhs, const char *rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const char *lhs, const ImmutableString &rhs) {
- return !(rhs == lhs);
-}
-
inline std::ostream &operator<<(std::ostream &o, const ImmutableString &s) {
return o.write(s.c_str(), s.size());
}
@@ -371,8 +343,7 @@ inline std::string &operator+=(std::string &lhs, const ImmutableString &rhs) {
// StringRef is a reference to a string owned by something else. So
// it behaves like simple string, but it does not own pointer. When
// it is default constructed, it has empty string. You can freely
-// copy or move around this struct, but never free its pointer. str()
-// function can be used to export the content as std::string.
+// copy or move around this struct, but never free its pointer.
class StringRef {
public:
using traits_type = std::char_traits<char>;
@@ -386,28 +357,28 @@ public:
using const_iterator = const_pointer;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- constexpr StringRef() : base(""), len(0) {}
- explicit StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {}
- explicit StringRef(const ImmutableString &s)
+ constexpr StringRef() noexcept : base(""), len(0) {}
+ constexpr StringRef(const StringRef &other) noexcept = default;
+ constexpr StringRef(std::nullptr_t) = delete;
+ constexpr StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {}
+ constexpr explicit StringRef(const std::string_view &s)
+ : base(s.data()), len(s.size()) {}
+ constexpr explicit StringRef(const ImmutableString &s)
: base(s.c_str()), len(s.size()) {}
- explicit StringRef(const char *s) : base(s), len(strlen(s)) {}
+ constexpr StringRef(const char *s) : base(s), len(traits_type::length(s)) {}
constexpr StringRef(const char *s, size_t n) : base(s), len(n) {}
- template <typename CharT>
- constexpr StringRef(const CharT *s, size_t n)
+ explicit StringRef(const uint8_t *s, size_t n)
: base(reinterpret_cast<const char *>(s)), len(n) {}
- template <typename InputIt>
- StringRef(InputIt first, InputIt last)
- : base(reinterpret_cast<const char *>(&*first)),
- len(std::distance(first, last)) {}
- template <typename InputIt>
- StringRef(InputIt *first, InputIt *last)
- : base(reinterpret_cast<const char *>(first)),
- len(std::distance(first, last)) {}
- template <typename CharT, size_t N>
- constexpr static StringRef from_lit(const CharT (&s)[N]) {
- return StringRef{s, N - 1};
- }
- static StringRef from_maybe_nullptr(const char *s) {
+ template <std::contiguous_iterator InputIt,
+ typename = std::enable_if_t<
+ std::is_same_v<std::iter_value_t<InputIt>, char>>>
+ constexpr StringRef(InputIt first, InputIt last)
+ : base(std::to_address(first)), len(std::distance(first, last)) {}
+ constexpr StringRef(std::span<const char> s)
+ : base(s.data()), len(s.size_bytes()) {}
+ explicit StringRef(std::span<const uint8_t> s)
+ : base(reinterpret_cast<const char *>(s.data())), len(s.size_bytes()) {}
+ static constexpr StringRef from_maybe_nullptr(const char *s) noexcept {
if (s == nullptr) {
return StringRef();
}
@@ -415,105 +386,103 @@ public:
return StringRef(s);
}
- constexpr const_iterator begin() const { return base; };
- constexpr const_iterator cbegin() const { return base; };
+ constexpr StringRef &operator=(const StringRef &other) noexcept = default;
+
+ constexpr const_iterator begin() const noexcept { return base; };
+ constexpr const_iterator cbegin() const noexcept { return base; };
- constexpr const_iterator end() const { return base + len; };
- constexpr const_iterator cend() const { return base + len; };
+ constexpr const_iterator end() const noexcept { return base + len; };
+ constexpr const_iterator cend() const noexcept { return base + len; };
- const_reverse_iterator rbegin() const {
+ constexpr const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator{base + len};
}
- const_reverse_iterator crbegin() const {
+ constexpr const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator{base + len};
}
- const_reverse_iterator rend() const { return const_reverse_iterator{base}; }
- const_reverse_iterator crend() const { return const_reverse_iterator{base}; }
+ constexpr const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator{base};
+ }
+ constexpr const_reverse_iterator crend() const noexcept {
+ return const_reverse_iterator{base};
+ }
- constexpr const char *c_str() const { return base; }
- constexpr size_type size() const { return len; }
- constexpr bool empty() const { return len == 0; }
+ constexpr const_pointer data() const noexcept { return base; }
+ constexpr size_type size() const noexcept { return len; }
+ [[nodiscard]] constexpr bool empty() const noexcept { return len == 0; }
constexpr const_reference operator[](size_type pos) const {
return *(base + pos);
}
- std::string str() const { return std::string(base, len); }
const uint8_t *byte() const {
return reinterpret_cast<const uint8_t *>(base);
}
+ constexpr operator std::string_view() const noexcept { return {base, len}; }
+
+ static constexpr size_type npos = size_type(-1);
+
+ constexpr StringRef substr(size_type pos = 0, size_type count = npos) const {
+ return {base + pos, std::min(count, len - pos)};
+ }
+
private:
const char *base;
size_type len;
};
-inline bool operator==(const StringRef &lhs, const StringRef &rhs) {
+inline constexpr bool operator==(const StringRef &lhs,
+ const StringRef &rhs) noexcept {
return lhs.size() == rhs.size() &&
std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}
-inline bool operator==(const StringRef &lhs, const std::string &rhs) {
+inline constexpr bool operator==(const StringRef &lhs,
+ const ImmutableString &rhs) noexcept {
return lhs.size() == rhs.size() &&
std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
}
-inline bool operator==(const std::string &lhs, const StringRef &rhs) {
- return rhs == lhs;
-}
-
-inline bool operator==(const StringRef &lhs, const char *rhs) {
- return lhs.size() == strlen(rhs) &&
- std::equal(std::begin(lhs), std::end(lhs), rhs);
-}
-
-inline bool operator==(const StringRef &lhs, const ImmutableString &rhs) {
- return lhs.size() == rhs.size() &&
- std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
+#ifndef __APPLE__
+inline constexpr std::strong_ordering
+operator<=>(const StringRef &lhs, const StringRef &rhs) noexcept {
+ return std::lexicographical_compare_three_way(std::begin(lhs), std::end(lhs),
+ std::begin(rhs), std::end(rhs));
}
-
-inline bool operator==(const ImmutableString &lhs, const StringRef &rhs) {
- return rhs == lhs;
-}
-
-inline bool operator==(const char *lhs, const StringRef &rhs) {
- return rhs == lhs;
-}
-
-inline bool operator!=(const StringRef &lhs, const StringRef &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const StringRef &lhs, const std::string &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const std::string &lhs, const StringRef &rhs) {
- return !(rhs == lhs);
-}
-
-inline bool operator!=(const StringRef &lhs, const char *rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator!=(const char *lhs, const StringRef &rhs) {
- return !(rhs == lhs);
-}
-
-inline bool operator<(const StringRef &lhs, const StringRef &rhs) {
+#else // __APPLE__
+inline constexpr bool operator<(const StringRef &lhs,
+ const StringRef &rhs) noexcept {
return std::lexicographical_compare(std::begin(lhs), std::end(lhs),
std::begin(rhs), std::end(rhs));
}
+#endif // __APPLE__
inline std::ostream &operator<<(std::ostream &o, const StringRef &s) {
- return o.write(s.c_str(), s.size());
+ return o.write(s.data(), s.size());
}
inline std::string &operator+=(std::string &lhs, const StringRef &rhs) {
- lhs.append(rhs.c_str(), rhs.size());
+ lhs.append(rhs.data(), rhs.size());
return lhs;
}
+constexpr StringRef operator""_sr(const char *str, size_t len) noexcept {
+ return {str, len};
+}
+
+template <typename T, std::size_t N>
+[[nodiscard]] std::span<const uint8_t, N == std::dynamic_extent
+ ? std::dynamic_extent
+ : N * sizeof(T)>
+as_uint8_span(std::span<T, N> s) noexcept {
+ return std::span < const uint8_t,
+ N == std::dynamic_extent
+ ? std::dynamic_extent
+ : N * sizeof(T) > {reinterpret_cast<const uint8_t *>(s.data()),
+ s.size_bytes()};
+}
+
inline int run_app(std::function<int(int, char **)> app, int argc,
char **argv) {
try {