X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/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 index 0000000..733e798 --- /dev/null +++ b/iOS/Pods/Realm/include/core/realm/null.hpp @@ -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 +#include + +#include +#include +#include +#include + +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 + operator util::Optional() + { + return util::none; + } + + template + bool operator==(const T&) const + { + REALM_ASSERT(false); + return false; + } + template + bool operator!=(const T&) const + { + REALM_ASSERT(false); + return false; + } + template + bool operator>(const T&) const + { + REALM_ASSERT(false); + return false; + } + template + bool operator>=(const T&) const + { + REALM_ASSERT(false); + return false; + } + template + bool operator<=(const T&) const + { + REALM_ASSERT(false); + return false; + } + template + bool operator<(const T&) const + { + REALM_ASSERT(false); + return false; + } + + /// Returns whether `v` bitwise equals the null bit-pattern + template + static bool is_null_float(T v) + { + T i = null::get_null_float(); + return std::memcmp(&i, &v, sizeof(T)) == 0; + } + + /// Returns the quiet NaNs that represent null for floats/doubles in Realm in stored payload. + template + static T get_null_float() + { + typename std::conditional::value, uint32_t, uint64_t>::type i; + int64_t double_nan = 0x7ff80000000000aa; + i = std::is_same::value ? 0x7fc000aa : static_cast(double_nan); + T d = type_punning(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 + static bool is_signaling(T v) + { + REALM_ASSERT(std::isnan(static_cast(v))); + typename std::conditional::value, uint32_t, uint64_t>::type i; + size_t signal_bit = std::is_same::value ? 22 : 51; // If this bit is set, it's quiet + i = type_punning(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 + static T to_realm(T v) + { + if (std::isnan(static_cast(v))) { + typename std::conditional::value, uint32_t, uint64_t>::type i; + if (std::is_same::value) { + i = is_signaling(v) ? 0x7fa00000 : 0x7fc00000; + } + else { + i = static_cast(is_signaling(v) ? 0x7ff4000000000000 : 0x7ff8000000000000); + } + return type_punning(i); + } + else { + return v; + } + } +}; + +template +OS& operator<<(OS& os, const null&) +{ + os << "(null)"; + return os; +} + +} // namespace realm + +#endif // REALM_NULL_HPP