added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / binding_context.hpp
1 ////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2015 Realm Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 ////////////////////////////////////////////////////////////////////////////
18
19 #ifndef BINDING_CONTEXT_HPP
20 #define BINDING_CONTEXT_HPP
21
22 #include "index_set.hpp"
23
24 #include <memory>
25 #include <tuple>
26 #include <vector>
27
28 namespace realm {
29 // BindingContext is the extension point for adding binding-specific behavior to
30 // a SharedRealm. It can be used to store additonal data associated with the
31 // Realm which is needed by the binding, and there are several methods which
32 // can be overridden to receive notifications of state changes within the Realm.
33 //
34 // A simple implementation which lets the user register functions to be
35 // called on refresh could look like the following:
36 //
37 // class BindingContextImplementation : public BindingContext {
38 // public:
39 //     // A token returned from add_notification that can be used to remove the
40 //     // notification later
41 //     struct token : private std::list<std::function<void ()>>::iterator {
42 //         token(std::list<std::function<void ()>>::iterator it) : std::list<std::function<void ()>>::iterator(it) { }
43 //         friend class DelegateImplementation;
44 //     };
45 //
46 //     token add_notification(std::function<void ()> func)
47 //     {
48 //         m_registered_notifications.push_back(std::move(func));
49 //         return token(std::prev(m_registered_notifications.end()));
50 //     }
51 //
52 //     void remove_notification(token entry)
53 //     {
54 //         m_registered_notifications.erase(entry);
55 //     }
56 //
57 //     // Override the did_change method to call each registered notification
58 //     void did_change(std::vector<ObserverState> const&, std::vector<void*> const&, bool) override
59 //     {
60 //         // Loop oddly so that unregistering a notification from within the
61 //         // registered function works
62 //         for (auto it = m_registered_notifications.begin(); it != m_registered_notifications.end(); ) {
63 //             (*it++)();
64 //         }
65 //     }
66 //
67 // private:
68 //     std::list<std::function<void ()>> m_registered_notifications;
69 // };
70 class Realm;
71 class Schema;
72 class BindingContext {
73 public:
74     virtual ~BindingContext() = default;
75
76     std::weak_ptr<Realm> realm;
77
78     // If the user adds a notification handler to the Realm, will it ever
79     // actually be called?
80     virtual bool can_deliver_notifications() const noexcept { return true; }
81
82     // Called by the Realm when refresh called or a notification arrives which
83     // is triggered through write transaction committed by itself or a different
84     // Realm instance.
85     virtual void before_notify() { }
86
87     // Called by the Realm when a write transaction is committed to the file by
88     // a different Realm instance (possibly in a different process)
89     virtual void changes_available() { }
90
91     struct ObserverState;
92
93     // Override this function if you want to receive detailed information about
94     // external changes to a specific set of objects.
95     // This is called before each operation which may advance the read
96     // transaction to include
97     // ObserverStates for each row for which detailed change information is
98     // desired.
99     virtual std::vector<ObserverState> get_observed_rows() { return {}; }
100
101     // Called immediately before the read transaction is advanced if detailed
102     // change information was requested (by returning a non-empty array from
103     // get_observed_rows()).
104     // The observers vector is the vector returned by get_observed_row(),
105     // updated with change information. The invalidated vector is a list of the
106     // `info` fields of observed rows which will be deleted.
107     virtual void will_change(std::vector<ObserverState> const& observers,
108                              std::vector<void*> const& invalidated);
109
110     // Called immediately after the read transaction version is advanced. Unlike
111     // will_change(), this is called even if detailed change information was not
112     // requested or if the Realm is not actually in a read transaction, although
113     // both vectors will be empty in that case.
114     virtual void did_change(std::vector<ObserverState> const& observers,
115                             std::vector<void*> const& invalidated,
116                             bool version_changed=true);
117
118     // Called immediately after the corresponding Realm's schema is changed through
119     // update_schema()/set_schema_subset() or the schema is changed by another Realm
120     // instance. The parameter is a schema reference which is the same as the return
121     // value of Realm::schema().
122     virtual void schema_did_change(Schema const&) {}
123
124     // Change information for a single field of a row
125     struct ColumnInfo {
126         // The index of this column prior to the changes in the tracked
127         // transaction, or -1 for newly inserted columns.
128         size_t initial_column_index = -1;
129         // What kind of change occurred?
130         // Always Set or None for everything but LinkList columns.
131         enum class Kind {
132             None,   // No change
133             Set,    // The value or entries at `indices` were assigned to
134             Insert, // New values were inserted at each of the indices given
135             Remove, // Values were removed at each of the indices given
136             SetAll  // The entire LinkList has been replaced with a new set of values
137         } kind = Kind::None;
138         // The indices where things happened for Set, Insert and Remove on
139         // LinkList columns. Not used for other types or for None or SetAll.
140         IndexSet indices;
141     };
142
143     // Information about an observed row in a table
144     //
145     // Each object which needs detailed change information should have an
146     // ObserverState entry in the vector returned from get_observed_rows(), with
147     // the initial table and row indexes set (and optionally the info field).
148     // The Realm parses the transaction log, and populates the `changes` vector
149     // in each ObserverState with information about what changes were made.
150     struct ObserverState {
151         // Initial table and row which is observed
152         // May be updated by row insertions and removals
153         size_t table_ndx;
154         size_t row_ndx;
155
156         // Opaque userdata for the delegate's use
157         void* info;
158
159         // Populated with information about which columns were changed
160         // May be shorter than the actual number of columns if the later columns
161         // are not modified
162         std::vector<ColumnInfo> changes;
163
164         // Simple lexographic ordering
165         friend bool operator<(ObserverState const& lft, ObserverState const& rgt)
166         {
167             return std::tie(lft.table_ndx, lft.row_ndx) < std::tie(rgt.table_ndx, rgt.row_ndx);
168         }
169     };
170 };
171
172 inline void BindingContext::will_change(std::vector<ObserverState> const&, std::vector<void*> const&) { }
173 inline void BindingContext::did_change(std::vector<ObserverState> const&, std::vector<void*> const&, bool) { }
174 } // namespace realm
175
176 #endif /* BINDING_CONTEXT_HPP */