Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/one-of.h @ 49:3ab5a40c4e3b
Add Capnp and KJ builds for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 14:48:23 +0100 |
parents | |
children | 0994c39f1e94 |
comparison
equal
deleted
inserted
replaced
48:9530b331f8c1 | 49:3ab5a40c4e3b |
---|---|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors | |
2 // Licensed under the MIT License: | |
3 // | |
4 // Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 // of this software and associated documentation files (the "Software"), to deal | |
6 // in the Software without restriction, including without limitation the rights | |
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 // copies of the Software, and to permit persons to whom the Software is | |
9 // furnished to do so, subject to the following conditions: | |
10 // | |
11 // The above copyright notice and this permission notice shall be included in | |
12 // all copies or substantial portions of the Software. | |
13 // | |
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 // THE SOFTWARE. | |
21 | |
22 #ifndef KJ_ONE_OF_H_ | |
23 #define KJ_ONE_OF_H_ | |
24 | |
25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS | |
26 #pragma GCC system_header | |
27 #endif | |
28 | |
29 #include "common.h" | |
30 | |
31 namespace kj { | |
32 | |
33 namespace _ { // private | |
34 | |
35 template <uint i, typename Key, typename First, typename... Rest> | |
36 struct TypeIndex_ { static constexpr uint value = TypeIndex_<i + 1, Key, Rest...>::value; }; | |
37 template <uint i, typename Key, typename... Rest> | |
38 struct TypeIndex_<i, Key, Key, Rest...> { static constexpr uint value = i; }; | |
39 | |
40 } // namespace _ (private) | |
41 | |
42 template <typename... Variants> | |
43 class OneOf { | |
44 template <typename Key> | |
45 static inline constexpr uint typeIndex() { return _::TypeIndex_<1, Key, Variants...>::value; } | |
46 // Get the 1-based index of Key within the type list Types. | |
47 | |
48 public: | |
49 inline OneOf(): tag(0) {} | |
50 OneOf(const OneOf& other) { copyFrom(other); } | |
51 OneOf(OneOf&& other) { moveFrom(other); } | |
52 ~OneOf() { destroy(); } | |
53 | |
54 OneOf& operator=(const OneOf& other) { if (tag != 0) destroy(); copyFrom(other); return *this; } | |
55 OneOf& operator=(OneOf&& other) { if (tag != 0) destroy(); moveFrom(other); return *this; } | |
56 | |
57 inline bool operator==(decltype(nullptr)) const { return tag == 0; } | |
58 inline bool operator!=(decltype(nullptr)) const { return tag != 0; } | |
59 | |
60 template <typename T> | |
61 bool is() const { | |
62 return tag == typeIndex<T>(); | |
63 } | |
64 | |
65 template <typename T> | |
66 T& get() { | |
67 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>()."); | |
68 return *reinterpret_cast<T*>(space); | |
69 } | |
70 template <typename T> | |
71 const T& get() const { | |
72 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>()."); | |
73 return *reinterpret_cast<const T*>(space); | |
74 } | |
75 | |
76 template <typename T, typename... Params> | |
77 void init(Params&&... params) { | |
78 if (tag != 0) destroy(); | |
79 ctor(*reinterpret_cast<T*>(space), kj::fwd<Params>(params)...); | |
80 tag = typeIndex<T>(); | |
81 } | |
82 | |
83 private: | |
84 uint tag; | |
85 | |
86 static inline constexpr size_t maxSize(size_t a) { | |
87 return a; | |
88 } | |
89 template <typename... Rest> | |
90 static inline constexpr size_t maxSize(size_t a, size_t b, Rest... rest) { | |
91 return maxSize(kj::max(a, b), rest...); | |
92 } | |
93 // Returns the maximum of all the parameters. | |
94 // TODO(someday): Generalize the above template and make it common. I tried, but C++ decided to | |
95 // be difficult so I cut my losses. | |
96 | |
97 union { | |
98 byte space[maxSize(sizeof(Variants)...)]; | |
99 | |
100 void* forceAligned; | |
101 // TODO(someday): Use C++11 alignas() once we require GCC 4.8 / Clang 3.3. | |
102 }; | |
103 | |
104 template <typename... T> | |
105 inline void doAll(T... t) {} | |
106 | |
107 template <typename T> | |
108 inline bool destroyVariant() { | |
109 if (tag == typeIndex<T>()) { | |
110 tag = 0; | |
111 dtor(*reinterpret_cast<T*>(space)); | |
112 } | |
113 return false; | |
114 } | |
115 void destroy() { | |
116 doAll(destroyVariant<Variants>()...); | |
117 } | |
118 | |
119 template <typename T> | |
120 inline bool copyVariantFrom(const OneOf& other) { | |
121 if (other.is<T>()) { | |
122 ctor(*reinterpret_cast<T*>(space), other.get<T>()); | |
123 } | |
124 return false; | |
125 } | |
126 void copyFrom(const OneOf& other) { | |
127 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag | |
128 // is invalid. | |
129 tag = other.tag; | |
130 doAll(copyVariantFrom<Variants>(other)...); | |
131 } | |
132 | |
133 template <typename T> | |
134 inline bool moveVariantFrom(OneOf& other) { | |
135 if (other.is<T>()) { | |
136 ctor(*reinterpret_cast<T*>(space), kj::mv(other.get<T>())); | |
137 } | |
138 return false; | |
139 } | |
140 void moveFrom(OneOf& other) { | |
141 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag | |
142 // is invalid. | |
143 tag = other.tag; | |
144 doAll(moveVariantFrom<Variants>(other)...); | |
145 } | |
146 }; | |
147 | |
148 } // namespace kj | |
149 | |
150 #endif // KJ_ONE_OF_H_ |