blob: 52ed7e746c805899dc3bc89f4b7c2113a7eedd89 [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
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015#include "buffer.hpp"
16#include "tlv.hpp"
17
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080018namespace ndn {
19
Alexander Afanasyev233750e2014-02-16 00:50:07 -080020template<bool> class EncodingImpl;
21typedef EncodingImpl<true> EncodingBuffer;
22
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080023/**
24 * @brief Class representing wire element of the NDN packet
25 */
26class Block
27{
28public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080029 typedef std::vector<Block> element_container;
30 typedef element_container::iterator element_iterator;
31 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080032
33 /// @brief Error that can be thrown from the block
34 struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
35
36 /**
37 * @brief Default constructor to create an empty Block
38 */
39 Block();
40
41 /**
Alexander Afanasyev15151312014-02-16 00:53:51 -080042 * @brief Create block based on EncodingBuffer object
43 */
44 explicit
45 Block(const EncodingBuffer& buffer);
46
47 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080048 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
49 */
50 Block(const ConstBufferPtr &buffer);
51
52 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080053 * @brief Another helper to create block from a buffer, directly specifying boundaries
54 * of the block within the buffer
55 *
56 * This version will automatically detect type and position of the value within the block
57 */
58 Block(const ConstBufferPtr &buffer,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080059 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
60 bool verifyLength = true);
Alexander Afanasyev187bc482014-02-06 15:04:04 -080061
62 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080063 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
64 */
65 Block(const uint8_t *buffer, size_t maxlength);
66
67 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080068
69 /*
70 * @brief A helper version of a constructor to create Block from the stream.
71 */
72 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073
74 /**
75 * @brief Create Block from the wire buffer (no parsing)
76 *
77 * This version of the constructor does not do any parsing
78 */
79 Block(const ConstBufferPtr &wire,
80 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080081 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
82 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080083
84 /**
85 * @brief Create Block of a specific type with empty wire buffer
86 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080087 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080088 Block(uint32_t type);
89
90 /**
91 * @brief Create Block of a specific type with the specified value
92 *
93 * The underlying buffer hold only value, additional operations are needed
94 * to construct wire encoding, one need to prepend the wire buffer with type
95 * and value-length VAR-NUMBERs
96 */
97 Block(uint32_t type, const ConstBufferPtr &value);
98
99 /**
100 * @brief Create nested Block of a specific type with the specified value
101 *
102 * The underlying buffer hold only value, additional operations are needed
103 * to construct wire encoding, one need to prepend the wire buffer with type
104 * and value-length VAR-NUMBERs
105 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800106 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800107 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800108
109 /**
110 * @brief Check if the Block is empty
111 */
112 inline bool
113 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800114
115 /**
116 * @brief Check if the Block has fully encoded wire
117 */
118 inline bool
119 hasWire() const;
120
121 /**
122 * @brief Check if the Block has value block (no type and length are encoded)
123 */
124 inline bool
125 hasValue() const;
126
127 /**
128 * @brief Reset wire buffer of the element
129 */
130 inline void
131 reset();
132
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800133 /**
134 * @brief Reset wire buffer but keep sub elements (if any)
135 */
136 inline void
137 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800138
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800139 /**
140 * @brief Parse wire buffer into subblocks
141 *
142 * This method is not really const, but it does not modify any data. It simply
143 * parses contents of the buffer into subblocks
144 */
145 void
146 parse() const;
147
148 /**
149 * @brief Encode subblocks into wire buffer
150 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800151 void
152 encode();
153
154 inline uint32_t
155 type() const;
156
157 /**
158 * @brief Get the first subelement of the requested type
159 */
160 inline const Block &
161 get(uint32_t type) const;
162
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800163 inline element_const_iterator
164 find(uint32_t type) const;
165
166 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800167 remove(uint32_t type);
168
169 inline element_iterator
170 erase(element_iterator position);
171
172 inline element_iterator
173 erase(element_iterator first, element_iterator last);
174
175 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800176 push_back(const Block &element);
177
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800178 inline Buffer::const_iterator
179 begin() const;
180
181 inline Buffer::const_iterator
182 end() const;
183
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800184 inline const uint8_t*
185 wire() const;
186
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800187 inline size_t
188 size() const;
189
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800190 // inline const uint8_t*
191 // buf() const;
192
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800193 inline Buffer::const_iterator
194 value_begin() const;
195
196 inline Buffer::const_iterator
197 value_end() const;
198
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800199 inline const uint8_t*
200 value() const;
201
202 inline size_t
203 value_size() const;
204
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800205 /**
206 * @brief Get all subelements
207 */
208 inline const element_container&
209 elements () const;
210
211 inline element_const_iterator
212 elements_begin() const;
213
214 inline element_const_iterator
215 elements_end() const;
216
217 inline size_t
218 elements_size() const;
219
Yingdi Yu4270f202014-01-28 14:19:16 -0800220 Block
221 blockFromValue() const;
222
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800223protected:
224 ConstBufferPtr m_buffer;
225
226 uint32_t m_type;
227
228 Buffer::const_iterator m_begin;
229 Buffer::const_iterator m_end;
230 uint32_t m_size;
231
232 Buffer::const_iterator m_value_begin;
233 Buffer::const_iterator m_value_end;
234
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800235 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800236 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800237};
238
239////////////////////////////////////////////////////////////////////////////////
240////////////////////////////////////////////////////////////////////////////////
241////////////////////////////////////////////////////////////////////////////////
242
243inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800244Block::empty() const
245{
246 return m_type == std::numeric_limits<uint32_t>::max();
247}
248
249
250inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800251Block::hasWire() const
252{
253 return m_buffer && (m_begin != m_end);
254}
255
256inline bool
257Block::hasValue() const
258{
259 return static_cast<bool>(m_buffer);
260}
261
262inline void
263Block::reset()
264{
265 m_buffer.reset(); // reset of the shared_ptr
266 m_subBlocks.clear(); // remove all parsed subelements
267
268 m_type = std::numeric_limits<uint32_t>::max();
269 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
270}
271
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800272inline void
273Block::resetWire()
274{
275 m_buffer.reset(); // reset of the shared_ptr
276 // keep subblocks
277
278 // keep type
279 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
280}
281
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800282inline uint32_t
283Block::type() const
284{
285 return m_type;
286}
287
288inline const Block &
289Block::get(uint32_t type) const
290{
291 for (element_const_iterator i = m_subBlocks.begin ();
292 i != m_subBlocks.end();
293 i++)
294 {
295 if (i->type () == type)
296 {
297 return *i;
298 }
299 }
300
301 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
302}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800303
304inline Block::element_const_iterator
305Block::find(uint32_t type) const
306{
307 for (element_const_iterator i = m_subBlocks.begin ();
308 i != m_subBlocks.end();
309 i++)
310 {
311 if (i->type () == type)
312 {
313 return i;
314 }
315 }
316 return m_subBlocks.end();
317}
318
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800319inline void
320Block::remove(uint32_t type)
321{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800322 resetWire();
323
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800324 element_container newContainer;
325 newContainer.reserve(m_subBlocks.size());
326 for (element_iterator i = m_subBlocks.begin();
327 i != m_subBlocks.end();
328 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800329 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800330 if (i->type() != type)
331 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800332 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800333 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800334}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800335
336inline Block::element_iterator
337Block::erase(Block::element_iterator position)
338{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800339 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800340 return m_subBlocks.erase(position);
341}
342
343inline Block::element_iterator
344Block::erase(Block::element_iterator first, Block::element_iterator last)
345{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800346 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800347 return m_subBlocks.erase(first, last);
348}
349
350
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800351inline void
352Block::push_back(const Block &element)
353{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800354 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800355 m_subBlocks.push_back(element);
356}
357
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800358inline Buffer::const_iterator
359Block::begin() const
360{
361 if (!hasWire())
362 throw Error("Underlying wire buffer is empty");
363
364 return m_begin;
365}
366
367inline Buffer::const_iterator
368Block::end() const
369{
370 if (!hasWire())
371 throw Error("Underlying wire buffer is empty");
372
373 return m_end;
374}
375
376inline size_t
377Block::size() const
378{
379 if (hasWire() || hasValue()) {
380 return m_size;
381 }
382 else
383 throw Error("Block size cannot be determined (undefined block size)");
384}
385
386inline Buffer::const_iterator
387Block::value_begin() const
388{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800389 return m_value_begin;
390}
391
392inline Buffer::const_iterator
393Block::value_end() const
394{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800395 return m_value_end;
396}
397
398inline const uint8_t*
399Block::wire() const
400{
401 if (!hasWire())
402 throw Error("(Block::wire) Underlying wire buffer is empty");
403
404 return &*m_begin;
405}
406
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800407inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800408Block::value() const
409{
410 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800411 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800412
413 return &*m_value_begin;
414}
415
416inline size_t
417Block::value_size() const
418{
419 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800420 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800421
422 return m_value_end - m_value_begin;
423}
424
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800425inline const Block::element_container&
426Block::elements () const
427{
428 return m_subBlocks;
429}
430
431inline Block::element_const_iterator
432Block::elements_begin() const
433{
434 return m_subBlocks.begin();
435}
436
437inline Block::element_const_iterator
438Block::elements_end() const
439{
440 return m_subBlocks.end();
441}
442
443inline size_t
444Block::elements_size() const
445{
446 return m_subBlocks.size();
447}
448
449
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800450} // ndn
451
452#include "block-helpers.hpp"
453
454#endif // NDN_BLOCK_HPP