blob: 6777f77cea4f7d79cabc3ca06c127813343fad9f [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 *
5 * BSD license, See the LICENSE file for more information
6 *
7 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
8 */
9
10#ifndef NDN_BLOCK_HPP
11#define NDN_BLOCK_HPP
12
Alexander Afanasyev19508852014-01-29 01:01:51 -080013#include "../common.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080014
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015#include "buffer.hpp"
16#include "tlv.hpp"
17
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080018namespace ndn {
19
Alexander Afanasyev233750e2014-02-16 00:50:07 -080020template<bool> class EncodingImpl;
21typedef EncodingImpl<true> EncodingBuffer;
22
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080023/**
24 * @brief Class representing wire element of the NDN packet
25 */
26class Block
27{
28public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080029 typedef std::vector<Block> element_container;
30 typedef element_container::iterator element_iterator;
31 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080032
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070033 /// @brief Error that can be thrown from Block
Yingdi Yue52f4ef2014-04-17 19:21:13 -070034 class Error : public Tlv::Error
Alexander Afanasyev937aa782014-03-21 13:17:57 -070035 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070036 public:
37 explicit
38 Error(const std::string& what)
Yingdi Yue52f4ef2014-04-17 19:21:13 -070039 : Tlv::Error(what)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070040 {
41 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -070042 };
43
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080044 /**
45 * @brief Default constructor to create an empty Block
46 */
47 Block();
48
49 /**
Alexander Afanasyev15151312014-02-16 00:53:51 -080050 * @brief Create block based on EncodingBuffer object
51 */
52 explicit
53 Block(const EncodingBuffer& buffer);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070054
Alexander Afanasyev15151312014-02-16 00:53:51 -080055 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070056 * @brief A helper version of a constructor to create Block from the raw buffer (type
57 * and value-length parsing)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070058 *
59 * This constructor provides ability of implicit conversion from ConstBufferPtr to Block
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080060 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070061 Block(const ConstBufferPtr& buffer);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080062
63 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080064 * @brief Another helper to create block from a buffer, directly specifying boundaries
65 * of the block within the buffer
66 *
67 * This version will automatically detect type and position of the value within the block
68 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070069 Block(const ConstBufferPtr& buffer,
70 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080071 bool verifyLength = true);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070072
Alexander Afanasyev187bc482014-02-06 15:04:04 -080073 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070074 * @brief A helper version of a constructor to create Block from the raw buffer (type
75 * and value-length parsing)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080076 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070077 Block(const uint8_t* buffer, size_t maxlength);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080078
Alexander Afanasyev937aa782014-03-21 13:17:57 -070079 Block(const void* buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080080
81 /*
Alexander Afanasyev937aa782014-03-21 13:17:57 -070082 * @brief A helper version of a constructor to create Block from the stream.
Yingdi Yu27158392014-01-20 13:04:20 -080083 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070084 explicit
Yingdi Yu27158392014-01-20 13:04:20 -080085 Block(std::istream& is);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070086
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080087 /**
88 * @brief Create Block from the wire buffer (no parsing)
89 *
90 * This version of the constructor does not do any parsing
91 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070092 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080093 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -070094 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
95 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080096
97 /**
98 * @brief Create Block of a specific type with empty wire buffer
99 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800100 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800101 Block(uint32_t type);
102
103 /**
104 * @brief Create Block of a specific type with the specified value
105 *
106 * The underlying buffer hold only value, additional operations are needed
107 * to construct wire encoding, one need to prepend the wire buffer with type
108 * and value-length VAR-NUMBERs
109 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700110 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800111
112 /**
113 * @brief Create nested Block of a specific type with the specified value
114 *
115 * The underlying buffer hold only value, additional operations are needed
116 * to construct wire encoding, one need to prepend the wire buffer with type
117 * and value-length VAR-NUMBERs
118 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800119 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700120 Block(uint32_t type, const Block& value);
121
122 /**
123 * @brief Try to construct block from Buffer, referencing data block pointed by wire
124 *
125 * @throws This method never throws an exception
126 *
127 * @returns true if Block successfully created, false if block cannot be created
128 */
129 static bool
130 fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block);
131
132 /**
133 * @brief Try to construct block from Buffer, referencing data block pointed by wire
134 *
135 * @throws This method never throws an exception
136 *
137 * @returns true if Block successfully created, false if block cannot be created
138 */
139 static bool
140 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800141
142 /**
143 * @brief Check if the Block is empty
144 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700145 bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800146 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700147
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800148 /**
149 * @brief Check if the Block has fully encoded wire
150 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700151 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800152 hasWire() const;
153
154 /**
155 * @brief Check if the Block has value block (no type and length are encoded)
156 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700157 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800158 hasValue() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700159
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800160 /**
161 * @brief Reset wire buffer of the element
162 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700163 void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800164 reset();
165
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800166 /**
167 * @brief Reset wire buffer but keep sub elements (if any)
168 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700169 void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800170 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800171
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800172 /**
173 * @brief Parse wire buffer into subblocks
174 *
175 * This method is not really const, but it does not modify any data. It simply
176 * parses contents of the buffer into subblocks
177 */
178 void
179 parse() const;
180
181 /**
182 * @brief Encode subblocks into wire buffer
183 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800184 void
185 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700186
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700187 uint32_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800188 type() const;
189
190 /**
191 * @brief Get the first subelement of the requested type
192 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700193 const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800194 get(uint32_t type) const;
195
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700196 element_const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800197 find(uint32_t type) const;
198
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700199 void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800200 remove(uint32_t type);
201
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700202 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800203 erase(element_iterator position);
204
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700205 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800206 erase(element_iterator first, element_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700207
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700208 void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700209 push_back(const Block& element);
210
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700211 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800212 begin() const;
213
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700214 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800215 end() const;
216
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700217 const uint8_t*
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800218 wire() const;
219
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700220 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800221 size() const;
222
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700223 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800224 value_begin() const;
225
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700226 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800227 value_end() const;
228
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700229 const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800230 value() const;
231
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700232 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800233 value_size() const;
234
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800235 /**
236 * @brief Get all subelements
237 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700238 const element_container&
239 elements() const;
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800240
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700241 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800242 elements_begin() const;
243
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700244 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800245 elements_end() const;
246
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700247 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800248 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700249
Yingdi Yu4270f202014-01-28 14:19:16 -0800250 Block
251 blockFromValue() const;
252
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700253public: // EqualityComparable concept
254 bool
255 operator==(const Block& other) const;
256
257 bool
258 operator!=(const Block& other) const;
259
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800260protected:
261 ConstBufferPtr m_buffer;
262
263 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700264
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800265 Buffer::const_iterator m_begin;
266 Buffer::const_iterator m_end;
267 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700268
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800269 Buffer::const_iterator m_value_begin;
270 Buffer::const_iterator m_value_end;
271
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800272 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800273 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800274};
275
276////////////////////////////////////////////////////////////////////////////////
277////////////////////////////////////////////////////////////////////////////////
278////////////////////////////////////////////////////////////////////////////////
279
280inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800281Block::empty() const
282{
283 return m_type == std::numeric_limits<uint32_t>::max();
284}
285
286
287inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800288Block::hasWire() const
289{
290 return m_buffer && (m_begin != m_end);
291}
292
293inline bool
294Block::hasValue() const
295{
296 return static_cast<bool>(m_buffer);
297}
298
299inline void
300Block::reset()
301{
302 m_buffer.reset(); // reset of the shared_ptr
303 m_subBlocks.clear(); // remove all parsed subelements
304
305 m_type = std::numeric_limits<uint32_t>::max();
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700306 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800307}
308
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800309inline void
310Block::resetWire()
311{
312 m_buffer.reset(); // reset of the shared_ptr
313 // keep subblocks
314
315 // keep type
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700316 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800317}
318
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800319inline uint32_t
320Block::type() const
321{
322 return m_type;
323}
324
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700325inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800326Block::get(uint32_t type) const
327{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700328 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800329 i != m_subBlocks.end();
330 i++)
331 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700332 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800333 {
334 return *i;
335 }
336 }
337
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700338 throw Error("(Block::get) Requested a non-existed type [" +
339 boost::lexical_cast<std::string>(type) + "] from Block");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800340}
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700341
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800342inline Block::element_const_iterator
343Block::find(uint32_t type) const
344{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700345 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800346 i != m_subBlocks.end();
347 i++)
348 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700349 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800350 {
351 return i;
352 }
353 }
354 return m_subBlocks.end();
355}
356
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800357inline void
358Block::remove(uint32_t type)
359{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800360 resetWire();
361
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800362 element_container newContainer;
363 newContainer.reserve(m_subBlocks.size());
364 for (element_iterator i = m_subBlocks.begin();
365 i != m_subBlocks.end();
366 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800367 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800368 if (i->type() != type)
369 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800370 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800371 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800372}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800373
374inline Block::element_iterator
375Block::erase(Block::element_iterator position)
376{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800377 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800378 return m_subBlocks.erase(position);
379}
380
381inline Block::element_iterator
382Block::erase(Block::element_iterator first, Block::element_iterator last)
383{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800384 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800385 return m_subBlocks.erase(first, last);
386}
387
388
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800389inline void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700390Block::push_back(const Block& element)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800391{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800392 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800393 m_subBlocks.push_back(element);
394}
395
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800396inline Buffer::const_iterator
397Block::begin() const
398{
399 if (!hasWire())
400 throw Error("Underlying wire buffer is empty");
401
402 return m_begin;
403}
404
405inline Buffer::const_iterator
406Block::end() const
407{
408 if (!hasWire())
409 throw Error("Underlying wire buffer is empty");
410
411 return m_end;
412}
413
414inline size_t
415Block::size() const
416{
417 if (hasWire() || hasValue()) {
418 return m_size;
419 }
420 else
421 throw Error("Block size cannot be determined (undefined block size)");
422}
423
424inline Buffer::const_iterator
425Block::value_begin() const
426{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800427 return m_value_begin;
428}
429
430inline Buffer::const_iterator
431Block::value_end() const
432{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800433 return m_value_end;
434}
435
436inline const uint8_t*
437Block::wire() const
438{
439 if (!hasWire())
440 throw Error("(Block::wire) Underlying wire buffer is empty");
441
442 return &*m_begin;
443}
444
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800445inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800446Block::value() const
447{
448 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800449 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700450
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800451 return &*m_value_begin;
452}
453
454inline size_t
455Block::value_size() const
456{
457 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800458 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800459
460 return m_value_end - m_value_begin;
461}
462
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800463inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700464Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800465{
466 return m_subBlocks;
467}
468
469inline Block::element_const_iterator
470Block::elements_begin() const
471{
472 return m_subBlocks.begin();
473}
474
475inline Block::element_const_iterator
476Block::elements_end() const
477{
478 return m_subBlocks.end();
479}
480
481inline size_t
482Block::elements_size() const
483{
484 return m_subBlocks.size();
485}
486
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700487inline bool
488Block::operator==(const Block& other) const
489{
490 return (this->size() == other.size()) &&
491 std::equal(this->begin(), this->end(), other.begin());
492}
493
494inline bool
495Block::operator!=(const Block& other) const
496{
497 return !this->operator==(other);
498}
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800499
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800500} // ndn
501
502#include "block-helpers.hpp"
503
504#endif // NDN_BLOCK_HPP