blob: 895df49e17b0416513d95e6306e40497f84da3c1 [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,
59 const Buffer::const_iterator &begin, const Buffer::const_iterator &end);
60
61 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080062 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
63 */
64 Block(const uint8_t *buffer, size_t maxlength);
65
66 Block(const void *buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080067
68 /*
69 * @brief A helper version of a constructor to create Block from the stream.
70 */
71 Block(std::istream& is);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080072
73 /**
74 * @brief Create Block from the wire buffer (no parsing)
75 *
76 * This version of the constructor does not do any parsing
77 */
78 Block(const ConstBufferPtr &wire,
79 uint32_t type,
Alexander Afanasyev187bc482014-02-06 15:04:04 -080080 const Buffer::const_iterator &begin, const Buffer::const_iterator &end,
81 const Buffer::const_iterator &valueBegin, const Buffer::const_iterator &valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080082
83 /**
84 * @brief Create Block of a specific type with empty wire buffer
85 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080086 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080087 Block(uint32_t type);
88
89 /**
90 * @brief Create Block of a specific type with the specified value
91 *
92 * The underlying buffer hold only value, additional operations are needed
93 * to construct wire encoding, one need to prepend the wire buffer with type
94 * and value-length VAR-NUMBERs
95 */
96 Block(uint32_t type, const ConstBufferPtr &value);
97
98 /**
99 * @brief Create nested Block of a specific type with the specified value
100 *
101 * The underlying buffer hold only value, additional operations are needed
102 * to construct wire encoding, one need to prepend the wire buffer with type
103 * and value-length VAR-NUMBERs
104 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800105 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800106 Block(uint32_t type, const Block &value);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800107
108 /**
109 * @brief Check if the Block is empty
110 */
111 inline bool
112 empty() const;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800113
114 /**
115 * @brief Check if the Block has fully encoded wire
116 */
117 inline bool
118 hasWire() const;
119
120 /**
121 * @brief Check if the Block has value block (no type and length are encoded)
122 */
123 inline bool
124 hasValue() const;
125
126 /**
127 * @brief Reset wire buffer of the element
128 */
129 inline void
130 reset();
131
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800132 /**
133 * @brief Reset wire buffer but keep sub elements (if any)
134 */
135 inline void
136 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800137
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800138 /**
139 * @brief Parse wire buffer into subblocks
140 *
141 * This method is not really const, but it does not modify any data. It simply
142 * parses contents of the buffer into subblocks
143 */
144 void
145 parse() const;
146
147 /**
148 * @brief Encode subblocks into wire buffer
149 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800150 void
151 encode();
152
153 inline uint32_t
154 type() const;
155
156 /**
157 * @brief Get the first subelement of the requested type
158 */
159 inline const Block &
160 get(uint32_t type) const;
161
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800162 inline element_const_iterator
163 find(uint32_t type) const;
164
165 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800166 remove(uint32_t type);
167
168 inline element_iterator
169 erase(element_iterator position);
170
171 inline element_iterator
172 erase(element_iterator first, element_iterator last);
173
174 inline void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800175 push_back(const Block &element);
176
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800177 inline Buffer::const_iterator
178 begin() const;
179
180 inline Buffer::const_iterator
181 end() const;
182
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800183 inline const uint8_t*
184 wire() const;
185
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186 inline size_t
187 size() const;
188
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800189 // inline const uint8_t*
190 // buf() const;
191
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800192 inline Buffer::const_iterator
193 value_begin() const;
194
195 inline Buffer::const_iterator
196 value_end() const;
197
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800198 inline const uint8_t*
199 value() const;
200
201 inline size_t
202 value_size() const;
203
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800204 /**
205 * @brief Get all subelements
206 */
207 inline const element_container&
208 elements () const;
209
210 inline element_const_iterator
211 elements_begin() const;
212
213 inline element_const_iterator
214 elements_end() const;
215
216 inline size_t
217 elements_size() const;
218
Yingdi Yu4270f202014-01-28 14:19:16 -0800219 Block
220 blockFromValue() const;
221
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800222protected:
223 ConstBufferPtr m_buffer;
224
225 uint32_t m_type;
226
227 Buffer::const_iterator m_begin;
228 Buffer::const_iterator m_end;
229 uint32_t m_size;
230
231 Buffer::const_iterator m_value_begin;
232 Buffer::const_iterator m_value_end;
233
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800234 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800235 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800236};
237
238////////////////////////////////////////////////////////////////////////////////
239////////////////////////////////////////////////////////////////////////////////
240////////////////////////////////////////////////////////////////////////////////
241
242inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800243Block::empty() const
244{
245 return m_type == std::numeric_limits<uint32_t>::max();
246}
247
248
249inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800250Block::hasWire() const
251{
252 return m_buffer && (m_begin != m_end);
253}
254
255inline bool
256Block::hasValue() const
257{
258 return static_cast<bool>(m_buffer);
259}
260
261inline void
262Block::reset()
263{
264 m_buffer.reset(); // reset of the shared_ptr
265 m_subBlocks.clear(); // remove all parsed subelements
266
267 m_type = std::numeric_limits<uint32_t>::max();
268 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
269}
270
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800271inline void
272Block::resetWire()
273{
274 m_buffer.reset(); // reset of the shared_ptr
275 // keep subblocks
276
277 // keep type
278 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
279}
280
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800281inline uint32_t
282Block::type() const
283{
284 return m_type;
285}
286
287inline const Block &
288Block::get(uint32_t type) const
289{
290 for (element_const_iterator i = m_subBlocks.begin ();
291 i != m_subBlocks.end();
292 i++)
293 {
294 if (i->type () == type)
295 {
296 return *i;
297 }
298 }
299
300 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
301}
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800302
303inline Block::element_const_iterator
304Block::find(uint32_t type) const
305{
306 for (element_const_iterator i = m_subBlocks.begin ();
307 i != m_subBlocks.end();
308 i++)
309 {
310 if (i->type () == type)
311 {
312 return i;
313 }
314 }
315 return m_subBlocks.end();
316}
317
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800318inline void
319Block::remove(uint32_t type)
320{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800321 resetWire();
322
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800323 element_container newContainer;
324 newContainer.reserve(m_subBlocks.size());
325 for (element_iterator i = m_subBlocks.begin();
326 i != m_subBlocks.end();
327 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800328 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800329 if (i->type() != type)
330 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800331 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800332 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800333}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800334
335inline Block::element_iterator
336Block::erase(Block::element_iterator position)
337{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800338 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800339 return m_subBlocks.erase(position);
340}
341
342inline Block::element_iterator
343Block::erase(Block::element_iterator first, Block::element_iterator last)
344{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800345 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800346 return m_subBlocks.erase(first, last);
347}
348
349
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800350inline void
351Block::push_back(const Block &element)
352{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800353 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800354 m_subBlocks.push_back(element);
355}
356
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800357inline Buffer::const_iterator
358Block::begin() const
359{
360 if (!hasWire())
361 throw Error("Underlying wire buffer is empty");
362
363 return m_begin;
364}
365
366inline Buffer::const_iterator
367Block::end() const
368{
369 if (!hasWire())
370 throw Error("Underlying wire buffer is empty");
371
372 return m_end;
373}
374
375inline size_t
376Block::size() const
377{
378 if (hasWire() || hasValue()) {
379 return m_size;
380 }
381 else
382 throw Error("Block size cannot be determined (undefined block size)");
383}
384
385inline Buffer::const_iterator
386Block::value_begin() const
387{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800388 return m_value_begin;
389}
390
391inline Buffer::const_iterator
392Block::value_end() const
393{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800394 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
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800406inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800407Block::value() const
408{
409 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800410 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800411
412 return &*m_value_begin;
413}
414
415inline size_t
416Block::value_size() const
417{
418 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800419 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800420
421 return m_value_end - m_value_begin;
422}
423
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800424inline const Block::element_container&
425Block::elements () const
426{
427 return m_subBlocks;
428}
429
430inline Block::element_const_iterator
431Block::elements_begin() const
432{
433 return m_subBlocks.begin();
434}
435
436inline Block::element_const_iterator
437Block::elements_end() const
438{
439 return m_subBlocks.end();
440}
441
442inline size_t
443Block::elements_size() const
444{
445 return m_subBlocks.size();
446}
447
448
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800449} // ndn
450
451#include "block-helpers.hpp"
452
453#endif // NDN_BLOCK_HPP