blob: a2507b54ef8083e48208f8a314fbfe3c12b3f807 [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
Alexander Afanasyev937aa782014-03-21 13:17:57 -070034 struct Error : public std::runtime_error
35 {
36 Error(const std::string& what) : std::runtime_error(what) {}
37 };
38
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080039 /**
40 * @brief Default constructor to create an empty Block
41 */
42 Block();
43
44 /**
Alexander Afanasyev15151312014-02-16 00:53:51 -080045 * @brief Create block based on EncodingBuffer object
46 */
47 explicit
48 Block(const EncodingBuffer& buffer);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070049
Alexander Afanasyev15151312014-02-16 00:53:51 -080050 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080051 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
52 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070053 Block(const ConstBufferPtr& buffer);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080054
55 /**
Alexander Afanasyev187bc482014-02-06 15:04:04 -080056 * @brief Another helper to create block from a buffer, directly specifying boundaries
57 * of the block within the buffer
58 *
59 * This version will automatically detect type and position of the value within the block
60 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070061 Block(const ConstBufferPtr& buffer,
62 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080063 bool verifyLength = true);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070064
Alexander Afanasyev187bc482014-02-06 15:04:04 -080065 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080066 * @brief A helper version of a constructor to create Block from the raw buffer (type and value-length parsing)
67 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070068 Block(const uint8_t* buffer, size_t maxlength);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080069
Alexander Afanasyev937aa782014-03-21 13:17:57 -070070 Block(const void* buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -080071
72 /*
Alexander Afanasyev937aa782014-03-21 13:17:57 -070073 * @brief A helper version of a constructor to create Block from the stream.
Yingdi Yu27158392014-01-20 13:04:20 -080074 */
75 Block(std::istream& is);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070076
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080077 /**
78 * @brief Create Block from the wire buffer (no parsing)
79 *
80 * This version of the constructor does not do any parsing
81 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070082 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080083 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -070084 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
85 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080086
87 /**
88 * @brief Create Block of a specific type with empty wire buffer
89 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -080090 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080091 Block(uint32_t type);
92
93 /**
94 * @brief Create Block of a specific type with the specified value
95 *
96 * The underlying buffer hold only value, additional operations are needed
97 * to construct wire encoding, one need to prepend the wire buffer with type
98 * and value-length VAR-NUMBERs
99 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700100 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800101
102 /**
103 * @brief Create nested Block of a specific type with the specified value
104 *
105 * The underlying buffer hold only value, additional operations are needed
106 * to construct wire encoding, one need to prepend the wire buffer with type
107 * and value-length VAR-NUMBERs
108 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800109 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700110 Block(uint32_t type, const Block& value);
111
112 /**
113 * @brief Try to construct block from Buffer, referencing data block pointed by wire
114 *
115 * @throws This method never throws an exception
116 *
117 * @returns true if Block successfully created, false if block cannot be created
118 */
119 static bool
120 fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block);
121
122 /**
123 * @brief Try to construct block from Buffer, referencing data block pointed by wire
124 *
125 * @throws This method never throws an exception
126 *
127 * @returns true if Block successfully created, false if block cannot be created
128 */
129 static bool
130 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block);
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800131
132 /**
133 * @brief Check if the Block is empty
134 */
135 inline bool
136 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700137
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800138 /**
139 * @brief Check if the Block has fully encoded wire
140 */
141 inline bool
142 hasWire() const;
143
144 /**
145 * @brief Check if the Block has value block (no type and length are encoded)
146 */
147 inline bool
148 hasValue() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700149
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800150 /**
151 * @brief Reset wire buffer of the element
152 */
153 inline void
154 reset();
155
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800156 /**
157 * @brief Reset wire buffer but keep sub elements (if any)
158 */
159 inline void
160 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800161
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800162 /**
163 * @brief Parse wire buffer into subblocks
164 *
165 * This method is not really const, but it does not modify any data. It simply
166 * parses contents of the buffer into subblocks
167 */
168 void
169 parse() const;
170
171 /**
172 * @brief Encode subblocks into wire buffer
173 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800174 void
175 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700176
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800177 inline uint32_t
178 type() const;
179
180 /**
181 * @brief Get the first subelement of the requested type
182 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700183 inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800184 get(uint32_t type) const;
185
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186 inline element_const_iterator
187 find(uint32_t type) const;
188
189 inline void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800190 remove(uint32_t type);
191
192 inline element_iterator
193 erase(element_iterator position);
194
195 inline element_iterator
196 erase(element_iterator first, element_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700197
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800198 inline void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700199 push_back(const Block& element);
200
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800201 inline Buffer::const_iterator
202 begin() const;
203
204 inline Buffer::const_iterator
205 end() const;
206
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800207 inline const uint8_t*
208 wire() const;
209
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800210 inline size_t
211 size() const;
212
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800213 // inline const uint8_t*
214 // buf() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700215
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800216 inline Buffer::const_iterator
217 value_begin() const;
218
219 inline Buffer::const_iterator
220 value_end() const;
221
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800222 inline const uint8_t*
223 value() const;
224
225 inline size_t
226 value_size() const;
227
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800228 /**
229 * @brief Get all subelements
230 */
231 inline const element_container&
232 elements () const;
233
234 inline element_const_iterator
235 elements_begin() const;
236
237 inline element_const_iterator
238 elements_end() const;
239
240 inline size_t
241 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700242
Yingdi Yu4270f202014-01-28 14:19:16 -0800243 Block
244 blockFromValue() const;
245
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800246protected:
247 ConstBufferPtr m_buffer;
248
249 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700250
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800251 Buffer::const_iterator m_begin;
252 Buffer::const_iterator m_end;
253 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700254
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800255 Buffer::const_iterator m_value_begin;
256 Buffer::const_iterator m_value_end;
257
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800258 mutable element_container m_subBlocks;
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800259 friend class EncodingImpl<true>;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800260};
261
262////////////////////////////////////////////////////////////////////////////////
263////////////////////////////////////////////////////////////////////////////////
264////////////////////////////////////////////////////////////////////////////////
265
266inline bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800267Block::empty() const
268{
269 return m_type == std::numeric_limits<uint32_t>::max();
270}
271
272
273inline bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800274Block::hasWire() const
275{
276 return m_buffer && (m_begin != m_end);
277}
278
279inline bool
280Block::hasValue() const
281{
282 return static_cast<bool>(m_buffer);
283}
284
285inline void
286Block::reset()
287{
288 m_buffer.reset(); // reset of the shared_ptr
289 m_subBlocks.clear(); // remove all parsed subelements
290
291 m_type = std::numeric_limits<uint32_t>::max();
292 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
293}
294
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800295inline void
296Block::resetWire()
297{
298 m_buffer.reset(); // reset of the shared_ptr
299 // keep subblocks
300
301 // keep type
302 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator(); // not really necessary, but for safety
303}
304
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800305inline uint32_t
306Block::type() const
307{
308 return m_type;
309}
310
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700311inline const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800312Block::get(uint32_t type) const
313{
314 for (element_const_iterator i = m_subBlocks.begin ();
315 i != m_subBlocks.end();
316 i++)
317 {
318 if (i->type () == type)
319 {
320 return *i;
321 }
322 }
323
324 throw Error("(Block::get) Requested a non-existed type [" + boost::lexical_cast<std::string>(type) + "] from Block");
325}
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700326
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800327inline Block::element_const_iterator
328Block::find(uint32_t type) const
329{
330 for (element_const_iterator i = m_subBlocks.begin ();
331 i != m_subBlocks.end();
332 i++)
333 {
334 if (i->type () == type)
335 {
336 return i;
337 }
338 }
339 return m_subBlocks.end();
340}
341
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800342inline void
343Block::remove(uint32_t type)
344{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800345 resetWire();
346
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800347 element_container newContainer;
348 newContainer.reserve(m_subBlocks.size());
349 for (element_iterator i = m_subBlocks.begin();
350 i != m_subBlocks.end();
351 ++i)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800352 {
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800353 if (i->type() != type)
354 newContainer.push_back(*i);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800355 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800356 m_subBlocks.swap(newContainer);
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800357}
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800358
359inline Block::element_iterator
360Block::erase(Block::element_iterator position)
361{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800362 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800363 return m_subBlocks.erase(position);
364}
365
366inline Block::element_iterator
367Block::erase(Block::element_iterator first, Block::element_iterator last)
368{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800369 resetWire();
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800370 return m_subBlocks.erase(first, last);
371}
372
373
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800374inline void
375Block::push_back(const Block &element)
376{
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800377 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800378 m_subBlocks.push_back(element);
379}
380
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800381inline Buffer::const_iterator
382Block::begin() const
383{
384 if (!hasWire())
385 throw Error("Underlying wire buffer is empty");
386
387 return m_begin;
388}
389
390inline Buffer::const_iterator
391Block::end() const
392{
393 if (!hasWire())
394 throw Error("Underlying wire buffer is empty");
395
396 return m_end;
397}
398
399inline size_t
400Block::size() const
401{
402 if (hasWire() || hasValue()) {
403 return m_size;
404 }
405 else
406 throw Error("Block size cannot be determined (undefined block size)");
407}
408
409inline Buffer::const_iterator
410Block::value_begin() const
411{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800412 return m_value_begin;
413}
414
415inline Buffer::const_iterator
416Block::value_end() const
417{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800418 return m_value_end;
419}
420
421inline const uint8_t*
422Block::wire() const
423{
424 if (!hasWire())
425 throw Error("(Block::wire) Underlying wire buffer is empty");
426
427 return &*m_begin;
428}
429
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800430inline const uint8_t*
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800431Block::value() const
432{
433 if (!hasValue())
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800434 return 0;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700435
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800436 return &*m_value_begin;
437}
438
439inline size_t
440Block::value_size() const
441{
442 if (!hasValue())
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800443 return 0;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800444
445 return m_value_end - m_value_begin;
446}
447
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800448inline const Block::element_container&
449Block::elements () const
450{
451 return m_subBlocks;
452}
453
454inline Block::element_const_iterator
455Block::elements_begin() const
456{
457 return m_subBlocks.begin();
458}
459
460inline Block::element_const_iterator
461Block::elements_end() const
462{
463 return m_subBlocks.end();
464}
465
466inline size_t
467Block::elements_size() const
468{
469 return m_subBlocks.size();
470}
471
472
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800473} // ndn
474
475#include "block-helpers.hpp"
476
477#endif // NDN_BLOCK_HPP