added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / null.hpp
diff --git a/iOS/Pods/Realm/include/core/realm/null.hpp b/iOS/Pods/Realm/include/core/realm/null.hpp
new file mode 100644 (file)
index 0000000..733e798
--- /dev/null
@@ -0,0 +1,172 @@
+/*************************************************************************
+ *
+ * Copyright 2016 Realm Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ **************************************************************************/
+
+#ifndef REALM_NULL_HPP
+#define REALM_NULL_HPP
+
+#include <cmath>
+#include <cstring>
+
+#include <realm/util/features.h>
+#include <realm/util/optional.hpp>
+#include <realm/utilities.hpp>
+#include <realm/exceptions.hpp>
+
+namespace realm {
+
+/*
+Represents null in Query, find(), get(), set(), etc.
+
+Float/Double: Realm can both store user-given NaNs and null. Any user-given signaling NaN is converted to
+0x7fa00000 (if float) or 0x7ff4000000000000 (if double). Any user-given quiet NaN is converted to
+0x7fc00000 (if float) or 0x7ff8000000000000 (if double). So Realm does not preserve the optional bits in
+user-given NaNs.
+
+However, since both clang and gcc on x64 and ARM, and also Java on x64, return these bit patterns when
+requesting NaNs, these will actually seem to roundtrip bit-exact for the end-user in most cases.
+
+If set_null() is called, a null is stored in form of the bit pattern 0xffffffff (if float) or
+0xffffffffffffffff (if double). These are quiet NaNs.
+
+Executing a query that involves a float/double column that contains NaNs gives an undefined result. If
+it contains signaling NaNs, it may throw an exception.
+
+Notes on IEEE:
+
+A NaN float is any bit pattern `s 11111111 S xxxxxxxxxxxxxxxxxxxxxx` where `s` and `x` are arbitrary, but at
+least 1 `x` must be 1. If `S` is 1, it's a quiet NaN, else it's a signaling NaN.
+
+A NaN doubule is the same as above, but for `s eeeeeeeeeee S xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`
+
+The `S` bit is at position 22 (float) or 51 (double).
+*/
+
+struct null {
+    null()
+    {
+    }
+    operator int64_t()
+    {
+        throw(LogicError::type_mismatch);
+    }
+    template <class T>
+    operator util::Optional<T>()
+    {
+        return util::none;
+    }
+
+    template <class T>
+    bool operator==(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+    template <class T>
+    bool operator!=(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+    template <class T>
+    bool operator>(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+    template <class T>
+    bool operator>=(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+    template <class T>
+    bool operator<=(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+    template <class T>
+    bool operator<(const T&) const
+    {
+        REALM_ASSERT(false);
+        return false;
+    }
+
+    /// Returns whether `v` bitwise equals the null bit-pattern
+    template <class T>
+    static bool is_null_float(T v)
+    {
+        T i = null::get_null_float<T>();
+        return std::memcmp(&i, &v, sizeof(T)) == 0;
+    }
+
+    /// Returns the quiet NaNs that represent null for floats/doubles in Realm in stored payload.
+    template <class T>
+    static T get_null_float()
+    {
+        typename std::conditional<std::is_same<T, float>::value, uint32_t, uint64_t>::type i;
+        int64_t double_nan = 0x7ff80000000000aa;
+        i = std::is_same<T, float>::value ? 0x7fc000aa : static_cast<decltype(i)>(double_nan);
+        T d = type_punning<T, decltype(i)>(i);
+        REALM_ASSERT_DEBUG(std::isnan(d));
+        REALM_ASSERT_DEBUG(!is_signaling(d));
+        return d;
+    }
+
+    /// Takes a NaN as argument and returns whether or not it's signaling
+    template <class T>
+    static bool is_signaling(T v)
+    {
+        REALM_ASSERT(std::isnan(static_cast<double>(v)));
+        typename std::conditional<std::is_same<T, float>::value, uint32_t, uint64_t>::type i;
+        size_t signal_bit = std::is_same<T, float>::value ? 22 : 51; // If this bit is set, it's quiet
+        i = type_punning<decltype(i), T>(v);
+        return !(i & (1ull << signal_bit));
+    }
+
+    /// Converts any signaling or quiet NaN to their their respective bit patterns that are used on x64 gcc+clang,
+    /// ARM clang and x64 Java.
+    template <class T>
+    static T to_realm(T v)
+    {
+        if (std::isnan(static_cast<double>(v))) {
+            typename std::conditional<std::is_same<T, float>::value, uint32_t, uint64_t>::type i;
+            if (std::is_same<T, float>::value) {
+                i = is_signaling(v) ? 0x7fa00000 : 0x7fc00000;
+            }
+            else {
+                i = static_cast<decltype(i)>(is_signaling(v) ? 0x7ff4000000000000 : 0x7ff8000000000000);
+            }
+            return type_punning<T, decltype(i)>(i);
+        }
+        else {
+            return v;
+        }
+    }
+};
+
+template <class OS>
+OS& operator<<(OS& os, const null&)
+{
+    os << "(null)";
+    return os;
+}
+
+} // namespace realm
+
+#endif // REALM_NULL_HPP