X-Git-Url: https://git.mdrn.pl/wl-app.git/blobdiff_plain/53b27422d140022594fc241cca91c3183be57bca..48b2fe9f7c2dc3d9aeaaa6dbfb27c7da4f3235ff:/iOS/Pods/Realm/include/core/realm/link_view.hpp diff --git a/iOS/Pods/Realm/include/core/realm/link_view.hpp b/iOS/Pods/Realm/include/core/realm/link_view.hpp new file mode 100644 index 0000000..14be525 --- /dev/null +++ b/iOS/Pods/Realm/include/core/realm/link_view.hpp @@ -0,0 +1,397 @@ +/************************************************************************* + * + * 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_LINK_VIEW_HPP +#define REALM_LINK_VIEW_HPP + +#include +#include +#include +#include + +namespace realm { + +class LinkListColumn; + +namespace _impl { +class LinkListFriend; +class TransactLogConvenientEncoder; +} + + +/// The effect of calling most of the link list functions on a detached accessor +/// is unspecified and may lead to general corruption, or even a crash. The +/// exceptions are is_attached() and the destructor. +/// +/// FIXME: Rename this class to `LinkList`. +class LinkView : public RowIndexes, public std::enable_shared_from_this { +public: + ~LinkView() noexcept; + bool is_attached() const noexcept; + + /// This method will return true if the LinkView is detached (no assert). + bool is_empty() const noexcept; + + /// This method will return 0 if the LinkView is detached (no assert). + size_t size() const noexcept override; + + bool operator==(const LinkView&) const noexcept; + bool operator!=(const LinkView&) const noexcept; + + // Getting links + Table::ConstRowExpr operator[](size_t link_ndx) const noexcept; + Table::RowExpr operator[](size_t link_ndx) noexcept; + Table::ConstRowExpr get(size_t link_ndx) const noexcept; + Table::RowExpr get(size_t link_ndx) noexcept; + + // Modifiers + void add(size_t target_row_ndx); + void insert(size_t link_ndx, size_t target_row_ndx); + void set(size_t link_ndx, size_t target_row_ndx); + /// Move the link at \a from_ndx such that it ends up at \a to_ndx. Other + /// links are shifted as necessary in such a way that their order is + /// preserved. + /// + /// Note that \a to_ndx is the desired final index of the moved link, + /// therefore, `move(1,1)` is a no-op, while `move(1,2)` moves the link at + /// index 1 by one position, such that it ends up at index 2. A side-effect + /// of that, is that the link, that was originally at index 2, is moved to + /// index 1. + void move(size_t from_ndx, size_t to_ndx); + void swap(size_t link1_ndx, size_t link2_ndx); + void remove(size_t link_ndx); + void clear(); + + void sort(size_t column, bool ascending = true); + void sort(SortDescriptor&& order); + + TableView get_sorted_view(size_t column_index, bool ascending = true) const; + TableView get_sorted_view(SortDescriptor order) const; + + /// Remove the target row of the specified link from the target table. This + /// also removes the specified link from this link list, and any other link + /// pointing to that row. This is merely a shorthand for + /// `get_target_table.move_last_over(get(link_ndx))`. + void remove_target_row(size_t link_ndx); + + /// Remove all target rows pointed to by links in this link list, and clear + /// this link list. + void remove_all_target_rows(); + + /// Search this list for a link to the specified target table row (specified + /// by its index in the target table). If found, the index of the link to + /// that row within this list is returned, otherwise `realm::not_found` is + /// returned. + size_t find(size_t target_row_ndx, size_t start = 0) const noexcept; + + const ColumnBase& get_column_base(size_t index) + const override; // FIXME: `ColumnBase` is not part of the public API, so this function must be made private. + const Table& get_origin_table() const noexcept; + Table& get_origin_table() noexcept; + + size_t get_origin_row_index() const noexcept; + + const Table& get_target_table() const noexcept; + Table& get_target_table() noexcept; + + // No-op because LinkViews are always kept in sync. + uint_fast64_t sync_if_needed() const override; + bool is_in_sync() const override + { + return true; + } + +private: + struct ctor_cookie { + }; + + TableRef m_origin_table; + LinkListColumn* m_origin_column; + + using HandoverPatch = LinkViewHandoverPatch; + static void generate_patch(const ConstLinkViewRef& ref, std::unique_ptr& patch); + static LinkViewRef create_from_and_consume_patch(std::unique_ptr& patch, Group& group); + + void detach(); + void set_origin_row_index(size_t row_ndx) noexcept; + + void do_insert(size_t link_ndx, size_t target_row_ndx); + size_t do_set(size_t link_ndx, size_t target_row_ndx); + size_t do_remove(size_t link_ndx); + void do_clear(bool broken_reciprocal_backlinks); + + void do_nullify_link(size_t old_target_row_ndx); + void do_update_link(size_t old_target_row_ndx, size_t new_target_row_ndx); + void do_swap_link(size_t target_row_ndx_1, size_t target_row_ndx_2); + + void refresh_accessor_tree(size_t new_row_ndx) noexcept; + + void update_from_parent(size_t old_baseline) noexcept; + + Replication* get_repl() noexcept; + void repl_unselect() noexcept; + friend class _impl::TransactLogConvenientEncoder; + +#ifdef REALM_DEBUG + void verify(size_t row_ndx) const; +#endif + // allocate using make_shared: + static std::shared_ptr create(Table* origin_table, LinkListColumn&, size_t row_ndx); + static std::shared_ptr create_detached(); + + friend class _impl::LinkListFriend; + friend class LinkListColumn; + friend class LangBindHelper; + friend class SharedGroup; + friend class Query; + friend class TableViewBase; + + // must be public for use by make_shared, but cannot be called from outside, + // because ctor_cookie is private +public: + LinkView(const ctor_cookie&, Table* origin_table, LinkListColumn&, size_t row_ndx); + LinkView(const ctor_cookie&); +}; + + +// Implementation + +inline LinkView::LinkView(const ctor_cookie&, Table* origin_table, LinkListColumn& column, size_t row_ndx) + : RowIndexes(IntegerColumn::unattached_root_tag(), column.get_alloc()) // Throws + , m_origin_table(origin_table->get_table_ref()) + , m_origin_column(&column) +{ + m_row_indexes.set_parent(m_origin_column, row_ndx); + m_row_indexes.init_from_parent(); +} + +// create a detached LinkView. Only partially initialized, as it will never be used for +// anything, but indicating that it is detached. +inline LinkView::LinkView(const ctor_cookie&) + : RowIndexes(IntegerColumn::unattached_root_tag(), Allocator::get_default()) // Throws + , m_origin_table(TableRef()) + , m_origin_column(nullptr) +{ +} + +inline std::shared_ptr LinkView::create(Table* origin_table, LinkListColumn& column, size_t row_ndx) +{ + return std::make_shared(ctor_cookie(), origin_table, column, row_ndx); +} + +inline std::shared_ptr LinkView::create_detached() +{ + return std::make_shared(ctor_cookie()); +} + +inline LinkView::~LinkView() noexcept +{ + if (is_attached()) { + repl_unselect(); + m_origin_column->unregister_linkview(); + } +} + +inline void LinkView::detach() +{ + REALM_ASSERT(is_attached()); + repl_unselect(); + m_origin_table.reset(); + m_row_indexes.detach(); +} + +inline bool LinkView::is_attached() const noexcept +{ + return static_cast(m_origin_table); +} + +inline bool LinkView::is_empty() const noexcept +{ + if (!is_attached()) + return true; + + if (!m_row_indexes.is_attached()) + return true; + + return m_row_indexes.is_empty(); +} + +inline size_t LinkView::size() const noexcept +{ + if (!is_attached()) + return 0; + + if (!m_row_indexes.is_attached()) + return 0; + + return m_row_indexes.size(); +} + +inline bool LinkView::operator==(const LinkView& link_list) const noexcept +{ + Table& target_table_1 = m_origin_column->get_target_table(); + Table& target_table_2 = link_list.m_origin_column->get_target_table(); + if (target_table_1.get_index_in_group() != target_table_2.get_index_in_group()) + return false; + if (!m_row_indexes.is_attached() || m_row_indexes.is_empty()) { + return !link_list.m_row_indexes.is_attached() || link_list.m_row_indexes.is_empty(); + } + return link_list.m_row_indexes.is_attached() && m_row_indexes.compare(link_list.m_row_indexes); +} + +inline bool LinkView::operator!=(const LinkView& link_list) const noexcept +{ + return !(*this == link_list); +} + +inline Table::ConstRowExpr LinkView::get(size_t link_ndx) const noexcept +{ + return const_cast(this)->get(link_ndx); +} + +inline Table::RowExpr LinkView::get(size_t link_ndx) noexcept +{ + REALM_ASSERT(is_attached()); + REALM_ASSERT(m_row_indexes.is_attached()); + REALM_ASSERT_3(link_ndx, <, m_row_indexes.size()); + + Table& target_table = m_origin_column->get_target_table(); + size_t target_row_ndx = to_size_t(m_row_indexes.get(link_ndx)); + return target_table[target_row_ndx]; +} + +inline Table::ConstRowExpr LinkView::operator[](size_t link_ndx) const noexcept +{ + return get(link_ndx); +} + +inline Table::RowExpr LinkView::operator[](size_t link_ndx) noexcept +{ + return get(link_ndx); +} + +inline void LinkView::add(size_t target_row_ndx) +{ + REALM_ASSERT(is_attached()); + size_t ins_pos = (m_row_indexes.is_attached()) ? m_row_indexes.size() : 0; + insert(ins_pos, target_row_ndx); +} + +inline size_t LinkView::find(size_t target_row_ndx, size_t start) const noexcept +{ + REALM_ASSERT(is_attached()); + REALM_ASSERT_3(target_row_ndx, <, m_origin_column->get_target_table().size()); + REALM_ASSERT_3(start, <=, size()); + + if (!m_row_indexes.is_attached()) + return not_found; + + return m_row_indexes.find_first(target_row_ndx, start); +} + +inline const ColumnBase& LinkView::get_column_base(size_t index) const +{ + return get_target_table().get_column_base(index); +} + +inline const Table& LinkView::get_origin_table() const noexcept +{ + return *m_origin_table; +} + +inline Table& LinkView::get_origin_table() noexcept +{ + return *m_origin_table; +} + +inline size_t LinkView::get_origin_row_index() const noexcept +{ + REALM_ASSERT(is_attached()); + return m_row_indexes.get_root_array()->get_ndx_in_parent(); +} + +inline void LinkView::set_origin_row_index(size_t row_ndx) noexcept +{ + REALM_ASSERT(is_attached()); + m_row_indexes.get_root_array()->set_ndx_in_parent(row_ndx); +} + +inline const Table& LinkView::get_target_table() const noexcept +{ + return m_origin_column->get_target_table(); +} + +inline Table& LinkView::get_target_table() noexcept +{ + return m_origin_column->get_target_table(); +} + +inline void LinkView::refresh_accessor_tree(size_t new_row_ndx) noexcept +{ + set_origin_row_index(new_row_ndx); + m_row_indexes.init_from_parent(); +} + +inline void LinkView::update_from_parent(size_t old_baseline) noexcept +{ + if (m_row_indexes.is_attached()) + m_row_indexes.update_from_parent(old_baseline); +} + +inline Replication* LinkView::get_repl() noexcept +{ + typedef _impl::TableFriend tf; + return tf::get_repl(*m_origin_table); +} + + +// The purpose of this class is to give internal access to some, but not all of +// the non-public parts of LinkView. +class _impl::LinkListFriend { +public: + static void do_set(LinkView& list, size_t link_ndx, size_t target_row_ndx) + { + list.do_set(link_ndx, target_row_ndx); + } + + static void do_remove(LinkView& list, size_t link_ndx) + { + list.do_remove(link_ndx); + } + + static void do_clear(LinkView& list) + { + bool broken_reciprocal_backlinks = false; + list.do_clear(broken_reciprocal_backlinks); + } + + static void do_insert(LinkView& list, size_t link_ndx, size_t target_row_ndx) + { + list.do_insert(link_ndx, target_row_ndx); + } + + static const LinkListColumn& get_origin_column(const LinkView& list) + { + REALM_ASSERT(list.is_attached()); + return *list.m_origin_column; + } +}; + +} // namespace realm + +#endif // REALM_LINK_VIEW_HPP