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 | // This file contains types which are intended to help detect incorrect usage at compile |
23 | // time, but should then be optimized down to basic primitives (usually, integers) by the |
24 | // compiler. |
25 | |
26 | #pragma once |
27 | |
28 | #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) |
29 | #pragma GCC system_header |
30 | #endif |
31 | |
32 | #include <inttypes.h> |
33 | #include <kj/string.h> |
34 | #include <kj/memory.h> |
35 | #include <kj/windows-sanity.h> // work-around macro conflict with `VOID` |
36 | |
37 | #if CAPNP_DEBUG_TYPES |
38 | #include <kj/units.h> |
39 | #endif |
40 | |
41 | namespace capnp { |
42 | |
43 | #define CAPNP_VERSION_MAJOR 0 |
44 | #define CAPNP_VERSION_MINOR 8 |
45 | #define CAPNP_VERSION_MICRO 0 |
46 | |
47 | #define CAPNP_VERSION \ |
48 | (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) |
49 | |
50 | #ifndef CAPNP_LITE |
51 | #define CAPNP_LITE 0 |
52 | #endif |
53 | |
54 | #if CAPNP_TESTING_CAPNP // defined in Cap'n Proto's own unit tests; others should not define this |
55 | #define CAPNP_DEPRECATED(reason) |
56 | #else |
57 | #define CAPNP_DEPRECATED KJ_DEPRECATED |
58 | #endif |
59 | |
60 | typedef unsigned int uint; |
61 | |
62 | struct Void { |
63 | // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves |
64 | // differently from other types. |
65 | |
66 | inline constexpr bool operator==(Void other) const { return true; } |
67 | inline constexpr bool operator!=(Void other) const { return false; } |
68 | }; |
69 | |
70 | static constexpr Void VOID = Void(); |
71 | // Constant value for `Void`, which is an empty struct. |
72 | |
73 | inline kj::StringPtr KJ_STRINGIFY(Void) { return "void" ; } |
74 | |
75 | struct Text; |
76 | struct Data; |
77 | |
78 | enum class Kind: uint8_t { |
79 | PRIMITIVE, |
80 | BLOB, |
81 | ENUM, |
82 | STRUCT, |
83 | UNION, |
84 | INTERFACE, |
85 | LIST, |
86 | |
87 | OTHER |
88 | // Some other type which is often a type parameter to Cap'n Proto templates, but which needs |
89 | // special handling. This includes types like AnyPointer, Dynamic*, etc. |
90 | }; |
91 | |
92 | enum class Style: uint8_t { |
93 | PRIMITIVE, |
94 | POINTER, // other than struct |
95 | STRUCT, |
96 | CAPABILITY |
97 | }; |
98 | |
99 | enum class ElementSize: uint8_t { |
100 | // Size of a list element. |
101 | |
102 | VOID = 0, |
103 | BIT = 1, |
104 | BYTE = 2, |
105 | TWO_BYTES = 3, |
106 | FOUR_BYTES = 4, |
107 | EIGHT_BYTES = 5, |
108 | |
109 | POINTER = 6, |
110 | |
111 | INLINE_COMPOSITE = 7 |
112 | }; |
113 | |
114 | enum class PointerType { |
115 | // Various wire types a pointer field can take |
116 | |
117 | NULL_, |
118 | // Should be NULL, but that's #defined in stddef.h |
119 | |
120 | STRUCT, |
121 | LIST, |
122 | CAPABILITY |
123 | }; |
124 | |
125 | namespace schemas { |
126 | |
127 | template <typename T> |
128 | struct EnumInfo; |
129 | |
130 | } // namespace schemas |
131 | |
132 | namespace _ { // private |
133 | |
134 | template <typename T, typename = void> struct Kind_; |
135 | |
136 | template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
137 | template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
138 | template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
139 | template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
140 | template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
141 | template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
142 | template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
143 | template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
144 | template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
145 | template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
146 | template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
147 | template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; }; |
148 | template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; }; |
149 | template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; }; |
150 | |
151 | template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> { |
152 | static constexpr Kind kind = Kind::STRUCT; |
153 | }; |
154 | template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> { |
155 | static constexpr Kind kind = Kind::INTERFACE; |
156 | }; |
157 | template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> { |
158 | static constexpr Kind kind = Kind::ENUM; |
159 | }; |
160 | |
161 | } // namespace _ (private) |
162 | |
163 | template <typename T, Kind k = _::Kind_<T>::kind> |
164 | inline constexpr Kind kind() { |
165 | // This overload of kind() matches types which have a Kind_ specialization. |
166 | |
167 | return k; |
168 | } |
169 | |
170 | #if _MSC_VER |
171 | |
172 | #define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind |
173 | // Avoid constexpr methods in MSVC (it remains buggy in many situations). |
174 | |
175 | #else // _MSC_VER |
176 | |
177 | #define CAPNP_KIND(T) ::capnp::kind<T>() |
178 | // Use this macro rather than kind<T>() in any code which must work in MSVC. |
179 | |
180 | #endif // _MSC_VER, else |
181 | |
182 | #if !CAPNP_LITE |
183 | |
184 | template <typename T, Kind k = kind<T>()> |
185 | inline constexpr Style style() { |
186 | return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE |
187 | : k == Kind::STRUCT ? Style::STRUCT |
188 | : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; |
189 | } |
190 | |
191 | #endif // !CAPNP_LITE |
192 | |
193 | template <typename T, Kind k = CAPNP_KIND(T)> |
194 | struct List; |
195 | |
196 | #if _MSC_VER |
197 | |
198 | template <typename T, Kind k> |
199 | struct List {}; |
200 | // For some reason, without this declaration, MSVC will error out on some uses of List |
201 | // claiming that "T" -- as used in the default initializer for the second template param, "k" -- |
202 | // is not defined. I do not understand this error, but adding this empty default declaration fixes |
203 | // it. |
204 | |
205 | #endif |
206 | |
207 | template <typename T> struct ListElementType_; |
208 | template <typename T> struct ListElementType_<List<T>> { typedef T Type; }; |
209 | template <typename T> using ListElementType = typename ListElementType_<T>::Type; |
210 | |
211 | namespace _ { // private |
212 | template <typename T, Kind k> struct Kind_<List<T, k>> { |
213 | static constexpr Kind kind = Kind::LIST; |
214 | }; |
215 | } // namespace _ (private) |
216 | |
217 | template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; }; |
218 | template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; |
219 | template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; }; |
220 | template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; |
221 | template <typename T> using ReaderFor = typename ReaderFor_<T>::Type; |
222 | // The type returned by List<T>::Reader::operator[]. |
223 | |
224 | template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; }; |
225 | template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; |
226 | template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; }; |
227 | template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; |
228 | template <typename T> using BuilderFor = typename BuilderFor_<T>::Type; |
229 | // The type returned by List<T>::Builder::operator[]. |
230 | |
231 | template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;}; |
232 | template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; |
233 | template <typename T> using PipelineFor = typename PipelineFor_<T>::Type; |
234 | |
235 | template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_; |
236 | template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; }; |
237 | |
238 | template <typename T> |
239 | using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type; |
240 | |
241 | template <typename T> |
242 | using FromReader = typename kj::Decay<T>::Reads; |
243 | // FromReader<MyType::Reader> = MyType (for any Cap'n Proto type). |
244 | |
245 | template <typename T> |
246 | using FromBuilder = typename kj::Decay<T>::Builds; |
247 | // FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type). |
248 | |
249 | template <typename T> |
250 | using FromPipeline = typename kj::Decay<T>::Pipelines; |
251 | // FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type). |
252 | |
253 | template <typename T> |
254 | using FromClient = typename kj::Decay<T>::Calls; |
255 | // FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type). |
256 | |
257 | template <typename T> |
258 | using FromServer = typename kj::Decay<T>::Serves; |
259 | // FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type). |
260 | |
261 | template <typename T, typename = void> |
262 | struct FromAny_; |
263 | |
264 | template <typename T> |
265 | struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> { |
266 | using Type = FromReader<T>; |
267 | }; |
268 | |
269 | template <typename T> |
270 | struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> { |
271 | using Type = FromBuilder<T>; |
272 | }; |
273 | |
274 | template <typename T> |
275 | struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> { |
276 | using Type = FromPipeline<T>; |
277 | }; |
278 | |
279 | // Note that T::Client is covered by FromReader |
280 | |
281 | template <typename T> |
282 | struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> { |
283 | using Type = FromServer<T>; |
284 | }; |
285 | |
286 | template <typename T> |
287 | struct FromAny_<T, |
288 | kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> { |
289 | // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC |
290 | // cannot yet use style<T>() in this constexpr context. |
291 | |
292 | using Type = kj::Decay<T>; |
293 | }; |
294 | |
295 | template <typename T> |
296 | using FromAny = typename FromAny_<T>::Type; |
297 | // Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: |
298 | // |
299 | // Foo::Reader -> Foo |
300 | // Foo::Builder -> Foo |
301 | // Foo::Pipeline -> Foo |
302 | // Foo::Client -> Foo |
303 | // Own<Foo::Server> -> Foo |
304 | // uint32_t -> uint32_t |
305 | |
306 | namespace _ { // private |
307 | |
308 | template <typename T, Kind k = CAPNP_KIND(T)> |
309 | struct PointerHelpers; |
310 | |
311 | #if _MSC_VER |
312 | |
313 | template <typename T, Kind k> |
314 | struct PointerHelpers {}; |
315 | // For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers |
316 | // claiming that "T" -- as used in the default initializer for the second template param, "k" -- |
317 | // is not defined. I do not understand this error, but adding this empty default declaration fixes |
318 | // it. |
319 | |
320 | #endif |
321 | |
322 | } // namespace _ (private) |
323 | |
324 | struct MessageSize { |
325 | // Size of a message. Every struct and list type has a method `.totalSize()` that returns this. |
326 | uint64_t wordCount; |
327 | uint capCount; |
328 | |
329 | inline constexpr MessageSize operator+(const MessageSize& other) const { |
330 | return { wordCount + other.wordCount, capCount + other.capCount }; |
331 | } |
332 | }; |
333 | |
334 | // ======================================================================================= |
335 | // Raw memory types and measures |
336 | |
337 | using kj::byte; |
338 | |
339 | class word { |
340 | // word is an opaque type with size of 64 bits. This type is useful only to make pointer |
341 | // arithmetic clearer. Since the contents are private, the only way to access them is to first |
342 | // reinterpret_cast to some other pointer type. |
343 | // |
344 | // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of |
345 | // aliasing rules. |
346 | // |
347 | // A pointer of type word* should always be word-aligned even if won't actually be dereferenced |
348 | // as that type. |
349 | public: |
350 | word() = default; |
351 | private: |
352 | uint64_t content KJ_UNUSED_MEMBER; |
353 | #if __GNUC__ < 8 || __clang__ |
354 | // GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed |
355 | // the copy constructor. We don't want to disable the warning becaues it's a useful warning and |
356 | // we'd have to disable it for all applications that include this header. Instead we allow `word` |
357 | // to be copyable on GCC. |
358 | KJ_DISALLOW_COPY(word); |
359 | #endif |
360 | }; |
361 | |
362 | static_assert(sizeof(byte) == 1, "uint8_t is not one byte?" ); |
363 | static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?" ); |
364 | |
365 | #if CAPNP_DEBUG_TYPES |
366 | // Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are |
367 | // used. All the code should still operate exactly the same, we just lose compile-time checking. |
368 | // Note that this will also change symbol names, so it's important that the library and any clients |
369 | // be compiled with the same setting here. |
370 | // |
371 | // We disable this by default to reduce symbol name size and avoid any possibility of the compiler |
372 | // failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this |
373 | // during development and testing. |
374 | |
375 | namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } |
376 | |
377 | template <uint width, typename T = uint> |
378 | using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>; |
379 | template <uint width, typename T = uint> |
380 | using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>; |
381 | template <uint width, typename T = uint> |
382 | using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>; |
383 | template <uint width, typename T = uint> |
384 | using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>; |
385 | template <uint width, typename T = uint> |
386 | using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>; |
387 | |
388 | typedef BitCountN<8, uint8_t> BitCount8; |
389 | typedef BitCountN<16, uint16_t> BitCount16; |
390 | typedef BitCountN<32, uint32_t> BitCount32; |
391 | typedef BitCountN<64, uint64_t> BitCount64; |
392 | typedef BitCountN<sizeof(uint) * 8, uint> BitCount; |
393 | |
394 | typedef ByteCountN<8, uint8_t> ByteCount8; |
395 | typedef ByteCountN<16, uint16_t> ByteCount16; |
396 | typedef ByteCountN<32, uint32_t> ByteCount32; |
397 | typedef ByteCountN<64, uint64_t> ByteCount64; |
398 | typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; |
399 | |
400 | typedef WordCountN<8, uint8_t> WordCount8; |
401 | typedef WordCountN<16, uint16_t> WordCount16; |
402 | typedef WordCountN<32, uint32_t> WordCount32; |
403 | typedef WordCountN<64, uint64_t> WordCount64; |
404 | typedef WordCountN<sizeof(uint) * 8, uint> WordCount; |
405 | |
406 | typedef ElementCountN<8, uint8_t> ElementCount8; |
407 | typedef ElementCountN<16, uint16_t> ElementCount16; |
408 | typedef ElementCountN<32, uint32_t> ElementCount32; |
409 | typedef ElementCountN<64, uint64_t> ElementCount64; |
410 | typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; |
411 | |
412 | typedef WirePointerCountN<8, uint8_t> WirePointerCount8; |
413 | typedef WirePointerCountN<16, uint16_t> WirePointerCount16; |
414 | typedef WirePointerCountN<32, uint32_t> WirePointerCount32; |
415 | typedef WirePointerCountN<64, uint64_t> WirePointerCount64; |
416 | typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; |
417 | |
418 | template <uint width> |
419 | using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); |
420 | template <uint width> |
421 | using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); |
422 | template <uint width> |
423 | using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); |
424 | template <uint width> |
425 | using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); |
426 | |
427 | using kj::bounded; |
428 | using kj::unbound; |
429 | using kj::unboundAs; |
430 | using kj::unboundMax; |
431 | using kj::unboundMaxBits; |
432 | using kj::assertMax; |
433 | using kj::assertMaxBits; |
434 | using kj::upgradeBound; |
435 | using kj::ThrowOverflow; |
436 | using kj::assumeBits; |
437 | using kj::assumeMax; |
438 | using kj::subtractChecked; |
439 | using kj::trySubtract; |
440 | |
441 | template <typename T, typename U> |
442 | inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) { |
443 | return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
444 | } |
445 | template <typename T, typename U> |
446 | inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) { |
447 | return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
448 | } |
449 | template <typename T, typename U> |
450 | inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) { |
451 | return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
452 | } |
453 | template <typename T, typename U> |
454 | inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) { |
455 | return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
456 | } |
457 | |
458 | template <typename T, typename U> |
459 | inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) { |
460 | return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
461 | } |
462 | template <typename T, typename U> |
463 | inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) { |
464 | return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
465 | } |
466 | template <typename T, typename U> |
467 | inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) { |
468 | return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
469 | } |
470 | template <typename T, typename U> |
471 | inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) { |
472 | return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); |
473 | } |
474 | |
475 | constexpr auto BITS = kj::unit<BitCountN<1>>(); |
476 | constexpr auto BYTES = kj::unit<ByteCountN<1>>(); |
477 | constexpr auto WORDS = kj::unit<WordCountN<1>>(); |
478 | constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>(); |
479 | constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>(); |
480 | |
481 | constexpr auto ZERO = kj::bounded<0>(); |
482 | constexpr auto ONE = kj::bounded<1>(); |
483 | |
484 | // GCC 4.7 actually gives unused warnings on these constants in opt mode... |
485 | constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES; |
486 | constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS; |
487 | constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS; |
488 | |
489 | constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS; |
490 | constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS; |
491 | constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS; |
492 | |
493 | constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; |
494 | |
495 | constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. |
496 | constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. |
497 | constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. |
498 | constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. |
499 | constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. |
500 | |
501 | typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; |
502 | typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; |
503 | typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; |
504 | typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; |
505 | typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; |
506 | |
507 | constexpr auto MAX_SEGMENT_WORDS = |
508 | bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS; |
509 | constexpr auto MAX_LIST_ELEMENTS = |
510 | bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS; |
511 | constexpr auto MAX_STUCT_DATA_WORDS = |
512 | bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS; |
513 | constexpr auto MAX_STRUCT_POINTER_COUNT = |
514 | bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS; |
515 | |
516 | using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD); |
517 | // Number of bits in a Struct data segment (should come out to BitCountN<22>). |
518 | |
519 | using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS)); |
520 | using StructPointerOffset = StructPointerCount; |
521 | // Type of a field offset. |
522 | |
523 | inline StructDataOffset assumeDataOffset(uint32_t offset) { |
524 | return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS), |
525 | bounded(offset) * ELEMENTS); |
526 | } |
527 | |
528 | inline StructPointerOffset assumePointerOffset(uint32_t offset) { |
529 | return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS); |
530 | } |
531 | |
532 | constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; |
533 | typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize; |
534 | // Not including NUL terminator. |
535 | |
536 | template <typename T> |
537 | inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() { |
538 | return bounded<sizeof(T)>() * BYTES / ELEMENTS; |
539 | } |
540 | |
541 | template <typename T> |
542 | inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() { |
543 | return bounded<sizeof(T) * 8>() * BITS / ELEMENTS; |
544 | } |
545 | |
546 | template <typename T, uint maxN> |
547 | inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T> |
548 | intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) { |
549 | return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>(); |
550 | } |
551 | |
552 | template <typename T, typename U> |
553 | inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) { |
554 | return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); |
555 | } |
556 | template <typename T, typename U> |
557 | inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) { |
558 | return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); |
559 | } |
560 | |
561 | #else |
562 | |
563 | template <uint width, typename T = uint> |
564 | using BitCountN = T; |
565 | template <uint width, typename T = uint> |
566 | using ByteCountN = T; |
567 | template <uint width, typename T = uint> |
568 | using WordCountN = T; |
569 | template <uint width, typename T = uint> |
570 | using ElementCountN = T; |
571 | template <uint width, typename T = uint> |
572 | using WirePointerCountN = T; |
573 | |
574 | |
575 | // XXX |
576 | typedef BitCountN<8, uint8_t> BitCount8; |
577 | typedef BitCountN<16, uint16_t> BitCount16; |
578 | typedef BitCountN<32, uint32_t> BitCount32; |
579 | typedef BitCountN<64, uint64_t> BitCount64; |
580 | typedef BitCountN<sizeof(uint) * 8, uint> BitCount; |
581 | |
582 | typedef ByteCountN<8, uint8_t> ByteCount8; |
583 | typedef ByteCountN<16, uint16_t> ByteCount16; |
584 | typedef ByteCountN<32, uint32_t> ByteCount32; |
585 | typedef ByteCountN<64, uint64_t> ByteCount64; |
586 | typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; |
587 | |
588 | typedef WordCountN<8, uint8_t> WordCount8; |
589 | typedef WordCountN<16, uint16_t> WordCount16; |
590 | typedef WordCountN<32, uint32_t> WordCount32; |
591 | typedef WordCountN<64, uint64_t> WordCount64; |
592 | typedef WordCountN<sizeof(uint) * 8, uint> WordCount; |
593 | |
594 | typedef ElementCountN<8, uint8_t> ElementCount8; |
595 | typedef ElementCountN<16, uint16_t> ElementCount16; |
596 | typedef ElementCountN<32, uint32_t> ElementCount32; |
597 | typedef ElementCountN<64, uint64_t> ElementCount64; |
598 | typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; |
599 | |
600 | typedef WirePointerCountN<8, uint8_t> WirePointerCount8; |
601 | typedef WirePointerCountN<16, uint16_t> WirePointerCount16; |
602 | typedef WirePointerCountN<32, uint32_t> WirePointerCount32; |
603 | typedef WirePointerCountN<64, uint64_t> WirePointerCount64; |
604 | typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; |
605 | |
606 | template <uint width> |
607 | using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); |
608 | template <uint width> |
609 | using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); |
610 | template <uint width> |
611 | using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); |
612 | template <uint width> |
613 | using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); |
614 | |
615 | using kj::ThrowOverflow; |
616 | // YYY |
617 | |
618 | template <uint i> inline constexpr uint bounded() { return i; } |
619 | template <typename T> inline constexpr T bounded(T i) { return i; } |
620 | template <typename T> inline constexpr T unbound(T i) { return i; } |
621 | |
622 | template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; } |
623 | |
624 | template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; } |
625 | template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; } |
626 | |
627 | template <uint newMax, typename T, typename ErrorFunc> |
628 | inline T assertMax(T value, ErrorFunc&& func) { |
629 | if (KJ_UNLIKELY(value > newMax)) func(); |
630 | return value; |
631 | } |
632 | |
633 | template <typename T, typename ErrorFunc> |
634 | inline T assertMax(uint newMax, T value, ErrorFunc&& func) { |
635 | if (KJ_UNLIKELY(value > newMax)) func(); |
636 | return value; |
637 | } |
638 | |
639 | template <uint bits, typename T, typename ErrorFunc = ThrowOverflow> |
640 | inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) { |
641 | if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func(); |
642 | return value; |
643 | } |
644 | |
645 | template <typename T, typename ErrorFunc = ThrowOverflow> |
646 | inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) { |
647 | if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func(); |
648 | return value; |
649 | } |
650 | |
651 | template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; } |
652 | |
653 | template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; } |
654 | template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; } |
655 | |
656 | template <typename T, typename U, typename ErrorFunc = ThrowOverflow> |
657 | inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc()) |
658 | -> decltype(a - b) { |
659 | if (b > a) errorFunc(); |
660 | return a - b; |
661 | } |
662 | |
663 | template <typename T, typename U> |
664 | inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> { |
665 | if (b > a) { |
666 | return nullptr; |
667 | } else { |
668 | return a - b; |
669 | } |
670 | } |
671 | |
672 | constexpr uint BITS = 1; |
673 | constexpr uint BYTES = 1; |
674 | constexpr uint WORDS = 1; |
675 | constexpr uint ELEMENTS = 1; |
676 | constexpr uint POINTERS = 1; |
677 | |
678 | constexpr uint ZERO = 0; |
679 | constexpr uint ONE = 1; |
680 | |
681 | // GCC 4.7 actually gives unused warnings on these constants in opt mode... |
682 | constexpr uint BITS_PER_BYTE KJ_UNUSED = 8; |
683 | constexpr uint BITS_PER_WORD KJ_UNUSED = 64; |
684 | constexpr uint BYTES_PER_WORD KJ_UNUSED = 8; |
685 | |
686 | constexpr uint BITS_PER_POINTER KJ_UNUSED = 64; |
687 | constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8; |
688 | constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1; |
689 | |
690 | // XXX |
691 | constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; |
692 | |
693 | constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. |
694 | constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. |
695 | constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. |
696 | constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. |
697 | constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. |
698 | |
699 | typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; |
700 | typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; |
701 | typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; |
702 | typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; |
703 | typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; |
704 | // YYY |
705 | |
706 | constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>(); |
707 | constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>(); |
708 | constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>(); |
709 | constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>(); |
710 | |
711 | typedef uint StructDataBitCount; |
712 | typedef uint StructDataOffset; |
713 | typedef uint StructPointerOffset; |
714 | |
715 | inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; } |
716 | inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; } |
717 | |
718 | constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; |
719 | typedef uint TextSize; |
720 | |
721 | template <typename T> |
722 | inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); } |
723 | |
724 | template <typename T> |
725 | inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; } |
726 | |
727 | template <typename T> |
728 | inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) { |
729 | return b - a; |
730 | } |
731 | |
732 | template <typename T, typename U> |
733 | inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) { |
734 | return kj::arrayPtr(ptr, size); |
735 | } |
736 | template <typename T, typename U> |
737 | inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) { |
738 | return kj::arrayPtr(ptr, size); |
739 | } |
740 | |
741 | #endif |
742 | |
743 | } // namespace capnp |
744 | |