blob: 32523a5c8601a6fc5d99312ca8032694349397e1 [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
20/**
21 * @brief Class representing wire element of the NDN packet
22 */
23class Block
24{
25public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080026 typedef std::vector<Block> element_container;
27 typedef element_container::iterator element_iterator;
28 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080029
30 /// @brief Error that can be thrown from the block
31 struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
32
33 /**
34 * @brief Default constructor to create an empty Block
35 */
36 Block();
37
38 /**
39 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
40 */
41 Block(const ConstBufferPtr &buffer);
42
43 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080044 * @brief Another helper to create block from a buffer, directly specifying boundaries
45 * of the block within the buffer
46 *
47 * This version will automatically detect type and position of the value within the block
48 */
49 Block(const ConstBufferPtr &buffer,
50 const Buffer::const_iterator &begin, const Buffer::const_iterator &end);
51
52 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080053 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
54 */
55 Block(const uint8_t *buffer, size_t maxlength);
56
57 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080058
59 /*
60 * @brief A helper version of a constructor to create Block from the stream.
61 */
62 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080063
64 /**
65 * @brief Create Block from the wire buffer (no parsing)
66 *
67 * This version of the constructor does not do any parsing
68 */
69 Block(const ConstBufferPtr &wire,
70 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080071 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
72 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073
74 /**
75 * @brief Create Block of a specific type with empty wire buffer
76 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080077 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080078 Block(uint32_t type);
79
80 /**
81 * @brief Create Block of a specific type with the specified value
82 *
83 * The underlying buffer hold only value, additional operations are needed
84 * to construct wire encoding, one need to prepend the wire buffer with type
85 * and value-length VAR-NUMBERs
86 */
87 Block(uint32_t type, const ConstBufferPtr &value);
88
89 /**
90 * @brief Create nested Block of a specific type with the specified value
91 *
92 * The underlying buffer hold only value, additional operations are needed
93 * to construct wire encoding, one need to prepend the wire buffer with type
94 * and value-length VAR-NUMBERs
95 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080096 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080097 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -080098
99 /**
100 * @brief Check if the Block is empty
101 */
102 inline bool
103 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800104
105 /**
106 * @brief Check if the Block has fully encoded wire
107 */
108 inline bool
109 hasWire() const;
110
111 /**
112 * @brief Check if the Block has value block (no type and length are encoded)
113 */
114 inline bool
115 hasValue() const;
116
117 /**
118 * @brief Reset wire buffer of the element
119 */
120 inline void
121 reset();
122
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800123 /**
124 * @brief Reset wire buffer but keep sub elements (if any)
125 */
126 inline void
127 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800128
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800129 /**
130 * @brief Parse wire buffer into subblocks
131 *
132 * This method is not really const, but it does not modify any data. It simply
133 * parses contents of the buffer into subblocks
134 */
135 void
136 parse() const;
137
138 /**
139 * @brief Encode subblocks into wire buffer
140 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800141 void
142 encode();
143
144 inline uint32_t
145 type() const;
146
147 /**
148 * @brief Get the first subelement of the requested type
149 */
150 inline const Block &
151 get(uint32_t type) const;
152
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800153 inline element_const_iterator
154 find(uint32_t type) const;
155
156 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800157 remove(uint32_t type);
158
159 inline element_iterator
160 erase(element_iterator position);
161
162 inline element_iterator
163 erase(element_iterator first, element_iterator last);
164
165 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800166 push_back(const Block &element);
167
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800168 inline Buffer::const_iterator
169 begin() const;
170
171 inline Buffer::const_iterator
172 end() const;
173
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800174 inline const uint8_t*
175 wire() const;
176
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800177 inline size_t
178 size() const;
179
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800180 // inline const uint8_t*
181 // buf() const;
182
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800183 inline Buffer::const_iterator
184 value_begin() const;
185
186 inline Buffer::const_iterator
187 value_end() const;
188
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800189 inline const uint8_t*
190 value() const;
191
192 inline size_t
193 value_size() const;
194
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800195 /**
196 * @brief Get all subelements
197 */
198 inline const element_container&
199 elements () const;
200
201 inline element_const_iterator
202 elements_begin() const;
203
204 inline element_const_iterator
205 elements_end() const;
206
207 inline size_t
208 elements_size() const;
209
Yingdi Yu4270f202014-01-28 14:19:16 -0800210 Block
211 blockFromValue() const;
212
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800213protected:
214 ConstBufferPtr m_buffer;
215
216 uint32_t m_type;
217
218 Buffer::const_iterator m_begin;
219 Buffer::const_iterator m_end;
220 uint32_t m_size;
221
222 Buffer::const_iterator m_value_begin;
223 Buffer::const_iterator m_value_end;
224
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800225 mutable element_container m_subBlocks;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800226};
227
228////////////////////////////////////////////////////////////////////////////////
229////////////////////////////////////////////////////////////////////////////////
230////////////////////////////////////////////////////////////////////////////////
231
232inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800233Block::empty() const
234{
235 return m_type == std::numeric_limits<uint32_t>::max();
236}
237
238
239inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800240Block::hasWire() const
241{
242 return m_buffer && (m_begin != m_end);
243}
244
245inline bool
246Block::hasValue() const
247{
248 return static_cast<bool>(m_buffer);
249}
250
251inline void
252Block::reset()
253{
254 m_buffer.reset(); // reset of the shared_ptr
255 m_subBlocks.clear(); // remove all parsed subelements
256
257 m_type = std::numeric_limits<uint32_t>::max();
258 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
259}
260
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800261inline void
262Block::resetWire()
263{
264 m_buffer.reset(); // reset of the shared_ptr
265 // keep subblocks
266
267 // keep type
268 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
269}
270
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800271inline uint32_t
272Block::type() const
273{
274 return m_type;
275}
276
277inline const Block &
278Block::get(uint32_t type) const
279{
280 for (element_const_iterator i = m_subBlocks.begin ();
281 i != m_subBlocks.end();
282 i++)
283 {
284 if (i->type () == type)
285 {
286 return *i;
287 }
288 }
289
290 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
291}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800292
293inline Block::element_const_iterator
294Block::find(uint32_t type) const
295{
296 for (element_const_iterator i = m_subBlocks.begin ();
297 i != m_subBlocks.end();
298 i++)
299 {
300 if (i->type () == type)
301 {
302 return i;
303 }
304 }
305 return m_subBlocks.end();
306}
307
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800308inline void
309Block::remove(uint32_t type)
310{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800311 resetWire();
312
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800313 element_container newContainer;
314 newContainer.reserve(m_subBlocks.size());
315 for (element_iterator i = m_subBlocks.begin();
316 i != m_subBlocks.end();
317 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800318 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800319 if (i->type() != type)
320 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800321 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800322 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800323}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800324
325inline Block::element_iterator
326Block::erase(Block::element_iterator position)
327{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800328 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800329 return m_subBlocks.erase(position);
330}
331
332inline Block::element_iterator
333Block::erase(Block::element_iterator first, Block::element_iterator last)
334{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800335 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800336 return m_subBlocks.erase(first, last);
337}
338
339
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800340inline void
341Block::push_back(const Block &element)
342{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800343 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800344 m_subBlocks.push_back(element);
345}
346
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800347inline Buffer::const_iterator
348Block::begin() const
349{
350 if (!hasWire())
351 throw Error("Underlying wire buffer is empty");
352
353 return m_begin;
354}
355
356inline Buffer::const_iterator
357Block::end() const
358{
359 if (!hasWire())
360 throw Error("Underlying wire buffer is empty");
361
362 return m_end;
363}
364
365inline size_t
366Block::size() const
367{
368 if (hasWire() || hasValue()) {
369 return m_size;
370 }
371 else
372 throw Error("Block size cannot be determined (undefined block size)");
373}
374
375inline Buffer::const_iterator
376Block::value_begin() const
377{
378 if (!hasValue())
379 throw Error("(Block::value_begin) Underlying value buffer is empty");
380
381 return m_value_begin;
382}
383
384inline Buffer::const_iterator
385Block::value_end() const
386{
387 if (!hasValue())
388 throw Error("(Block::value_end) Underlying value buffer is empty");
389
390 return m_value_end;
391}
392
393inline const uint8_t*
394Block::wire() const
395{
396 if (!hasWire())
397 throw Error("(Block::wire) Underlying wire buffer is empty");
398
399 return &*m_begin;
400}
401
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800402inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800403Block::value() const
404{
405 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800406 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800407
408 return &*m_value_begin;
409}
410
411inline size_t
412Block::value_size() const
413{
414 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800415 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800416
417 return m_value_end - m_value_begin;
418}
419
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800420inline const Block::element_container&
421Block::elements () const
422{
423 return m_subBlocks;
424}
425
426inline Block::element_const_iterator
427Block::elements_begin() const
428{
429 return m_subBlocks.begin();
430}
431
432inline Block::element_const_iterator
433Block::elements_end() const
434{
435 return m_subBlocks.end();
436}
437
438inline size_t
439Block::elements_size() const
440{
441 return m_subBlocks.size();
442}
443
444
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800445} // ndn
446
447#include "block-helpers.hpp"
448
449#endif // NDN_BLOCK_HPP