cannam@134
|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
cannam@134
|
2 // Licensed under the MIT License:
|
cannam@134
|
3 //
|
cannam@134
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
cannam@134
|
5 // of this software and associated documentation files (the "Software"), to deal
|
cannam@134
|
6 // in the Software without restriction, including without limitation the rights
|
cannam@134
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
cannam@134
|
8 // copies of the Software, and to permit persons to whom the Software is
|
cannam@134
|
9 // furnished to do so, subject to the following conditions:
|
cannam@134
|
10 //
|
cannam@134
|
11 // The above copyright notice and this permission notice shall be included in
|
cannam@134
|
12 // all copies or substantial portions of the Software.
|
cannam@134
|
13 //
|
cannam@134
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
cannam@134
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
cannam@134
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
cannam@134
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
cannam@134
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
cannam@134
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
cannam@134
|
20 // THE SOFTWARE.
|
cannam@134
|
21
|
cannam@134
|
22 // This file contains types which are intended to help detect incorrect usage at compile
|
cannam@134
|
23 // time, but should then be optimized down to basic primitives (usually, integers) by the
|
cannam@134
|
24 // compiler.
|
cannam@134
|
25
|
cannam@134
|
26 #ifndef CAPNP_COMMON_H_
|
cannam@134
|
27 #define CAPNP_COMMON_H_
|
cannam@134
|
28
|
cannam@134
|
29 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
|
cannam@134
|
30 #pragma GCC system_header
|
cannam@134
|
31 #endif
|
cannam@134
|
32
|
cannam@134
|
33 #include <kj/units.h>
|
cannam@134
|
34 #include <inttypes.h>
|
cannam@134
|
35 #include <kj/string.h>
|
cannam@134
|
36 #include <kj/memory.h>
|
cannam@134
|
37
|
cannam@134
|
38 namespace capnp {
|
cannam@134
|
39
|
cannam@134
|
40 #define CAPNP_VERSION_MAJOR 0
|
cannam@134
|
41 #define CAPNP_VERSION_MINOR 6
|
cannam@134
|
42 #define CAPNP_VERSION_MICRO 0
|
cannam@134
|
43
|
cannam@134
|
44 #define CAPNP_VERSION \
|
cannam@134
|
45 (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)
|
cannam@134
|
46
|
cannam@134
|
47 #ifdef _MSC_VER
|
cannam@134
|
48 #define CAPNP_LITE 1
|
cannam@134
|
49 // MSVC only supports "lite" mode for now, due to missing C++11 features.
|
cannam@134
|
50 #endif
|
cannam@134
|
51
|
cannam@134
|
52 #ifndef CAPNP_LITE
|
cannam@134
|
53 #define CAPNP_LITE 0
|
cannam@134
|
54 #endif
|
cannam@134
|
55
|
cannam@134
|
56 typedef unsigned int uint;
|
cannam@134
|
57
|
cannam@134
|
58 struct Void {
|
cannam@134
|
59 // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves
|
cannam@134
|
60 // differently from other types.
|
cannam@134
|
61
|
cannam@134
|
62 inline constexpr bool operator==(Void other) const { return true; }
|
cannam@134
|
63 inline constexpr bool operator!=(Void other) const { return false; }
|
cannam@134
|
64 };
|
cannam@134
|
65
|
cannam@134
|
66 static constexpr Void VOID = Void();
|
cannam@134
|
67 // Constant value for `Void`, which is an empty struct.
|
cannam@134
|
68
|
cannam@134
|
69 inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
|
cannam@134
|
70
|
cannam@134
|
71 struct Text;
|
cannam@134
|
72 struct Data;
|
cannam@134
|
73
|
cannam@134
|
74 enum class Kind: uint8_t {
|
cannam@134
|
75 PRIMITIVE,
|
cannam@134
|
76 BLOB,
|
cannam@134
|
77 ENUM,
|
cannam@134
|
78 STRUCT,
|
cannam@134
|
79 UNION,
|
cannam@134
|
80 INTERFACE,
|
cannam@134
|
81 LIST,
|
cannam@134
|
82
|
cannam@134
|
83 OTHER
|
cannam@134
|
84 // Some other type which is often a type parameter to Cap'n Proto templates, but which needs
|
cannam@134
|
85 // special handling. This includes types like AnyPointer, Dynamic*, etc.
|
cannam@134
|
86 };
|
cannam@134
|
87
|
cannam@134
|
88 enum class Style: uint8_t {
|
cannam@134
|
89 PRIMITIVE,
|
cannam@134
|
90 POINTER, // other than struct
|
cannam@134
|
91 STRUCT,
|
cannam@134
|
92 CAPABILITY
|
cannam@134
|
93 };
|
cannam@134
|
94
|
cannam@134
|
95 enum class ElementSize: uint8_t {
|
cannam@134
|
96 // Size of a list element.
|
cannam@134
|
97
|
cannam@134
|
98 VOID = 0,
|
cannam@134
|
99 BIT = 1,
|
cannam@134
|
100 BYTE = 2,
|
cannam@134
|
101 TWO_BYTES = 3,
|
cannam@134
|
102 FOUR_BYTES = 4,
|
cannam@134
|
103 EIGHT_BYTES = 5,
|
cannam@134
|
104
|
cannam@134
|
105 POINTER = 6,
|
cannam@134
|
106
|
cannam@134
|
107 INLINE_COMPOSITE = 7
|
cannam@134
|
108 };
|
cannam@134
|
109
|
cannam@134
|
110 enum class PointerType {
|
cannam@134
|
111 // Various wire types a pointer field can take
|
cannam@134
|
112
|
cannam@134
|
113 NULL_,
|
cannam@134
|
114 // Should be NULL, but that's #defined in stddef.h
|
cannam@134
|
115
|
cannam@134
|
116 STRUCT,
|
cannam@134
|
117 LIST,
|
cannam@134
|
118 CAPABILITY
|
cannam@134
|
119 };
|
cannam@134
|
120
|
cannam@134
|
121 namespace schemas {
|
cannam@134
|
122
|
cannam@134
|
123 template <typename T>
|
cannam@134
|
124 struct EnumInfo;
|
cannam@134
|
125
|
cannam@134
|
126 } // namespace schemas
|
cannam@134
|
127
|
cannam@134
|
128 namespace _ { // private
|
cannam@134
|
129
|
cannam@134
|
130 template <typename T, typename = void> struct Kind_;
|
cannam@134
|
131
|
cannam@134
|
132 template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
133 template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
134 template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
135 template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
136 template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
137 template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
138 template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
139 template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
140 template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
141 template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
142 template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
143 template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; };
|
cannam@134
|
144 template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
|
cannam@134
|
145 template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
|
cannam@134
|
146
|
cannam@134
|
147 template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
|
cannam@134
|
148 static constexpr Kind kind = Kind::STRUCT;
|
cannam@134
|
149 };
|
cannam@134
|
150 template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
|
cannam@134
|
151 static constexpr Kind kind = Kind::INTERFACE;
|
cannam@134
|
152 };
|
cannam@134
|
153 template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
|
cannam@134
|
154 static constexpr Kind kind = Kind::ENUM;
|
cannam@134
|
155 };
|
cannam@134
|
156
|
cannam@134
|
157 } // namespace _ (private)
|
cannam@134
|
158
|
cannam@134
|
159 template <typename T, Kind k = _::Kind_<T>::kind>
|
cannam@134
|
160 inline constexpr Kind kind() {
|
cannam@134
|
161 // This overload of kind() matches types which have a Kind_ specialization.
|
cannam@134
|
162
|
cannam@134
|
163 return k;
|
cannam@134
|
164 }
|
cannam@134
|
165
|
cannam@134
|
166 #if CAPNP_LITE
|
cannam@134
|
167
|
cannam@134
|
168 #define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
|
cannam@134
|
169 // Avoid constexpr methods in lite mode (MSVC is bad at constexpr).
|
cannam@134
|
170
|
cannam@134
|
171 #else // CAPNP_LITE
|
cannam@134
|
172
|
cannam@134
|
173 #define CAPNP_KIND(T) ::capnp::kind<T>()
|
cannam@134
|
174 // Use this macro rather than kind<T>() in any code which must work in lite mode.
|
cannam@134
|
175
|
cannam@134
|
176 template <typename T, Kind k = kind<T>()>
|
cannam@134
|
177 inline constexpr Style style() {
|
cannam@134
|
178 return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE
|
cannam@134
|
179 : k == Kind::STRUCT ? Style::STRUCT
|
cannam@134
|
180 : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER;
|
cannam@134
|
181 }
|
cannam@134
|
182
|
cannam@134
|
183 #endif // CAPNP_LITE, else
|
cannam@134
|
184
|
cannam@134
|
185 template <typename T, Kind k = CAPNP_KIND(T)>
|
cannam@134
|
186 struct List;
|
cannam@134
|
187
|
cannam@134
|
188 #if _MSC_VER
|
cannam@134
|
189
|
cannam@134
|
190 template <typename T, Kind k>
|
cannam@134
|
191 struct List {};
|
cannam@134
|
192 // For some reason, without this declaration, MSVC will error out on some uses of List
|
cannam@134
|
193 // claiming that "T" -- as used in the default initializer for the second template param, "k" --
|
cannam@134
|
194 // is not defined. I do not understand this error, but adding this empty default declaration fixes
|
cannam@134
|
195 // it.
|
cannam@134
|
196
|
cannam@134
|
197 #endif
|
cannam@134
|
198
|
cannam@134
|
199 template <typename T> struct ListElementType_;
|
cannam@134
|
200 template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
|
cannam@134
|
201 template <typename T> using ListElementType = typename ListElementType_<T>::Type;
|
cannam@134
|
202
|
cannam@134
|
203 namespace _ { // private
|
cannam@134
|
204 template <typename T, Kind k> struct Kind_<List<T, k>> {
|
cannam@134
|
205 static constexpr Kind kind = Kind::LIST;
|
cannam@134
|
206 };
|
cannam@134
|
207 } // namespace _ (private)
|
cannam@134
|
208
|
cannam@134
|
209 template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
|
cannam@134
|
210 template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
|
cannam@134
|
211 template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
|
cannam@134
|
212 template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
cannam@134
|
213 template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
|
cannam@134
|
214 // The type returned by List<T>::Reader::operator[].
|
cannam@134
|
215
|
cannam@134
|
216 template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
|
cannam@134
|
217 template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
|
cannam@134
|
218 template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
|
cannam@134
|
219 template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
cannam@134
|
220 template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
|
cannam@134
|
221 // The type returned by List<T>::Builder::operator[].
|
cannam@134
|
222
|
cannam@134
|
223 template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
|
cannam@134
|
224 template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
|
cannam@134
|
225 template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;
|
cannam@134
|
226
|
cannam@134
|
227 template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
|
cannam@134
|
228 template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };
|
cannam@134
|
229
|
cannam@134
|
230 template <typename T>
|
cannam@134
|
231 using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type;
|
cannam@134
|
232
|
cannam@134
|
233 template <typename T>
|
cannam@134
|
234 using FromReader = typename kj::Decay<T>::Reads;
|
cannam@134
|
235 // FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
|
cannam@134
|
236
|
cannam@134
|
237 template <typename T>
|
cannam@134
|
238 using FromBuilder = typename kj::Decay<T>::Builds;
|
cannam@134
|
239 // FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
|
cannam@134
|
240
|
cannam@134
|
241 template <typename T>
|
cannam@134
|
242 using FromPipeline = typename kj::Decay<T>::Pipelines;
|
cannam@134
|
243 // FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).
|
cannam@134
|
244
|
cannam@134
|
245 template <typename T>
|
cannam@134
|
246 using FromClient = typename kj::Decay<T>::Calls;
|
cannam@134
|
247 // FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).
|
cannam@134
|
248
|
cannam@134
|
249 template <typename T>
|
cannam@134
|
250 using FromServer = typename kj::Decay<T>::Serves;
|
cannam@134
|
251 // FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
|
cannam@134
|
252
|
cannam@134
|
253 template <typename T, typename = void>
|
cannam@134
|
254 struct FromAny_;
|
cannam@134
|
255
|
cannam@134
|
256 template <typename T>
|
cannam@134
|
257 struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
|
cannam@134
|
258 using Type = FromReader<T>;
|
cannam@134
|
259 };
|
cannam@134
|
260
|
cannam@134
|
261 template <typename T>
|
cannam@134
|
262 struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
|
cannam@134
|
263 using Type = FromBuilder<T>;
|
cannam@134
|
264 };
|
cannam@134
|
265
|
cannam@134
|
266 template <typename T>
|
cannam@134
|
267 struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
|
cannam@134
|
268 using Type = FromPipeline<T>;
|
cannam@134
|
269 };
|
cannam@134
|
270
|
cannam@134
|
271 // Note that T::Client is covered by FromReader
|
cannam@134
|
272
|
cannam@134
|
273 template <typename T>
|
cannam@134
|
274 struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
|
cannam@134
|
275 using Type = FromServer<T>;
|
cannam@134
|
276 };
|
cannam@134
|
277
|
cannam@134
|
278 template <typename T>
|
cannam@134
|
279 struct FromAny_<T,
|
cannam@134
|
280 kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
|
cannam@134
|
281 // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
|
cannam@134
|
282 // cannot yet use style<T>() in this constexpr context.
|
cannam@134
|
283
|
cannam@134
|
284 using Type = kj::Decay<T>;
|
cannam@134
|
285 };
|
cannam@134
|
286
|
cannam@134
|
287 template <typename T>
|
cannam@134
|
288 using FromAny = typename FromAny_<T>::Type;
|
cannam@134
|
289 // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
|
cannam@134
|
290 //
|
cannam@134
|
291 // Foo::Reader -> Foo
|
cannam@134
|
292 // Foo::Builder -> Foo
|
cannam@134
|
293 // Foo::Pipeline -> Foo
|
cannam@134
|
294 // Foo::Client -> Foo
|
cannam@134
|
295 // Own<Foo::Server> -> Foo
|
cannam@134
|
296 // uint32_t -> uint32_t
|
cannam@134
|
297
|
cannam@134
|
298 namespace _ { // private
|
cannam@134
|
299
|
cannam@134
|
300 template <typename T, Kind k = CAPNP_KIND(T)>
|
cannam@134
|
301 struct PointerHelpers;
|
cannam@134
|
302
|
cannam@134
|
303 #if _MSC_VER
|
cannam@134
|
304
|
cannam@134
|
305 template <typename T, Kind k>
|
cannam@134
|
306 struct PointerHelpers {};
|
cannam@134
|
307 // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
|
cannam@134
|
308 // claiming that "T" -- as used in the default initializer for the second template param, "k" --
|
cannam@134
|
309 // is not defined. I do not understand this error, but adding this empty default declaration fixes
|
cannam@134
|
310 // it.
|
cannam@134
|
311
|
cannam@134
|
312 #endif
|
cannam@134
|
313
|
cannam@134
|
314 } // namespace _ (private)
|
cannam@134
|
315
|
cannam@134
|
316 struct MessageSize {
|
cannam@134
|
317 // Size of a message. Every struct type has a method `.totalSize()` that returns this.
|
cannam@134
|
318 uint64_t wordCount;
|
cannam@134
|
319 uint capCount;
|
cannam@134
|
320 };
|
cannam@134
|
321
|
cannam@134
|
322 // =======================================================================================
|
cannam@134
|
323 // Raw memory types and measures
|
cannam@134
|
324
|
cannam@134
|
325 using kj::byte;
|
cannam@134
|
326
|
cannam@134
|
327 class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; };
|
cannam@134
|
328 // word is an opaque type with size of 64 bits. This type is useful only to make pointer
|
cannam@134
|
329 // arithmetic clearer. Since the contents are private, the only way to access them is to first
|
cannam@134
|
330 // reinterpret_cast to some other pointer type.
|
cannam@134
|
331 //
|
cannam@134
|
332 // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
|
cannam@134
|
333 // aliasing rules.
|
cannam@134
|
334 //
|
cannam@134
|
335 // A pointer of type word* should always be word-aligned even if won't actually be dereferenced as
|
cannam@134
|
336 // that type.
|
cannam@134
|
337
|
cannam@134
|
338 static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
|
cannam@134
|
339 static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");
|
cannam@134
|
340
|
cannam@134
|
341 #if CAPNP_DEBUG_TYPES
|
cannam@134
|
342 // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are
|
cannam@134
|
343 // used. All the code should still operate exactly the same, we just lose compile-time checking.
|
cannam@134
|
344 // Note that this will also change symbol names, so it's important that the library and any clients
|
cannam@134
|
345 // be compiled with the same setting here.
|
cannam@134
|
346 //
|
cannam@134
|
347 // We disable this by default to reduce symbol name size and avoid any possibility of the compiler
|
cannam@134
|
348 // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
|
cannam@134
|
349 // during development and testing.
|
cannam@134
|
350
|
cannam@134
|
351 namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
|
cannam@134
|
352
|
cannam@134
|
353 typedef kj::Quantity<uint, _::BitLabel> BitCount;
|
cannam@134
|
354 typedef kj::Quantity<uint8_t, _::BitLabel> BitCount8;
|
cannam@134
|
355 typedef kj::Quantity<uint16_t, _::BitLabel> BitCount16;
|
cannam@134
|
356 typedef kj::Quantity<uint32_t, _::BitLabel> BitCount32;
|
cannam@134
|
357 typedef kj::Quantity<uint64_t, _::BitLabel> BitCount64;
|
cannam@134
|
358
|
cannam@134
|
359 typedef kj::Quantity<uint, byte> ByteCount;
|
cannam@134
|
360 typedef kj::Quantity<uint8_t, byte> ByteCount8;
|
cannam@134
|
361 typedef kj::Quantity<uint16_t, byte> ByteCount16;
|
cannam@134
|
362 typedef kj::Quantity<uint32_t, byte> ByteCount32;
|
cannam@134
|
363 typedef kj::Quantity<uint64_t, byte> ByteCount64;
|
cannam@134
|
364
|
cannam@134
|
365 typedef kj::Quantity<uint, word> WordCount;
|
cannam@134
|
366 typedef kj::Quantity<uint8_t, word> WordCount8;
|
cannam@134
|
367 typedef kj::Quantity<uint16_t, word> WordCount16;
|
cannam@134
|
368 typedef kj::Quantity<uint32_t, word> WordCount32;
|
cannam@134
|
369 typedef kj::Quantity<uint64_t, word> WordCount64;
|
cannam@134
|
370
|
cannam@134
|
371 typedef kj::Quantity<uint, _::ElementLabel> ElementCount;
|
cannam@134
|
372 typedef kj::Quantity<uint8_t, _::ElementLabel> ElementCount8;
|
cannam@134
|
373 typedef kj::Quantity<uint16_t, _::ElementLabel> ElementCount16;
|
cannam@134
|
374 typedef kj::Quantity<uint32_t, _::ElementLabel> ElementCount32;
|
cannam@134
|
375 typedef kj::Quantity<uint64_t, _::ElementLabel> ElementCount64;
|
cannam@134
|
376
|
cannam@134
|
377 typedef kj::Quantity<uint, _::WirePointer> WirePointerCount;
|
cannam@134
|
378 typedef kj::Quantity<uint8_t, _::WirePointer> WirePointerCount8;
|
cannam@134
|
379 typedef kj::Quantity<uint16_t, _::WirePointer> WirePointerCount16;
|
cannam@134
|
380 typedef kj::Quantity<uint32_t, _::WirePointer> WirePointerCount32;
|
cannam@134
|
381 typedef kj::Quantity<uint64_t, _::WirePointer> WirePointerCount64;
|
cannam@134
|
382
|
cannam@134
|
383 template <typename T, typename U>
|
cannam@134
|
384 inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
385 return ptr + offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
386 }
|
cannam@134
|
387 template <typename T, typename U>
|
cannam@134
|
388 inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
389 return ptr + offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
390 }
|
cannam@134
|
391 template <typename T, typename U>
|
cannam@134
|
392 inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
393 return ptr = ptr + offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
394 }
|
cannam@134
|
395 template <typename T, typename U>
|
cannam@134
|
396 inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
397 return ptr = ptr + offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
398 }
|
cannam@134
|
399
|
cannam@134
|
400 template <typename T, typename U>
|
cannam@134
|
401 inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
402 return ptr - offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
403 }
|
cannam@134
|
404 template <typename T, typename U>
|
cannam@134
|
405 inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
406 return ptr - offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
407 }
|
cannam@134
|
408 template <typename T, typename U>
|
cannam@134
|
409 inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
410 return ptr = ptr - offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
411 }
|
cannam@134
|
412 template <typename T, typename U>
|
cannam@134
|
413 inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) {
|
cannam@134
|
414 return ptr = ptr - offset / kj::unit<kj::Quantity<T, U>>();
|
cannam@134
|
415 }
|
cannam@134
|
416
|
cannam@134
|
417 #else
|
cannam@134
|
418
|
cannam@134
|
419 typedef uint BitCount;
|
cannam@134
|
420 typedef uint8_t BitCount8;
|
cannam@134
|
421 typedef uint16_t BitCount16;
|
cannam@134
|
422 typedef uint32_t BitCount32;
|
cannam@134
|
423 typedef uint64_t BitCount64;
|
cannam@134
|
424
|
cannam@134
|
425 typedef uint ByteCount;
|
cannam@134
|
426 typedef uint8_t ByteCount8;
|
cannam@134
|
427 typedef uint16_t ByteCount16;
|
cannam@134
|
428 typedef uint32_t ByteCount32;
|
cannam@134
|
429 typedef uint64_t ByteCount64;
|
cannam@134
|
430
|
cannam@134
|
431 typedef uint WordCount;
|
cannam@134
|
432 typedef uint8_t WordCount8;
|
cannam@134
|
433 typedef uint16_t WordCount16;
|
cannam@134
|
434 typedef uint32_t WordCount32;
|
cannam@134
|
435 typedef uint64_t WordCount64;
|
cannam@134
|
436
|
cannam@134
|
437 typedef uint ElementCount;
|
cannam@134
|
438 typedef uint8_t ElementCount8;
|
cannam@134
|
439 typedef uint16_t ElementCount16;
|
cannam@134
|
440 typedef uint32_t ElementCount32;
|
cannam@134
|
441 typedef uint64_t ElementCount64;
|
cannam@134
|
442
|
cannam@134
|
443 typedef uint WirePointerCount;
|
cannam@134
|
444 typedef uint8_t WirePointerCount8;
|
cannam@134
|
445 typedef uint16_t WirePointerCount16;
|
cannam@134
|
446 typedef uint32_t WirePointerCount32;
|
cannam@134
|
447 typedef uint64_t WirePointerCount64;
|
cannam@134
|
448
|
cannam@134
|
449 #endif
|
cannam@134
|
450
|
cannam@134
|
451 constexpr BitCount BITS = kj::unit<BitCount>();
|
cannam@134
|
452 constexpr ByteCount BYTES = kj::unit<ByteCount>();
|
cannam@134
|
453 constexpr WordCount WORDS = kj::unit<WordCount>();
|
cannam@134
|
454 constexpr ElementCount ELEMENTS = kj::unit<ElementCount>();
|
cannam@134
|
455 constexpr WirePointerCount POINTERS = kj::unit<WirePointerCount>();
|
cannam@134
|
456
|
cannam@134
|
457 // GCC 4.7 actually gives unused warnings on these constants in opt mode...
|
cannam@134
|
458 constexpr auto BITS_PER_BYTE KJ_UNUSED = 8 * BITS / BYTES;
|
cannam@134
|
459 constexpr auto BITS_PER_WORD KJ_UNUSED = 64 * BITS / WORDS;
|
cannam@134
|
460 constexpr auto BYTES_PER_WORD KJ_UNUSED = 8 * BYTES / WORDS;
|
cannam@134
|
461
|
cannam@134
|
462 constexpr auto BITS_PER_POINTER KJ_UNUSED = 64 * BITS / POINTERS;
|
cannam@134
|
463 constexpr auto BYTES_PER_POINTER KJ_UNUSED = 8 * BYTES / POINTERS;
|
cannam@134
|
464 constexpr auto WORDS_PER_POINTER KJ_UNUSED = 1 * WORDS / POINTERS;
|
cannam@134
|
465
|
cannam@134
|
466 constexpr WordCount POINTER_SIZE_IN_WORDS = 1 * POINTERS * WORDS_PER_POINTER;
|
cannam@134
|
467
|
cannam@134
|
468 template <typename T>
|
cannam@134
|
469 inline KJ_CONSTEXPR() decltype(BYTES / ELEMENTS) bytesPerElement() {
|
cannam@134
|
470 return sizeof(T) * BYTES / ELEMENTS;
|
cannam@134
|
471 }
|
cannam@134
|
472
|
cannam@134
|
473 template <typename T>
|
cannam@134
|
474 inline KJ_CONSTEXPR() decltype(BITS / ELEMENTS) bitsPerElement() {
|
cannam@134
|
475 return sizeof(T) * 8 * BITS / ELEMENTS;
|
cannam@134
|
476 }
|
cannam@134
|
477
|
cannam@134
|
478 inline constexpr ByteCount intervalLength(const byte* a, const byte* b) {
|
cannam@134
|
479 return uint(b - a) * BYTES;
|
cannam@134
|
480 }
|
cannam@134
|
481 inline constexpr WordCount intervalLength(const word* a, const word* b) {
|
cannam@134
|
482 return uint(b - a) * WORDS;
|
cannam@134
|
483 }
|
cannam@134
|
484
|
cannam@134
|
485 } // namespace capnp
|
cannam@134
|
486
|
cannam@134
|
487 #endif // CAPNP_COMMON_H_
|