blob: 0c8314954570a3009d4dc7713c3a5cd89a2cc42c [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07002/**
Alexander Afanasyevaf99f462015-01-19 21:43:09 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08004 *
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07005 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080022 */
23
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070024#ifndef NDN_ENCODING_BLOCK_HPP
25#define NDN_ENCODING_BLOCK_HPP
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080026
Alexander Afanasyev19508852014-01-29 01:01:51 -080027#include "../common.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080028
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080029#include "buffer.hpp"
30#include "tlv.hpp"
Alexander Afanasyev74633892015-02-08 18:08:46 -080031#include "encoding-buffer-fwd.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080032
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -070033namespace boost {
34namespace asio {
35class const_buffer;
36} // namespace asio
37} // namespace boost
38
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080039namespace ndn {
40
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070041/** @brief Class representing a wire element of NDN-TLV packet format
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080042 */
43class Block
44{
45public:
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -080046 typedef std::vector<Block> element_container;
47 typedef element_container::iterator element_iterator;
48 typedef element_container::const_iterator element_const_iterator;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080049
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060050 class Error : public tlv::Error
Alexander Afanasyev937aa782014-03-21 13:17:57 -070051 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070052 public:
53 explicit
54 Error(const std::string& what)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060055 : tlv::Error(what)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070056 {
57 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -070058 };
59
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070060public: // constructor, creation, assignment
61 /** @brief Create an empty Block
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080062 */
63 Block();
64
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070065 /** @brief Create a Block based on EncodingBuffer object
Alexander Afanasyev15151312014-02-16 00:53:51 -080066 */
67 explicit
68 Block(const EncodingBuffer& buffer);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070069
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070070 /** @brief Create a Block from the raw buffer with Type-Length parsing
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080071 */
Alexander Afanasyev197e5652014-06-13 16:56:31 -070072 explicit
Alexander Afanasyev937aa782014-03-21 13:17:57 -070073 Block(const ConstBufferPtr& buffer);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080074
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070075 /** @brief Create a Block from a buffer, directly specifying boundaries
76 * of the block within the buffer
Alexander Afanasyev187bc482014-02-06 15:04:04 -080077 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070078 * This overload will automatically detect type and position of the value within the block
Alexander Afanasyev187bc482014-02-06 15:04:04 -080079 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070080 Block(const ConstBufferPtr& buffer,
81 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -080082 bool verifyLength = true);
Alexander Afanasyev937aa782014-03-21 13:17:57 -070083
Alexander Afanasyev4448d292015-08-09 20:11:37 -070084 /** @brief Create a Block from existing block (reusing the underlying buffer), directly
85 * specifying boundaries of the block within the buffer
86 *
87 * This overload will automatically detect type and position of the value within the block
88 */
89 Block(const Block& block,
90 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
91 bool verifyLength = true);
92
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070093 /** @brief Create a Block from the raw buffer with Type-Length parsing
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080094 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070095 Block(const uint8_t* buffer, size_t maxlength);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080096
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070097 /** @brief Create a Block from the raw buffer with Type-Length parsing
98 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -070099 Block(const void* buffer, size_t maxlength);
Yingdi Yu27158392014-01-20 13:04:20 -0800100
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700101 /** @brief Create a Block from the wire buffer (no parsing)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800102 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700103 * This overload does not do any parsing
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800104 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700105 Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800106 uint32_t type,
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700107 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
108 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800109
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700110 /** @brief Create Block of a specific type with empty wire buffer
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800111 */
Alexander Afanasyevf42ce132014-01-07 13:32:30 -0800112 explicit
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800113 Block(uint32_t type);
114
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700115 /** @brief Create a Block of a specific type with the specified value
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800116 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700117 * The underlying buffer holds only value Additional operations are needed
118 * to construct wire encoding, one need to prepend the wire buffer with type
119 * and value-length VAR-NUMBERs
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800120 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700121 Block(uint32_t type, const ConstBufferPtr& value);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800122
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700123 /** @brief Create a nested Block of a specific type with the specified value
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800124 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700125 * The underlying buffer holds only value. Additional operations are needed
126 * to construct wire encoding, one need to prepend the wire buffer with type
127 * and value-length VAR-NUMBERs
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800128 */
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700129 Block(uint32_t type, const Block& value);
130
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700131 /** @brief Create a Block from an input stream
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700132 */
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700133 static Block
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700134 fromStream(std::istream& is);
135
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700136 /** @brief Try to construct block from Buffer
137 * @param buffer the buffer to construct block from
138 * @note buffer is passed by value because the constructed block
139 * takes shared ownership of the buffer
140 * @param offset offset from beginning of \p buffer to construct Block from
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700141 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700142 * This method does not throw upon decoding error.
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700143 * This method does not copy the bytes.
144 *
145 * @return true and the Block, if Block is successfully created; otherwise false
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700146 */
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700147 static std::tuple<bool, Block>
148 fromBuffer(ConstBufferPtr buffer, size_t offset);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700149
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700150 /** @deprecated use fromBuffer(ConstBufferPtr, size_t)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700151 */
Junxiao Shi1a750b42015-02-28 22:20:45 -0700152 DEPRECATED(
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700153 static bool
Junxiao Shi1a750b42015-02-28 22:20:45 -0700154 fromBuffer(const ConstBufferPtr& buffer, size_t offset, Block& block))
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700155 {
156 bool isOk = false;
157 std::tie(isOk, block) = Block::fromBuffer(buffer, offset);
158 return isOk;
159 }
160
161 /** @brief Try to construct block from raw buffer
162 * @param buffer the raw buffer to copy bytes from
163 * @param maxSize the maximum size of constructed block;
164 * @p buffer must have a size of at least @p maxSize
165 *
166 * This method does not throw upon decoding error.
167 * This method copies the bytes into a new Buffer.
168 *
169 * @return true and the Block, if Block is successfully created; otherwise false
170 */
171 static std::tuple<bool, Block>
172 fromBuffer(const uint8_t* buffer, size_t maxSize);
173
174 /** @deprecated use fromBuffer(const uint8_t*, size_t)
175 */
Junxiao Shi1a750b42015-02-28 22:20:45 -0700176 DEPRECATED(
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700177 static bool
Junxiao Shi1a750b42015-02-28 22:20:45 -0700178 fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block))
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700179 {
180 bool isOk = false;
181 std::tie(isOk, block) = Block::fromBuffer(buffer, maxSize);
182 return isOk;
183 }
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800184
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700185public: // wire format
186 /** @brief Check if the Block is empty
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800187 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700188 bool
Alexander Afanasyev196b9aa2014-01-31 17:19:16 -0800189 empty() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700190
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700191 /** @brief Check if the Block has fully encoded wire
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800192 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700193 bool
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800194 hasWire() const;
195
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700196 /** @brief Reset wire buffer of the element
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800197 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700198 void
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800199 reset();
200
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700201 /** @brief Reset wire buffer but keep sub elements (if any)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800202 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700203 void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800204 resetWire();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800205
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700206 Buffer::const_iterator
207 begin() const;
208
209 Buffer::const_iterator
210 end() const;
211
212 const uint8_t*
213 wire() const;
214
215 size_t
216 size() const;
217
218public: // type and value
219 uint32_t
220 type() const;
221
222 /** @brief Check if the Block has value block (no type and length are encoded)
223 */
224 bool
225 hasValue() const;
226
227 Buffer::const_iterator
228 value_begin() const;
229
230 Buffer::const_iterator
231 value_end() const;
232
233 const uint8_t*
234 value() const;
235
236 size_t
237 value_size() const;
238
239public: // sub elements
240 /** @brief Parse wire buffer into subblocks
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800241 *
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700242 * This method is not really const, but it does not modify any data. It simply
243 * parses contents of the buffer into subblocks
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800244 */
245 void
246 parse() const;
247
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700248 /** @brief Encode subblocks into wire buffer
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800249 */
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800250 void
251 encode();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700252
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700253 /** @brief Get the first subelement of the requested type
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800254 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700255 const Block&
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800256 get(uint32_t type) const;
257
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700258 element_const_iterator
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800259 find(uint32_t type) const;
260
Eric Newberrya3d9fc02015-07-26 10:55:44 -0700261 /**
262 * @brief remove all subelements of \p type
263 * @param type TLV-TYPE of subelements to remove
264 * @pre parse() has been invoked
265 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700266 void
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800267 remove(uint32_t type);
268
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700269 element_iterator
Joao Pereira7476ebf2015-07-07 14:54:39 -0400270 erase(element_const_iterator position);
Alexander Afanasyevf5c35ae2014-01-17 16:06:31 -0800271
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700272 element_iterator
Joao Pereira7476ebf2015-07-07 14:54:39 -0400273 erase(element_const_iterator first, element_const_iterator last);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700274
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700275 void
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700276 push_back(const Block& element);
277
Joao Pereira7476ebf2015-07-07 14:54:39 -0400278 /**
279 * @brief insert Insert a new element in a specific position
280 * @param pos Position to insert the new element
281 * @param element Element to be inserted
282 * @return An iterator that points to the first of the newly inserted elements.
283 */
284 element_iterator
285 insert(element_const_iterator pos, const Block& element);
286
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700287 /** @brief Get all subelements
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800288 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700289 const element_container&
290 elements() const;
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800291
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700292 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800293 elements_begin() const;
294
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700295 element_const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800296 elements_end() const;
297
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700298 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800299 elements_size() const;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700300
Yingdi Yu4270f202014-01-28 14:19:16 -0800301 Block
302 blockFromValue() const;
303
Alexander Afanasyev74633892015-02-08 18:08:46 -0800304 /**
305 * @brief Get underlying buffer
306 */
307 shared_ptr<const Buffer>
308 getBuffer() const;
309
Junxiao Shiaf8eeea2014-03-31 20:10:56 -0700310public: // EqualityComparable concept
311 bool
312 operator==(const Block& other) const;
313
314 bool
315 operator!=(const Block& other) const;
316
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700317public: // ConvertibleToConstBuffer
318 operator boost::asio::const_buffer() const;
319
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800320protected:
Alexander Afanasyev74633892015-02-08 18:08:46 -0800321 shared_ptr<const Buffer> m_buffer;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800322
323 uint32_t m_type;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700324
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800325 Buffer::const_iterator m_begin;
326 Buffer::const_iterator m_end;
327 uint32_t m_size;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700328
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800329 Buffer::const_iterator m_value_begin;
330 Buffer::const_iterator m_value_end;
331
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800332 mutable element_container m_subBlocks;
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800333};
334
335////////////////////////////////////////////////////////////////////////////////
336////////////////////////////////////////////////////////////////////////////////
337////////////////////////////////////////////////////////////////////////////////
338
Alexander Afanasyev74633892015-02-08 18:08:46 -0800339inline shared_ptr<const Buffer>
340Block::getBuffer() const
341{
342 return m_buffer;
343}
344
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700345inline uint32_t
346Block::type() const
347{
348 return m_type;
349}
350
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800351inline Buffer::const_iterator
352Block::value_begin() const
353{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800354 return m_value_begin;
355}
356
357inline Buffer::const_iterator
358Block::value_end() const
359{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800360 return m_value_end;
361}
362
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800363inline const Block::element_container&
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700364Block::elements() const
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800365{
366 return m_subBlocks;
367}
368
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700369} // namespace ndn
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800370
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700371#endif // NDN_ENCODING_BLOCK_HPP