diff options
Diffstat (limited to '')
-rw-r--r-- | src/template.h | 267 |
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 { |