blob: f5157279cb5a6c20455e36b9aff858c4e8182b48 [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
15#include <list>
16#include <exception>
17
18#include "buffer.hpp"
19#include "tlv.hpp"
20
21#include <boost/lexical_cast.hpp>
22
23namespace ndn {
24
25/**
26 * @brief Class representing wire element of the NDN packet
27 */
28class Block
29{
30public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080031 typedef std::vector<Block> element_container;
32 typedef element_container::iterator element_iterator;
33 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080034
35 /// @brief Error that can be thrown from the block
36 struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
37
38 /**
39 * @brief Default constructor to create an empty Block
40 */
41 Block();
42
43 /**
44 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
45 */
46 Block(const ConstBufferPtr &buffer);
47
48 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080049 * @brief Another helper to create block from a buffer, directly specifying boundaries
50 * of the block within the buffer
51 *
52 * This version will automatically detect type and position of the value within the block
53 */
54 Block(const ConstBufferPtr &buffer,
55 const Buffer::const_iterator &begin, const Buffer::const_iterator &end);
56
57 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080058 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
59 */
60 Block(const uint8_t *buffer, size_t maxlength);
61
62 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080063
64 /*
65 * @brief A helper version of a constructor to create Block from the stream.
66 */
67 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080068
69 /**
70 * @brief Create Block from the wire buffer (no parsing)
71 *
72 * This version of the constructor does not do any parsing
73 */
74 Block(const ConstBufferPtr &wire,
75 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080076 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
77 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080078
79 /**
80 * @brief Create Block of a specific type with empty wire buffer
81 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080082 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080083 Block(uint32_t type);
84
85 /**
86 * @brief Create Block of a specific type with the specified value
87 *
88 * The underlying buffer hold only value, additional operations are needed
89 * to construct wire encoding, one need to prepend the wire buffer with type
90 * and value-length VAR-NUMBERs
91 */
92 Block(uint32_t type, const ConstBufferPtr &value);
93
94 /**
95 * @brief Create nested Block of a specific type with the specified value
96 *
97 * The underlying buffer hold only value, additional operations are needed
98 * to construct wire encoding, one need to prepend the wire buffer with type
99 * and value-length VAR-NUMBERs
100 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800101 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800102 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800103
104 /**
105 * @brief Check if the Block is empty
106 */
107 inline bool
108 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800109
110 /**
111 * @brief Check if the Block has fully encoded wire
112 */
113 inline bool
114 hasWire() const;
115
116 /**
117 * @brief Check if the Block has value block (no type and length are encoded)
118 */
119 inline bool
120 hasValue() const;
121
122 /**
123 * @brief Reset wire buffer of the element
124 */
125 inline void
126 reset();
127
128 void
129 parse();
130
131 void
132 encode();
133
134 inline uint32_t
135 type() const;
136
137 /**
138 * @brief Get the first subelement of the requested type
139 */
140 inline const Block &
141 get(uint32_t type) const;
142
143 inline Block &
144 get(uint32_t type);
145
146 inline element_iterator
147 find(uint32_t type);
148
149 inline element_const_iterator
150 find(uint32_t type) const;
151
152 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800153 remove(uint32_t type);
154
155 inline element_iterator
156 erase(element_iterator position);
157
158 inline element_iterator
159 erase(element_iterator first, element_iterator last);
160
161 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800162 push_back(const Block &element);
163
164 /**
165 * @brief Get all subelements
166 */
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800167 inline const element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800168 getAll () const;
169
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800170 inline element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800171 getAll ();
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800172
173 inline const element_container&
174 elements () const;
175
176 inline element_container&
177 elements ();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800178
179 /**
180 * @brief Get all elements of the requested type
181 */
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800182 element_container
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800183 getAll(uint32_t type) const;
184
185 inline Buffer::const_iterator
186 begin() const;
187
188 inline Buffer::const_iterator
189 end() const;
190
191 inline size_t
192 size() const;
193
194 inline Buffer::const_iterator
195 value_begin() const;
196
197 inline Buffer::const_iterator
198 value_end() const;
199
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800200 inline element_iterator
201 element_begin();
202
203 inline element_iterator
204 element_end();
205
206 inline element_const_iterator
207 element_begin() const;
208
209 inline element_const_iterator
210 element_end() const;
211
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800212 inline const uint8_t*
213 wire() const;
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800214
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800215 // inline const uint8_t*
216 // buf() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800217
218 inline const uint8_t*
219 value() const;
220
221 inline size_t
222 value_size() const;
223
Yingdi Yu4270f202014-01-28 14:19:16 -0800224 Block
225 blockFromValue() const;
226
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800227protected:
228 ConstBufferPtr m_buffer;
229
230 uint32_t m_type;
231
232 Buffer::const_iterator m_begin;
233 Buffer::const_iterator m_end;
234 uint32_t m_size;
235
236 Buffer::const_iterator m_value_begin;
237 Buffer::const_iterator m_value_end;
238
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800239 element_container m_subBlocks;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800240};
241
242////////////////////////////////////////////////////////////////////////////////
243////////////////////////////////////////////////////////////////////////////////
244////////////////////////////////////////////////////////////////////////////////
245
246inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800247Block::empty() const
248{
249 return m_type == std::numeric_limits<uint32_t>::max();
250}
251
252
253inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800254Block::hasWire() const
255{
256 return m_buffer && (m_begin != m_end);
257}
258
259inline bool
260Block::hasValue() const
261{
262 return static_cast<bool>(m_buffer);
263}
264
265inline void
266Block::reset()
267{
268 m_buffer.reset(); // reset of the shared_ptr
269 m_subBlocks.clear(); // remove all parsed subelements
270
271 m_type = std::numeric_limits<uint32_t>::max();
272 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
273}
274
275inline uint32_t
276Block::type() const
277{
278 return m_type;
279}
280
281inline const Block &
282Block::get(uint32_t type) const
283{
284 for (element_const_iterator i = m_subBlocks.begin ();
285 i != m_subBlocks.end();
286 i++)
287 {
288 if (i->type () == type)
289 {
290 return *i;
291 }
292 }
293
294 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
295}
296
297inline Block &
298Block::get(uint32_t type)
299{
300 for (element_iterator i = m_subBlocks.begin ();
301 i != m_subBlocks.end();
302 i++)
303 {
304 if (i->type () == type)
305 {
306 return *i;
307 }
308 }
309
310 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
311}
312
313inline Block::element_const_iterator
314Block::find(uint32_t type) const
315{
316 for (element_const_iterator i = m_subBlocks.begin ();
317 i != m_subBlocks.end();
318 i++)
319 {
320 if (i->type () == type)
321 {
322 return i;
323 }
324 }
325 return m_subBlocks.end();
326}
327
328inline Block::element_iterator
329Block::find(uint32_t type)
330{
331 for (element_iterator i = m_subBlocks.begin ();
332 i != m_subBlocks.end();
333 i++)
334 {
335 if (i->type () == type)
336 {
337 return i;
338 }
339 }
340 return m_subBlocks.end();
341}
342
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800343inline void
344Block::remove(uint32_t type)
345{
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800346 element_container newContainer;
347 newContainer.reserve(m_subBlocks.size());
348 for (element_iterator i = m_subBlocks.begin();
349 i != m_subBlocks.end();
350 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800351 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800352 if (i->type() != type)
353 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800354 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800355 m_subBlocks.swap(newContainer);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800356 }
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800357
358inline Block::element_iterator
359Block::erase(Block::element_iterator position)
360{
361 return m_subBlocks.erase(position);
362}
363
364inline Block::element_iterator
365Block::erase(Block::element_iterator first, Block::element_iterator last)
366{
367 return m_subBlocks.erase(first, last);
368}
369
370
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800371inline void
372Block::push_back(const Block &element)
373{
374 m_subBlocks.push_back(element);
375}
376
377
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800378inline const Block::element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800379Block::getAll () const
380{
381 return m_subBlocks;
382}
383
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800384inline Block::element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800385Block::getAll ()
386{
387 return m_subBlocks;
388}
389
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800390inline const Block::element_container&
391Block::elements () const
392{
393 return m_subBlocks;
394}
395
396inline Block::element_container&
397Block::elements ()
398{
399 return m_subBlocks;
400}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800401
402inline Buffer::const_iterator
403Block::begin() const
404{
405 if (!hasWire())
406 throw Error("Underlying wire buffer is empty");
407
408 return m_begin;
409}
410
411inline Buffer::const_iterator
412Block::end() const
413{
414 if (!hasWire())
415 throw Error("Underlying wire buffer is empty");
416
417 return m_end;
418}
419
420inline size_t
421Block::size() const
422{
423 if (hasWire() || hasValue()) {
424 return m_size;
425 }
426 else
427 throw Error("Block size cannot be determined (undefined block size)");
428}
429
430inline Buffer::const_iterator
431Block::value_begin() const
432{
433 if (!hasValue())
434 throw Error("(Block::value_begin) Underlying value buffer is empty");
435
436 return m_value_begin;
437}
438
439inline Buffer::const_iterator
440Block::value_end() const
441{
442 if (!hasValue())
443 throw Error("(Block::value_end) Underlying value buffer is empty");
444
445 return m_value_end;
446}
447
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800448inline Block::element_iterator
449Block::element_begin()
450{
451 return m_subBlocks.begin();
452}
453
454inline Block::element_iterator
455Block::element_end()
456{
457 return m_subBlocks.end();
458}
459
460inline Block::element_const_iterator
461Block::element_begin() const
462{
463 return m_subBlocks.begin();
464}
465
466inline Block::element_const_iterator
467Block::element_end() const
468{
469 return m_subBlocks.end();
470}
471
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800472inline const uint8_t*
473Block::wire() const
474{
475 if (!hasWire())
476 throw Error("(Block::wire) Underlying wire buffer is empty");
477
478 return &*m_begin;
479}
480
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800481// inline const uint8_t*
482// Block::buf() const
483// {
484// if (!hasWire())
485// throw Error("(Block::wire) Underlying wire buffer is empty");
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800486
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800487// return &*m_begin;
488// }
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800489
490inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800491Block::value() const
492{
493 if (!hasValue())
494 throw Error("(Block::value) Underlying value buffer is empty");
495
496 return &*m_value_begin;
497}
498
499inline size_t
500Block::value_size() const
501{
502 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800503 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800504
505 return m_value_end - m_value_begin;
506}
507
508} // ndn
509
510#include "block-helpers.hpp"
511
512#endif // NDN_BLOCK_HPP