32 #include <boost/asio/buffer.hpp> 33 #include <boost/range/adaptor/reversed.hpp> 38 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Block>));
53 auto pos = buffer.begin();
54 const auto end = buffer.end();
60 BOOST_ASSERT(pos <=
end);
61 if (length > static_cast<uint64_t>(std::distance(pos,
end))) {
62 NDN_THROW(
Error(
"Not enough bytes in the buffer to fully parse TLV"));
64 std::advance(pos, length);
67 m_buffer = std::make_shared<Buffer>(buffer.begin(), pos);
95 NDN_THROW(std::invalid_argument(
"Buffer is empty"));
98 const uint8_t* bufferBegin = &
m_buffer->front();
99 const uint8_t* bufferEnd = bufferBegin +
m_buffer->size();
100 if (&*begin < bufferBegin || &*begin > bufferEnd ||
101 &*end < bufferBegin || &*end > bufferEnd) {
102 NDN_THROW(std::invalid_argument(
"Begin/end iterators point outside the buffer"));
121 Buffer::const_iterator begin, Buffer::const_iterator end,
122 Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd)
161 std::tuple<bool, Block>
164 auto begin = std::next(buffer->begin(), offset);
166 const auto end = buffer->end();
171 return std::make_tuple(
false,
Block());
177 return std::make_tuple(
false,
Block());
181 BOOST_ASSERT(pos <= end);
182 if (length > static_cast<uint64_t>(std::distance(pos, end))) {
183 return std::make_tuple(
false,
Block());
186 return std::make_tuple(
true,
Block(
std::move(buffer), type, begin, pos + length, pos, pos + length));
189 std::tuple<bool, Block>
192 auto pos = buffer.begin();
193 const auto end = buffer.end();
198 return std::make_tuple(
false,
Block());
203 return std::make_tuple(
false,
Block());
207 BOOST_ASSERT(pos <= end);
208 if (length > static_cast<uint64_t>(std::distance(pos, end))) {
209 return std::make_tuple(
false,
Block());
211 std::advance(pos, length);
214 auto b = std::make_shared<Buffer>(buffer.begin(), pos);
215 return std::make_tuple(
true,
Block(b, type, b->begin(), b->end(),
216 std::prev(b->end(), length), b->end()));
222 std::istream_iterator<uint8_t>
begin(is >> std::noskipws);
223 std::istream_iterator<uint8_t>
end;
232 if (tlSize + length > MAX_SIZE_OF_BLOCK_FROM_STREAM) {
237 uint8_t* valueBuf = eb.data();
238 is.read(reinterpret_cast<char*>(valueBuf), length);
239 if (length != static_cast<uint64_t>(is.gcount())) {
240 NDN_THROW(
Error(
"Not enough bytes from stream to fully parse TLV"));
243 eb.prependVarNumber(length);
244 eb.prependVarNumber(type);
248 return Block(eb.getBuffer());
332 while (begin != end) {
336 if (length > static_cast<uint64_t>(end - pos)) {
339 " exceeds TLV-VALUE boundary of parent block"));
343 auto subEnd = std::next(pos, length);
357 size_t estimatedSize =
encode(estimator);
370 size_t len = encodeValue(estimator);
371 len += estimator.prependVarNumber(len);
372 len += estimator.prependVarNumber(
m_type);
381 len += element.encode(estimator);
390 m_end = encoder.begin();
396 len += element.encode(encoder);
402 len += encoder.prependVarNumber(len);
403 len += encoder.prependVarNumber(
m_type);
414 auto it = this->
find(type);
427 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
436 [
type] (
const Block& subBlock) {
return subBlock.type() ==
type; });
477 Block::operator boost::asio::const_buffer()
const 494 auto oldFmt = os.flags(std::ios_base::dec);
501 size_t tlvLength = block.encodeValue(estimator);
502 os << block.
type() <<
'[' << tlvLength <<
"]={";
511 os << block.
type() <<
"[empty]";
521 namespace t = security::transform;
526 for (
const char* end = input + len; input !=
end; ++input) {
527 if (std::strchr(
"0123456789ABCDEF", *input) !=
nullptr) {
528 ss.write({
reinterpret_cast<const uint8_t*
>(input), 1});
535 catch (
const t::Error&) {
536 NDN_THROW(std::invalid_argument(
"Input has odd number of hexadecimal digits"));
size_t m_size
Total size including Type-Length-Value.
shared_ptr< const Buffer > m_buffer
Underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields.
static NDN_CXX_NODISCARD std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset=0)
Try to parse Block from a wire buffer.
static Block fromStream(std::istream &is)
Parse Block from an input stream.
Copyright (c) 2011-2015 Regents of the University of California.
Buffer::const_iterator m_valueBegin
std::string to_string(const T &val)
Buffer::const_iterator m_begin
span_CONFIG_SIZE_TYPE size_t
const_iterator value_begin() const noexcept
Get begin iterator of TLV-VALUE.
element_container::const_iterator element_const_iterator
const_iterator begin() const
Get begin iterator of encoded wire.
size_t value_size() const noexcept
Return the size of TLV-VALUE, i.e., the TLV-LENGTH.
void parse() const
Parse TLV-VALUE into sub-elements.
element_container m_elements
Contains the sub-elements.
friend std::ostream & operator<<(std::ostream &os, const Block &block)
Print block to os.
Represents a TLV element of the NDN packet format.
void resetWire() noexcept
Reset wire buffer but keep TLV-TYPE and sub-elements (if any)
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
element_const_iterator elements_begin() const
Equivalent to elements().begin()
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 m_valueEnd
ConstBufferPtr getBuffer() const
Get underlying buffer.
size_t size() const
Return the size of the encoded wire, i.e., of the whole TLV.
element_const_iterator elements_end() const
Equivalent to elements().end()
const uint8_t * data() const
Return a raw pointer to the beginning of the encoded wire.
const Block & get(uint32_t type) const
Return the first sub-element of the specified TLV-TYPE.
constexpr size_t sizeOfVarNumber(uint64_t number) noexcept
Get the number of bytes necessary to hold the value of number encoded as VAR-NUMBER.
element_const_iterator find(uint32_t type) const
Find the first sub-element of the specified TLV-TYPE.
void reset() noexcept
Reset the Block to a default-constructed state.
Backport of ostream_joiner from the Library Fundamentals v2 TS.
Block & operator=(const Block &)
Copy assignment operator.
NDN_CXX_NODISCARD bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
NDN_CXX_NODISCARD bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
element_container::iterator element_iterator
void remove(uint32_t type)
Remove all sub-elements of the specified TLV-TYPE.
void push_back(const Block &element)
Append a sub-element.
bool isValid() const noexcept
Check if the Block is valid.
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
span< const uint8_t > value_bytes() const noexcept
Return a read-only view of TLV-VALUE as a contiguous range of bytes.
bool hasValue() const noexcept
Check if the Block has a non-empty TLV-VALUE.
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
shared_ptr< Buffer > buf()
Flush written data to the stream and return shared pointer to the underlying buffer.
void encode()
Encode sub-elements into TLV-VALUE.
Block blockFromValue() const
Return a new Block constructed from the TLV-VALUE of this Block.
Buffer::const_iterator m_end
bool operator==(const Data &lhs, const Data &rhs)
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
implements an output stream that constructs ndn::Buffer
const_iterator value_end() const noexcept
Get end iterator of TLV-VALUE.
Block()
Create an invalid Block.
const_iterator end() const
Get end iterator of encoded wire.
EncodingImpl< EncoderTag > EncodingBuffer
Buffer::const_iterator const_iterator
EncodingImpl< EstimatorTag > EncodingEstimator
const size_t MAX_NDN_PACKET_SIZE
Practical size limit of a network-layer packet.
const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM
shared_ptr< const Buffer > ConstBufferPtr