31 #include <boost/lexical_cast.hpp> 32 #include <boost/asio/buffer.hpp> 36 #if NDN_CXX_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE 37 static_assert(std::is_nothrow_move_constructible<Block>::value,
38 "Block must be MoveConstructible with noexcept");
39 #endif // NDN_CXX_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE 41 #if NDN_CXX_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE 42 static_assert(std::is_nothrow_move_assignable<Block>::value,
43 "Block must be MoveAssignable with noexcept");
44 #endif // NDN_CXX_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE 49 : m_type(
std::numeric_limits<uint32_t>::max())
66 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length doesn't match buffer length"));
72 const Buffer::const_iterator&
begin,
const Buffer::const_iterator&
end,
73 const Buffer::const_iterator& valueBegin,
const Buffer::const_iterator& valueEnd)
98 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length doesn't match buffer length"));
103 const Buffer::const_iterator&
begin,
const Buffer::const_iterator&
end,
117 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length doesn't match buffer length"));
123 const Buffer::const_iterator&
begin,
const Buffer::const_iterator&
end,
132 BOOST_THROW_EXCEPTION(
Error(
"begin/end iterators do not point to the underlying buffer of the block"));
142 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length doesn't match buffer length"));
149 const uint8_t* tmp_begin = buffer;
150 const uint8_t* tmp_end = buffer + maxlength;
155 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
157 BOOST_THROW_EXCEPTION(
tlv::Error(
"Not enough data in the buffer to fully parse TLV"));
160 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
172 const uint8_t* buffer =
reinterpret_cast<const uint8_t*
>(bufferX);
174 const uint8_t* tmp_begin = buffer;
175 const uint8_t* tmp_end = buffer + maxlength;
180 if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
182 BOOST_THROW_EXCEPTION(
tlv::Error(
"Not enough data in the buffer to fully parse TLV"));
185 m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
225 std::istream_iterator<uint8_t>
begin(is >> std::noskipws);
226 std::istream_iterator<uint8_t>
end;
235 if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
236 BOOST_THROW_EXCEPTION(
tlv::Error(
"Length of block from stream is too large"));
243 is.read(buf + 1, length - 1);
245 if (length != static_cast<uint64_t>(is.gcount()) + 1) {
246 BOOST_THROW_EXCEPTION(
tlv::Error(
"Not enough data in the buffer to fully parse TLV"));
252 std::tuple<bool, Block>
255 Buffer::const_iterator tempBegin = buffer->begin() + offset;
260 return std::make_tuple(
false,
Block());
265 return std::make_tuple(
false,
Block());
267 if (length > static_cast<uint64_t>(buffer->end() - tempBegin))
268 return std::make_tuple(
false,
Block());
270 return std::make_tuple(
true,
Block(buffer, type,
271 buffer->begin() + offset, tempBegin + length,
272 tempBegin, tempBegin + length));
275 std::tuple<bool, Block>
278 const uint8_t* tempBegin = buffer;
279 const uint8_t* tempEnd = buffer + maxSize;
284 return std::make_tuple(
false,
Block());
289 return std::make_tuple(
false,
Block());
291 if (length > static_cast<uint64_t>(tempEnd - tempBegin))
292 return std::make_tuple(
false,
Block());
294 BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
295 return std::make_tuple(
true,
296 Block(sharedBuffer, type,
297 sharedBuffer->begin(), sharedBuffer->end(),
298 sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end()));
307 m_type = std::numeric_limits<uint32_t>::max();
332 Buffer::const_iterator element_begin =
begin;
337 if (length > static_cast<uint64_t>(end - begin))
340 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length exceeds buffer length"));
342 Buffer::const_iterator element_end = begin + length;
346 element_begin, element_end,
347 begin, element_end));
374 size_t valueSize = 0;
376 valueSize += i->size();
383 os.write(reinterpret_cast<const char*>(i->wire()), i->size());
384 else if (i->hasValue()) {
387 os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
390 BOOST_THROW_EXCEPTION(
Error(
"Underlying value buffer is empty"));
415 BOOST_THROW_EXCEPTION(
Error(
"(Block::get) Requested a non-existed type [" +
416 boost::lexical_cast<std::string>(type) +
"] from Block"));
423 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
432 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
440 BOOST_THROW_EXCEPTION(
Error(
"Underlying value buffer is empty"));
445 Buffer::const_iterator element_begin =
begin;
450 if (length != static_cast<uint64_t>(
end - begin))
451 BOOST_THROW_EXCEPTION(
tlv::Error(
"TLV length mismatches buffer length"));
459 Block::operator boost::asio::const_buffer()
const 461 return boost::asio::const_buffer(
wire(),
size());
467 return m_type == std::numeric_limits<uint32_t>::max();
476 Buffer::const_iterator
480 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
485 Buffer::const_iterator
489 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
498 BOOST_THROW_EXCEPTION(
Error(
"(Block::wire) Underlying wire buffer is empty"));
510 BOOST_THROW_EXCEPTION(
Error(
"Block size cannot be determined (undefined block size)"));
542 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 546 std::advance(it, std::distance(
m_subBlocks.cbegin(), position));
556 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 561 std::advance(itStart, std::distance(
m_subBlocks.cbegin(), first));
562 std::advance(itEnd, std::distance(
m_subBlocks.cbegin(), last));
579 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 583 std::advance(it, std::distance(
m_subBlocks.cbegin(), pos));
615 return this->
size() == other.
size() &&
shared_ptr< const Buffer > m_buffer
element_const_iterator elements_begin() const
bool hasWire() const
Check if the Block has fully encoded wire.
static Block fromStream(std::istream &is)
Create a Block from an input stream.
Copyright (c) 2011-2015 Regents of the University of California.
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset)
Try to construct block from Buffer.
Block makeEmptyBlock(uint32_t type)
Create a TLV block type type containing no value (i.e., a boolean block)
shared_ptr< Buffer > BufferPtr
Buffer::const_iterator m_begin
size_t value_size() const
bool operator==(const Block &other) const
element_const_iterator elements_end() const
const uint8_t * wire() const
element_container::iterator element_iterator
void parse() const
Parse wire buffer into subblocks.
Class representing a wire element of NDN-TLV packet format.
bool readType(InputIterator &begin, const InputIterator &end, uint32_t &type)
Read TLV Type.
shared_ptr< const Buffer > getBuffer() const
Get underlying buffer.
element_iterator insert(element_const_iterator pos, const Block &element)
insert Insert a new element in a specific position
const uint8_t * value() const
element_iterator erase(element_const_iterator position)
void resetWire()
Reset wire buffer but keep sub elements (if any)
Buffer::const_iterator value_begin() const
size_t writeVarNumber(std::ostream &os, uint64_t varNumber)
Write VAR-NUMBER to the specified stream.
bool readVarNumber(InputIterator &begin, const InputIterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
bool empty() const
Check if the Block is empty.
Buffer::const_iterator m_value_end
const Block & get(uint32_t type) const
Get the first subelement of the requested type.
EncodingImpl< EncoderTag > EncodingBuffer
element_const_iterator find(uint32_t type) const
Block makeBinaryBlock(uint32_t type, const uint8_t *value, size_t length)
Create a TLV block type type with value from a buffer value of size length.
bool operator!=(const Block &other) const
Buffer::const_iterator value_end() const
element_container::const_iterator element_const_iterator
Buffer::const_iterator begin() const
void remove(uint32_t type)
remove all subelements of type
void reset()
Reset wire buffer of the element.
void push_back(const Block &element)
Buffer::const_iterator end() const
size_t elements_size() const
void encode()
Encode subblocks into wire buffer.
Block blockFromValue() const
element_container m_subBlocks
Buffer::const_iterator m_end
Class implementing interface similar to ostringstream, but to construct ndn::Buffer.
bool hasValue() const
Check if the Block has value block (no type and length are encoded)
Buffer::const_iterator m_value_begin
shared_ptr< const Buffer > ConstBufferPtr
Block()
Create an empty Block.
represents an error in TLV encoding or decoding
size_t sizeOfVarNumber(uint64_t varNumber)
Get number of bytes necessary to hold value of VAR-NUMBER.
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM