blob: eef9b3db95c9777347f89a44ee1473a576bf55c0 [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
33 /// @brief Error that can be thrown from the block
Alexander Afanasyeva465e972014-03-22 17:21:49 -070034 class Error : public std::runtime_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)
39 : std::runtime_error(what)
40 {
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 Afanasyev13bb51a2014-01-02 19:13:26 -080056 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070057 *
58 * This constructor provides ability of implicit conversion from ConstBufferPtr to Block
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080059 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070060 Block(const ConstBufferPtr& buffer);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080061
62 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080063 * @brief Another helper to create block from a buffer, directly specifying boundaries
64 * of the block within the buffer
65 *
66 * This version will automatically detect type and position of the value within the block
67 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070068 Block(const ConstBufferPtr& buffer,
69 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080070 bool verifyLength = true);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070071
Alexander Afanasyev187bc482014-02-06 15:04:04 -080072 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
74 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070075 Block(const uint8_t* buffer, size_t maxlength);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080076
Alexander Afanasyev937aa782014-03-21 13:17:57 -070077 Block(const void* buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080078
79 /*
Alexander Afanasyev937aa782014-03-21 13:17:57 -070080 * @brief A helper version of a constructor to create Block from the stream.
Yingdi Yu27158392014-01-20 13:04:20 -080081 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070082 explicit
Yingdi Yu27158392014-01-20 13:04:20 -080083 Block(std::istream& is);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070084
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080085 /**
86 * @brief Create Block from the wire buffer (no parsing)
87 *
88 * This version of the constructor does not do any parsing
89 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070090 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080091 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -070092 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
93 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080094
95 /**
96 * @brief Create Block of a specific type with empty wire buffer
97 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080098 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080099 Block(uint32_t type);
100
101 /**
102 * @brief Create Block of a specific type with the specified value
103 *
104 * The underlying buffer hold only value, additional operations are needed
105 * to construct wire encoding, one need to prepend the wire buffer with type
106 * and value-length VAR-NUMBERs
107 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700108 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800109
110 /**
111 * @brief Create nested Block of a specific type with the specified value
112 *
113 * The underlying buffer hold only value, additional operations are needed
114 * to construct wire encoding, one need to prepend the wire buffer with type
115 * and value-length VAR-NUMBERs
116 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800117 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700118 Block(uint32_t type, const Block& value);
119
120 /**
121 * @brief Try to construct block from Buffer, referencing data block pointed by wire
122 *
123 * @throws This method never throws an exception
124 *
125 * @returns true if Block successfully created, false if block cannot be created
126 */
127 static bool
128 fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block);
129
130 /**
131 * @brief Try to construct block from Buffer, referencing data block pointed by wire
132 *
133 * @throws This method never throws an exception
134 *
135 * @returns true if Block successfully created, false if block cannot be created
136 */
137 static bool
138 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800139
140 /**
141 * @brief Check if the Block is empty
142 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700143 bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800144 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700145
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800146 /**
147 * @brief Check if the Block has fully encoded wire
148 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700149 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800150 hasWire() const;
151
152 /**
153 * @brief Check if the Block has value block (no type and length are encoded)
154 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700155 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800156 hasValue() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700157
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800158 /**
159 * @brief Reset wire buffer of the element
160 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700161 void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800162 reset();
163
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800164 /**
165 * @brief Reset wire buffer but keep sub elements (if any)
166 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700167 void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800168 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800169
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800170 /**
171 * @brief Parse wire buffer into subblocks
172 *
173 * This method is not really const, but it does not modify any data. It simply
174 * parses contents of the buffer into subblocks
175 */
176 void
177 parse() const;
178
179 /**
180 * @brief Encode subblocks into wire buffer
181 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800182 void
183 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700184
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700185 uint32_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186 type() const;
187
188 /**
189 * @brief Get the first subelement of the requested type
190 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700191 const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800192 get(uint32_t type) const;
193
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700194 element_const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800195 find(uint32_t type) const;
196
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700197 void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800198 remove(uint32_t type);
199
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700200 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800201 erase(element_iterator position);
202
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700203 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800204 erase(element_iterator first, element_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700205
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700206 void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700207 push_back(const Block& element);
208
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700209 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800210 begin() const;
211
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700212 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800213 end() const;
214
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700215 const uint8_t*
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800216 wire() const;
217
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700218 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800219 size() const;
220
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700221 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800222 value_begin() const;
223
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700224 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800225 value_end() const;
226
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700227 const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800228 value() const;
229
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700230 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800231 value_size() const;
232
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800233 /**
234 * @brief Get all subelements
235 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700236 const element_container&
237 elements() const;
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800238
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700239 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800240 elements_begin() const;
241
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700242 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800243 elements_end() const;
244
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700245 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800246 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700247
Yingdi Yu4270f202014-01-28 14:19:16 -0800248 Block
249 blockFromValue() const;
250
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700251public: // EqualityComparable concept
252 bool
253 operator==(const Block& other) const;
254
255 bool
256 operator!=(const Block& other) const;
257
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800258protected:
259 ConstBufferPtr m_buffer;
260
261 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700262
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800263 Buffer::const_iterator m_begin;
264 Buffer::const_iterator m_end;
265 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700266
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800267 Buffer::const_iterator m_value_begin;
268 Buffer::const_iterator m_value_end;
269
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800270 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800271 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800272};
273
274////////////////////////////////////////////////////////////////////////////////
275////////////////////////////////////////////////////////////////////////////////
276////////////////////////////////////////////////////////////////////////////////
277
278inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800279Block::empty() const
280{
281 return m_type == std::numeric_limits<uint32_t>::max();
282}
283
284
285inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800286Block::hasWire() const
287{
288 return m_buffer && (m_begin != m_end);
289}
290
291inline bool
292Block::hasValue() const
293{
294 return static_cast<bool>(m_buffer);
295}
296
297inline void
298Block::reset()
299{
300 m_buffer.reset(); // reset of the shared_ptr
301 m_subBlocks.clear(); // remove all parsed subelements
302
303 m_type = std::numeric_limits<uint32_t>::max();
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700304 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800305}
306
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800307inline void
308Block::resetWire()
309{
310 m_buffer.reset(); // reset of the shared_ptr
311 // keep subblocks
312
313 // keep type
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700314 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800315}
316
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800317inline uint32_t
318Block::type() const
319{
320 return m_type;
321}
322
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700323inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800324Block::get(uint32_t type) const
325{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700326 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800327 i != m_subBlocks.end();
328 i++)
329 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700330 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800331 {
332 return *i;
333 }
334 }
335
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700336 throw Error("(Block::get) Requested a non-existed type [" +
337 boost::lexical_cast<std::string>(type) + "] from Block");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800338}
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700339
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800340inline Block::element_const_iterator
341Block::find(uint32_t type) const
342{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700343 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800344 i != m_subBlocks.end();
345 i++)
346 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700347 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800348 {
349 return i;
350 }
351 }
352 return m_subBlocks.end();
353}
354
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800355inline void
356Block::remove(uint32_t type)
357{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800358 resetWire();
359
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800360 element_container newContainer;
361 newContainer.reserve(m_subBlocks.size());
362 for (element_iterator i = m_subBlocks.begin();
363 i != m_subBlocks.end();
364 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800365 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800366 if (i->type() != type)
367 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800368 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800369 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800370}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800371
372inline Block::element_iterator
373Block::erase(Block::element_iterator position)
374{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800375 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800376 return m_subBlocks.erase(position);
377}
378
379inline Block::element_iterator
380Block::erase(Block::element_iterator first, Block::element_iterator last)
381{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800382 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800383 return m_subBlocks.erase(first, last);
384}
385
386
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800387inline void
388Block::push_back(const Block &element)
389{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800390 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800391 m_subBlocks.push_back(element);
392}
393
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800394inline Buffer::const_iterator
395Block::begin() const
396{
397 if (!hasWire())
398 throw Error("Underlying wire buffer is empty");
399
400 return m_begin;
401}
402
403inline Buffer::const_iterator
404Block::end() const
405{
406 if (!hasWire())
407 throw Error("Underlying wire buffer is empty");
408
409 return m_end;
410}
411
412inline size_t
413Block::size() const
414{
415 if (hasWire() || hasValue()) {
416 return m_size;
417 }
418 else
419 throw Error("Block size cannot be determined (undefined block size)");
420}
421
422inline Buffer::const_iterator
423Block::value_begin() const
424{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800425 return m_value_begin;
426}
427
428inline Buffer::const_iterator
429Block::value_end() const
430{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800431 return m_value_end;
432}
433
434inline const uint8_t*
435Block::wire() const
436{
437 if (!hasWire())
438 throw Error("(Block::wire) Underlying wire buffer is empty");
439
440 return &*m_begin;
441}
442
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800443inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800444Block::value() const
445{
446 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800447 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700448
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800449 return &*m_value_begin;
450}
451
452inline size_t
453Block::value_size() const
454{
455 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800456 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800457
458 return m_value_end - m_value_begin;
459}
460
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800461inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700462Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800463{
464 return m_subBlocks;
465}
466
467inline Block::element_const_iterator
468Block::elements_begin() const
469{
470 return m_subBlocks.begin();
471}
472
473inline Block::element_const_iterator
474Block::elements_end() const
475{
476 return m_subBlocks.end();
477}
478
479inline size_t
480Block::elements_size() const
481{
482 return m_subBlocks.size();
483}
484
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700485inline bool
486Block::operator==(const Block& other) const
487{
488 return (this->size() == other.size()) &&
489 std::equal(this->begin(), this->end(), other.begin());
490}
491
492inline bool
493Block::operator!=(const Block& other) const
494{
495 return !this->operator==(other);
496}
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800497
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800498} // ndn
499
500#include "block-helpers.hpp"
501
502#endif // NDN_BLOCK_HPP