added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / column_timestamp.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 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 REALM_COLUMN_TIMESTAMP_HPP
20 #define REALM_COLUMN_TIMESTAMP_HPP
21
22 #include <realm/column.hpp>
23 #include <realm/timestamp.hpp>
24
25 namespace realm {
26
27 // Inherits from ColumnTemplate to get a compare_values() that can be called without knowing the
28 // column type
29 class TimestampColumn : public ColumnBaseSimple {
30 public:
31     TimestampColumn(bool nullable, Allocator& alloc, ref_type ref, size_t col_ndx = npos);
32
33     static ref_type create(Allocator& alloc, size_t size, bool nullable);
34     static size_t get_size_from_ref(ref_type root_ref, Allocator& alloc) noexcept;
35
36     /// Get the number of entries in this column. This operation is relatively
37     /// slow.
38     size_t size() const noexcept override;
39     /// Whether or not this column is nullable.
40     bool is_nullable() const noexcept override;
41     /// Whether or not the value at \a row_ndx is NULL. If the column is not
42     /// nullable, always returns false.
43     bool is_null(size_t row_ndx) const noexcept override;
44     /// Sets the value at \a row_ndx to be NULL.
45     /// \throw LogicError Thrown if this column is not nullable.
46     void set_null(size_t row_ndx) override;
47     void insert_rows(size_t row_ndx, size_t num_rows_to_insert, size_t prior_num_rows, bool nullable) override;
48     void erase_rows(size_t row_ndx, size_t num_rows_to_erase, size_t prior_num_rows,
49                     bool broken_reciprocal_backlinks) override;
50     void move_last_row_over(size_t row_ndx, size_t prior_num_rows, bool broken_reciprocal_backlinks) override;
51     void clear(size_t num_rows, bool broken_reciprocal_backlinks) override;
52     void swap_rows(size_t row_ndx_1, size_t row_ndx_2) override;
53     void destroy() noexcept override;
54
55     bool has_search_index() const noexcept final
56     {
57         return bool(m_search_index);
58     }
59     StringIndex* get_search_index() noexcept final
60     {
61         return m_search_index.get();
62     }
63     StringIndex* get_search_index() const noexcept final
64     {
65         return m_search_index.get();
66     }
67     void destroy_search_index() noexcept override;
68     void set_search_index_ref(ref_type ref, ArrayParent* parent, size_t ndx_in_parent) final;
69     void populate_search_index();
70     StringIndex* create_search_index() override;
71     bool supports_search_index() const noexcept final
72     {
73         return true;
74     }
75
76     StringData get_index_data(size_t, StringIndex::StringConversionBuffer& buffer) const noexcept override;
77     ref_type write(size_t slice_offset, size_t slice_size, size_t table_size, _impl::OutputStream&) const override;
78     void update_from_parent(size_t old_baseline) noexcept override;
79     void set_ndx_in_parent(size_t ndx) noexcept override;
80     void refresh_accessor_tree(size_t new_col_ndx, const Spec&) override;
81
82     void verify() const override;
83     void to_dot(std::ostream&, StringData title = StringData()) const override;
84     void do_dump_node_structure(std::ostream&, int level) const override;
85     void leaf_to_dot(MemRef, ArrayParent*, size_t ndx_in_parent, std::ostream&) const override;
86
87     void add(const Timestamp& ts = Timestamp{});
88     Timestamp get(size_t row_ndx) const noexcept;
89     void set(size_t row_ndx, const Timestamp& ts);
90     bool compare(const TimestampColumn& c) const noexcept;
91     int compare_values(size_t row1, size_t row2) const noexcept override;
92
93     Timestamp maximum(size_t* result_index) const;
94     Timestamp minimum(size_t* result_index) const;
95     size_t count(Timestamp) const;
96     void erase(size_t row_ndx, bool is_last);
97
98     template <class Condition>
99     size_t find(Timestamp value, size_t begin, size_t end) const noexcept
100     {
101         // FIXME: Here we can do all sorts of clever optimizations. Use bithack-search on seconds, then for each match
102         // check nanoseconds, etc. Lots of possibilities. Below code is naive and slow but works.
103
104         Condition cond;
105         for (size_t t = begin; t < end; t++) {
106             Timestamp ts = get(t);
107             if (cond(ts, value, ts.is_null(), value.is_null()))
108                 return t;
109         }
110         return npos;
111     }
112
113     typedef Timestamp value_type;
114
115 private:
116     std::unique_ptr<BpTree<util::Optional<int64_t>>> m_seconds;
117     std::unique_ptr<BpTree<int64_t>> m_nanoseconds;
118
119     std::unique_ptr<StringIndex> m_search_index;
120     bool m_nullable;
121
122     template <class BT>
123     class CreateHandler;
124
125     template <class Condition>
126     Timestamp minmax(size_t* result_index) const noexcept
127     {
128         // Condition is realm::Greater for maximum and realm::Less for minimum. Any non-null value is both larger
129         // and smaller than a null value.
130         if (size() == 0) {
131             if (result_index)
132                 *result_index = npos;
133             return Timestamp{};
134         }
135
136         Timestamp best = get(0);
137         size_t best_index = best.is_null() ? npos : 0;
138
139         for (size_t i = 1; i < size(); ++i) {
140             Timestamp candidate = get(i);
141             // Condition() will return false if any of the two values are null.
142             if ((best.is_null() && !candidate.is_null()) || Condition()(candidate, best, candidate.is_null(), best.is_null())) {
143                 best = candidate;
144                 best_index = i;
145             }
146         }
147         if (result_index)
148             *result_index = best_index;
149         return best;
150     }
151 };
152
153 } // namespace realm
154
155 #endif // REALM_COLUMN_TIMESTAMP_HPP