blob: 9c2777dd0aaefc5be3d322ce25982ffb0da94ce8 [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);
93
94 /**
95 * @brief Check if the Block has fully encoded wire
96 */
97 inline bool
98 hasWire() const;
99
100 /**
101 * @brief Check if the Block has value block (no type and length are encoded)
102 */
103 inline bool
104 hasValue() const;
105
106 /**
107 * @brief Reset wire buffer of the element
108 */
109 inline void
110 reset();
111
112 void
113 parse();
114
115 void
116 encode();
117
118 inline uint32_t
119 type() const;
120
121 /**
122 * @brief Get the first subelement of the requested type
123 */
124 inline const Block &
125 get(uint32_t type) const;
126
127 inline Block &
128 get(uint32_t type);
129
130 inline element_iterator
131 find(uint32_t type);
132
133 inline element_const_iterator
134 find(uint32_t type) const;
135
136 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800137 remove(uint32_t type);
138
139 inline element_iterator
140 erase(element_iterator position);
141
142 inline element_iterator
143 erase(element_iterator first, element_iterator last);
144
145 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800146 push_back(const Block &element);
147
148 /**
149 * @brief Get all subelements
150 */
151 inline const std::list<Block>&
152 getAll () const;
153
154 inline std::list<Block>&
155 getAll ();
156
157 /**
158 * @brief Get all elements of the requested type
159 */
160 std::list<Block>
161 getAll(uint32_t type) const;
162
163 inline Buffer::const_iterator
164 begin() const;
165
166 inline Buffer::const_iterator
167 end() const;
168
169 inline size_t
170 size() const;
171
172 inline Buffer::const_iterator
173 value_begin() const;
174
175 inline Buffer::const_iterator
176 value_end() const;
177
178 inline const uint8_t*
179 wire() const;
180
181 inline const uint8_t*
182 value() const;
183
184 inline size_t
185 value_size() const;
186
Yingdi Yu4270f202014-01-28 14:19:16 -0800187 Block
188 blockFromValue() const;
189
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800190protected:
191 ConstBufferPtr m_buffer;
192
193 uint32_t m_type;
194
195 Buffer::const_iterator m_begin;
196 Buffer::const_iterator m_end;
197 uint32_t m_size;
198
199 Buffer::const_iterator m_value_begin;
200 Buffer::const_iterator m_value_end;
201
202 std::list<Block> m_subBlocks;
203};
204
205////////////////////////////////////////////////////////////////////////////////
206////////////////////////////////////////////////////////////////////////////////
207////////////////////////////////////////////////////////////////////////////////
208
209inline bool
210Block::hasWire() const
211{
212 return m_buffer && (m_begin != m_end);
213}
214
215inline bool
216Block::hasValue() const
217{
218 return static_cast<bool>(m_buffer);
219}
220
221inline void
222Block::reset()
223{
224 m_buffer.reset(); // reset of the shared_ptr
225 m_subBlocks.clear(); // remove all parsed subelements
226
227 m_type = std::numeric_limits<uint32_t>::max();
228 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
229}
230
231inline uint32_t
232Block::type() const
233{
234 return m_type;
235}
236
237inline const Block &
238Block::get(uint32_t type) const
239{
240 for (element_const_iterator i = m_subBlocks.begin ();
241 i != m_subBlocks.end();
242 i++)
243 {
244 if (i->type () == type)
245 {
246 return *i;
247 }
248 }
249
250 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
251}
252
253inline Block &
254Block::get(uint32_t type)
255{
256 for (element_iterator i = m_subBlocks.begin ();
257 i != m_subBlocks.end();
258 i++)
259 {
260 if (i->type () == type)
261 {
262 return *i;
263 }
264 }
265
266 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
267}
268
269inline Block::element_const_iterator
270Block::find(uint32_t type) const
271{
272 for (element_const_iterator i = m_subBlocks.begin ();
273 i != m_subBlocks.end();
274 i++)
275 {
276 if (i->type () == type)
277 {
278 return i;
279 }
280 }
281 return m_subBlocks.end();
282}
283
284inline Block::element_iterator
285Block::find(uint32_t type)
286{
287 for (element_iterator i = m_subBlocks.begin ();
288 i != m_subBlocks.end();
289 i++)
290 {
291 if (i->type () == type)
292 {
293 return i;
294 }
295 }
296 return m_subBlocks.end();
297}
298
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800299struct block_type
300{
301 block_type(uint32_t type)
302 : m_type(type)
303 {
304 }
305
306 inline bool
307 operator()(const Block &block)
308 {
309 return (block.type() == m_type);
310 }
311private:
312 uint32_t m_type;
313};
314
315inline void
316Block::remove(uint32_t type)
317{
318 m_subBlocks.remove_if(block_type(type));
319}
320
321inline Block::element_iterator
322Block::erase(Block::element_iterator position)
323{
324 return m_subBlocks.erase(position);
325}
326
327inline Block::element_iterator
328Block::erase(Block::element_iterator first, Block::element_iterator last)
329{
330 return m_subBlocks.erase(first, last);
331}
332
333
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800334inline void
335Block::push_back(const Block &element)
336{
337 m_subBlocks.push_back(element);
338}
339
340
341inline const std::list<Block>&
342Block::getAll () const
343{
344 return m_subBlocks;
345}
346
347inline std::list<Block>&
348Block::getAll ()
349{
350 return m_subBlocks;
351}
352
353
354inline Buffer::const_iterator
355Block::begin() const
356{
357 if (!hasWire())
358 throw Error("Underlying wire buffer is empty");
359
360 return m_begin;
361}
362
363inline Buffer::const_iterator
364Block::end() const
365{
366 if (!hasWire())
367 throw Error("Underlying wire buffer is empty");
368
369 return m_end;
370}
371
372inline size_t
373Block::size() const
374{
375 if (hasWire() || hasValue()) {
376 return m_size;
377 }
378 else
379 throw Error("Block size cannot be determined (undefined block size)");
380}
381
382inline Buffer::const_iterator
383Block::value_begin() const
384{
385 if (!hasValue())
386 throw Error("(Block::value_begin) Underlying value buffer is empty");
387
388 return m_value_begin;
389}
390
391inline Buffer::const_iterator
392Block::value_end() const
393{
394 if (!hasValue())
395 throw Error("(Block::value_end) Underlying value buffer is empty");
396
397 return m_value_end;
398}
399
400inline const uint8_t*
401Block::wire() const
402{
403 if (!hasWire())
404 throw Error("(Block::wire) Underlying wire buffer is empty");
405
406 return &*m_begin;
407}
408
409inline const uint8_t*
410Block::value() const
411{
412 if (!hasValue())
413 throw Error("(Block::value) Underlying value buffer is empty");
414
415 return &*m_value_begin;
416}
417
418inline size_t
419Block::value_size() const
420{
421 if (!hasValue())
422 throw Error("(Block::value_size) Underlying value buffer is empty");
423
424 return m_value_end - m_value_begin;
425}
426
427} // ndn
428
429#include "block-helpers.hpp"
430
431#endif // NDN_BLOCK_HPP