28 #include "../util/string-helper.hpp" 30 #include <boost/asio/buffer.hpp> 31 #include <boost/range/adaptor/reversed.hpp> 36 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Block>));
37 #if NDN_CXX_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE 38 static_assert(std::is_nothrow_move_constructible<Block>::value,
39 "Block must be MoveConstructible with noexcept");
40 #endif // NDN_CXX_HAVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE 42 #if NDN_CXX_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE 43 static_assert(std::is_nothrow_move_assignable<Block>::value,
44 "Block must be MoveAssignable with noexcept");
45 #endif // NDN_CXX_HAVE_IS_NOTHROW_MOVE_ASSIGNABLE 52 : m_type(
std::numeric_limits<uint32_t>::max())
77 BOOST_THROW_EXCEPTION(std::invalid_argument(
"buffer is empty"));
80 const uint8_t* bufferBegin = &
m_buffer->front();
81 const uint8_t* bufferEnd = bufferBegin +
m_buffer->size();
82 if (&*begin < bufferBegin || &*begin > bufferEnd ||
83 &*end < bufferBegin || &*end > bufferEnd) {
84 BOOST_THROW_EXCEPTION(std::invalid_argument(
"begin/end iterators points out of the buffer"));
92 BOOST_THROW_EXCEPTION(
Error(
"TLV-LENGTH doesn't match buffer size"));
103 Buffer::const_iterator
begin, Buffer::const_iterator
end,
104 Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd)
117 const uint8_t* pos = buf;
118 const uint8_t*
const end = buf + bufSize;
124 if (length > static_cast<uint64_t>(end - pos)) {
125 BOOST_THROW_EXCEPTION(
Error(
"Not enough bytes in the buffer to fully parse TLV"));
127 size_t typeLengthSize = pos - buf;
128 m_size = typeLengthSize + length;
167 std::istream_iterator<uint8_t>
begin(is >> std::noskipws);
168 std::istream_iterator<uint8_t>
end;
177 if (tlSize + length > MAX_SIZE_OF_BLOCK_FROM_STREAM) {
178 BOOST_THROW_EXCEPTION(
Error(
"TLV-LENGTH from stream exceeds limit"));
182 uint8_t* valueBuf = eb.buf();
183 is.read(reinterpret_cast<char*>(valueBuf), length);
184 if (length != static_cast<uint64_t>(is.gcount())) {
185 BOOST_THROW_EXCEPTION(
Error(
"Not enough bytes from stream to fully parse TLV"));
188 eb.prependVarNumber(length);
189 eb.prependVarNumber(type);
193 return Block(eb.getBuffer());
196 std::tuple<bool, Block>
199 const Buffer::const_iterator
begin = buffer->begin() + offset;
200 Buffer::const_iterator pos =
begin;
205 return std::make_tuple(
false,
Block());
210 return std::make_tuple(
false,
Block());
214 if (length > static_cast<uint64_t>(buffer->end() - pos)) {
215 return std::make_tuple(
false,
Block());
218 return std::make_tuple(
true,
Block(buffer, type, begin, pos + length, pos, pos + length));
221 std::tuple<bool, Block>
224 const uint8_t* pos = buf;
225 const uint8_t*
const end = buf + bufSize;
230 return std::make_tuple(
false,
Block());
235 return std::make_tuple(
false,
Block());
239 if (length > static_cast<uint64_t>(end - pos)) {
240 return std::make_tuple(
false,
Block());
243 size_t typeLengthSize = pos - buf;
244 auto b = make_shared<Buffer>(buf, pos + length);
245 return std::make_tuple(
true,
Block(b, type, b->begin(), b->end(),
246 b->begin() + typeLengthSize, b->end()));
262 m_type = std::numeric_limits<uint32_t>::max();
273 Buffer::const_iterator
277 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
282 Buffer::const_iterator
286 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
295 BOOST_THROW_EXCEPTION(
Error(
"Underlying wire buffer is empty"));
304 BOOST_THROW_EXCEPTION(
Error(
"Block size cannot be determined (undefined block size)"));
328 BOOST_THROW_EXCEPTION(
Error(
"Block has no TLV-VALUE"));
344 while (begin != end) {
345 Buffer::const_iterator pos =
begin;
349 if (length > static_cast<uint64_t>(end - pos)) {
351 BOOST_THROW_EXCEPTION(
Error(
"TLV-LENGTH of sub-element of type " +
to_string(type) +
352 " exceeds TLV-VALUE boundary of parent block"));
356 Buffer::const_iterator subEnd = pos + length;
370 size_t estimatedSize =
encode(estimator);
383 size_t len = encodeValue(estimator);
384 len += estimator.prependVarNumber(len);
385 len += estimator.prependVarNumber(
m_type);
394 len += element.encode(estimator);
403 m_end = encoder.begin();
409 len += element.encode(encoder);
415 len += encoder.prependVarNumber(len);
416 len += encoder.prependVarNumber(
m_type);
427 auto it = this->
find(type);
432 BOOST_THROW_EXCEPTION(
Error(
"No sub-element of type " +
to_string(type) +
440 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
449 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
458 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 462 std::advance(it, std::distance(
m_elements.cbegin(), position));
472 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 477 std::advance(itStart, std::distance(
m_elements.cbegin(), first));
478 std::advance(itEnd, std::distance(
m_elements.cbegin(), last));
495 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR 499 std::advance(it, std::distance(
m_elements.cbegin(), pos));
506 Block::operator boost::asio::const_buffer()
const 508 return boost::asio::const_buffer(
wire(),
size());
523 auto oldFmt = os.flags(std::ios_base::dec);
530 size_t tlvLength = block.encodeValue(estimator);
531 os << block.
type() <<
'[' << tlvLength <<
"]={";
540 os << block.
type() <<
"[empty]";
shared_ptr< const Buffer > m_buffer
underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
bool empty() const
Check if the Block is empty.
static Block fromStream(std::istream &is)
Parse Block from an input stream.
Copyright (c) 2013-2017 Regents of the University of California.
bool hasValue() const
Get begin iterator of TLV-VALUE.
bool readType(Iterator &begin, const Iterator &end, uint32_t &type)
Read TLV-TYPE.
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset)
Try to parse Block from a wire buffer.
Buffer::const_iterator m_valueBegin
Buffer::const_iterator end() const
Get end iterator of encoded wire.
Buffer::const_iterator m_begin
element_const_iterator find(uint32_t type) const
Find the first sub element of specified TLV-TYPE.
element_container::const_iterator element_const_iterator
element_container m_elements
sub elements
friend std::ostream & operator<<(std::ostream &os, const Block &block)
Print block to os.
Represents a TLV element of NDN packet format.
element_iterator insert(element_const_iterator pos, const Block &element)
Insert a sub element.
element_iterator erase(element_const_iterator position)
Erase a sub element.
Buffer::const_iterator value_begin() const
Get begin iterator of TLV-VALUE.
Buffer::const_iterator value_end() const
Get end iterator of TLV-VALUE.
void resetWire()
Reset wire buffer but keep TLV-TYPE and sub elements (if any)
ostream_joiner< typename std::decay< DelimT >::type, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
uint32_t m_size
total size including Type-Length-Value
bool readVarNumber(Iterator &begin, const Iterator &end, uint64_t &number)
Read VAR-NUMBER in NDN-TLV encoding.
Buffer::const_iterator m_valueEnd
size_t size() const
Get size of encoded wire, including Type-Length-Value.
Block blockFromValue() const
const Block & get(uint32_t type) const
Get the first sub element of specified TLV-TYPE.
element_container::iterator element_iterator
void remove(uint32_t type)
Remove all sub elements of specified TLV-TYPE.
void reset()
Reset wire buffer of the element.
void push_back(const Block &element)
Append a sub element.
size_t value_size() const
Get size of TLV-VALUE aka TLV-LENGTH.
void parse() const
Parse TLV-VALUE into sub elements.
uint32_t type() const
Get TLV-TYPE.
void encode()
Encode sub elements into TLV-VALUE.
const uint8_t * wire() const
Get pointer to encoded wire.
Buffer::const_iterator m_end
bool hasWire() const
Check if the Block has fully encoded wire.
const uint8_t * value() const
Get pointer to TLV-VALUE.
bool operator==(const Data &lhs, const Data &rhs)
shared_ptr< const Buffer > getBuffer() const
Get underlying buffer.
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
std::string to_string(const V &v)
element_const_iterator elements_end() const
Equivalent to elements().end()
constexpr size_t sizeOfVarNumber(uint64_t number)
Get number of bytes necessary to hold value of VAR-NUMBER.
element_const_iterator elements_begin() const
Equivalent to elements().begin()
Block()
Create an empty Block.
EncodingImpl< EncoderTag > EncodingBuffer
Buffer::const_iterator begin() const
Get begin iterator of encoded wire.
EncodingImpl< EstimatorTag > EncodingEstimator
const size_t MAX_NDN_PACKET_SIZE
practical limit of network layer packet size
const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM
shared_ptr< const Buffer > ConstBufferPtr