added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / binary_data.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_BINARY_DATA_HPP
20 #define REALM_BINARY_DATA_HPP
21
22 #include <realm/owned_data.hpp>
23 #include <realm/util/features.h>
24 #include <realm/utilities.hpp>
25
26 #include <algorithm>
27 #include <cstddef>
28 #include <ostream>
29 #include <string>
30
31 namespace realm {
32
33 /// A reference to a chunk of binary data.
34 ///
35 /// This class does not own the referenced memory, nor does it in any other way
36 /// attempt to manage the lifetime of it.
37 ///
38 /// \sa StringData
39 class BinaryData {
40 public:
41     BinaryData() noexcept
42         : m_data(nullptr)
43         , m_size(0)
44     {
45     }
46     BinaryData(const char* external_data, size_t data_size) noexcept
47         : m_data(external_data)
48         , m_size(data_size)
49     {
50     }
51     template <size_t N>
52     explicit BinaryData(const char (&external_data)[N])
53         : m_data(external_data)
54         , m_size(N)
55     {
56     }
57     template <class T, class A>
58     explicit BinaryData(const std::basic_string<char, T, A>&);
59
60     // BinaryData does not store data, callers must manage their own strings.
61     template <class T, class A>
62     BinaryData(const std::basic_string<char, T, A>&&) = delete;
63
64     template <class T, class A>
65     explicit operator std::basic_string<char, T, A>() const;
66
67     char operator[](size_t i) const noexcept
68     {
69         return m_data[i];
70     }
71
72     const char* data() const noexcept
73     {
74         return m_data;
75     }
76     size_t size() const noexcept
77     {
78         return m_size;
79     }
80
81     /// Is this a null reference?
82     ///
83     /// An instance of BinaryData is a null reference when, and only when the
84     /// stored size is zero (size()) and the stored pointer is the null pointer
85     /// (data()).
86     ///
87     /// In the case of the empty byte sequence, the stored size is still zero,
88     /// but the stored pointer is **not** the null pointer. Note that the actual
89     /// value of the pointer is immaterial in this case (as long as it is not
90     /// zero), because when the size is zero, it is an error to dereference the
91     /// pointer.
92     ///
93     /// Conversion of a BinaryData object to `bool` yields the logical negation
94     /// of the result of calling this function. In other words, a BinaryData
95     /// object is converted to true if it is not the null reference, otherwise
96     /// it is converted to false.
97     ///
98     /// It is important to understand that all of the functions and operators in
99     /// this class, and most of the functions in the Realm API in general
100     /// makes no distinction between a null reference and a reference to the
101     /// empty byte sequence. These functions and operators never look at the
102     /// stored pointer if the stored size is zero.
103     bool is_null() const noexcept;
104
105     friend bool operator==(const BinaryData&, const BinaryData&) noexcept;
106     friend bool operator!=(const BinaryData&, const BinaryData&) noexcept;
107
108     //@{
109     /// Trivial bytewise lexicographical comparison.
110     friend bool operator<(const BinaryData&, const BinaryData&) noexcept;
111     friend bool operator>(const BinaryData&, const BinaryData&) noexcept;
112     friend bool operator<=(const BinaryData&, const BinaryData&) noexcept;
113     friend bool operator>=(const BinaryData&, const BinaryData&) noexcept;
114     //@}
115
116     bool begins_with(BinaryData) const noexcept;
117     bool ends_with(BinaryData) const noexcept;
118     bool contains(BinaryData) const noexcept;
119
120     template <class C, class T>
121     friend std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>&, const BinaryData&);
122
123     explicit operator bool() const noexcept;
124
125 private:
126     const char* m_data;
127     size_t m_size;
128 };
129
130 /// A read-only chunk of binary data.
131 class OwnedBinaryData : public OwnedData {
132 public:
133     using OwnedData::OwnedData;
134
135     OwnedBinaryData() = default;
136     OwnedBinaryData(const BinaryData& binary_data)
137         : OwnedData(binary_data.data(), binary_data.size())
138     {
139     }
140
141     BinaryData get() const
142     {
143         return {data(), size()};
144     }
145 };
146
147
148 // Implementation:
149
150 template <class T, class A>
151 inline BinaryData::BinaryData(const std::basic_string<char, T, A>& s)
152     : m_data(s.data())
153     , m_size(s.size())
154 {
155 }
156
157 template <class T, class A>
158 inline BinaryData::operator std::basic_string<char, T, A>() const
159 {
160     return std::basic_string<char, T, A>(m_data, m_size);
161 }
162
163 inline bool BinaryData::is_null() const noexcept
164 {
165     return !m_data;
166 }
167
168 inline bool operator==(const BinaryData& a, const BinaryData& b) noexcept
169 {
170     return a.m_size == b.m_size && a.is_null() == b.is_null() && safe_equal(a.m_data, a.m_data + a.m_size, b.m_data);
171 }
172
173 inline bool operator!=(const BinaryData& a, const BinaryData& b) noexcept
174 {
175     return !(a == b);
176 }
177
178 inline bool operator<(const BinaryData& a, const BinaryData& b) noexcept
179 {
180     if (a.is_null() || b.is_null())
181         return !a.is_null() < !b.is_null();
182
183     return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, b.m_data, b.m_data + b.m_size);
184 }
185
186 inline bool operator>(const BinaryData& a, const BinaryData& b) noexcept
187 {
188     return b < a;
189 }
190
191 inline bool operator<=(const BinaryData& a, const BinaryData& b) noexcept
192 {
193     return !(b < a);
194 }
195
196 inline bool operator>=(const BinaryData& a, const BinaryData& b) noexcept
197 {
198     return !(a < b);
199 }
200
201 inline bool BinaryData::begins_with(BinaryData d) const noexcept
202 {
203     if (is_null() && !d.is_null())
204         return false;
205
206     return d.m_size <= m_size && safe_equal(m_data, m_data + d.m_size, d.m_data);
207 }
208
209 inline bool BinaryData::ends_with(BinaryData d) const noexcept
210 {
211     if (is_null() && !d.is_null())
212         return false;
213
214     return d.m_size <= m_size && safe_equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data);
215 }
216
217 inline bool BinaryData::contains(BinaryData d) const noexcept
218 {
219     if (is_null() && !d.is_null())
220         return false;
221
222     return d.m_size == 0 || std::search(m_data, m_data + m_size, d.m_data, d.m_data + d.m_size) != m_data + m_size;
223 }
224
225 template <class C, class T>
226 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const BinaryData& d)
227 {
228     out << "BinaryData(" << static_cast<const void*>(d.m_data) << ", " << d.m_size << ")";
229     return out;
230 }
231
232 inline BinaryData::operator bool() const noexcept
233 {
234     return !is_null();
235 }
236
237 } // namespace realm
238
239 #endif // REALM_BINARY_DATA_HPP