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