blob: d23e8c833b3b4bcc478124eaa9c23d40905547de [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
3 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08005 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08008 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07009 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080013 */
14
15#ifndef NDN_BLOCK_HPP
16#define NDN_BLOCK_HPP
17
Alexander Afanasyev19508852014-01-29 01:01:51 -080018#include "../common.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080019
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080020#include "buffer.hpp"
21#include "tlv.hpp"
22
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080023namespace ndn {
24
Alexander Afanasyev233750e2014-02-16 00:50:07 -080025template<bool> class EncodingImpl;
26typedef EncodingImpl<true> EncodingBuffer;
27
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080028/**
29 * @brief Class representing wire element of the NDN packet
30 */
31class Block
32{
33public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080034 typedef std::vector<Block> element_container;
35 typedef element_container::iterator element_iterator;
36 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080037
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070038 /// @brief Error that can be thrown from Block
Yingdi Yue52f4ef2014-04-17 19:21:13 -070039 class Error : public Tlv::Error
Alexander Afanasyev937aa782014-03-21 13:17:57 -070040 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070041 public:
42 explicit
43 Error(const std::string& what)
Yingdi Yue52f4ef2014-04-17 19:21:13 -070044 : Tlv::Error(what)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070045 {
46 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -070047 };
48
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080049 /**
50 * @brief Default constructor to create an empty Block
51 */
52 Block();
53
54 /**
Alexander Afanasyev15151312014-02-16 00:53:51 -080055 * @brief Create block based on EncodingBuffer object
56 */
57 explicit
58 Block(const EncodingBuffer& buffer);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070059
Alexander Afanasyev15151312014-02-16 00:53:51 -080060 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070061 * @brief A helper version of a constructor to create Block from the raw buffer (type
62 * and value-length parsing)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070063 *
64 * This constructor provides ability of implicit conversion from ConstBufferPtr to Block
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080065 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070066 Block(const ConstBufferPtr& buffer);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080067
68 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080069 * @brief Another helper to create block from a buffer, directly specifying boundaries
70 * of the block within the buffer
71 *
72 * This version will automatically detect type and position of the value within the block
73 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070074 Block(const ConstBufferPtr& buffer,
75 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080076 bool verifyLength = true);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070077
Alexander Afanasyev187bc482014-02-06 15:04:04 -080078 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070079 * @brief A helper version of a constructor to create Block from the raw buffer (type
80 * and value-length parsing)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080081 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070082 Block(const uint8_t* buffer, size_t maxlength);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080083
Alexander Afanasyev937aa782014-03-21 13:17:57 -070084 Block(const void* buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080085
86 /*
Alexander Afanasyev937aa782014-03-21 13:17:57 -070087 * @brief A helper version of a constructor to create Block from the stream.
Yingdi Yu27158392014-01-20 13:04:20 -080088 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070089 explicit
Yingdi Yu27158392014-01-20 13:04:20 -080090 Block(std::istream& is);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070091
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080092 /**
93 * @brief Create Block from the wire buffer (no parsing)
94 *
95 * This version of the constructor does not do any parsing
96 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070097 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080098 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -070099 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
100 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800101
102 /**
103 * @brief Create Block of a specific type with empty wire buffer
104 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800105 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800106 Block(uint32_t type);
107
108 /**
109 * @brief Create Block of a specific type with the specified value
110 *
111 * The underlying buffer hold only value, additional operations are needed
112 * to construct wire encoding, one need to prepend the wire buffer with type
113 * and value-length VAR-NUMBERs
114 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700115 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800116
117 /**
118 * @brief Create nested Block of a specific type with the specified value
119 *
120 * The underlying buffer hold only value, additional operations are needed
121 * to construct wire encoding, one need to prepend the wire buffer with type
122 * and value-length VAR-NUMBERs
123 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800124 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700125 Block(uint32_t type, const Block& value);
126
127 /**
128 * @brief Try to construct block from Buffer, referencing data block pointed by wire
129 *
130 * @throws This method never throws an exception
131 *
132 * @returns true if Block successfully created, false if block cannot be created
133 */
134 static bool
135 fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block);
136
137 /**
138 * @brief Try to construct block from Buffer, referencing data block pointed by wire
139 *
140 * @throws This method never throws an exception
141 *
142 * @returns true if Block successfully created, false if block cannot be created
143 */
144 static bool
145 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800146
147 /**
148 * @brief Check if the Block is empty
149 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700150 bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800151 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700152
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800153 /**
154 * @brief Check if the Block has fully encoded wire
155 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700156 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800157 hasWire() const;
158
159 /**
160 * @brief Check if the Block has value block (no type and length are encoded)
161 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700162 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800163 hasValue() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700164
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800165 /**
166 * @brief Reset wire buffer of the element
167 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700168 void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800169 reset();
170
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800171 /**
172 * @brief Reset wire buffer but keep sub elements (if any)
173 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700174 void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800175 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800176
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800177 /**
178 * @brief Parse wire buffer into subblocks
179 *
180 * This method is not really const, but it does not modify any data. It simply
181 * parses contents of the buffer into subblocks
182 */
183 void
184 parse() const;
185
186 /**
187 * @brief Encode subblocks into wire buffer
188 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800189 void
190 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700191
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700192 uint32_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800193 type() const;
194
195 /**
196 * @brief Get the first subelement of the requested type
197 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700198 const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800199 get(uint32_t type) const;
200
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700201 element_const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800202 find(uint32_t type) const;
203
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700204 void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800205 remove(uint32_t type);
206
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700207 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800208 erase(element_iterator position);
209
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700210 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800211 erase(element_iterator first, element_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700212
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700213 void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700214 push_back(const Block& element);
215
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700216 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800217 begin() const;
218
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700219 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800220 end() const;
221
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700222 const uint8_t*
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800223 wire() const;
224
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700225 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800226 size() const;
227
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700228 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800229 value_begin() const;
230
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700231 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800232 value_end() const;
233
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700234 const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800235 value() const;
236
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700237 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800238 value_size() const;
239
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800240 /**
241 * @brief Get all subelements
242 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700243 const element_container&
244 elements() const;
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800245
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700246 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800247 elements_begin() const;
248
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700249 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800250 elements_end() const;
251
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700252 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800253 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700254
Yingdi Yu4270f202014-01-28 14:19:16 -0800255 Block
256 blockFromValue() const;
257
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700258public: // EqualityComparable concept
259 bool
260 operator==(const Block& other) const;
261
262 bool
263 operator!=(const Block& other) const;
264
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800265protected:
266 ConstBufferPtr m_buffer;
267
268 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700269
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800270 Buffer::const_iterator m_begin;
271 Buffer::const_iterator m_end;
272 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700273
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800274 Buffer::const_iterator m_value_begin;
275 Buffer::const_iterator m_value_end;
276
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800277 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800278 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800279};
280
281////////////////////////////////////////////////////////////////////////////////
282////////////////////////////////////////////////////////////////////////////////
283////////////////////////////////////////////////////////////////////////////////
284
285inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800286Block::empty() const
287{
288 return m_type == std::numeric_limits<uint32_t>::max();
289}
290
291
292inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800293Block::hasWire() const
294{
295 return m_buffer && (m_begin != m_end);
296}
297
298inline bool
299Block::hasValue() const
300{
301 return static_cast<bool>(m_buffer);
302}
303
304inline void
305Block::reset()
306{
307 m_buffer.reset(); // reset of the shared_ptr
308 m_subBlocks.clear(); // remove all parsed subelements
309
310 m_type = std::numeric_limits<uint32_t>::max();
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700311 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800312}
313
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800314inline void
315Block::resetWire()
316{
317 m_buffer.reset(); // reset of the shared_ptr
318 // keep subblocks
319
320 // keep type
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700321 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800322}
323
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800324inline uint32_t
325Block::type() const
326{
327 return m_type;
328}
329
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700330inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800331Block::get(uint32_t type) const
332{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700333 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800334 i != m_subBlocks.end();
335 i++)
336 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700337 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800338 {
339 return *i;
340 }
341 }
342
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700343 throw Error("(Block::get) Requested a non-existed type [" +
344 boost::lexical_cast<std::string>(type) + "] from Block");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800345}
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700346
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800347inline Block::element_const_iterator
348Block::find(uint32_t type) const
349{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700350 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800351 i != m_subBlocks.end();
352 i++)
353 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700354 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800355 {
356 return i;
357 }
358 }
359 return m_subBlocks.end();
360}
361
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800362inline void
363Block::remove(uint32_t type)
364{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800365 resetWire();
366
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800367 element_container newContainer;
368 newContainer.reserve(m_subBlocks.size());
369 for (element_iterator i = m_subBlocks.begin();
370 i != m_subBlocks.end();
371 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800372 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800373 if (i->type() != type)
374 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800375 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800376 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800377}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800378
379inline Block::element_iterator
380Block::erase(Block::element_iterator position)
381{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800382 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800383 return m_subBlocks.erase(position);
384}
385
386inline Block::element_iterator
387Block::erase(Block::element_iterator first, Block::element_iterator last)
388{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800389 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800390 return m_subBlocks.erase(first, last);
391}
392
393
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800394inline void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700395Block::push_back(const Block& element)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800396{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800397 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800398 m_subBlocks.push_back(element);
399}
400
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800401inline Buffer::const_iterator
402Block::begin() const
403{
404 if (!hasWire())
405 throw Error("Underlying wire buffer is empty");
406
407 return m_begin;
408}
409
410inline Buffer::const_iterator
411Block::end() const
412{
413 if (!hasWire())
414 throw Error("Underlying wire buffer is empty");
415
416 return m_end;
417}
418
419inline size_t
420Block::size() const
421{
422 if (hasWire() || hasValue()) {
423 return m_size;
424 }
425 else
426 throw Error("Block size cannot be determined (undefined block size)");
427}
428
429inline Buffer::const_iterator
430Block::value_begin() const
431{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800432 return m_value_begin;
433}
434
435inline Buffer::const_iterator
436Block::value_end() const
437{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800438 return m_value_end;
439}
440
441inline const uint8_t*
442Block::wire() const
443{
444 if (!hasWire())
445 throw Error("(Block::wire) Underlying wire buffer is empty");
446
447 return &*m_begin;
448}
449
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800450inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800451Block::value() const
452{
453 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800454 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700455
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800456 return &*m_value_begin;
457}
458
459inline size_t
460Block::value_size() const
461{
462 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800463 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800464
465 return m_value_end - m_value_begin;
466}
467
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800468inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700469Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800470{
471 return m_subBlocks;
472}
473
474inline Block::element_const_iterator
475Block::elements_begin() const
476{
477 return m_subBlocks.begin();
478}
479
480inline Block::element_const_iterator
481Block::elements_end() const
482{
483 return m_subBlocks.end();
484}
485
486inline size_t
487Block::elements_size() const
488{
489 return m_subBlocks.size();
490}
491
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700492inline bool
493Block::operator==(const Block& other) const
494{
495 return (this->size() == other.size()) &&
496 std::equal(this->begin(), this->end(), other.begin());
497}
498
499inline bool
500Block::operator!=(const Block& other) const
501{
502 return !this->operator==(other);
503}
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800504
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800505} // ndn
506
507#include "block-helpers.hpp"
508
509#endif // NDN_BLOCK_HPP