blob: 1383343f1607d7af63c964c77a01ab0b0d13cb53 [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 */
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
132 push_back(const Block &element);
133
134 /**
135 * @brief Get all subelements
136 */
137 inline const std::list<Block>&
138 getAll () const;
139
140 inline std::list<Block>&
141 getAll ();
142
143 /**
144 * @brief Get all elements of the requested type
145 */
146 std::list<Block>
147 getAll(uint32_t type) const;
148
149 inline Buffer::const_iterator
150 begin() const;
151
152 inline Buffer::const_iterator
153 end() const;
154
155 inline size_t
156 size() const;
157
158 inline Buffer::const_iterator
159 value_begin() const;
160
161 inline Buffer::const_iterator
162 value_end() const;
163
164 inline const uint8_t*
165 wire() const;
166
167 inline const uint8_t*
168 value() const;
169
170 inline size_t
171 value_size() const;
172
173protected:
174 ConstBufferPtr m_buffer;
175
176 uint32_t m_type;
177
178 Buffer::const_iterator m_begin;
179 Buffer::const_iterator m_end;
180 uint32_t m_size;
181
182 Buffer::const_iterator m_value_begin;
183 Buffer::const_iterator m_value_end;
184
185 std::list<Block> m_subBlocks;
186};
187
188////////////////////////////////////////////////////////////////////////////////
189////////////////////////////////////////////////////////////////////////////////
190////////////////////////////////////////////////////////////////////////////////
191
192inline bool
193Block::hasWire() const
194{
195 return m_buffer && (m_begin != m_end);
196}
197
198inline bool
199Block::hasValue() const
200{
201 return static_cast<bool>(m_buffer);
202}
203
204inline void
205Block::reset()
206{
207 m_buffer.reset(); // reset of the shared_ptr
208 m_subBlocks.clear(); // remove all parsed subelements
209
210 m_type = std::numeric_limits<uint32_t>::max();
211 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
212}
213
214inline uint32_t
215Block::type() const
216{
217 return m_type;
218}
219
220inline const Block &
221Block::get(uint32_t type) const
222{
223 for (element_const_iterator i = m_subBlocks.begin ();
224 i != m_subBlocks.end();
225 i++)
226 {
227 if (i->type () == type)
228 {
229 return *i;
230 }
231 }
232
233 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
234}
235
236inline Block &
237Block::get(uint32_t type)
238{
239 for (element_iterator i = m_subBlocks.begin ();
240 i != m_subBlocks.end();
241 i++)
242 {
243 if (i->type () == type)
244 {
245 return *i;
246 }
247 }
248
249 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
250}
251
252inline Block::element_const_iterator
253Block::find(uint32_t type) const
254{
255 for (element_const_iterator i = m_subBlocks.begin ();
256 i != m_subBlocks.end();
257 i++)
258 {
259 if (i->type () == type)
260 {
261 return i;
262 }
263 }
264 return m_subBlocks.end();
265}
266
267inline Block::element_iterator
268Block::find(uint32_t type)
269{
270 for (element_iterator i = m_subBlocks.begin ();
271 i != m_subBlocks.end();
272 i++)
273 {
274 if (i->type () == type)
275 {
276 return i;
277 }
278 }
279 return m_subBlocks.end();
280}
281
282inline void
283Block::push_back(const Block &element)
284{
285 m_subBlocks.push_back(element);
286}
287
288
289inline const std::list<Block>&
290Block::getAll () const
291{
292 return m_subBlocks;
293}
294
295inline std::list<Block>&
296Block::getAll ()
297{
298 return m_subBlocks;
299}
300
301
302inline Buffer::const_iterator
303Block::begin() const
304{
305 if (!hasWire())
306 throw Error("Underlying wire buffer is empty");
307
308 return m_begin;
309}
310
311inline Buffer::const_iterator
312Block::end() const
313{
314 if (!hasWire())
315 throw Error("Underlying wire buffer is empty");
316
317 return m_end;
318}
319
320inline size_t
321Block::size() const
322{
323 if (hasWire() || hasValue()) {
324 return m_size;
325 }
326 else
327 throw Error("Block size cannot be determined (undefined block size)");
328}
329
330inline Buffer::const_iterator
331Block::value_begin() const
332{
333 if (!hasValue())
334 throw Error("(Block::value_begin) Underlying value buffer is empty");
335
336 return m_value_begin;
337}
338
339inline Buffer::const_iterator
340Block::value_end() const
341{
342 if (!hasValue())
343 throw Error("(Block::value_end) Underlying value buffer is empty");
344
345 return m_value_end;
346}
347
348inline const uint8_t*
349Block::wire() const
350{
351 if (!hasWire())
352 throw Error("(Block::wire) Underlying wire buffer is empty");
353
354 return &*m_begin;
355}
356
357inline const uint8_t*
358Block::value() const
359{
360 if (!hasValue())
361 throw Error("(Block::value) Underlying value buffer is empty");
362
363 return &*m_value_begin;
364}
365
366inline size_t
367Block::value_size() const
368{
369 if (!hasValue())
370 throw Error("(Block::value_size) Underlying value buffer is empty");
371
372 return m_value_end - m_value_begin;
373}
374
375} // ndn
376
377#include "block-helpers.hpp"
378
379#endif // NDN_BLOCK_HPP