diff --git a/src/list.cpp b/src/list.cpp index cc9ec842..8276eb50 100644 --- a/src/list.cpp +++ b/src/list.cpp @@ -21,9 +21,10 @@ #include "impl/list_notifier.hpp" #include "impl/realm_coordinator.hpp" #include "results.hpp" +#include "shared_realm.hpp" #include "util/format.hpp" -#include +#include using namespace realm; using namespace realm::_impl; @@ -49,11 +50,17 @@ Query List::get_query() const return m_link_view->get_target_table().where(m_link_view); } +size_t List::get_origin_row_index() const +{ + verify_attached(); + return m_link_view->get_origin_row_index(); +} + void List::verify_valid_row(size_t row_ndx, bool insertion) const { size_t size = m_link_view->size(); if (row_ndx > size || (!insertion && row_ndx == size)) { - throw std::out_of_range(util::format("Index %1 is outside of range 0...%2.", row_ndx, size)); + throw OutOfBoundsIndexException{row_ndx, size + insertion}; } } @@ -66,7 +73,7 @@ bool List::is_valid() const void List::verify_attached() const { if (!is_valid()) { - throw std::runtime_error("LinkView is not attached"); + throw InvalidatedException{}; } } @@ -91,6 +98,11 @@ RowExpr List::get(size_t row_ndx) const return m_link_view->get(row_ndx); } +size_t List::get_unchecked(size_t row_ndx) const noexcept +{ + return m_link_view->get(row_ndx).get_index(); +} + size_t List::find(ConstRow const& row) const { verify_attached(); @@ -191,3 +203,7 @@ NotificationToken List::add_notification_callback(CollectionChangeCallback cb) } return {m_notifier, m_notifier->add_callback(std::move(cb))}; } + +List::OutOfBoundsIndexException::OutOfBoundsIndexException(size_t r, size_t c) +: std::out_of_range(util::format("Requested index %1 greater than max %2", r, c)) +, requested(r), valid_count(c) {} diff --git a/src/list.hpp b/src/list.hpp index 4b1e178d..7c412e67 100644 --- a/src/list.hpp +++ b/src/list.hpp @@ -37,10 +37,6 @@ class Realm; class Results; struct SortOrder; -namespace _impl { - class BackgroundCollection; -} - class List { public: List() noexcept; @@ -55,6 +51,7 @@ public: const std::shared_ptr& get_realm() const { return m_realm; } Query get_query() const; const ObjectSchema& get_object_schema() const { return *m_object_schema; } + size_t get_origin_row_index() const; bool is_valid() const; void verify_attached() const; @@ -62,6 +59,7 @@ public: size_t size() const; RowExpr get(size_t row_ndx) const; + size_t get_unchecked(size_t row_ndx) const noexcept; size_t find(ConstRow const& row) const; void add(size_t target_row_ndx); @@ -91,6 +89,20 @@ public: template void set(ContextType ctx, ValueType value, size_t list_ndx); + // The List object has been invalidated (due to the Realm being invalidated, + // or the containing object being deleted) + // All non-noexcept functions can throw this + struct InvalidatedException : public std::runtime_error { + InvalidatedException() : std::runtime_error("Access to invalidated List object") {} + }; + + // The input index parameter was out of bounds + struct OutOfBoundsIndexException : public std::out_of_range { + OutOfBoundsIndexException(size_t r, size_t c); + size_t requested; + size_t valid_count; + }; + private: std::shared_ptr m_realm; const ObjectSchema* m_object_schema;