blob: a2f19bec82d911bd61a4e86a95637a1edff389d7 [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 /**
42 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
43 */
44 Block(const ConstBufferPtr &buffer);
45
46 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080047 * @brief Another helper to create block from a buffer, directly specifying boundaries
48 * of the block within the buffer
49 *
50 * This version will automatically detect type and position of the value within the block
51 */
52 Block(const ConstBufferPtr &buffer,
53 const Buffer::const_iterator &begin, const Buffer::const_iterator &end);
54
55 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080056 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
57 */
58 Block(const uint8_t *buffer, size_t maxlength);
59
60 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080061
62 /*
63 * @brief A helper version of a constructor to create Block from the stream.
64 */
65 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080066
67 /**
68 * @brief Create Block from the wire buffer (no parsing)
69 *
70 * This version of the constructor does not do any parsing
71 */
72 Block(const ConstBufferPtr &wire,
73 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080074 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
75 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080076
77 /**
78 * @brief Create Block of a specific type with empty wire buffer
79 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080080 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080081 Block(uint32_t type);
82
83 /**
84 * @brief Create Block of a specific type with the specified value
85 *
86 * The underlying buffer hold only value, additional operations are needed
87 * to construct wire encoding, one need to prepend the wire buffer with type
88 * and value-length VAR-NUMBERs
89 */
90 Block(uint32_t type, const ConstBufferPtr &value);
91
92 /**
93 * @brief Create nested Block of a specific type with the specified value
94 *
95 * The underlying buffer hold only value, additional operations are needed
96 * to construct wire encoding, one need to prepend the wire buffer with type
97 * and value-length VAR-NUMBERs
98 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080099 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800100 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800101
102 /**
103 * @brief Check if the Block is empty
104 */
105 inline bool
106 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800107
108 /**
109 * @brief Check if the Block has fully encoded wire
110 */
111 inline bool
112 hasWire() const;
113
114 /**
115 * @brief Check if the Block has value block (no type and length are encoded)
116 */
117 inline bool
118 hasValue() const;
119
120 /**
121 * @brief Reset wire buffer of the element
122 */
123 inline void
124 reset();
125
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800126 /**
127 * @brief Reset wire buffer but keep sub elements (if any)
128 */
129 inline void
130 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800131
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800132 /**
133 * @brief Parse wire buffer into subblocks
134 *
135 * This method is not really const, but it does not modify any data. It simply
136 * parses contents of the buffer into subblocks
137 */
138 void
139 parse() const;
140
141 /**
142 * @brief Encode subblocks into wire buffer
143 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800144 void
145 encode();
146
147 inline uint32_t
148 type() const;
149
150 /**
151 * @brief Get the first subelement of the requested type
152 */
153 inline const Block &
154 get(uint32_t type) const;
155
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800156 inline element_const_iterator
157 find(uint32_t type) const;
158
159 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800160 remove(uint32_t type);
161
162 inline element_iterator
163 erase(element_iterator position);
164
165 inline element_iterator
166 erase(element_iterator first, element_iterator last);
167
168 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800169 push_back(const Block &element);
170
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800171 inline Buffer::const_iterator
172 begin() const;
173
174 inline Buffer::const_iterator
175 end() const;
176
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800177 inline const uint8_t*
178 wire() const;
179
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800180 inline size_t
181 size() const;
182
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800183 // inline const uint8_t*
184 // buf() const;
185
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186 inline Buffer::const_iterator
187 value_begin() const;
188
189 inline Buffer::const_iterator
190 value_end() const;
191
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800192 inline const uint8_t*
193 value() const;
194
195 inline size_t
196 value_size() const;
197
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800198 /**
199 * @brief Get all subelements
200 */
201 inline const element_container&
202 elements () const;
203
204 inline element_const_iterator
205 elements_begin() const;
206
207 inline element_const_iterator
208 elements_end() const;
209
210 inline size_t
211 elements_size() const;
212
Yingdi Yu4270f202014-01-28 14:19:16 -0800213 Block
214 blockFromValue() const;
215
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800216protected:
217 ConstBufferPtr m_buffer;
218
219 uint32_t m_type;
220
221 Buffer::const_iterator m_begin;
222 Buffer::const_iterator m_end;
223 uint32_t m_size;
224
225 Buffer::const_iterator m_value_begin;
226 Buffer::const_iterator m_value_end;
227
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800228 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800229 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800230};
231
232////////////////////////////////////////////////////////////////////////////////
233////////////////////////////////////////////////////////////////////////////////
234////////////////////////////////////////////////////////////////////////////////
235
236inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800237Block::empty() const
238{
239 return m_type == std::numeric_limits<uint32_t>::max();
240}
241
242
243inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800244Block::hasWire() const
245{
246 return m_buffer && (m_begin != m_end);
247}
248
249inline bool
250Block::hasValue() const
251{
252 return static_cast<bool>(m_buffer);
253}
254
255inline void
256Block::reset()
257{
258 m_buffer.reset(); // reset of the shared_ptr
259 m_subBlocks.clear(); // remove all parsed subelements
260
261 m_type = std::numeric_limits<uint32_t>::max();
262 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
263}
264
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800265inline void
266Block::resetWire()
267{
268 m_buffer.reset(); // reset of the shared_ptr
269 // keep subblocks
270
271 // keep type
272 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
273}
274
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800275inline uint32_t
276Block::type() const
277{
278 return m_type;
279}
280
281inline const Block &
282Block::get(uint32_t type) const
283{
284 for (element_const_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
294 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
295}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800296
297inline Block::element_const_iterator
298Block::find(uint32_t type) const
299{
300 for (element_const_iterator i = m_subBlocks.begin ();
301 i != m_subBlocks.end();
302 i++)
303 {
304 if (i->type () == type)
305 {
306 return i;
307 }
308 }
309 return m_subBlocks.end();
310}
311
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800312inline void
313Block::remove(uint32_t type)
314{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800315 resetWire();
316
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800317 element_container newContainer;
318 newContainer.reserve(m_subBlocks.size());
319 for (element_iterator i = m_subBlocks.begin();
320 i != m_subBlocks.end();
321 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800322 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800323 if (i->type() != type)
324 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800325 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800326 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800327}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800328
329inline Block::element_iterator
330Block::erase(Block::element_iterator position)
331{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800332 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800333 return m_subBlocks.erase(position);
334}
335
336inline Block::element_iterator
337Block::erase(Block::element_iterator first, Block::element_iterator last)
338{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800339 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800340 return m_subBlocks.erase(first, last);
341}
342
343
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800344inline void
345Block::push_back(const Block &element)
346{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800347 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800348 m_subBlocks.push_back(element);
349}
350
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800351inline 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{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800382 return m_value_begin;
383}
384
385inline Buffer::const_iterator
386Block::value_end() const
387{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800388 return m_value_end;
389}
390
391inline const uint8_t*
392Block::wire() const
393{
394 if (!hasWire())
395 throw Error("(Block::wire) Underlying wire buffer is empty");
396
397 return &*m_begin;
398}
399
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800400inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800401Block::value() const
402{
403 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800404 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800405
406 return &*m_value_begin;
407}
408
409inline size_t
410Block::value_size() const
411{
412 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800413 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800414
415 return m_value_end - m_value_begin;
416}
417
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800418inline const Block::element_container&
419Block::elements () const
420{
421 return m_subBlocks;
422}
423
424inline Block::element_const_iterator
425Block::elements_begin() const
426{
427 return m_subBlocks.begin();
428}
429
430inline Block::element_const_iterator
431Block::elements_end() const
432{
433 return m_subBlocks.end();
434}
435
436inline size_t
437Block::elements_size() const
438{
439 return m_subBlocks.size();
440}
441
442
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800443} // ndn
444
445#include "block-helpers.hpp"
446
447#endif // NDN_BLOCK_HPP