12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2015 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#ifndef TEMPLATE_H 262c593315Sopenharmony_ci#define TEMPLATE_H 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci#include "nghttp2_config.h" 292c593315Sopenharmony_ci 302c593315Sopenharmony_ci#include <cstring> 312c593315Sopenharmony_ci#include <cstdio> 322c593315Sopenharmony_ci#include <cstdlib> 332c593315Sopenharmony_ci#include <memory> 342c593315Sopenharmony_ci#include <array> 352c593315Sopenharmony_ci#include <functional> 362c593315Sopenharmony_ci#include <typeinfo> 372c593315Sopenharmony_ci#include <algorithm> 382c593315Sopenharmony_ci#include <ostream> 392c593315Sopenharmony_ci#include <utility> 402c593315Sopenharmony_ci 412c593315Sopenharmony_cinamespace nghttp2 { 422c593315Sopenharmony_ci 432c593315Sopenharmony_ci// std::forward is constexpr since C++14 442c593315Sopenharmony_citemplate <typename... T> 452c593315Sopenharmony_ciconstexpr std::array< 462c593315Sopenharmony_ci typename std::decay<typename std::common_type<T...>::type>::type, 472c593315Sopenharmony_ci sizeof...(T)> 482c593315Sopenharmony_cimake_array(T &&...t) { 492c593315Sopenharmony_ci return std::array< 502c593315Sopenharmony_ci typename std::decay<typename std::common_type<T...>::type>::type, 512c593315Sopenharmony_ci sizeof...(T)>{{std::forward<T>(t)...}}; 522c593315Sopenharmony_ci} 532c593315Sopenharmony_ci 542c593315Sopenharmony_citemplate <typename T, size_t N> constexpr size_t array_size(T (&)[N]) { 552c593315Sopenharmony_ci return N; 562c593315Sopenharmony_ci} 572c593315Sopenharmony_ci 582c593315Sopenharmony_citemplate <typename T, size_t N> constexpr size_t str_size(T (&)[N]) { 592c593315Sopenharmony_ci return N - 1; 602c593315Sopenharmony_ci} 612c593315Sopenharmony_ci 622c593315Sopenharmony_ci// inspired by <http://blog.korfuri.fr/post/go-defer-in-cpp/>, but our 632c593315Sopenharmony_ci// template can take functions returning other than void. 642c593315Sopenharmony_citemplate <typename F, typename... T> struct Defer { 652c593315Sopenharmony_ci Defer(F &&f, T &&...t) 662c593315Sopenharmony_ci : f(std::bind(std::forward<F>(f), std::forward<T>(t)...)) {} 672c593315Sopenharmony_ci Defer(Defer &&o) noexcept : f(std::move(o.f)) {} 682c593315Sopenharmony_ci ~Defer() { f(); } 692c593315Sopenharmony_ci 702c593315Sopenharmony_ci using ResultType = typename std::result_of<typename std::decay<F>::type( 712c593315Sopenharmony_ci typename std::decay<T>::type...)>::type; 722c593315Sopenharmony_ci std::function<ResultType()> f; 732c593315Sopenharmony_ci}; 742c593315Sopenharmony_ci 752c593315Sopenharmony_citemplate <typename F, typename... T> Defer<F, T...> defer(F &&f, T &&...t) { 762c593315Sopenharmony_ci return Defer<F, T...>(std::forward<F>(f), std::forward<T>(t)...); 772c593315Sopenharmony_ci} 782c593315Sopenharmony_ci 792c593315Sopenharmony_citemplate <typename T, typename F> bool test_flags(T t, F flags) { 802c593315Sopenharmony_ci return (t & flags) == flags; 812c593315Sopenharmony_ci} 822c593315Sopenharmony_ci 832c593315Sopenharmony_ci// doubly linked list of element T*. T must have field T *dlprev and 842c593315Sopenharmony_ci// T *dlnext, which point to previous element and next element in the 852c593315Sopenharmony_ci// list respectively. 862c593315Sopenharmony_citemplate <typename T> struct DList { 872c593315Sopenharmony_ci DList() : head(nullptr), tail(nullptr), len(0) {} 882c593315Sopenharmony_ci 892c593315Sopenharmony_ci DList(const DList &) = delete; 902c593315Sopenharmony_ci DList &operator=(const DList &) = delete; 912c593315Sopenharmony_ci 922c593315Sopenharmony_ci DList(DList &&other) noexcept 932c593315Sopenharmony_ci : head{std::exchange(other.head, nullptr)}, 942c593315Sopenharmony_ci tail{std::exchange(other.tail, nullptr)}, 952c593315Sopenharmony_ci len{std::exchange(other.len, 0)} {} 962c593315Sopenharmony_ci 972c593315Sopenharmony_ci DList &operator=(DList &&other) noexcept { 982c593315Sopenharmony_ci if (this == &other) { 992c593315Sopenharmony_ci return *this; 1002c593315Sopenharmony_ci } 1012c593315Sopenharmony_ci head = std::exchange(other.head, nullptr); 1022c593315Sopenharmony_ci tail = std::exchange(other.tail, nullptr); 1032c593315Sopenharmony_ci len = std::exchange(other.len, 0); 1042c593315Sopenharmony_ci 1052c593315Sopenharmony_ci return *this; 1062c593315Sopenharmony_ci } 1072c593315Sopenharmony_ci 1082c593315Sopenharmony_ci void append(T *t) { 1092c593315Sopenharmony_ci ++len; 1102c593315Sopenharmony_ci if (tail) { 1112c593315Sopenharmony_ci tail->dlnext = t; 1122c593315Sopenharmony_ci t->dlprev = tail; 1132c593315Sopenharmony_ci tail = t; 1142c593315Sopenharmony_ci return; 1152c593315Sopenharmony_ci } 1162c593315Sopenharmony_ci head = tail = t; 1172c593315Sopenharmony_ci } 1182c593315Sopenharmony_ci 1192c593315Sopenharmony_ci void remove(T *t) { 1202c593315Sopenharmony_ci --len; 1212c593315Sopenharmony_ci auto p = t->dlprev; 1222c593315Sopenharmony_ci auto n = t->dlnext; 1232c593315Sopenharmony_ci if (p) { 1242c593315Sopenharmony_ci p->dlnext = n; 1252c593315Sopenharmony_ci } 1262c593315Sopenharmony_ci if (head == t) { 1272c593315Sopenharmony_ci head = n; 1282c593315Sopenharmony_ci } 1292c593315Sopenharmony_ci if (n) { 1302c593315Sopenharmony_ci n->dlprev = p; 1312c593315Sopenharmony_ci } 1322c593315Sopenharmony_ci if (tail == t) { 1332c593315Sopenharmony_ci tail = p; 1342c593315Sopenharmony_ci } 1352c593315Sopenharmony_ci t->dlprev = t->dlnext = nullptr; 1362c593315Sopenharmony_ci } 1372c593315Sopenharmony_ci 1382c593315Sopenharmony_ci bool empty() const { return head == nullptr; } 1392c593315Sopenharmony_ci 1402c593315Sopenharmony_ci size_t size() const { return len; } 1412c593315Sopenharmony_ci 1422c593315Sopenharmony_ci T *head, *tail; 1432c593315Sopenharmony_ci size_t len; 1442c593315Sopenharmony_ci}; 1452c593315Sopenharmony_ci 1462c593315Sopenharmony_citemplate <typename T> void dlist_delete_all(DList<T> &dl) { 1472c593315Sopenharmony_ci for (auto e = dl.head; e;) { 1482c593315Sopenharmony_ci auto next = e->dlnext; 1492c593315Sopenharmony_ci delete e; 1502c593315Sopenharmony_ci e = next; 1512c593315Sopenharmony_ci } 1522c593315Sopenharmony_ci} 1532c593315Sopenharmony_ci 1542c593315Sopenharmony_ci// User-defined literals for K, M, and G (powers of 1024) 1552c593315Sopenharmony_ci 1562c593315Sopenharmony_ciconstexpr unsigned long long operator"" _k(unsigned long long k) { 1572c593315Sopenharmony_ci return k * 1024; 1582c593315Sopenharmony_ci} 1592c593315Sopenharmony_ci 1602c593315Sopenharmony_ciconstexpr unsigned long long operator"" _m(unsigned long long m) { 1612c593315Sopenharmony_ci return m * 1024 * 1024; 1622c593315Sopenharmony_ci} 1632c593315Sopenharmony_ci 1642c593315Sopenharmony_ciconstexpr unsigned long long operator"" _g(unsigned long long g) { 1652c593315Sopenharmony_ci return g * 1024 * 1024 * 1024; 1662c593315Sopenharmony_ci} 1672c593315Sopenharmony_ci 1682c593315Sopenharmony_ci// User-defined literals for time, converted into double in seconds 1692c593315Sopenharmony_ci 1702c593315Sopenharmony_ci// hours 1712c593315Sopenharmony_ciconstexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; } 1722c593315Sopenharmony_ci 1732c593315Sopenharmony_ci// minutes 1742c593315Sopenharmony_ciconstexpr double operator"" _min(unsigned long long min) { return min * 60; } 1752c593315Sopenharmony_ci 1762c593315Sopenharmony_ci// seconds 1772c593315Sopenharmony_ciconstexpr double operator"" _s(unsigned long long s) { return s; } 1782c593315Sopenharmony_ci 1792c593315Sopenharmony_ci// milliseconds 1802c593315Sopenharmony_ciconstexpr double operator"" _ms(unsigned long long ms) { return ms / 1000.; } 1812c593315Sopenharmony_ci 1822c593315Sopenharmony_ci// Returns a copy of NULL-terminated string [first, last). 1832c593315Sopenharmony_citemplate <typename InputIt> 1842c593315Sopenharmony_cistd::unique_ptr<char[]> strcopy(InputIt first, InputIt last) { 1852c593315Sopenharmony_ci auto res = std::make_unique<char[]>(last - first + 1); 1862c593315Sopenharmony_ci *std::copy(first, last, res.get()) = '\0'; 1872c593315Sopenharmony_ci return res; 1882c593315Sopenharmony_ci} 1892c593315Sopenharmony_ci 1902c593315Sopenharmony_ci// Returns a copy of NULL-terminated string |val|. 1912c593315Sopenharmony_ciinline std::unique_ptr<char[]> strcopy(const char *val) { 1922c593315Sopenharmony_ci return strcopy(val, val + strlen(val)); 1932c593315Sopenharmony_ci} 1942c593315Sopenharmony_ci 1952c593315Sopenharmony_ciinline std::unique_ptr<char[]> strcopy(const char *val, size_t n) { 1962c593315Sopenharmony_ci return strcopy(val, val + n); 1972c593315Sopenharmony_ci} 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_ci// Returns a copy of val.c_str(). 2002c593315Sopenharmony_ciinline std::unique_ptr<char[]> strcopy(const std::string &val) { 2012c593315Sopenharmony_ci return strcopy(std::begin(val), std::end(val)); 2022c593315Sopenharmony_ci} 2032c593315Sopenharmony_ci 2042c593315Sopenharmony_ciinline std::unique_ptr<char[]> strcopy(const std::unique_ptr<char[]> &val) { 2052c593315Sopenharmony_ci if (!val) { 2062c593315Sopenharmony_ci return nullptr; 2072c593315Sopenharmony_ci } 2082c593315Sopenharmony_ci return strcopy(val.get()); 2092c593315Sopenharmony_ci} 2102c593315Sopenharmony_ci 2112c593315Sopenharmony_ciinline std::unique_ptr<char[]> strcopy(const std::unique_ptr<char[]> &val, 2122c593315Sopenharmony_ci size_t n) { 2132c593315Sopenharmony_ci if (!val) { 2142c593315Sopenharmony_ci return nullptr; 2152c593315Sopenharmony_ci } 2162c593315Sopenharmony_ci return strcopy(val.get(), val.get() + n); 2172c593315Sopenharmony_ci} 2182c593315Sopenharmony_ci 2192c593315Sopenharmony_ci// ImmutableString represents string that is immutable unlike 2202c593315Sopenharmony_ci// std::string. It has c_str() and size() functions to mimic 2212c593315Sopenharmony_ci// std::string. It manages buffer by itself. Just like std::string, 2222c593315Sopenharmony_ci// c_str() returns NULL-terminated string, but NULL character may 2232c593315Sopenharmony_ci// appear before the final terminal NULL. 2242c593315Sopenharmony_ciclass ImmutableString { 2252c593315Sopenharmony_cipublic: 2262c593315Sopenharmony_ci using traits_type = std::char_traits<char>; 2272c593315Sopenharmony_ci using value_type = traits_type::char_type; 2282c593315Sopenharmony_ci using allocator_type = std::allocator<char>; 2292c593315Sopenharmony_ci using size_type = std::allocator_traits<allocator_type>::size_type; 2302c593315Sopenharmony_ci using difference_type = 2312c593315Sopenharmony_ci std::allocator_traits<allocator_type>::difference_type; 2322c593315Sopenharmony_ci using const_reference = const value_type &; 2332c593315Sopenharmony_ci using const_pointer = const value_type *; 2342c593315Sopenharmony_ci using const_iterator = const_pointer; 2352c593315Sopenharmony_ci using const_reverse_iterator = std::reverse_iterator<const_iterator>; 2362c593315Sopenharmony_ci 2372c593315Sopenharmony_ci ImmutableString() : len(0), base("") {} 2382c593315Sopenharmony_ci ImmutableString(const char *s, size_t slen) 2392c593315Sopenharmony_ci : len(slen), base(copystr(s, s + len)) {} 2402c593315Sopenharmony_ci explicit ImmutableString(const char *s) 2412c593315Sopenharmony_ci : len(strlen(s)), base(copystr(s, s + len)) {} 2422c593315Sopenharmony_ci explicit ImmutableString(const std::string &s) 2432c593315Sopenharmony_ci : len(s.size()), base(copystr(std::begin(s), std::end(s))) {} 2442c593315Sopenharmony_ci template <typename InputIt> 2452c593315Sopenharmony_ci ImmutableString(InputIt first, InputIt last) 2462c593315Sopenharmony_ci : len(std::distance(first, last)), base(copystr(first, last)) {} 2472c593315Sopenharmony_ci ImmutableString(const ImmutableString &other) 2482c593315Sopenharmony_ci : len(other.len), base(copystr(std::begin(other), std::end(other))) {} 2492c593315Sopenharmony_ci ImmutableString(ImmutableString &&other) noexcept 2502c593315Sopenharmony_ci : len{std::exchange(other.len, 0)}, base{std::exchange(other.base, "")} {} 2512c593315Sopenharmony_ci ~ImmutableString() { 2522c593315Sopenharmony_ci if (len) { 2532c593315Sopenharmony_ci delete[] base; 2542c593315Sopenharmony_ci } 2552c593315Sopenharmony_ci } 2562c593315Sopenharmony_ci 2572c593315Sopenharmony_ci ImmutableString &operator=(const ImmutableString &other) { 2582c593315Sopenharmony_ci if (this == &other) { 2592c593315Sopenharmony_ci return *this; 2602c593315Sopenharmony_ci } 2612c593315Sopenharmony_ci if (len) { 2622c593315Sopenharmony_ci delete[] base; 2632c593315Sopenharmony_ci } 2642c593315Sopenharmony_ci len = other.len; 2652c593315Sopenharmony_ci base = copystr(std::begin(other), std::end(other)); 2662c593315Sopenharmony_ci return *this; 2672c593315Sopenharmony_ci } 2682c593315Sopenharmony_ci ImmutableString &operator=(ImmutableString &&other) noexcept { 2692c593315Sopenharmony_ci if (this == &other) { 2702c593315Sopenharmony_ci return *this; 2712c593315Sopenharmony_ci } 2722c593315Sopenharmony_ci if (len) { 2732c593315Sopenharmony_ci delete[] base; 2742c593315Sopenharmony_ci } 2752c593315Sopenharmony_ci len = std::exchange(other.len, 0); 2762c593315Sopenharmony_ci base = std::exchange(other.base, ""); 2772c593315Sopenharmony_ci return *this; 2782c593315Sopenharmony_ci } 2792c593315Sopenharmony_ci 2802c593315Sopenharmony_ci template <size_t N> static ImmutableString from_lit(const char (&s)[N]) { 2812c593315Sopenharmony_ci return ImmutableString(s, N - 1); 2822c593315Sopenharmony_ci } 2832c593315Sopenharmony_ci 2842c593315Sopenharmony_ci const_iterator begin() const { return base; }; 2852c593315Sopenharmony_ci const_iterator cbegin() const { return base; }; 2862c593315Sopenharmony_ci 2872c593315Sopenharmony_ci const_iterator end() const { return base + len; }; 2882c593315Sopenharmony_ci const_iterator cend() const { return base + len; }; 2892c593315Sopenharmony_ci 2902c593315Sopenharmony_ci const_reverse_iterator rbegin() const { 2912c593315Sopenharmony_ci return const_reverse_iterator{base + len}; 2922c593315Sopenharmony_ci } 2932c593315Sopenharmony_ci const_reverse_iterator crbegin() const { 2942c593315Sopenharmony_ci return const_reverse_iterator{base + len}; 2952c593315Sopenharmony_ci } 2962c593315Sopenharmony_ci 2972c593315Sopenharmony_ci const_reverse_iterator rend() const { return const_reverse_iterator{base}; } 2982c593315Sopenharmony_ci const_reverse_iterator crend() const { return const_reverse_iterator{base}; } 2992c593315Sopenharmony_ci 3002c593315Sopenharmony_ci const char *c_str() const { return base; } 3012c593315Sopenharmony_ci size_type size() const { return len; } 3022c593315Sopenharmony_ci bool empty() const { return len == 0; } 3032c593315Sopenharmony_ci const_reference operator[](size_type pos) const { return *(base + pos); } 3042c593315Sopenharmony_ci 3052c593315Sopenharmony_ciprivate: 3062c593315Sopenharmony_ci template <typename InputIt> const char *copystr(InputIt first, InputIt last) { 3072c593315Sopenharmony_ci if (first == last) { 3082c593315Sopenharmony_ci return ""; 3092c593315Sopenharmony_ci } 3102c593315Sopenharmony_ci auto res = new char[std::distance(first, last) + 1]; 3112c593315Sopenharmony_ci *std::copy(first, last, res) = '\0'; 3122c593315Sopenharmony_ci return res; 3132c593315Sopenharmony_ci } 3142c593315Sopenharmony_ci 3152c593315Sopenharmony_ci size_type len; 3162c593315Sopenharmony_ci const char *base; 3172c593315Sopenharmony_ci}; 3182c593315Sopenharmony_ci 3192c593315Sopenharmony_ciinline bool operator==(const ImmutableString &lhs, const ImmutableString &rhs) { 3202c593315Sopenharmony_ci return lhs.size() == rhs.size() && 3212c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); 3222c593315Sopenharmony_ci} 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_ciinline bool operator==(const ImmutableString &lhs, const std::string &rhs) { 3252c593315Sopenharmony_ci return lhs.size() == rhs.size() && 3262c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); 3272c593315Sopenharmony_ci} 3282c593315Sopenharmony_ci 3292c593315Sopenharmony_ciinline bool operator==(const std::string &lhs, const ImmutableString &rhs) { 3302c593315Sopenharmony_ci return rhs == lhs; 3312c593315Sopenharmony_ci} 3322c593315Sopenharmony_ci 3332c593315Sopenharmony_ciinline bool operator==(const ImmutableString &lhs, const char *rhs) { 3342c593315Sopenharmony_ci return lhs.size() == strlen(rhs) && 3352c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), rhs); 3362c593315Sopenharmony_ci} 3372c593315Sopenharmony_ci 3382c593315Sopenharmony_ciinline bool operator==(const char *lhs, const ImmutableString &rhs) { 3392c593315Sopenharmony_ci return rhs == lhs; 3402c593315Sopenharmony_ci} 3412c593315Sopenharmony_ci 3422c593315Sopenharmony_ciinline bool operator!=(const ImmutableString &lhs, const ImmutableString &rhs) { 3432c593315Sopenharmony_ci return !(lhs == rhs); 3442c593315Sopenharmony_ci} 3452c593315Sopenharmony_ci 3462c593315Sopenharmony_ciinline bool operator!=(const ImmutableString &lhs, const std::string &rhs) { 3472c593315Sopenharmony_ci return !(lhs == rhs); 3482c593315Sopenharmony_ci} 3492c593315Sopenharmony_ci 3502c593315Sopenharmony_ciinline bool operator!=(const std::string &lhs, const ImmutableString &rhs) { 3512c593315Sopenharmony_ci return !(rhs == lhs); 3522c593315Sopenharmony_ci} 3532c593315Sopenharmony_ci 3542c593315Sopenharmony_ciinline bool operator!=(const ImmutableString &lhs, const char *rhs) { 3552c593315Sopenharmony_ci return !(lhs == rhs); 3562c593315Sopenharmony_ci} 3572c593315Sopenharmony_ci 3582c593315Sopenharmony_ciinline bool operator!=(const char *lhs, const ImmutableString &rhs) { 3592c593315Sopenharmony_ci return !(rhs == lhs); 3602c593315Sopenharmony_ci} 3612c593315Sopenharmony_ci 3622c593315Sopenharmony_ciinline std::ostream &operator<<(std::ostream &o, const ImmutableString &s) { 3632c593315Sopenharmony_ci return o.write(s.c_str(), s.size()); 3642c593315Sopenharmony_ci} 3652c593315Sopenharmony_ci 3662c593315Sopenharmony_ciinline std::string &operator+=(std::string &lhs, const ImmutableString &rhs) { 3672c593315Sopenharmony_ci lhs.append(rhs.c_str(), rhs.size()); 3682c593315Sopenharmony_ci return lhs; 3692c593315Sopenharmony_ci} 3702c593315Sopenharmony_ci 3712c593315Sopenharmony_ci// StringRef is a reference to a string owned by something else. So 3722c593315Sopenharmony_ci// it behaves like simple string, but it does not own pointer. When 3732c593315Sopenharmony_ci// it is default constructed, it has empty string. You can freely 3742c593315Sopenharmony_ci// copy or move around this struct, but never free its pointer. str() 3752c593315Sopenharmony_ci// function can be used to export the content as std::string. 3762c593315Sopenharmony_ciclass StringRef { 3772c593315Sopenharmony_cipublic: 3782c593315Sopenharmony_ci using traits_type = std::char_traits<char>; 3792c593315Sopenharmony_ci using value_type = traits_type::char_type; 3802c593315Sopenharmony_ci using allocator_type = std::allocator<char>; 3812c593315Sopenharmony_ci using size_type = std::allocator_traits<allocator_type>::size_type; 3822c593315Sopenharmony_ci using difference_type = 3832c593315Sopenharmony_ci std::allocator_traits<allocator_type>::difference_type; 3842c593315Sopenharmony_ci using const_reference = const value_type &; 3852c593315Sopenharmony_ci using const_pointer = const value_type *; 3862c593315Sopenharmony_ci using const_iterator = const_pointer; 3872c593315Sopenharmony_ci using const_reverse_iterator = std::reverse_iterator<const_iterator>; 3882c593315Sopenharmony_ci 3892c593315Sopenharmony_ci constexpr StringRef() : base(""), len(0) {} 3902c593315Sopenharmony_ci explicit StringRef(const std::string &s) : base(s.c_str()), len(s.size()) {} 3912c593315Sopenharmony_ci explicit StringRef(const ImmutableString &s) 3922c593315Sopenharmony_ci : base(s.c_str()), len(s.size()) {} 3932c593315Sopenharmony_ci explicit StringRef(const char *s) : base(s), len(strlen(s)) {} 3942c593315Sopenharmony_ci constexpr StringRef(const char *s, size_t n) : base(s), len(n) {} 3952c593315Sopenharmony_ci template <typename CharT> 3962c593315Sopenharmony_ci constexpr StringRef(const CharT *s, size_t n) 3972c593315Sopenharmony_ci : base(reinterpret_cast<const char *>(s)), len(n) {} 3982c593315Sopenharmony_ci template <typename InputIt> 3992c593315Sopenharmony_ci StringRef(InputIt first, InputIt last) 4002c593315Sopenharmony_ci : base(reinterpret_cast<const char *>(&*first)), 4012c593315Sopenharmony_ci len(std::distance(first, last)) {} 4022c593315Sopenharmony_ci template <typename InputIt> 4032c593315Sopenharmony_ci StringRef(InputIt *first, InputIt *last) 4042c593315Sopenharmony_ci : base(reinterpret_cast<const char *>(first)), 4052c593315Sopenharmony_ci len(std::distance(first, last)) {} 4062c593315Sopenharmony_ci template <typename CharT, size_t N> 4072c593315Sopenharmony_ci constexpr static StringRef from_lit(const CharT (&s)[N]) { 4082c593315Sopenharmony_ci return StringRef{s, N - 1}; 4092c593315Sopenharmony_ci } 4102c593315Sopenharmony_ci static StringRef from_maybe_nullptr(const char *s) { 4112c593315Sopenharmony_ci if (s == nullptr) { 4122c593315Sopenharmony_ci return StringRef(); 4132c593315Sopenharmony_ci } 4142c593315Sopenharmony_ci 4152c593315Sopenharmony_ci return StringRef(s); 4162c593315Sopenharmony_ci } 4172c593315Sopenharmony_ci 4182c593315Sopenharmony_ci constexpr const_iterator begin() const { return base; }; 4192c593315Sopenharmony_ci constexpr const_iterator cbegin() const { return base; }; 4202c593315Sopenharmony_ci 4212c593315Sopenharmony_ci constexpr const_iterator end() const { return base + len; }; 4222c593315Sopenharmony_ci constexpr const_iterator cend() const { return base + len; }; 4232c593315Sopenharmony_ci 4242c593315Sopenharmony_ci const_reverse_iterator rbegin() const { 4252c593315Sopenharmony_ci return const_reverse_iterator{base + len}; 4262c593315Sopenharmony_ci } 4272c593315Sopenharmony_ci const_reverse_iterator crbegin() const { 4282c593315Sopenharmony_ci return const_reverse_iterator{base + len}; 4292c593315Sopenharmony_ci } 4302c593315Sopenharmony_ci 4312c593315Sopenharmony_ci const_reverse_iterator rend() const { return const_reverse_iterator{base}; } 4322c593315Sopenharmony_ci const_reverse_iterator crend() const { return const_reverse_iterator{base}; } 4332c593315Sopenharmony_ci 4342c593315Sopenharmony_ci constexpr const char *c_str() const { return base; } 4352c593315Sopenharmony_ci constexpr size_type size() const { return len; } 4362c593315Sopenharmony_ci constexpr bool empty() const { return len == 0; } 4372c593315Sopenharmony_ci constexpr const_reference operator[](size_type pos) const { 4382c593315Sopenharmony_ci return *(base + pos); 4392c593315Sopenharmony_ci } 4402c593315Sopenharmony_ci 4412c593315Sopenharmony_ci std::string str() const { return std::string(base, len); } 4422c593315Sopenharmony_ci const uint8_t *byte() const { 4432c593315Sopenharmony_ci return reinterpret_cast<const uint8_t *>(base); 4442c593315Sopenharmony_ci } 4452c593315Sopenharmony_ci 4462c593315Sopenharmony_ciprivate: 4472c593315Sopenharmony_ci const char *base; 4482c593315Sopenharmony_ci size_type len; 4492c593315Sopenharmony_ci}; 4502c593315Sopenharmony_ci 4512c593315Sopenharmony_ciinline bool operator==(const StringRef &lhs, const StringRef &rhs) { 4522c593315Sopenharmony_ci return lhs.size() == rhs.size() && 4532c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); 4542c593315Sopenharmony_ci} 4552c593315Sopenharmony_ci 4562c593315Sopenharmony_ciinline bool operator==(const StringRef &lhs, const std::string &rhs) { 4572c593315Sopenharmony_ci return lhs.size() == rhs.size() && 4582c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); 4592c593315Sopenharmony_ci} 4602c593315Sopenharmony_ci 4612c593315Sopenharmony_ciinline bool operator==(const std::string &lhs, const StringRef &rhs) { 4622c593315Sopenharmony_ci return rhs == lhs; 4632c593315Sopenharmony_ci} 4642c593315Sopenharmony_ci 4652c593315Sopenharmony_ciinline bool operator==(const StringRef &lhs, const char *rhs) { 4662c593315Sopenharmony_ci return lhs.size() == strlen(rhs) && 4672c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), rhs); 4682c593315Sopenharmony_ci} 4692c593315Sopenharmony_ci 4702c593315Sopenharmony_ciinline bool operator==(const StringRef &lhs, const ImmutableString &rhs) { 4712c593315Sopenharmony_ci return lhs.size() == rhs.size() && 4722c593315Sopenharmony_ci std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs)); 4732c593315Sopenharmony_ci} 4742c593315Sopenharmony_ci 4752c593315Sopenharmony_ciinline bool operator==(const ImmutableString &lhs, const StringRef &rhs) { 4762c593315Sopenharmony_ci return rhs == lhs; 4772c593315Sopenharmony_ci} 4782c593315Sopenharmony_ci 4792c593315Sopenharmony_ciinline bool operator==(const char *lhs, const StringRef &rhs) { 4802c593315Sopenharmony_ci return rhs == lhs; 4812c593315Sopenharmony_ci} 4822c593315Sopenharmony_ci 4832c593315Sopenharmony_ciinline bool operator!=(const StringRef &lhs, const StringRef &rhs) { 4842c593315Sopenharmony_ci return !(lhs == rhs); 4852c593315Sopenharmony_ci} 4862c593315Sopenharmony_ci 4872c593315Sopenharmony_ciinline bool operator!=(const StringRef &lhs, const std::string &rhs) { 4882c593315Sopenharmony_ci return !(lhs == rhs); 4892c593315Sopenharmony_ci} 4902c593315Sopenharmony_ci 4912c593315Sopenharmony_ciinline bool operator!=(const std::string &lhs, const StringRef &rhs) { 4922c593315Sopenharmony_ci return !(rhs == lhs); 4932c593315Sopenharmony_ci} 4942c593315Sopenharmony_ci 4952c593315Sopenharmony_ciinline bool operator!=(const StringRef &lhs, const char *rhs) { 4962c593315Sopenharmony_ci return !(lhs == rhs); 4972c593315Sopenharmony_ci} 4982c593315Sopenharmony_ci 4992c593315Sopenharmony_ciinline bool operator!=(const char *lhs, const StringRef &rhs) { 5002c593315Sopenharmony_ci return !(rhs == lhs); 5012c593315Sopenharmony_ci} 5022c593315Sopenharmony_ci 5032c593315Sopenharmony_ciinline bool operator<(const StringRef &lhs, const StringRef &rhs) { 5042c593315Sopenharmony_ci return std::lexicographical_compare(std::begin(lhs), std::end(lhs), 5052c593315Sopenharmony_ci std::begin(rhs), std::end(rhs)); 5062c593315Sopenharmony_ci} 5072c593315Sopenharmony_ci 5082c593315Sopenharmony_ciinline std::ostream &operator<<(std::ostream &o, const StringRef &s) { 5092c593315Sopenharmony_ci return o.write(s.c_str(), s.size()); 5102c593315Sopenharmony_ci} 5112c593315Sopenharmony_ci 5122c593315Sopenharmony_ciinline std::string &operator+=(std::string &lhs, const StringRef &rhs) { 5132c593315Sopenharmony_ci lhs.append(rhs.c_str(), rhs.size()); 5142c593315Sopenharmony_ci return lhs; 5152c593315Sopenharmony_ci} 5162c593315Sopenharmony_ci 5172c593315Sopenharmony_ciinline int run_app(std::function<int(int, char **)> app, int argc, 5182c593315Sopenharmony_ci char **argv) { 5192c593315Sopenharmony_ci try { 5202c593315Sopenharmony_ci return app(argc, argv); 5212c593315Sopenharmony_ci } catch (const std::bad_alloc &) { 5222c593315Sopenharmony_ci fputs("Out of memory\n", stderr); 5232c593315Sopenharmony_ci } catch (const std::exception &x) { 5242c593315Sopenharmony_ci fprintf(stderr, "Caught %s:\n%s\n", typeid(x).name(), x.what()); 5252c593315Sopenharmony_ci } catch (...) { 5262c593315Sopenharmony_ci fputs("Unknown exception caught\n", stderr); 5272c593315Sopenharmony_ci } 5282c593315Sopenharmony_ci return EXIT_FAILURE; 5292c593315Sopenharmony_ci} 5302c593315Sopenharmony_ci 5312c593315Sopenharmony_ci} // namespace nghttp2 5322c593315Sopenharmony_ci 5332c593315Sopenharmony_cinamespace std { 5342c593315Sopenharmony_citemplate <> struct hash<nghttp2::StringRef> { 5352c593315Sopenharmony_ci std::size_t operator()(const nghttp2::StringRef &s) const noexcept { 5362c593315Sopenharmony_ci // 32 bit FNV-1a: 5372c593315Sopenharmony_ci // https://tools.ietf.org/html/draft-eastlake-fnv-16#section-6.1.1 5382c593315Sopenharmony_ci uint32_t h = 2166136261u; 5392c593315Sopenharmony_ci for (auto c : s) { 5402c593315Sopenharmony_ci h ^= static_cast<uint8_t>(c); 5412c593315Sopenharmony_ci h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24); 5422c593315Sopenharmony_ci } 5432c593315Sopenharmony_ci return h; 5442c593315Sopenharmony_ci } 5452c593315Sopenharmony_ci}; 5462c593315Sopenharmony_ci} // namespace std 5472c593315Sopenharmony_ci 5482c593315Sopenharmony_ci#endif // TEMPLATE_H 549