blob: e8d2cf908e39f961d6ab3898edd25c90b86a47be [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)
54 : m_buffer(buffer.m_buffer)
55 , 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
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700225bool
226Block::fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block)
227{
228 Buffer::const_iterator tempBegin = wire->begin() + offset;
229
230 uint32_t type;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600231 bool isOk = tlv::readType(tempBegin, wire->end(), type);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700232 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700233 return false;
234
235 uint64_t length;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600236 isOk = tlv::readVarNumber(tempBegin, wire->end(), length);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700237 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700238 return false;
239
240 if (length > static_cast<uint64_t>(wire->end() - tempBegin))
241 {
242 return false;
243 }
244
245 block = Block(wire, type,
246 wire->begin() + offset, tempBegin + length,
247 tempBegin, tempBegin + length);
248
249 return true;
250}
251
252bool
253Block::fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block)
254{
255 const uint8_t* tempBegin = buffer;
256 const uint8_t* tempEnd = buffer + maxSize;
257
Mickey Sweatt632e0572014-04-20 00:36:32 -0700258 uint32_t type = 0;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600259 bool isOk = tlv::readType(tempBegin, tempEnd, type);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700260 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700261 return false;
262
263 uint64_t length;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600264 isOk = tlv::readVarNumber(tempBegin, tempEnd, length);
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700265 if (!isOk)
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700266 return false;
267
268 if (length > static_cast<uint64_t>(tempEnd - tempBegin))
269 {
270 return false;
271 }
272
273 BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
274 block = Block(sharedBuffer, type,
275 sharedBuffer->begin(), sharedBuffer->end(),
276 sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end());
277
278 return true;
279}
280
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800281void
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700282Block::reset()
283{
284 m_buffer.reset(); // reset of the shared_ptr
285 m_subBlocks.clear(); // remove all parsed subelements
286
287 m_type = std::numeric_limits<uint32_t>::max();
288 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
289}
290
291void
292Block::resetWire()
293{
294 m_buffer.reset(); // reset of the shared_ptr
295 // keep subblocks
296
297 // keep type
298 m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
299}
300
301void
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800302Block::parse() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800303{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700304 if (!m_subBlocks.empty() || value_size() == 0)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800305 return;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700306
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700307 Buffer::const_iterator begin = value_begin();
308 Buffer::const_iterator end = value_end();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800309
310 while (begin != end)
311 {
312 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700313
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600314 uint32_t type = tlv::readType(begin, end);
315 uint64_t length = tlv::readVarNumber(begin, end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800316
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800317 if (length > static_cast<uint64_t>(end - begin))
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800318 {
319 m_subBlocks.clear();
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600320 throw tlv::Error("TLV length exceeds buffer length");
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800321 }
322 Buffer::const_iterator element_end = begin + length;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700323
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800324 m_subBlocks.push_back(Block(m_buffer,
325 type,
326 element_begin, element_end,
327 begin, element_end));
328
329 begin = element_end;
330 // don't do recursive parsing, just the top level
331 }
332}
333
334void
335Block::encode()
336{
337 if (hasWire())
338 return;
339
340 OBufferStream os;
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600341 tlv::writeVarNumber(os, type());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800342
343 if (hasValue())
344 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600345 tlv::writeVarNumber(os, value_size());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800346 os.write(reinterpret_cast<const char*>(value()), value_size());
347 }
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800348 else if (m_subBlocks.size() == 0)
349 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600350 tlv::writeVarNumber(os, 0);
Alexander Afanasyev8ea763d2014-02-06 20:32:52 -0800351 }
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800352 else
353 {
354 size_t valueSize = 0;
355 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
356 valueSize += i->size();
357 }
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700358
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600359 tlv::writeVarNumber(os, valueSize);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800360
361 for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
362 if (i->hasWire())
363 os.write(reinterpret_cast<const char*>(i->wire()), i->size());
364 else if (i->hasValue()) {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600365 tlv::writeVarNumber(os, i->type());
366 tlv::writeVarNumber(os, i->value_size());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800367 os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
368 }
369 else
370 throw Error("Underlying value buffer is empty");
371 }
372 }
373
374 // now assign correct block
375
376 m_buffer = os.buf();
377 m_begin = m_buffer->begin();
378 m_end = m_buffer->end();
379 m_size = m_end - m_begin;
380
381 m_value_begin = m_buffer->begin();
382 m_value_end = m_buffer->end();
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700383
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600384 tlv::readType(m_value_begin, m_value_end);
385 tlv::readVarNumber(m_value_begin, m_value_end);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800386}
387
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700388const Block&
389Block::get(uint32_t type) const
390{
391 element_const_iterator it = this->find(type);
392 if (it != m_subBlocks.end())
393 return *it;
394
395 throw Error("(Block::get) Requested a non-existed type [" +
396 boost::lexical_cast<std::string>(type) + "] from Block");
397}
398
399Block::element_const_iterator
400Block::find(uint32_t type) const
401{
402 return std::find_if(m_subBlocks.begin(), m_subBlocks.end(),
403 [type] (const Block& subBlock) { return subBlock.type() == type; });
404}
405
406void
407Block::remove(uint32_t type)
408{
409 resetWire();
410
411 auto it = std::remove_if(m_subBlocks.begin(), m_subBlocks.end(),
412 [type] (const Block& subBlock) { return subBlock.type() != type; });
413 m_subBlocks.resize(it - m_subBlocks.begin());
414}
415
Yingdi Yu4270f202014-01-28 14:19:16 -0800416Block
417Block::blockFromValue() const
418{
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700419 if (value_size() == 0)
Yingdi Yu4270f202014-01-28 14:19:16 -0800420 throw Error("Underlying value buffer is empty");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700421
Yingdi Yu4270f202014-01-28 14:19:16 -0800422 Buffer::const_iterator begin = value_begin(),
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700423 end = value_end();
Yingdi Yu4270f202014-01-28 14:19:16 -0800424
425 Buffer::const_iterator element_begin = begin;
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700426
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600427 uint32_t type = tlv::readType(begin, end);
428 uint64_t length = tlv::readVarNumber(begin, end);
Yingdi Yu4270f202014-01-28 14:19:16 -0800429
Alexander Afanasyev9c7ed112014-02-07 12:23:03 -0800430 if (length != static_cast<uint64_t>(end - begin))
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600431 throw tlv::Error("TLV length mismatches buffer length");
Alexander Afanasyev937aa782014-03-21 13:17:57 -0700432
Yingdi Yu4270f202014-01-28 14:19:16 -0800433 return Block(m_buffer,
434 type,
435 element_begin, end,
436 begin, end);
437}
438
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700439bool
440Block::operator==(const Block& other) const
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700441{
Junxiao Shi81a6c5d2014-11-30 00:14:42 -0700442 return this->size() == other.size() &&
443 std::equal(this->begin(), this->end(), other.begin());
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -0700444}
445
Alexander Afanasyev6a05b4b2014-07-18 17:23:00 -0700446Block::operator boost::asio::const_buffer() const
447{
448 return boost::asio::const_buffer(wire(), size());
449}
450
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800451} // namespace ndn