blob: d1a762ffb61a7c625a6be8f6e7d9f2140bb4d1bd [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
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070015#ifndef NDN_ENCODING_BLOCK_HPP
16#define NDN_ENCODING_BLOCK_HPP
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080017
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
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080086 /**
87 * @brief Create Block from the wire buffer (no parsing)
88 *
89 * This version of the constructor does not do any parsing
90 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070091 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080092 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -070093 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
94 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080095
96 /**
97 * @brief Create Block of a specific type with empty wire buffer
98 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080099 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800100 Block(uint32_t type);
101
102 /**
103 * @brief Create Block of a specific type with the specified value
104 *
105 * The underlying buffer hold only value, additional operations are needed
106 * to construct wire encoding, one need to prepend the wire buffer with type
107 * and value-length VAR-NUMBERs
108 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700109 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800110
111 /**
112 * @brief Create nested Block of a specific type with the specified value
113 *
114 * The underlying buffer hold only value, additional operations are needed
115 * to construct wire encoding, one need to prepend the wire buffer with type
116 * and value-length VAR-NUMBERs
117 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800118 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700119 Block(uint32_t type, const Block& value);
120
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700121 /*
122 * @brief A helper version of a constructor to create Block from the stream
123 *
124 * @deprecated Use Block::fromStream instead
125 */
126 explicit
127 Block(std::istream& is)
128 {
129 *this = Block::fromStream(is);
130 }
131
132 /*
133 * @brief A helper version of a constructor to create Block from the stream.
134 */
135 Block
136 fromStream(std::istream& is);
137
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700138 /**
139 * @brief Try to construct block from Buffer, referencing data block pointed by wire
140 *
141 * @throws This method never throws an exception
142 *
143 * @returns true if Block successfully created, false if block cannot be created
144 */
145 static bool
146 fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block);
147
148 /**
149 * @brief Try to construct block from Buffer, referencing data block pointed by wire
150 *
151 * @throws This method never throws an exception
152 *
153 * @returns true if Block successfully created, false if block cannot be created
154 */
155 static bool
156 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800157
158 /**
159 * @brief Check if the Block is empty
160 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700161 bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800162 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700163
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800164 /**
165 * @brief Check if the Block has fully encoded wire
166 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700167 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800168 hasWire() const;
169
170 /**
171 * @brief Check if the Block has value block (no type and length are encoded)
172 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700173 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800174 hasValue() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700175
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800176 /**
177 * @brief Reset wire buffer of the element
178 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700179 void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800180 reset();
181
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800182 /**
183 * @brief Reset wire buffer but keep sub elements (if any)
184 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700185 void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800186 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800187
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800188 /**
189 * @brief Parse wire buffer into subblocks
190 *
191 * This method is not really const, but it does not modify any data. It simply
192 * parses contents of the buffer into subblocks
193 */
194 void
195 parse() const;
196
197 /**
198 * @brief Encode subblocks into wire buffer
199 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800200 void
201 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700202
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700203 uint32_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800204 type() const;
205
206 /**
207 * @brief Get the first subelement of the requested type
208 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700209 const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800210 get(uint32_t type) const;
211
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700212 element_const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800213 find(uint32_t type) const;
214
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700215 void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800216 remove(uint32_t type);
217
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700218 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800219 erase(element_iterator position);
220
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700221 element_iterator
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800222 erase(element_iterator first, element_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700223
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700224 void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700225 push_back(const Block& element);
226
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700227 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800228 begin() const;
229
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700230 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800231 end() const;
232
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700233 const uint8_t*
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800234 wire() const;
235
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700236 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800237 size() const;
238
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700239 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800240 value_begin() const;
241
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700242 Buffer::const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800243 value_end() const;
244
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700245 const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800246 value() const;
247
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700248 size_t
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800249 value_size() const;
250
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800251 /**
252 * @brief Get all subelements
253 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700254 const element_container&
255 elements() const;
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800256
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700257 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800258 elements_begin() const;
259
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700260 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800261 elements_end() const;
262
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700263 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800264 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700265
Yingdi Yu4270f202014-01-28 14:19:16 -0800266 Block
267 blockFromValue() const;
268
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700269public: // EqualityComparable concept
270 bool
271 operator==(const Block& other) const;
272
273 bool
274 operator!=(const Block& other) const;
275
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800276protected:
277 ConstBufferPtr m_buffer;
278
279 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700280
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800281 Buffer::const_iterator m_begin;
282 Buffer::const_iterator m_end;
283 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700284
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800285 Buffer::const_iterator m_value_begin;
286 Buffer::const_iterator m_value_end;
287
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800288 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800289 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800290};
291
292////////////////////////////////////////////////////////////////////////////////
293////////////////////////////////////////////////////////////////////////////////
294////////////////////////////////////////////////////////////////////////////////
295
296inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800297Block::empty() const
298{
299 return m_type == std::numeric_limits<uint32_t>::max();
300}
301
302
303inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800304Block::hasWire() const
305{
306 return m_buffer && (m_begin != m_end);
307}
308
309inline bool
310Block::hasValue() const
311{
312 return static_cast<bool>(m_buffer);
313}
314
315inline void
316Block::reset()
317{
318 m_buffer.reset(); // reset of the shared_ptr
319 m_subBlocks.clear(); // remove all parsed subelements
320
321 m_type = std::numeric_limits<uint32_t>::max();
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700322 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800323}
324
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800325inline void
326Block::resetWire()
327{
328 m_buffer.reset(); // reset of the shared_ptr
329 // keep subblocks
330
331 // keep type
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700332 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800333}
334
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800335inline uint32_t
336Block::type() const
337{
338 return m_type;
339}
340
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800341inline Block::element_const_iterator
342Block::find(uint32_t type) const
343{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700344 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800345 i != m_subBlocks.end();
346 i++)
347 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700348 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800349 {
350 return i;
351 }
352 }
353 return m_subBlocks.end();
354}
355
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800356inline void
357Block::remove(uint32_t type)
358{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800359 resetWire();
360
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800361 element_container newContainer;
362 newContainer.reserve(m_subBlocks.size());
363 for (element_iterator i = m_subBlocks.begin();
364 i != m_subBlocks.end();
365 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800366 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800367 if (i->type() != type)
368 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800369 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800370 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800371}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800372
373inline Block::element_iterator
374Block::erase(Block::element_iterator position)
375{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800376 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800377 return m_subBlocks.erase(position);
378}
379
380inline Block::element_iterator
381Block::erase(Block::element_iterator first, Block::element_iterator last)
382{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800383 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800384 return m_subBlocks.erase(first, last);
385}
386
387
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800388inline void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700389Block::push_back(const Block& element)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800390{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800391 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800392 m_subBlocks.push_back(element);
393}
394
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800395inline Buffer::const_iterator
396Block::begin() const
397{
398 if (!hasWire())
399 throw Error("Underlying wire buffer is empty");
400
401 return m_begin;
402}
403
404inline Buffer::const_iterator
405Block::end() const
406{
407 if (!hasWire())
408 throw Error("Underlying wire buffer is empty");
409
410 return m_end;
411}
412
413inline size_t
414Block::size() const
415{
416 if (hasWire() || hasValue()) {
417 return m_size;
418 }
419 else
420 throw Error("Block size cannot be determined (undefined block size)");
421}
422
423inline Buffer::const_iterator
424Block::value_begin() const
425{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800426 return m_value_begin;
427}
428
429inline Buffer::const_iterator
430Block::value_end() const
431{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800432 return m_value_end;
433}
434
435inline const uint8_t*
436Block::wire() const
437{
438 if (!hasWire())
439 throw Error("(Block::wire) Underlying wire buffer is empty");
440
441 return &*m_begin;
442}
443
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800444inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800445Block::value() const
446{
447 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800448 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700449
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800450 return &*m_value_begin;
451}
452
453inline size_t
454Block::value_size() const
455{
456 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800457 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800458
459 return m_value_end - m_value_begin;
460}
461
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800462inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700463Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800464{
465 return m_subBlocks;
466}
467
468inline Block::element_const_iterator
469Block::elements_begin() const
470{
471 return m_subBlocks.begin();
472}
473
474inline Block::element_const_iterator
475Block::elements_end() const
476{
477 return m_subBlocks.end();
478}
479
480inline size_t
481Block::elements_size() const
482{
483 return m_subBlocks.size();
484}
485
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700486inline bool
487Block::operator==(const Block& other) const
488{
489 return (this->size() == other.size()) &&
490 std::equal(this->begin(), this->end(), other.begin());
491}
492
493inline bool
494Block::operator!=(const Block& other) const
495{
496 return !this->operator==(other);
497}
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800498
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800499} // ndn
500
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700501#endif // NDN_ENCODING_BLOCK_HPP