Blame view

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