blob: 09bc93df7a25641e55adabbd3ace17cdf5e71d2b [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
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800251protected:
252 ConstBufferPtr m_buffer;
253
254 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700255
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800256 Buffer::const_iterator m_begin;
257 Buffer::const_iterator m_end;
258 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700259
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800260 Buffer::const_iterator m_value_begin;
261 Buffer::const_iterator m_value_end;
262
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800263 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800264 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800265};
266
267////////////////////////////////////////////////////////////////////////////////
268////////////////////////////////////////////////////////////////////////////////
269////////////////////////////////////////////////////////////////////////////////
270
271inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800272Block::empty() const
273{
274 return m_type == std::numeric_limits<uint32_t>::max();
275}
276
277
278inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800279Block::hasWire() const
280{
281 return m_buffer && (m_begin != m_end);
282}
283
284inline bool
285Block::hasValue() const
286{
287 return static_cast<bool>(m_buffer);
288}
289
290inline void
291Block::reset()
292{
293 m_buffer.reset(); // reset of the shared_ptr
294 m_subBlocks.clear(); // remove all parsed subelements
295
296 m_type = std::numeric_limits<uint32_t>::max();
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700297 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800298}
299
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800300inline void
301Block::resetWire()
302{
303 m_buffer.reset(); // reset of the shared_ptr
304 // keep subblocks
305
306 // keep type
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700307 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800308}
309
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800310inline uint32_t
311Block::type() const
312{
313 return m_type;
314}
315
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700316inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800317Block::get(uint32_t type) const
318{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700319 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800320 i != m_subBlocks.end();
321 i++)
322 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700323 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800324 {
325 return *i;
326 }
327 }
328
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700329 throw Error("(Block::get) Requested a non-existed type [" +
330 boost::lexical_cast<std::string>(type) + "] from Block");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800331}
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700332
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800333inline Block::element_const_iterator
334Block::find(uint32_t type) const
335{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700336 for (element_const_iterator i = m_subBlocks.begin();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800337 i != m_subBlocks.end();
338 i++)
339 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700340 if (i->type() == type)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800341 {
342 return i;
343 }
344 }
345 return m_subBlocks.end();
346}
347
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800348inline void
349Block::remove(uint32_t type)
350{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800351 resetWire();
352
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800353 element_container newContainer;
354 newContainer.reserve(m_subBlocks.size());
355 for (element_iterator i = m_subBlocks.begin();
356 i != m_subBlocks.end();
357 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800358 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800359 if (i->type() != type)
360 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800361 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800362 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800363}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800364
365inline Block::element_iterator
366Block::erase(Block::element_iterator position)
367{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800368 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800369 return m_subBlocks.erase(position);
370}
371
372inline Block::element_iterator
373Block::erase(Block::element_iterator first, Block::element_iterator last)
374{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800375 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800376 return m_subBlocks.erase(first, last);
377}
378
379
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800380inline void
381Block::push_back(const Block &element)
382{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800383 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800384 m_subBlocks.push_back(element);
385}
386
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800387inline Buffer::const_iterator
388Block::begin() const
389{
390 if (!hasWire())
391 throw Error("Underlying wire buffer is empty");
392
393 return m_begin;
394}
395
396inline Buffer::const_iterator
397Block::end() const
398{
399 if (!hasWire())
400 throw Error("Underlying wire buffer is empty");
401
402 return m_end;
403}
404
405inline size_t
406Block::size() const
407{
408 if (hasWire() || hasValue()) {
409 return m_size;
410 }
411 else
412 throw Error("Block size cannot be determined (undefined block size)");
413}
414
415inline Buffer::const_iterator
416Block::value_begin() const
417{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800418 return m_value_begin;
419}
420
421inline Buffer::const_iterator
422Block::value_end() const
423{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800424 return m_value_end;
425}
426
427inline const uint8_t*
428Block::wire() const
429{
430 if (!hasWire())
431 throw Error("(Block::wire) Underlying wire buffer is empty");
432
433 return &*m_begin;
434}
435
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800436inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800437Block::value() const
438{
439 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800440 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700441
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800442 return &*m_value_begin;
443}
444
445inline size_t
446Block::value_size() const
447{
448 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800449 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800450
451 return m_value_end - m_value_begin;
452}
453
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800454inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700455Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800456{
457 return m_subBlocks;
458}
459
460inline Block::element_const_iterator
461Block::elements_begin() const
462{
463 return m_subBlocks.begin();
464}
465
466inline Block::element_const_iterator
467Block::elements_end() const
468{
469 return m_subBlocks.end();
470}
471
472inline size_t
473Block::elements_size() const
474{
475 return m_subBlocks.size();
476}
477
478
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800479} // ndn
480
481#include "block-helpers.hpp"
482
483#endif // NDN_BLOCK_HPP