1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
19 #ifndef REALM_BINARY_DATA_HPP
20 #define REALM_BINARY_DATA_HPP
22 #include <realm/owned_data.hpp>
23 #include <realm/util/features.h>
24 #include <realm/utilities.hpp>
33 /// A reference to a chunk of binary data.
35 /// This class does not own the referenced memory, nor does it in any other way
36 /// attempt to manage the lifetime of it.
46 BinaryData(const char* external_data, size_t data_size) noexcept
47 : m_data(external_data)
52 explicit BinaryData(const char (&external_data)[N])
53 : m_data(external_data)
57 template <class T, class A>
58 explicit BinaryData(const std::basic_string<char, T, A>&);
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;
64 template <class T, class A>
65 explicit operator std::basic_string<char, T, A>() const;
67 char operator[](size_t i) const noexcept
72 const char* data() const noexcept
76 size_t size() const noexcept
81 /// Is this a null reference?
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
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
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.
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;
105 friend bool operator==(const BinaryData&, const BinaryData&) noexcept;
106 friend bool operator!=(const BinaryData&, const BinaryData&) noexcept;
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;
116 bool begins_with(BinaryData) const noexcept;
117 bool ends_with(BinaryData) const noexcept;
118 bool contains(BinaryData) const noexcept;
120 template <class C, class T>
121 friend std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>&, const BinaryData&);
123 explicit operator bool() const noexcept;
130 /// A read-only chunk of binary data.
131 class OwnedBinaryData : public OwnedData {
133 using OwnedData::OwnedData;
135 OwnedBinaryData() = default;
136 OwnedBinaryData(const BinaryData& binary_data)
137 : OwnedData(binary_data.data(), binary_data.size())
141 BinaryData get() const
143 return {data(), size()};
150 template <class T, class A>
151 inline BinaryData::BinaryData(const std::basic_string<char, T, A>& s)
157 template <class T, class A>
158 inline BinaryData::operator std::basic_string<char, T, A>() const
160 return std::basic_string<char, T, A>(m_data, m_size);
163 inline bool BinaryData::is_null() const noexcept
168 inline bool operator==(const BinaryData& a, const BinaryData& b) noexcept
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);
173 inline bool operator!=(const BinaryData& a, const BinaryData& b) noexcept
178 inline bool operator<(const BinaryData& a, const BinaryData& b) noexcept
180 if (a.is_null() || b.is_null())
181 return !a.is_null() < !b.is_null();
183 return std::lexicographical_compare(a.m_data, a.m_data + a.m_size, b.m_data, b.m_data + b.m_size);
186 inline bool operator>(const BinaryData& a, const BinaryData& b) noexcept
191 inline bool operator<=(const BinaryData& a, const BinaryData& b) noexcept
196 inline bool operator>=(const BinaryData& a, const BinaryData& b) noexcept
201 inline bool BinaryData::begins_with(BinaryData d) const noexcept
203 if (is_null() && !d.is_null())
206 return d.m_size <= m_size && safe_equal(m_data, m_data + d.m_size, d.m_data);
209 inline bool BinaryData::ends_with(BinaryData d) const noexcept
211 if (is_null() && !d.is_null())
214 return d.m_size <= m_size && safe_equal(m_data + m_size - d.m_size, m_data + m_size, d.m_data);
217 inline bool BinaryData::contains(BinaryData d) const noexcept
219 if (is_null() && !d.is_null())
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;
225 template <class C, class T>
226 inline std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& out, const BinaryData& d)
228 out << "BinaryData(" << static_cast<const void*>(d.m_data) << ", " << d.m_size << ")";
232 inline BinaryData::operator bool() const noexcept
239 #endif // REALM_BINARY_DATA_HPP