blob: 45cf1ad1b6daf71798f231f10819a0d608cae1a5 [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
123 void
124 parse();
125
126 void
127 encode();
128
129 inline uint32_t
130 type() const;
131
132 /**
133 * @brief Get the first subelement of the requested type
134 */
135 inline const Block &
136 get(uint32_t type) const;
137
138 inline Block &
139 get(uint32_t type);
140
141 inline element_iterator
142 find(uint32_t type);
143
144 inline element_const_iterator
145 find(uint32_t type) const;
146
147 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800148 remove(uint32_t type);
149
150 inline element_iterator
151 erase(element_iterator position);
152
153 inline element_iterator
154 erase(element_iterator first, element_iterator last);
155
156 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800157 push_back(const Block &element);
158
159 /**
160 * @brief Get all subelements
161 */
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800162 inline const element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800163 getAll () const;
164
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800165 inline element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800166 getAll ();
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800167
168 inline const element_container&
169 elements () const;
170
171 inline element_container&
172 elements ();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800173
174 /**
175 * @brief Get all elements of the requested type
176 */
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800177 element_container
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800178 getAll(uint32_t type) const;
179
180 inline Buffer::const_iterator
181 begin() const;
182
183 inline Buffer::const_iterator
184 end() const;
185
186 inline size_t
187 size() const;
188
189 inline Buffer::const_iterator
190 value_begin() const;
191
192 inline Buffer::const_iterator
193 value_end() const;
194
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800195 inline element_iterator
196 element_begin();
197
198 inline element_iterator
199 element_end();
200
201 inline element_const_iterator
202 element_begin() const;
203
204 inline element_const_iterator
205 element_end() const;
206
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800207 inline const uint8_t*
208 wire() const;
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800209
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800210 // inline const uint8_t*
211 // buf() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800212
213 inline const uint8_t*
214 value() const;
215
216 inline size_t
217 value_size() const;
218
Yingdi Yu4270f202014-01-28 14:19:16 -0800219 Block
220 blockFromValue() const;
221
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800222protected:
223 ConstBufferPtr m_buffer;
224
225 uint32_t m_type;
226
227 Buffer::const_iterator m_begin;
228 Buffer::const_iterator m_end;
229 uint32_t m_size;
230
231 Buffer::const_iterator m_value_begin;
232 Buffer::const_iterator m_value_end;
233
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800234 element_container m_subBlocks;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800235};
236
237////////////////////////////////////////////////////////////////////////////////
238////////////////////////////////////////////////////////////////////////////////
239////////////////////////////////////////////////////////////////////////////////
240
241inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800242Block::empty() const
243{
244 return m_type == std::numeric_limits<uint32_t>::max();
245}
246
247
248inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800249Block::hasWire() const
250{
251 return m_buffer && (m_begin != m_end);
252}
253
254inline bool
255Block::hasValue() const
256{
257 return static_cast<bool>(m_buffer);
258}
259
260inline void
261Block::reset()
262{
263 m_buffer.reset(); // reset of the shared_ptr
264 m_subBlocks.clear(); // remove all parsed subelements
265
266 m_type = std::numeric_limits<uint32_t>::max();
267 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
268}
269
270inline uint32_t
271Block::type() const
272{
273 return m_type;
274}
275
276inline const Block &
277Block::get(uint32_t type) const
278{
279 for (element_const_iterator i = m_subBlocks.begin ();
280 i != m_subBlocks.end();
281 i++)
282 {
283 if (i->type () == type)
284 {
285 return *i;
286 }
287 }
288
289 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
290}
291
292inline Block &
293Block::get(uint32_t type)
294{
295 for (element_iterator i = m_subBlocks.begin ();
296 i != m_subBlocks.end();
297 i++)
298 {
299 if (i->type () == type)
300 {
301 return *i;
302 }
303 }
304
305 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
306}
307
308inline Block::element_const_iterator
309Block::find(uint32_t type) const
310{
311 for (element_const_iterator i = m_subBlocks.begin ();
312 i != m_subBlocks.end();
313 i++)
314 {
315 if (i->type () == type)
316 {
317 return i;
318 }
319 }
320 return m_subBlocks.end();
321}
322
323inline Block::element_iterator
324Block::find(uint32_t type)
325{
326 for (element_iterator i = m_subBlocks.begin ();
327 i != m_subBlocks.end();
328 i++)
329 {
330 if (i->type () == type)
331 {
332 return i;
333 }
334 }
335 return m_subBlocks.end();
336}
337
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800338inline void
339Block::remove(uint32_t type)
340{
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800341 element_container newContainer;
342 newContainer.reserve(m_subBlocks.size());
343 for (element_iterator i = m_subBlocks.begin();
344 i != m_subBlocks.end();
345 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800346 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800347 if (i->type() != type)
348 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800349 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800350 m_subBlocks.swap(newContainer);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800351 }
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800352
353inline Block::element_iterator
354Block::erase(Block::element_iterator position)
355{
356 return m_subBlocks.erase(position);
357}
358
359inline Block::element_iterator
360Block::erase(Block::element_iterator first, Block::element_iterator last)
361{
362 return m_subBlocks.erase(first, last);
363}
364
365
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800366inline void
367Block::push_back(const Block &element)
368{
369 m_subBlocks.push_back(element);
370}
371
372
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800373inline const Block::element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800374Block::getAll () const
375{
376 return m_subBlocks;
377}
378
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800379inline Block::element_container&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800380Block::getAll ()
381{
382 return m_subBlocks;
383}
384
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800385inline const Block::element_container&
386Block::elements () const
387{
388 return m_subBlocks;
389}
390
391inline Block::element_container&
392Block::elements ()
393{
394 return m_subBlocks;
395}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800396
397inline Buffer::const_iterator
398Block::begin() const
399{
400 if (!hasWire())
401 throw Error("Underlying wire buffer is empty");
402
403 return m_begin;
404}
405
406inline Buffer::const_iterator
407Block::end() const
408{
409 if (!hasWire())
410 throw Error("Underlying wire buffer is empty");
411
412 return m_end;
413}
414
415inline size_t
416Block::size() const
417{
418 if (hasWire() || hasValue()) {
419 return m_size;
420 }
421 else
422 throw Error("Block size cannot be determined (undefined block size)");
423}
424
425inline Buffer::const_iterator
426Block::value_begin() const
427{
428 if (!hasValue())
429 throw Error("(Block::value_begin) Underlying value buffer is empty");
430
431 return m_value_begin;
432}
433
434inline Buffer::const_iterator
435Block::value_end() const
436{
437 if (!hasValue())
438 throw Error("(Block::value_end) Underlying value buffer is empty");
439
440 return m_value_end;
441}
442
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800443inline Block::element_iterator
444Block::element_begin()
445{
446 return m_subBlocks.begin();
447}
448
449inline Block::element_iterator
450Block::element_end()
451{
452 return m_subBlocks.end();
453}
454
455inline Block::element_const_iterator
456Block::element_begin() const
457{
458 return m_subBlocks.begin();
459}
460
461inline Block::element_const_iterator
462Block::element_end() const
463{
464 return m_subBlocks.end();
465}
466
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800467inline const uint8_t*
468Block::wire() const
469{
470 if (!hasWire())
471 throw Error("(Block::wire) Underlying wire buffer is empty");
472
473 return &*m_begin;
474}
475
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800476// inline const uint8_t*
477// Block::buf() const
478// {
479// if (!hasWire())
480// throw Error("(Block::wire) Underlying wire buffer is empty");
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800481
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800482// return &*m_begin;
483// }
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800484
485inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800486Block::value() const
487{
488 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800489 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800490
491 return &*m_value_begin;
492}
493
494inline size_t
495Block::value_size() const
496{
497 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800498 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800499
500 return m_value_end - m_value_begin;
501}
502
503} // ndn
504
505#include "block-helpers.hpp"
506
507#endif // NDN_BLOCK_HPP