blob: 6d104b1b0006f4703938d01ea340499461068333 [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
13#include <ndn-cpp/common.hpp>
14
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 */
67 Block(uint32_t type);
68
69 /**
70 * @brief Create Block of a specific type with the specified value
71 *
72 * The underlying buffer hold only value, additional operations are needed
73 * to construct wire encoding, one need to prepend the wire buffer with type
74 * and value-length VAR-NUMBERs
75 */
76 Block(uint32_t type, const ConstBufferPtr &value);
77
78 /**
79 * @brief Create nested Block of a specific type with the specified value
80 *
81 * The underlying buffer hold only value, additional operations are needed
82 * to construct wire encoding, one need to prepend the wire buffer with type
83 * and value-length VAR-NUMBERs
84 */
85 Block(uint32_t type, const Block &value);
86
87 /**
88 * @brief Check if the Block has fully encoded wire
89 */
90 inline bool
91 hasWire() const;
92
93 /**
94 * @brief Check if the Block has value block (no type and length are encoded)
95 */
96 inline bool
97 hasValue() const;
98
99 /**
100 * @brief Reset wire buffer of the element
101 */
102 inline void
103 reset();
104
105 void
106 parse();
107
108 void
109 encode();
110
111 inline uint32_t
112 type() const;
113
114 /**
115 * @brief Get the first subelement of the requested type
116 */
117 inline const Block &
118 get(uint32_t type) const;
119
120 inline Block &
121 get(uint32_t type);
122
123 inline element_iterator
124 find(uint32_t type);
125
126 inline element_const_iterator
127 find(uint32_t type) const;
128
129 inline void
130 push_back(const Block &element);
131
132 /**
133 * @brief Get all subelements
134 */
135 inline const std::list<Block>&
136 getAll () const;
137
138 inline std::list<Block>&
139 getAll ();
140
141 /**
142 * @brief Get all elements of the requested type
143 */
144 std::list<Block>
145 getAll(uint32_t type) const;
146
147 inline Buffer::const_iterator
148 begin() const;
149
150 inline Buffer::const_iterator
151 end() const;
152
153 inline size_t
154 size() const;
155
156 inline Buffer::const_iterator
157 value_begin() const;
158
159 inline Buffer::const_iterator
160 value_end() const;
161
162 inline const uint8_t*
163 wire() const;
164
165 inline const uint8_t*
166 value() const;
167
168 inline size_t
169 value_size() const;
170
171protected:
172 ConstBufferPtr m_buffer;
173
174 uint32_t m_type;
175
176 Buffer::const_iterator m_begin;
177 Buffer::const_iterator m_end;
178 uint32_t m_size;
179
180 Buffer::const_iterator m_value_begin;
181 Buffer::const_iterator m_value_end;
182
183 std::list<Block> m_subBlocks;
184};
185
186////////////////////////////////////////////////////////////////////////////////
187////////////////////////////////////////////////////////////////////////////////
188////////////////////////////////////////////////////////////////////////////////
189
190inline bool
191Block::hasWire() const
192{
193 return m_buffer && (m_begin != m_end);
194}
195
196inline bool
197Block::hasValue() const
198{
199 return static_cast<bool>(m_buffer);
200}
201
202inline void
203Block::reset()
204{
205 m_buffer.reset(); // reset of the shared_ptr
206 m_subBlocks.clear(); // remove all parsed subelements
207
208 m_type = std::numeric_limits<uint32_t>::max();
209 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
210}
211
212inline uint32_t
213Block::type() const
214{
215 return m_type;
216}
217
218inline const Block &
219Block::get(uint32_t type) const
220{
221 for (element_const_iterator i = m_subBlocks.begin ();
222 i != m_subBlocks.end();
223 i++)
224 {
225 if (i->type () == type)
226 {
227 return *i;
228 }
229 }
230
231 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
232}
233
234inline Block &
235Block::get(uint32_t type)
236{
237 for (element_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::element_const_iterator
251Block::find(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 return m_subBlocks.end();
263}
264
265inline Block::element_iterator
266Block::find(uint32_t type)
267{
268 for (element_iterator i = m_subBlocks.begin ();
269 i != m_subBlocks.end();
270 i++)
271 {
272 if (i->type () == type)
273 {
274 return i;
275 }
276 }
277 return m_subBlocks.end();
278}
279
280inline void
281Block::push_back(const Block &element)
282{
283 m_subBlocks.push_back(element);
284}
285
286
287inline const std::list<Block>&
288Block::getAll () const
289{
290 return m_subBlocks;
291}
292
293inline std::list<Block>&
294Block::getAll ()
295{
296 return m_subBlocks;
297}
298
299
300inline Buffer::const_iterator
301Block::begin() const
302{
303 if (!hasWire())
304 throw Error("Underlying wire buffer is empty");
305
306 return m_begin;
307}
308
309inline Buffer::const_iterator
310Block::end() const
311{
312 if (!hasWire())
313 throw Error("Underlying wire buffer is empty");
314
315 return m_end;
316}
317
318inline size_t
319Block::size() const
320{
321 if (hasWire() || hasValue()) {
322 return m_size;
323 }
324 else
325 throw Error("Block size cannot be determined (undefined block size)");
326}
327
328inline Buffer::const_iterator
329Block::value_begin() const
330{
331 if (!hasValue())
332 throw Error("(Block::value_begin) Underlying value buffer is empty");
333
334 return m_value_begin;
335}
336
337inline Buffer::const_iterator
338Block::value_end() const
339{
340 if (!hasValue())
341 throw Error("(Block::value_end) Underlying value buffer is empty");
342
343 return m_value_end;
344}
345
346inline const uint8_t*
347Block::wire() const
348{
349 if (!hasWire())
350 throw Error("(Block::wire) Underlying wire buffer is empty");
351
352 return &*m_begin;
353}
354
355inline const uint8_t*
356Block::value() const
357{
358 if (!hasValue())
359 throw Error("(Block::value) Underlying value buffer is empty");
360
361 return &*m_value_begin;
362}
363
364inline size_t
365Block::value_size() const
366{
367 if (!hasValue())
368 throw Error("(Block::value_size) Underlying value buffer is empty");
369
370 return m_value_end - m_value_begin;
371}
372
373} // ndn
374
375#include "block-helpers.hpp"
376
377#endif // NDN_BLOCK_HPP