X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/Realm/include/impl/object_accessor_impl.hpp diff --git a/iOS/Pods/Realm/include/impl/object_accessor_impl.hpp b/iOS/Pods/Realm/include/impl/object_accessor_impl.hpp new file mode 100644 index 0000000..650f46f --- /dev/null +++ b/iOS/Pods/Realm/include/impl/object_accessor_impl.hpp @@ -0,0 +1,220 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2017 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_OS_OBJECT_ACCESSOR_IMPL_HPP +#define REALM_OS_OBJECT_ACCESSOR_IMPL_HPP + +#include "object_accessor.hpp" + +#include + +namespace realm { +using AnyDict = std::map; +using AnyVector = std::vector; + +// An object accessor context which can be used to create and access objects +// using util::Any as the type-erased value type. In addition, this serves as +// the reference implementation of an accessor context that must be implemented +// by each binding. +class CppContext { +public: + // This constructor is the only one used by the object accessor code, and is + // used when recurring into a link or array property during object creation + // (i.e. prop.type will always be Object or Array). + CppContext(CppContext& c, Property const& prop) + : realm(c.realm) + , object_schema(prop.type == PropertyType::Object ? &*realm->schema().find(prop.object_type) : c.object_schema) + { } + + CppContext() = default; + CppContext(std::shared_ptr realm, const ObjectSchema* os=nullptr) + : realm(std::move(realm)), object_schema(os) { } + + // The use of util::Optional for the following two functions is not a hard + // requirement; only that it be some type which can be evaluated in a + // boolean context to determine if it contains a value, and if it does + // contain a value it must be dereferencable to obtain that value. + + // Get the value for a property in an input object, or `util::none` if no + // value present. The property is identified both by the name of the + // property and its index within the ObjectScehma's persisted_properties + // array. + util::Optional value_for_property(util::Any& dict, + std::string const& prop_name, + size_t /* property_index */) const + { + auto const& v = any_cast(dict); + auto it = v.find(prop_name); + return it == v.end() ? util::none : util::make_optional(it->second); + } + + // Get the default value for the given property in the given object schema, + // or `util::none` if there is none (which is distinct from the default + // being `null`). + // + // This implementation does not support default values; see the default + // value tests for an example of one which does. + util::Optional + default_value_for_property(ObjectSchema const&, std::string const&) const + { + return util::none; + } + + // Invoke `fn` with each of the values from an enumerable type + template + void enumerate_list(util::Any& value, Func&& fn) { + for (auto&& v : any_cast(value)) + fn(v); + } + + // Determine if `value` boxes the same List as `list` + bool is_same_list(List const& list, util::Any const& value) + { + if (auto list2 = any_cast(&value)) + return list == *list2; + return false; + } + + // Convert from core types to the boxed type + util::Any box(BinaryData v) const { return std::string(v); } + util::Any box(List v) const { return v; } + util::Any box(Object v) const { return v; } + util::Any box(Results v) const { return v; } + util::Any box(StringData v) const { return std::string(v); } + util::Any box(Timestamp v) const { return v; } + util::Any box(bool v) const { return v; } + util::Any box(double v) const { return v; } + util::Any box(float v) const { return v; } + util::Any box(int64_t v) const { return v; } + util::Any box(util::Optional v) const { return v; } + util::Any box(util::Optional v) const { return v; } + util::Any box(util::Optional v) const { return v; } + util::Any box(util::Optional v) const { return v; } + util::Any box(RowExpr) const; + + // Any properties are only supported by the Cocoa binding to enable reading + // old Realm files that may have used them. Other bindings can safely not + // implement this. + util::Any box(Mixed) const { REALM_TERMINATE("not supported"); } + + // Convert from the boxed type to core types. This needs to be implemented + // for all of the types which `box()` can take, plus `RowExpr` and optional + // versions of the numeric types, minus `List` and `Results`. + // + // `create` and `update` are only applicable to `unbox`. If + // `create` is false then when given something which is not a managed Realm + // object `unbox()` should simply return a detached row expr, while if it's + // true then `unbox()` should create a new object in the context's Realm + // using the provided value. If `update` is true then upsert semantics + // should be used for this. + template + T unbox(util::Any& v, bool /*create*/= false, bool /*update*/= false) const { return any_cast(v); } + + bool is_null(util::Any const& v) const noexcept { return !v.has_value(); } + util::Any null_value() const noexcept { return {}; } + util::Optional no_value() const noexcept { return {}; } + + // KVO hooks which will be called before and after modying a property from + // within Object::create(). + void will_change(Object const&, Property const&) {} + void did_change() {} + + // Get a string representation of the given value for use in error messages. + std::string print(util::Any const&) const { return "not implemented"; } + + // Cocoa allows supplying fewer values than there are properties when + // creating objects using an array of values. Other bindings should not + // mimick this behavior so just return false here. + bool allow_missing(util::Any const&) const { return false; } + +private: + std::shared_ptr realm; + const ObjectSchema* object_schema = nullptr; + +}; + +inline util::Any CppContext::box(RowExpr row) const +{ + REALM_ASSERT(object_schema); + return Object(realm, *object_schema, row); +} + +template<> +inline StringData CppContext::unbox(util::Any& v, bool, bool) const +{ + if (!v.has_value()) + return StringData(); + auto& value = any_cast(v); + return StringData(value.c_str(), value.size()); +} + +template<> +inline BinaryData CppContext::unbox(util::Any& v, bool, bool) const +{ + if (!v.has_value()) + return BinaryData(); + auto& value = any_cast(v); + return BinaryData(value.c_str(), value.size()); +} + +template<> +inline RowExpr CppContext::unbox(util::Any& v, bool create, bool update) const +{ + if (auto object = any_cast(&v)) + return object->row(); + if (auto row = any_cast(&v)) + return *row; + if (!create) + return RowExpr(); + + REALM_ASSERT(object_schema); + return Object::create(const_cast(*this), realm, *object_schema, v, update).row(); +} + +template<> +inline util::Optional CppContext::unbox(util::Any& v, bool, bool) const +{ + return v.has_value() ? util::make_optional(unbox(v)) : util::none; +} + +template<> +inline util::Optional CppContext::unbox(util::Any& v, bool, bool) const +{ + return v.has_value() ? util::make_optional(unbox(v)) : util::none; +} + +template<> +inline util::Optional CppContext::unbox(util::Any& v, bool, bool) const +{ + return v.has_value() ? util::make_optional(unbox(v)) : util::none; +} + +template<> +inline util::Optional CppContext::unbox(util::Any& v, bool, bool) const +{ + return v.has_value() ? util::make_optional(unbox(v)) : util::none; +} + +template<> +inline Mixed CppContext::unbox(util::Any&, bool, bool) const +{ + throw std::logic_error("'Any' type is unsupported"); +} +} + +#endif // REALM_OS_OBJECT_ACCESSOR_IMPL_HPP