blob: 3699f3677a303304b2bc2e7640b29f1ad1443254 [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 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080048 * @brief Another helper to create block from a buffer, directly specifying boundaries
49 * of the block within the buffer
50 *
51 * This version will automatically detect type and position of the value within the block
52 */
53 Block(const ConstBufferPtr &buffer,
54 const Buffer::const_iterator &begin, const Buffer::const_iterator &end);
55
56 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080057 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
58 */
59 Block(const uint8_t *buffer, size_t maxlength);
60
61 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080062
63 /*
64 * @brief A helper version of a constructor to create Block from the stream.
65 */
66 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080067
68 /**
69 * @brief Create Block from the wire buffer (no parsing)
70 *
71 * This version of the constructor does not do any parsing
72 */
73 Block(const ConstBufferPtr &wire,
74 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080075 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
76 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080077
78 /**
79 * @brief Create Block of a specific type with empty wire buffer
80 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080081 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080082 Block(uint32_t type);
83
84 /**
85 * @brief Create 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 */
91 Block(uint32_t type, const ConstBufferPtr &value);
92
93 /**
94 * @brief Create nested Block of a specific type with the specified value
95 *
96 * The underlying buffer hold only value, additional operations are needed
97 * to construct wire encoding, one need to prepend the wire buffer with type
98 * and value-length VAR-NUMBERs
99 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800100 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800101 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800102
103 /**
104 * @brief Check if the Block is empty
105 */
106 inline bool
107 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800108
109 /**
110 * @brief Check if the Block has fully encoded wire
111 */
112 inline bool
113 hasWire() const;
114
115 /**
116 * @brief Check if the Block has value block (no type and length are encoded)
117 */
118 inline bool
119 hasValue() const;
120
121 /**
122 * @brief Reset wire buffer of the element
123 */
124 inline void
125 reset();
126
127 void
128 parse();
129
130 void
131 encode();
132
133 inline uint32_t
134 type() const;
135
136 /**
137 * @brief Get the first subelement of the requested type
138 */
139 inline const Block &
140 get(uint32_t type) const;
141
142 inline Block &
143 get(uint32_t type);
144
145 inline element_iterator
146 find(uint32_t type);
147
148 inline element_const_iterator
149 find(uint32_t type) const;
150
151 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800152 remove(uint32_t type);
153
154 inline element_iterator
155 erase(element_iterator position);
156
157 inline element_iterator
158 erase(element_iterator first, element_iterator last);
159
160 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800161 push_back(const Block &element);
162
163 /**
164 * @brief Get all subelements
165 */
166 inline const std::list<Block>&
167 getAll () const;
168
169 inline std::list<Block>&
170 getAll ();
171
172 /**
173 * @brief Get all elements of the requested type
174 */
175 std::list<Block>
176 getAll(uint32_t type) const;
177
178 inline Buffer::const_iterator
179 begin() const;
180
181 inline Buffer::const_iterator
182 end() const;
183
184 inline size_t
185 size() const;
186
187 inline Buffer::const_iterator
188 value_begin() const;
189
190 inline Buffer::const_iterator
191 value_end() const;
192
193 inline const uint8_t*
194 wire() const;
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800195
196 inline const uint8_t*
197 buf() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800198
199 inline const uint8_t*
200 value() const;
201
202 inline size_t
203 value_size() const;
204
Yingdi Yu4270f202014-01-28 14:19:16 -0800205 Block
206 blockFromValue() const;
207
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800208protected:
209 ConstBufferPtr m_buffer;
210
211 uint32_t m_type;
212
213 Buffer::const_iterator m_begin;
214 Buffer::const_iterator m_end;
215 uint32_t m_size;
216
217 Buffer::const_iterator m_value_begin;
218 Buffer::const_iterator m_value_end;
219
220 std::list<Block> m_subBlocks;
221};
222
223////////////////////////////////////////////////////////////////////////////////
224////////////////////////////////////////////////////////////////////////////////
225////////////////////////////////////////////////////////////////////////////////
226
227inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800228Block::empty() const
229{
230 return m_type == std::numeric_limits<uint32_t>::max();
231}
232
233
234inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800235Block::hasWire() const
236{
237 return m_buffer && (m_begin != m_end);
238}
239
240inline bool
241Block::hasValue() const
242{
243 return static_cast<bool>(m_buffer);
244}
245
246inline void
247Block::reset()
248{
249 m_buffer.reset(); // reset of the shared_ptr
250 m_subBlocks.clear(); // remove all parsed subelements
251
252 m_type = std::numeric_limits<uint32_t>::max();
253 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
254}
255
256inline uint32_t
257Block::type() const
258{
259 return m_type;
260}
261
262inline const Block &
263Block::get(uint32_t type) const
264{
265 for (element_const_iterator i = m_subBlocks.begin ();
266 i != m_subBlocks.end();
267 i++)
268 {
269 if (i->type () == type)
270 {
271 return *i;
272 }
273 }
274
275 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
276}
277
278inline Block &
279Block::get(uint32_t type)
280{
281 for (element_iterator i = m_subBlocks.begin ();
282 i != m_subBlocks.end();
283 i++)
284 {
285 if (i->type () == type)
286 {
287 return *i;
288 }
289 }
290
291 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
292}
293
294inline Block::element_const_iterator
295Block::find(uint32_t type) const
296{
297 for (element_const_iterator i = m_subBlocks.begin ();
298 i != m_subBlocks.end();
299 i++)
300 {
301 if (i->type () == type)
302 {
303 return i;
304 }
305 }
306 return m_subBlocks.end();
307}
308
309inline Block::element_iterator
310Block::find(uint32_t type)
311{
312 for (element_iterator i = m_subBlocks.begin ();
313 i != m_subBlocks.end();
314 i++)
315 {
316 if (i->type () == type)
317 {
318 return i;
319 }
320 }
321 return m_subBlocks.end();
322}
323
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800324struct block_type
325{
326 block_type(uint32_t type)
327 : m_type(type)
328 {
329 }
330
331 inline bool
332 operator()(const Block &block)
333 {
334 return (block.type() == m_type);
335 }
336private:
337 uint32_t m_type;
338};
339
340inline void
341Block::remove(uint32_t type)
342{
343 m_subBlocks.remove_if(block_type(type));
344}
345
346inline Block::element_iterator
347Block::erase(Block::element_iterator position)
348{
349 return m_subBlocks.erase(position);
350}
351
352inline Block::element_iterator
353Block::erase(Block::element_iterator first, Block::element_iterator last)
354{
355 return m_subBlocks.erase(first, last);
356}
357
358
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800359inline void
360Block::push_back(const Block &element)
361{
362 m_subBlocks.push_back(element);
363}
364
365
366inline const std::list<Block>&
367Block::getAll () const
368{
369 return m_subBlocks;
370}
371
372inline std::list<Block>&
373Block::getAll ()
374{
375 return m_subBlocks;
376}
377
378
379inline Buffer::const_iterator
380Block::begin() const
381{
382 if (!hasWire())
383 throw Error("Underlying wire buffer is empty");
384
385 return m_begin;
386}
387
388inline Buffer::const_iterator
389Block::end() const
390{
391 if (!hasWire())
392 throw Error("Underlying wire buffer is empty");
393
394 return m_end;
395}
396
397inline size_t
398Block::size() const
399{
400 if (hasWire() || hasValue()) {
401 return m_size;
402 }
403 else
404 throw Error("Block size cannot be determined (undefined block size)");
405}
406
407inline Buffer::const_iterator
408Block::value_begin() const
409{
410 if (!hasValue())
411 throw Error("(Block::value_begin) Underlying value buffer is empty");
412
413 return m_value_begin;
414}
415
416inline Buffer::const_iterator
417Block::value_end() const
418{
419 if (!hasValue())
420 throw Error("(Block::value_end) Underlying value buffer is empty");
421
422 return m_value_end;
423}
424
425inline const uint8_t*
426Block::wire() const
427{
428 if (!hasWire())
429 throw Error("(Block::wire) Underlying wire buffer is empty");
430
431 return &*m_begin;
432}
433
434inline const uint8_t*
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800435Block::buf() const
436{
437 if (!hasWire())
438 throw Error("(Block::wire) Underlying wire buffer is empty");
439
440 return &*m_begin;
441}
442
443inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800444Block::value() const
445{
446 if (!hasValue())
447 throw Error("(Block::value) Underlying value buffer is empty");
448
449 return &*m_value_begin;
450}
451
452inline size_t
453Block::value_size() const
454{
455 if (!hasValue())
456 throw Error("(Block::value_size) Underlying value buffer is empty");
457
458 return m_value_end - m_value_begin;
459}
460
461} // ndn
462
463#include "block-helpers.hpp"
464
465#endif // NDN_BLOCK_HPP