blob: 984e8aad7a20d1b38e8225b482c89f95cb9b7266 [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:
31 typedef std::list<Block>::iterator element_iterator;
32 typedef std::list<Block>::const_iterator element_const_iterator;
33
34 /// @brief Error that can be thrown from the block
35 struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
36
37 /**
38 * @brief Default constructor to create an empty Block
39 */
40 Block();
41
42 /**
43 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
44 */
45 Block(const ConstBufferPtr &buffer);
46
47 /**
48 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
49 */
50 Block(const uint8_t *buffer, size_t maxlength);
51
52 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080053
54 /*
55 * @brief A helper version of a constructor to create Block from the stream.
56 */
57 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080058
59 /**
60 * @brief Create Block from the wire buffer (no parsing)
61 *
62 * This version of the constructor does not do any parsing
63 */
64 Block(const ConstBufferPtr &wire,
65 uint32_t type,
66 const Buffer::const_iterator &begin, Buffer::const_iterator &end,
67 const Buffer::const_iterator &valueBegin, Buffer::const_iterator &valueEnd);
68
69 /**
70 * @brief Create Block of a specific type with empty wire buffer
71 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080072 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073 Block(uint32_t type);
74
75 /**
76 * @brief Create Block of a specific type with the specified value
77 *
78 * The underlying buffer hold only value, additional operations are needed
79 * to construct wire encoding, one need to prepend the wire buffer with type
80 * and value-length VAR-NUMBERs
81 */
82 Block(uint32_t type, const ConstBufferPtr &value);
83
84 /**
85 * @brief Create nested Block of a specific type with the specified value
86 *
87 * The underlying buffer hold only value, additional operations are needed
88 * to construct wire encoding, one need to prepend the wire buffer with type
89 * and value-length VAR-NUMBERs
90 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080091 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080092 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -080093
94 /**
95 * @brief Check if the Block is empty
96 */
97 inline bool
98 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080099
100 /**
101 * @brief Check if the Block has fully encoded wire
102 */
103 inline bool
104 hasWire() const;
105
106 /**
107 * @brief Check if the Block has value block (no type and length are encoded)
108 */
109 inline bool
110 hasValue() const;
111
112 /**
113 * @brief Reset wire buffer of the element
114 */
115 inline void
116 reset();
117
118 void
119 parse();
120
121 void
122 encode();
123
124 inline uint32_t
125 type() const;
126
127 /**
128 * @brief Get the first subelement of the requested type
129 */
130 inline const Block &
131 get(uint32_t type) const;
132
133 inline Block &
134 get(uint32_t type);
135
136 inline element_iterator
137 find(uint32_t type);
138
139 inline element_const_iterator
140 find(uint32_t type) const;
141
142 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800143 remove(uint32_t type);
144
145 inline element_iterator
146 erase(element_iterator position);
147
148 inline element_iterator
149 erase(element_iterator first, element_iterator last);
150
151 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800152 push_back(const Block &element);
153
154 /**
155 * @brief Get all subelements
156 */
157 inline const std::list<Block>&
158 getAll () const;
159
160 inline std::list<Block>&
161 getAll ();
162
163 /**
164 * @brief Get all elements of the requested type
165 */
166 std::list<Block>
167 getAll(uint32_t type) const;
168
169 inline Buffer::const_iterator
170 begin() const;
171
172 inline Buffer::const_iterator
173 end() const;
174
175 inline size_t
176 size() const;
177
178 inline Buffer::const_iterator
179 value_begin() const;
180
181 inline Buffer::const_iterator
182 value_end() const;
183
184 inline const uint8_t*
185 wire() const;
186
187 inline const uint8_t*
188 value() const;
189
190 inline size_t
191 value_size() const;
192
Yingdi Yu4270f202014-01-28 14:19:16 -0800193 Block
194 blockFromValue() const;
195
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800196protected:
197 ConstBufferPtr m_buffer;
198
199 uint32_t m_type;
200
201 Buffer::const_iterator m_begin;
202 Buffer::const_iterator m_end;
203 uint32_t m_size;
204
205 Buffer::const_iterator m_value_begin;
206 Buffer::const_iterator m_value_end;
207
208 std::list<Block> m_subBlocks;
209};
210
211////////////////////////////////////////////////////////////////////////////////
212////////////////////////////////////////////////////////////////////////////////
213////////////////////////////////////////////////////////////////////////////////
214
215inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800216Block::empty() const
217{
218 return m_type == std::numeric_limits<uint32_t>::max();
219}
220
221
222inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800223Block::hasWire() const
224{
225 return m_buffer && (m_begin != m_end);
226}
227
228inline bool
229Block::hasValue() const
230{
231 return static_cast<bool>(m_buffer);
232}
233
234inline void
235Block::reset()
236{
237 m_buffer.reset(); // reset of the shared_ptr
238 m_subBlocks.clear(); // remove all parsed subelements
239
240 m_type = std::numeric_limits<uint32_t>::max();
241 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
242}
243
244inline uint32_t
245Block::type() const
246{
247 return m_type;
248}
249
250inline const Block &
251Block::get(uint32_t type) const
252{
253 for (element_const_iterator i = m_subBlocks.begin ();
254 i != m_subBlocks.end();
255 i++)
256 {
257 if (i->type () == type)
258 {
259 return *i;
260 }
261 }
262
263 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
264}
265
266inline Block &
267Block::get(uint32_t type)
268{
269 for (element_iterator i = m_subBlocks.begin ();
270 i != m_subBlocks.end();
271 i++)
272 {
273 if (i->type () == type)
274 {
275 return *i;
276 }
277 }
278
279 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
280}
281
282inline Block::element_const_iterator
283Block::find(uint32_t type) const
284{
285 for (element_const_iterator i = m_subBlocks.begin ();
286 i != m_subBlocks.end();
287 i++)
288 {
289 if (i->type () == type)
290 {
291 return i;
292 }
293 }
294 return m_subBlocks.end();
295}
296
297inline Block::element_iterator
298Block::find(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 return m_subBlocks.end();
310}
311
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800312struct block_type
313{
314 block_type(uint32_t type)
315 : m_type(type)
316 {
317 }
318
319 inline bool
320 operator()(const Block &block)
321 {
322 return (block.type() == m_type);
323 }
324private:
325 uint32_t m_type;
326};
327
328inline void
329Block::remove(uint32_t type)
330{
331 m_subBlocks.remove_if(block_type(type));
332}
333
334inline Block::element_iterator
335Block::erase(Block::element_iterator position)
336{
337 return m_subBlocks.erase(position);
338}
339
340inline Block::element_iterator
341Block::erase(Block::element_iterator first, Block::element_iterator last)
342{
343 return m_subBlocks.erase(first, last);
344}
345
346
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800347inline void
348Block::push_back(const Block &element)
349{
350 m_subBlocks.push_back(element);
351}
352
353
354inline const std::list<Block>&
355Block::getAll () const
356{
357 return m_subBlocks;
358}
359
360inline std::list<Block>&
361Block::getAll ()
362{
363 return m_subBlocks;
364}
365
366
367inline Buffer::const_iterator
368Block::begin() const
369{
370 if (!hasWire())
371 throw Error("Underlying wire buffer is empty");
372
373 return m_begin;
374}
375
376inline Buffer::const_iterator
377Block::end() const
378{
379 if (!hasWire())
380 throw Error("Underlying wire buffer is empty");
381
382 return m_end;
383}
384
385inline size_t
386Block::size() const
387{
388 if (hasWire() || hasValue()) {
389 return m_size;
390 }
391 else
392 throw Error("Block size cannot be determined (undefined block size)");
393}
394
395inline Buffer::const_iterator
396Block::value_begin() const
397{
398 if (!hasValue())
399 throw Error("(Block::value_begin) Underlying value buffer is empty");
400
401 return m_value_begin;
402}
403
404inline Buffer::const_iterator
405Block::value_end() const
406{
407 if (!hasValue())
408 throw Error("(Block::value_end) Underlying value buffer is empty");
409
410 return m_value_end;
411}
412
413inline const uint8_t*
414Block::wire() const
415{
416 if (!hasWire())
417 throw Error("(Block::wire) Underlying wire buffer is empty");
418
419 return &*m_begin;
420}
421
422inline const uint8_t*
423Block::value() const
424{
425 if (!hasValue())
426 throw Error("(Block::value) Underlying value buffer is empty");
427
428 return &*m_value_begin;
429}
430
431inline size_t
432Block::value_size() const
433{
434 if (!hasValue())
435 throw Error("(Block::value_size) Underlying value buffer is empty");
436
437 return m_value_end - m_value_begin;
438}
439
440} // ndn
441
442#include "block-helpers.hpp"
443
444#endif // NDN_BLOCK_HPP