blob: 4353c963235fb07bebce4ebf019d9bf08ad1b77f [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 Afanasyeve2dcdfd2014-02-07 15:53:28 -080024#include "block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070025#include "block-helpers.hpp"
26
Alexander Afanasyeve2dcdfd2014-02-07 15:53:28 -080027#include "tlv.hpp"
Alexander Afanasyev15151312014-02-16 00:53:51 -080028#include "encoding-buffer.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070029#include "buffer-stream.hpp"
30
31#include <boost/lexical_cast.hpp>
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -070032#include <boost/asio/buffer.hpp>
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080033
34namespace ndn {
35
Junxiao Shi81a6c5d2014-11-30 00:14:42 -070036#if NDN_CXX_HAVE_IS_MOVE_CONSTRUCTIBLE
37static_assert(std::is_move_constructible<Buffer>::value,
38 "Buffer must be MoveConstructible");
39#endif // NDN_CXX_HAVE_IS_MOVE_CONSTRUCTIBLE
40
41#if NDN_CXX_HAVE_IS_MOVE_ASSIGNABLE
42static_assert(std::is_move_assignable<Buffer>::value,
43 "Buffer must be MoveAssignable");
44#endif // NDN_CXX_HAVE_IS_MOVE_ASSIGNABLE
45
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070046const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM = 8800;
47
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080048Block::Block()
49 : m_type(std::numeric_limits<uint32_t>::max())
50{
51}
52
Alexander Afanasyev15151312014-02-16 00:53:51 -080053Block::Block(const EncodingBuffer& buffer)
Alexander Afanasyev74633892015-02-08 18:08:46 -080054 : m_buffer(const_cast<EncodingBuffer&>(buffer).getBuffer())
Alexander Afanasyev15151312014-02-16 00:53:51 -080055 , m_begin(buffer.begin())
56 , m_end(buffer.end())
57 , m_size(m_end - m_begin)
58{
59 m_value_begin = m_begin;
60 m_value_end = m_end;
61
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060062 m_type = tlv::readType(m_value_begin, m_value_end);
63 uint64_t length = tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev15151312014-02-16 00:53:51 -080064 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
65 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060066 throw tlv::Error("TLV length doesn't match buffer length");
Alexander Afanasyev15151312014-02-16 00:53:51 -080067 }
68}
69
Alexander Afanasyeva465e972014-03-22 17:21:49 -070070Block::Block(const ConstBufferPtr& wire,
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080071 uint32_t type,
Alexander Afanasyeva465e972014-03-22 17:21:49 -070072 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
73 const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080074 : m_buffer(wire)
75 , m_type(type)
76 , m_begin(begin)
77 , m_end(end)
78 , m_size(m_end - m_begin)
79 , m_value_begin(valueBegin)
80 , m_value_end(valueEnd)
81{
82}
83
Alexander Afanasyeva465e972014-03-22 17:21:49 -070084Block::Block(const ConstBufferPtr& buffer)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080085 : m_buffer(buffer)
86 , m_begin(m_buffer->begin())
87 , m_end(m_buffer->end())
88 , m_size(m_end - m_begin)
89{
Alexander Afanasyev233750e2014-02-16 00:50:07 -080090 m_value_begin = m_begin;
91 m_value_end = m_end;
Alexander Afanasyev937aa782014-03-21 13:17:57 -070092
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060093 m_type = tlv::readType(m_value_begin, m_value_end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080094
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060095 uint64_t length = tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -080096 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080097 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060098 throw tlv::Error("TLV length doesn't match buffer length");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080099 }
100}
101
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700102Block::Block(const ConstBufferPtr& buffer,
103 const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800104 bool verifyLength/* = true*/)
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800105 : m_buffer(buffer)
106 , m_begin(begin)
107 , m_end(end)
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800108 , m_size(m_end - m_begin)
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800109{
Alexander Afanasyev233750e2014-02-16 00:50:07 -0800110 m_value_begin = m_begin;
111 m_value_end = m_end;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800112
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600113 m_type = tlv::readType(m_value_begin, m_value_end);
114 uint64_t length = tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800115 if (verifyLength)
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800116 {
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800117 if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
118 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600119 throw tlv::Error("TLV length doesn't match buffer length");
Alexander Afanasyev5964fb72014-02-18 12:42:45 -0800120 }
Alexander Afanasyev187bc482014-02-06 15:04:04 -0800121 }
122}
123
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700124Block::Block(const uint8_t* buffer, size_t maxlength)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800125{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700126 const uint8_t* tmp_begin = buffer;
127 const uint8_t* tmp_end = buffer + maxlength;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700128
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600129 m_type = tlv::readType(tmp_begin, tmp_end);
130 uint64_t length = tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700131
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800132 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800133 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600134 throw tlv::Error("Not enough data in the buffer to fully parse TLV");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800135 }
136
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700137 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800138
139 m_begin = m_buffer->begin();
140 m_end = m_buffer->end();
141 m_size = m_end - m_begin;
142
143 m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
144 m_value_end = m_buffer->end();
145}
146
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700147Block::Block(const void* bufferX, size_t maxlength)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800148{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700149 const uint8_t* buffer = reinterpret_cast<const uint8_t*>(bufferX);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700150
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700151 const uint8_t* tmp_begin = buffer;
152 const uint8_t* tmp_end = buffer + maxlength;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700153
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600154 m_type = tlv::readType(tmp_begin, tmp_end);
155 uint64_t length = tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700156
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800157 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800158 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600159 throw tlv::Error("Not enough data in the buffer to fully parse TLV");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800160 }
161
Alexander Afanasyevf73f0632014-05-12 18:02:37 -0700162 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800163
164 m_begin = m_buffer->begin();
165 m_end = m_buffer->end();
166 m_size = m_end - m_begin;
167
168 m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
169 m_value_end = m_buffer->end();
170}
171
172Block::Block(uint32_t type)
173 : m_type(type)
174{
175}
176
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700177Block::Block(uint32_t type, const ConstBufferPtr& value)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800178 : m_buffer(value)
179 , m_type(type)
180 , m_begin(m_buffer->end())
181 , m_end(m_buffer->end())
182 , m_value_begin(m_buffer->begin())
183 , m_value_end(m_buffer->end())
184{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600185 m_size = tlv::sizeOfVarNumber(m_type) + tlv::sizeOfVarNumber(value_size()) + value_size();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186}
187
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700188Block::Block(uint32_t type, const Block& value)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800189 : m_buffer(value.m_buffer)
190 , m_type(type)
191 , m_begin(m_buffer->end())
192 , m_end(m_buffer->end())
Alexander Afanasyevc8823bc2014-02-09 19:33:33 -0800193 , m_value_begin(value.begin())
194 , m_value_end(value.end())
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800195{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600196 m_size = tlv::sizeOfVarNumber(m_type) + tlv::sizeOfVarNumber(value_size()) + value_size();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800197}
198
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700199Block
200Block::fromStream(std::istream& is)
201{
202 std::istream_iterator<uint8_t> tmp_begin(is);
203 std::istream_iterator<uint8_t> tmp_end;
204
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600205 uint32_t type = tlv::readType(tmp_begin, tmp_end);
206 uint64_t length = tlv::readVarNumber(tmp_begin, tmp_end);
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700207
208 if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600209 throw tlv::Error("Length of block from stream is too large");
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700210
211 // We may still have some problem here, if some exception happens,
212 // we may completely lose all the bytes extracted from the stream.
213
214 char buf[MAX_SIZE_OF_BLOCK_FROM_STREAM];
215 buf[0] = *tmp_begin;
216 is.read(buf+1, length-1);
217
218 if (length != static_cast<uint64_t>(is.gcount()) + 1) {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600219 throw tlv::Error("Not enough data in the buffer to fully parse TLV");
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700220 }
221
222 return dataBlock(type, buf, length);
223}
224
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700225std::tuple<bool, Block>
226Block::fromBuffer(ConstBufferPtr buffer, size_t offset)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700227{
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700228 Buffer::const_iterator tempBegin = buffer->begin() + offset;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700229
230 uint32_t type;
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700231 bool isOk = tlv::readType(tempBegin, buffer->end(), type);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700232 if (!isOk)
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700233 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700234
235 uint64_t length;
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700236 isOk = tlv::readVarNumber(tempBegin, buffer->end(), length);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700237 if (!isOk)
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700238 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700239
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700240 if (length > static_cast<uint64_t>(buffer->end() - tempBegin))
241 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700242
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700243 return std::make_tuple(true, Block(buffer, type,
244 buffer->begin() + offset, tempBegin + length,
245 tempBegin, tempBegin + length));
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700246}
247
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700248std::tuple<bool, Block>
249Block::fromBuffer(const uint8_t* buffer, size_t maxSize)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700250{
251 const uint8_t* tempBegin = buffer;
252 const uint8_t* tempEnd = buffer + maxSize;
253
Mickey Sweatt632e0572014-04-20 00:36:32 -0700254 uint32_t type = 0;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600255 bool isOk = tlv::readType(tempBegin, tempEnd, type);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700256 if (!isOk)
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700257 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700258
259 uint64_t length;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600260 isOk = tlv::readVarNumber(tempBegin, tempEnd, length);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700261 if (!isOk)
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700262 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700263
264 if (length > static_cast<uint64_t>(tempEnd - tempBegin))
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700265 return std::make_tuple(false, Block());
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700266
267 BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
Junxiao Shi02a4bf32015-02-21 21:07:46 -0700268 return std::make_tuple(true,
269 Block(sharedBuffer, type,
270 sharedBuffer->begin(), sharedBuffer->end(),
271 sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end()));
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700272}
273
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800274void
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700275Block::reset()
276{
277 m_buffer.reset(); // reset of the shared_ptr
278 m_subBlocks.clear(); // remove all parsed subelements
279
280 m_type = std::numeric_limits<uint32_t>::max();
281 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
282}
283
284void
285Block::resetWire()
286{
287 m_buffer.reset(); // reset of the shared_ptr
288 // keep subblocks
289
290 // keep type
291 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
292}
293
294void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800295Block::parse() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800296{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700297 if (!m_subBlocks.empty() || value_size() == 0)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800298 return;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700299
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700300 Buffer::const_iterator begin = value_begin();
301 Buffer::const_iterator end = value_end();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800302
303 while (begin != end)
304 {
305 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700306
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600307 uint32_t type = tlv::readType(begin, end);
308 uint64_t length = tlv::readVarNumber(begin, end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800309
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800310 if (length > static_cast<uint64_t>(end - begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800311 {
312 m_subBlocks.clear();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600313 throw tlv::Error("TLV length exceeds buffer length");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800314 }
315 Buffer::const_iterator element_end = begin + length;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700316
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800317 m_subBlocks.push_back(Block(m_buffer,
318 type,
319 element_begin, element_end,
320 begin, element_end));
321
322 begin = element_end;
323 // don't do recursive parsing, just the top level
324 }
325}
326
327void
328Block::encode()
329{
330 if (hasWire())
331 return;
332
333 OBufferStream os;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600334 tlv::writeVarNumber(os, type());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800335
336 if (hasValue())
337 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600338 tlv::writeVarNumber(os, value_size());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800339 os.write(reinterpret_cast<const char*>(value()), value_size());
340 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800341 else if (m_subBlocks.size() == 0)
342 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600343 tlv::writeVarNumber(os, 0);
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800344 }
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800345 else
346 {
347 size_t valueSize = 0;
348 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
349 valueSize += i->size();
350 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700351
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600352 tlv::writeVarNumber(os, valueSize);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800353
354 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
355 if (i->hasWire())
356 os.write(reinterpret_cast<const char*>(i->wire()), i->size());
357 else if (i->hasValue()) {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600358 tlv::writeVarNumber(os, i->type());
359 tlv::writeVarNumber(os, i->value_size());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800360 os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
361 }
362 else
363 throw Error("Underlying value buffer is empty");
364 }
365 }
366
367 // now assign correct block
368
369 m_buffer = os.buf();
370 m_begin = m_buffer->begin();
371 m_end = m_buffer->end();
372 m_size = m_end - m_begin;
373
374 m_value_begin = m_buffer->begin();
375 m_value_end = m_buffer->end();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700376
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600377 tlv::readType(m_value_begin, m_value_end);
378 tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800379}
380
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700381const Block&
382Block::get(uint32_t type) const
383{
384 element_const_iterator it = this->find(type);
385 if (it != m_subBlocks.end())
386 return *it;
387
388 throw Error("(Block::get) Requested a non-existed type [" +
389 boost::lexical_cast<std::string>(type) + "] from Block");
390}
391
392Block::element_const_iterator
393Block::find(uint32_t type) const
394{
395 return std::find_if(m_subBlocks.begin(), m_subBlocks.end(),
396 [type] (const Block& subBlock) { return subBlock.type() == type; });
397}
398
399void
400Block::remove(uint32_t type)
401{
402 resetWire();
403
404 auto it = std::remove_if(m_subBlocks.begin(), m_subBlocks.end(),
405 [type] (const Block& subBlock) { return subBlock.type() != type; });
406 m_subBlocks.resize(it - m_subBlocks.begin());
407}
408
Yingdi Yu4270f202014-01-28 14:19:16 -0800409Block
410Block::blockFromValue() const
411{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700412 if (value_size() == 0)
Yingdi Yu4270f202014-01-28 14:19:16 -0800413 throw Error("Underlying value buffer is empty");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700414
Yingdi Yu4270f202014-01-28 14:19:16 -0800415 Buffer::const_iterator begin = value_begin(),
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700416 end = value_end();
Yingdi Yu4270f202014-01-28 14:19:16 -0800417
418 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700419
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600420 uint32_t type = tlv::readType(begin, end);
421 uint64_t length = tlv::readVarNumber(begin, end);
Yingdi Yu4270f202014-01-28 14:19:16 -0800422
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800423 if (length != static_cast<uint64_t>(end - begin))
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600424 throw tlv::Error("TLV length mismatches buffer length");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700425
Yingdi Yu4270f202014-01-28 14:19:16 -0800426 return Block(m_buffer,
427 type,
428 element_begin, end,
429 begin, end);
430}
431
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700432bool
433Block::operator==(const Block& other) const
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700434{
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700435 return this->size() == other.size() &&
436 std::equal(this->begin(), this->end(), other.begin());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700437}
438
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700439Block::operator boost::asio::const_buffer() const
440{
441 return boost::asio::const_buffer(wire(), size());
442}
443
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800444} // namespace ndn