blob: 85cdaf5c0979a95ee8ba35733af6fc566170b3f6 [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
Yingdi Yu61ec2722014-01-20 14:22:32 -080013#include <ndn-cpp-dev/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);
53
54 /**
55 * @brief Create Block from the wire buffer (no parsing)
56 *
57 * This version of the constructor does not do any parsing
58 */
59 Block(const ConstBufferPtr &wire,
60 uint32_t type,
61 const Buffer::const_iterator &begin, Buffer::const_iterator &end,
62 const Buffer::const_iterator &valueBegin, Buffer::const_iterator &valueEnd);
63
64 /**
65 * @brief Create Block of a specific type with empty wire buffer
66 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080067 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080068 Block(uint32_t type);
69
70 /**
71 * @brief Create Block of a specific type with the specified value
72 *
73 * The underlying buffer hold only value, additional operations are needed
74 * to construct wire encoding, one need to prepend the wire buffer with type
75 * and value-length VAR-NUMBERs
76 */
77 Block(uint32_t type, const ConstBufferPtr &value);
78
79 /**
80 * @brief Create nested Block of a specific type with the specified value
81 *
82 * The underlying buffer hold only value, additional operations are needed
83 * to construct wire encoding, one need to prepend the wire buffer with type
84 * and value-length VAR-NUMBERs
85 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080086 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080087 Block(uint32_t type, const Block &value);
88
89 /**
90 * @brief Check if the Block has fully encoded wire
91 */
92 inline bool
93 hasWire() const;
94
95 /**
96 * @brief Check if the Block has value block (no type and length are encoded)
97 */
98 inline bool
99 hasValue() const;
100
101 /**
102 * @brief Reset wire buffer of the element
103 */
104 inline void
105 reset();
106
107 void
108 parse();
109
110 void
111 encode();
112
113 inline uint32_t
114 type() const;
115
116 /**
117 * @brief Get the first subelement of the requested type
118 */
119 inline const Block &
120 get(uint32_t type) const;
121
122 inline Block &
123 get(uint32_t type);
124
125 inline element_iterator
126 find(uint32_t type);
127
128 inline element_const_iterator
129 find(uint32_t type) const;
130
131 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800132 remove(uint32_t type);
133
134 inline element_iterator
135 erase(element_iterator position);
136
137 inline element_iterator
138 erase(element_iterator first, element_iterator last);
139
140 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800141 push_back(const Block &element);
142
143 /**
144 * @brief Get all subelements
145 */
146 inline const std::list<Block>&
147 getAll () const;
148
149 inline std::list<Block>&
150 getAll ();
151
152 /**
153 * @brief Get all elements of the requested type
154 */
155 std::list<Block>
156 getAll(uint32_t type) const;
157
158 inline Buffer::const_iterator
159 begin() const;
160
161 inline Buffer::const_iterator
162 end() const;
163
164 inline size_t
165 size() const;
166
167 inline Buffer::const_iterator
168 value_begin() const;
169
170 inline Buffer::const_iterator
171 value_end() const;
172
173 inline const uint8_t*
174 wire() const;
175
176 inline const uint8_t*
177 value() const;
178
179 inline size_t
180 value_size() const;
181
182protected:
183 ConstBufferPtr m_buffer;
184
185 uint32_t m_type;
186
187 Buffer::const_iterator m_begin;
188 Buffer::const_iterator m_end;
189 uint32_t m_size;
190
191 Buffer::const_iterator m_value_begin;
192 Buffer::const_iterator m_value_end;
193
194 std::list<Block> m_subBlocks;
195};
196
197////////////////////////////////////////////////////////////////////////////////
198////////////////////////////////////////////////////////////////////////////////
199////////////////////////////////////////////////////////////////////////////////
200
201inline bool
202Block::hasWire() const
203{
204 return m_buffer && (m_begin != m_end);
205}
206
207inline bool
208Block::hasValue() const
209{
210 return static_cast<bool>(m_buffer);
211}
212
213inline void
214Block::reset()
215{
216 m_buffer.reset(); // reset of the shared_ptr
217 m_subBlocks.clear(); // remove all parsed subelements
218
219 m_type = std::numeric_limits<uint32_t>::max();
220 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
221}
222
223inline uint32_t
224Block::type() const
225{
226 return m_type;
227}
228
229inline const Block &
230Block::get(uint32_t type) const
231{
232 for (element_const_iterator i = m_subBlocks.begin ();
233 i != m_subBlocks.end();
234 i++)
235 {
236 if (i->type () == type)
237 {
238 return *i;
239 }
240 }
241
242 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
243}
244
245inline Block &
246Block::get(uint32_t type)
247{
248 for (element_iterator i = m_subBlocks.begin ();
249 i != m_subBlocks.end();
250 i++)
251 {
252 if (i->type () == type)
253 {
254 return *i;
255 }
256 }
257
258 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
259}
260
261inline Block::element_const_iterator
262Block::find(uint32_t type) const
263{
264 for (element_const_iterator i = m_subBlocks.begin ();
265 i != m_subBlocks.end();
266 i++)
267 {
268 if (i->type () == type)
269 {
270 return i;
271 }
272 }
273 return m_subBlocks.end();
274}
275
276inline Block::element_iterator
277Block::find(uint32_t type)
278{
279 for (element_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 return m_subBlocks.end();
289}
290
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800291struct block_type
292{
293 block_type(uint32_t type)
294 : m_type(type)
295 {
296 }
297
298 inline bool
299 operator()(const Block &block)
300 {
301 return (block.type() == m_type);
302 }
303private:
304 uint32_t m_type;
305};
306
307inline void
308Block::remove(uint32_t type)
309{
310 m_subBlocks.remove_if(block_type(type));
311}
312
313inline Block::element_iterator
314Block::erase(Block::element_iterator position)
315{
316 return m_subBlocks.erase(position);
317}
318
319inline Block::element_iterator
320Block::erase(Block::element_iterator first, Block::element_iterator last)
321{
322 return m_subBlocks.erase(first, last);
323}
324
325
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800326inline void
327Block::push_back(const Block &element)
328{
329 m_subBlocks.push_back(element);
330}
331
332
333inline const std::list<Block>&
334Block::getAll () const
335{
336 return m_subBlocks;
337}
338
339inline std::list<Block>&
340Block::getAll ()
341{
342 return m_subBlocks;
343}
344
345
346inline Buffer::const_iterator
347Block::begin() const
348{
349 if (!hasWire())
350 throw Error("Underlying wire buffer is empty");
351
352 return m_begin;
353}
354
355inline Buffer::const_iterator
356Block::end() const
357{
358 if (!hasWire())
359 throw Error("Underlying wire buffer is empty");
360
361 return m_end;
362}
363
364inline size_t
365Block::size() const
366{
367 if (hasWire() || hasValue()) {
368 return m_size;
369 }
370 else
371 throw Error("Block size cannot be determined (undefined block size)");
372}
373
374inline Buffer::const_iterator
375Block::value_begin() const
376{
377 if (!hasValue())
378 throw Error("(Block::value_begin) Underlying value buffer is empty");
379
380 return m_value_begin;
381}
382
383inline Buffer::const_iterator
384Block::value_end() const
385{
386 if (!hasValue())
387 throw Error("(Block::value_end) Underlying value buffer is empty");
388
389 return m_value_end;
390}
391
392inline const uint8_t*
393Block::wire() const
394{
395 if (!hasWire())
396 throw Error("(Block::wire) Underlying wire buffer is empty");
397
398 return &*m_begin;
399}
400
401inline const uint8_t*
402Block::value() const
403{
404 if (!hasValue())
405 throw Error("(Block::value) Underlying value buffer is empty");
406
407 return &*m_value_begin;
408}
409
410inline size_t
411Block::value_size() const
412{
413 if (!hasValue())
414 throw Error("(Block::value_size) Underlying value buffer is empty");
415
416 return m_value_end - m_value_begin;
417}
418
419} // ndn
420
421#include "block-helpers.hpp"
422
423#endif // NDN_BLOCK_HPP