blob: 3ae5971c6ed232039ec41fbbeceef9a0d582f4f8 [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 Afanasyev09c613f2014-01-29 00:23:58 -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
187protected:
188 ConstBufferPtr m_buffer;
189
190 uint32_t m_type;
191
192 Buffer::const_iterator m_begin;
193 Buffer::const_iterator m_end;
194 uint32_t m_size;
195
196 Buffer::const_iterator m_value_begin;
197 Buffer::const_iterator m_value_end;
198
199 std::list<Block> m_subBlocks;
200};
201
202////////////////////////////////////////////////////////////////////////////////
203////////////////////////////////////////////////////////////////////////////////
204////////////////////////////////////////////////////////////////////////////////
205
206inline bool
207Block::hasWire() const
208{
209 return m_buffer && (m_begin != m_end);
210}
211
212inline bool
213Block::hasValue() const
214{
215 return static_cast<bool>(m_buffer);
216}
217
218inline void
219Block::reset()
220{
221 m_buffer.reset(); // reset of the shared_ptr
222 m_subBlocks.clear(); // remove all parsed subelements
223
224 m_type = std::numeric_limits<uint32_t>::max();
225 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
226}
227
228inline uint32_t
229Block::type() const
230{
231 return m_type;
232}
233
234inline const Block &
235Block::get(uint32_t type) const
236{
237 for (element_const_iterator i = m_subBlocks.begin ();
238 i != m_subBlocks.end();
239 i++)
240 {
241 if (i->type () == type)
242 {
243 return *i;
244 }
245 }
246
247 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
248}
249
250inline Block &
251Block::get(uint32_t type)
252{
253 for (element_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::element_const_iterator
267Block::find(uint32_t type) const
268{
269 for (element_const_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 return m_subBlocks.end();
279}
280
281inline Block::element_iterator
282Block::find(uint32_t type)
283{
284 for (element_iterator i = m_subBlocks.begin ();
285 i != m_subBlocks.end();
286 i++)
287 {
288 if (i->type () == type)
289 {
290 return i;
291 }
292 }
293 return m_subBlocks.end();
294}
295
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800296struct block_type
297{
298 block_type(uint32_t type)
299 : m_type(type)
300 {
301 }
302
303 inline bool
304 operator()(const Block &block)
305 {
306 return (block.type() == m_type);
307 }
308private:
309 uint32_t m_type;
310};
311
312inline void
313Block::remove(uint32_t type)
314{
315 m_subBlocks.remove_if(block_type(type));
316}
317
318inline Block::element_iterator
319Block::erase(Block::element_iterator position)
320{
321 return m_subBlocks.erase(position);
322}
323
324inline Block::element_iterator
325Block::erase(Block::element_iterator first, Block::element_iterator last)
326{
327 return m_subBlocks.erase(first, last);
328}
329
330
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800331inline void
332Block::push_back(const Block &element)
333{
334 m_subBlocks.push_back(element);
335}
336
337
338inline const std::list<Block>&
339Block::getAll () const
340{
341 return m_subBlocks;
342}
343
344inline std::list<Block>&
345Block::getAll ()
346{
347 return m_subBlocks;
348}
349
350
351inline Buffer::const_iterator
352Block::begin() const
353{
354 if (!hasWire())
355 throw Error("Underlying wire buffer is empty");
356
357 return m_begin;
358}
359
360inline Buffer::const_iterator
361Block::end() const
362{
363 if (!hasWire())
364 throw Error("Underlying wire buffer is empty");
365
366 return m_end;
367}
368
369inline size_t
370Block::size() const
371{
372 if (hasWire() || hasValue()) {
373 return m_size;
374 }
375 else
376 throw Error("Block size cannot be determined (undefined block size)");
377}
378
379inline Buffer::const_iterator
380Block::value_begin() const
381{
382 if (!hasValue())
383 throw Error("(Block::value_begin) Underlying value buffer is empty");
384
385 return m_value_begin;
386}
387
388inline Buffer::const_iterator
389Block::value_end() const
390{
391 if (!hasValue())
392 throw Error("(Block::value_end) Underlying value buffer is empty");
393
394 return m_value_end;
395}
396
397inline const uint8_t*
398Block::wire() const
399{
400 if (!hasWire())
401 throw Error("(Block::wire) Underlying wire buffer is empty");
402
403 return &*m_begin;
404}
405
406inline const uint8_t*
407Block::value() const
408{
409 if (!hasValue())
410 throw Error("(Block::value) Underlying value buffer is empty");
411
412 return &*m_value_begin;
413}
414
415inline size_t
416Block::value_size() const
417{
418 if (!hasValue())
419 throw Error("(Block::value_size) Underlying value buffer is empty");
420
421 return m_value_end - m_value_begin;
422}
423
424} // ndn
425
426#include "block-helpers.hpp"
427
428#endif // NDN_BLOCK_HPP