diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/osx/include/kj/one-of.h	Tue Oct 25 14:48:23 2016 +0100
@@ -0,0 +1,150 @@
+// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
+// Licensed under the MIT License:
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#ifndef KJ_ONE_OF_H_
+#define KJ_ONE_OF_H_
+
+#if defined(__GNUC__) && !KJ_HEADER_WARNINGS
+#pragma GCC system_header
+#endif
+
+#include "common.h"
+
+namespace kj {
+
+namespace _ {  // private
+
+template <uint i, typename Key, typename First, typename... Rest>
+struct TypeIndex_ { static constexpr uint value = TypeIndex_<i + 1, Key, Rest...>::value; };
+template <uint i, typename Key, typename... Rest>
+struct TypeIndex_<i, Key, Key, Rest...> { static constexpr uint value = i; };
+
+}  // namespace _ (private)
+
+template <typename... Variants>
+class OneOf {
+  template <typename Key>
+  static inline constexpr uint typeIndex() { return _::TypeIndex_<1, Key, Variants...>::value; }
+  // Get the 1-based index of Key within the type list Types.
+
+public:
+  inline OneOf(): tag(0) {}
+  OneOf(const OneOf& other) { copyFrom(other); }
+  OneOf(OneOf&& other) { moveFrom(other); }
+  ~OneOf() { destroy(); }
+
+  OneOf& operator=(const OneOf& other) { if (tag != 0) destroy(); copyFrom(other); return *this; }
+  OneOf& operator=(OneOf&& other) { if (tag != 0) destroy(); moveFrom(other); return *this; }
+
+  inline bool operator==(decltype(nullptr)) const { return tag == 0; }
+  inline bool operator!=(decltype(nullptr)) const { return tag != 0; }
+
+  template <typename T>
+  bool is() const {
+    return tag == typeIndex<T>();
+  }
+
+  template <typename T>
+  T& get() {
+    KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
+    return *reinterpret_cast<T*>(space);
+  }
+  template <typename T>
+  const T& get() const {
+    KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
+    return *reinterpret_cast<const T*>(space);
+  }
+
+  template <typename T, typename... Params>
+  void init(Params&&... params) {
+    if (tag != 0) destroy();
+    ctor(*reinterpret_cast<T*>(space), kj::fwd<Params>(params)...);
+    tag = typeIndex<T>();
+  }
+
+private:
+  uint tag;
+
+  static inline constexpr size_t maxSize(size_t a) {
+    return a;
+  }
+  template <typename... Rest>
+  static inline constexpr size_t maxSize(size_t a, size_t b, Rest... rest) {
+    return maxSize(kj::max(a, b), rest...);
+  }
+  // Returns the maximum of all the parameters.
+  // TODO(someday):  Generalize the above template and make it common.  I tried, but C++ decided to
+  //   be difficult so I cut my losses.
+
+  union {
+    byte space[maxSize(sizeof(Variants)...)];
+
+    void* forceAligned;
+    // TODO(someday):  Use C++11 alignas() once we require GCC 4.8 / Clang 3.3.
+  };
+
+  template <typename... T>
+  inline void doAll(T... t) {}
+
+  template <typename T>
+  inline bool destroyVariant() {
+    if (tag == typeIndex<T>()) {
+      tag = 0;
+      dtor(*reinterpret_cast<T*>(space));
+    }
+    return false;
+  }
+  void destroy() {
+    doAll(destroyVariant<Variants>()...);
+  }
+
+  template <typename T>
+  inline bool copyVariantFrom(const OneOf& other) {
+    if (other.is<T>()) {
+      ctor(*reinterpret_cast<T*>(space), other.get<T>());
+    }
+    return false;
+  }
+  void copyFrom(const OneOf& other) {
+    // Initialize as a copy of `other`.  Expects that `this` starts out uninitialized, so the tag
+    // is invalid.
+    tag = other.tag;
+    doAll(copyVariantFrom<Variants>(other)...);
+  }
+
+  template <typename T>
+  inline bool moveVariantFrom(OneOf& other) {
+    if (other.is<T>()) {
+      ctor(*reinterpret_cast<T*>(space), kj::mv(other.get<T>()));
+    }
+    return false;
+  }
+  void moveFrom(OneOf& other) {
+    // Initialize as a copy of `other`.  Expects that `this` starts out uninitialized, so the tag
+    // is invalid.
+    tag = other.tag;
+    doAll(moveVariantFrom<Variants>(other)...);
+  }
+};
+
+}  // namespace kj
+
+#endif  // KJ_ONE_OF_H_