Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / src / template.h
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2015 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #ifndef TEMPLATE_H
26 #define TEMPLATE_H
27
28 #include "nghttp2_config.h"
29
30 #include <memory>
31 #include <array>
32 #include <functional>
33
34 namespace nghttp2 {
35
36 template <typename T, typename... U>
37 typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
38 make_unique(U &&... u) {
39   return std::unique_ptr<T>(new T(std::forward<U>(u)...));
40 }
41
42 template <typename T>
43 typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
44 make_unique(size_t size) {
45   return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
46 }
47
48 template <typename T, typename... Rest>
49 std::array<T, sizeof...(Rest)+1> make_array(T &&t, Rest &&... rest) {
50   return std::array<T, sizeof...(Rest)+1>{
51       {std::forward<T>(t), std::forward<Rest>(rest)...}};
52 }
53
54 template <typename T, size_t N> constexpr size_t array_size(T (&)[N]) {
55   return N;
56 }
57
58 template <typename T, size_t N> constexpr size_t str_size(T (&)[N]) {
59   return N - 1;
60 }
61
62 // inspired by <http://blog.korfuri.fr/post/go-defer-in-cpp/>, but our
63 // template can take functions returning other than void.
64 template <typename F, typename... T> struct Defer {
65   Defer(F &&f, T &&... t)
66       : f(std::bind(std::forward<F>(f), std::forward<T>(t)...)) {}
67   Defer(Defer &&o) : f(std::move(o.f)) {}
68   ~Defer() { f(); }
69
70   using ResultType = typename std::result_of<
71       typename std::decay<F>::type(typename std::decay<T>::type...)>::type;
72   std::function<ResultType()> f;
73 };
74
75 template <typename F, typename... T> Defer<F, T...> defer(F &&f, T &&... t) {
76   return Defer<F, T...>(std::forward<F>(f), std::forward<T>(t)...);
77 }
78
79 template <typename T, typename F> bool test_flags(T t, F flags) {
80   return (t & flags) == flags;
81 }
82
83 // doubly linked list of element T*.  T must have field T *dlprev and
84 // T *dlnext, which point to previous element and next element in the
85 // list respectively.
86 template <typename T> struct DList {
87   DList() : head(nullptr), tail(nullptr) {}
88
89   DList(const DList &) = delete;
90
91   DList &operator=(const DList &) = delete;
92
93   DList(DList &&other) : head(other.head), tail(other.tail) {
94     other.head = other.tail = nullptr;
95   }
96
97   DList &operator=(DList &&other) {
98     if (this == &other) {
99       return *this;
100     }
101     head = other.head;
102     tail = other.tail;
103     other.head = other.tail = nullptr;
104     return *this;
105   }
106
107   void append(T *t) {
108     if (tail) {
109       tail->dlnext = t;
110       t->dlprev = tail;
111       tail = t;
112       return;
113     }
114     head = tail = t;
115   }
116
117   void remove(T *t) {
118     auto p = t->dlprev;
119     auto n = t->dlnext;
120     if (p) {
121       p->dlnext = n;
122     }
123     if (head == t) {
124       head = n;
125     }
126     if (n) {
127       n->dlprev = p;
128     }
129     if (tail == t) {
130       tail = p;
131     }
132     t->dlprev = t->dlnext = nullptr;
133   }
134
135   bool empty() const { return head == nullptr; }
136
137   T *head, *tail;
138 };
139
140 template <typename T> void dlist_delete_all(DList<T> &dl) {
141   for (auto e = dl.head; e;) {
142     auto next = e->dlnext;
143     delete e;
144     e = next;
145   }
146 }
147
148 } // namespace nghttp2
149
150 #endif // TEMPLATE_H