35 #include <boost/asio/buffer.hpp>
36 #include <boost/range/adaptor/reversed.hpp>
56 auto pos = buffer.begin();
57 const auto end = buffer.end();
63 BOOST_ASSERT(pos <=
end);
64 if (length >
static_cast<uint64_t
>(std::distance(pos,
end))) {
65 NDN_THROW(
Error(
"Not enough bytes in the buffer to fully parse TLV"));
67 std::advance(pos, length);
70 m_buffer = std::make_shared<Buffer>(buffer.begin(), pos);
79 :
Block(buffer.getBuffer(), buffer.begin(), buffer.end(), true)
84 :
Block(buffer, buffer->begin(), buffer->end(), true)
90 : m_buffer(std::move(buffer))
93 , m_valueBegin(m_begin)
95 , m_size(static_cast<size_t>(std::distance(m_begin, m_end)))
98 NDN_THROW(std::invalid_argument(
"Buffer is empty"));
101 const uint8_t* bufferBegin = &
m_buffer->front();
102 const uint8_t* bufferEnd = bufferBegin +
m_buffer->size();
103 if (&*begin < bufferBegin || &*begin > bufferEnd ||
104 &*end < bufferBegin || &*end > bufferEnd) {
105 NDN_THROW(std::invalid_argument(
"Begin/end iterators point outside the buffer"));
119 :
Block(block.m_buffer, begin, end, verifyLength)
124 Buffer::const_iterator begin, Buffer::const_iterator end,
125 Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd)
126 : m_buffer(std::move(buffer))
129 , m_valueBegin(valueBegin)
130 , m_valueEnd(valueEnd)
132 , m_size(static_cast<size_t>(std::distance(m_begin, m_end)))
143 : m_buffer(std::move(value))
144 , m_begin(m_buffer->end())
145 , m_end(m_buffer->end())
146 , m_valueBegin(m_buffer->begin())
147 , m_valueEnd(m_buffer->end())
154 : m_buffer(value.m_buffer)
155 , m_begin(m_buffer->end())
156 , m_end(m_buffer->end())
157 , m_valueBegin(value.begin())
158 , m_valueEnd(value.end())
164 std::tuple<bool, Block>
167 auto begin = std::next(buffer->begin(), offset);
169 const auto end = buffer->end();
184 BOOST_ASSERT(pos <=
end);
185 if (length >
static_cast<uint64_t
>(std::distance(pos,
end))) {
189 return {
true,
Block(std::move(buffer),
type,
begin, pos + length, pos, pos + length)};
192 std::tuple<bool, Block>
195 auto pos = buffer.begin();
196 const auto end = buffer.end();
210 BOOST_ASSERT(pos <=
end);
211 if (length >
static_cast<uint64_t
>(std::distance(pos,
end))) {
214 std::advance(pos, length);
217 auto b = std::make_shared<Buffer>(buffer.begin(), pos);
218 return {
true,
Block(b,
type, b->begin(), b->end(), std::prev(b->end(), length), b->end())};
224 std::istream_iterator<uint8_t>
begin(is >> std::noskipws);
225 std::istream_iterator<uint8_t>
end;
239 uint8_t* valueBuf = eb.data();
240 is.read(
reinterpret_cast<char*
>(valueBuf), length);
241 if (length !=
static_cast<uint64_t
>(is.gcount())) {
242 NDN_THROW(
Error(
"Not enough bytes from stream to fully parse TLV"));
245 eb.prependVarNumber(length);
246 eb.prependVarNumber(
type);
250 return Block(eb.getBuffer());
338 if (length >
static_cast<uint64_t
>(
end - pos)) {
341 " exceeds TLV-VALUE boundary of parent block"));
345 auto subEnd = std::next(pos, length);
359 size_t estimatedSize =
encode(estimator);
372 size_t len = encodeValue(estimator);
373 len += estimator.prependVarNumber(len);
374 len += estimator.prependVarNumber(
m_type);
383 len += element.encode(estimator);
392 m_end = encoder.begin();
398 len += element.encode(encoder);
404 len += encoder.prependVarNumber(len);
405 len += encoder.prependVarNumber(
m_type);
428 [
type] (
const Block& subBlock) { return subBlock.type() == type; });
437 [
type] (
const Block& subBlock) { return subBlock.type() == type; });
478 Block::operator boost::asio::const_buffer()
const
480 return {data(), size()};
484 Block::equals(
const Block& other)
const noexcept
486 return type() == other.type() &&
487 value_size() == other.value_size() &&
488 (value_size() == 0 ||
489 std::equal(value_begin(), value_end(), other.value_begin()));
493 Block::print(std::ostream& os)
const
495 auto oldFlags = os.flags(std::ios_base::dec);
496 auto restoreFlags = make_scope_exit([&] {
505 size_t tlvLength = encodeValue(estimator);
506 os <<
type() <<
'[' << tlvLength <<
"]={";
515 os <<
type() <<
"[empty]";
519 inline namespace literals {
520 inline namespace block_literals {
523 operator ""_block(
const char* input, std::size_t len)
525 namespace t = security::transform;
530 for (
const char* end = input + len; input != end; ++input) {
531 if (std::strchr(
"0123456789ABCDEF", *input) !=
nullptr) {
532 ss.write({
reinterpret_cast<const uint8_t*
>(input), 1});
539 catch (
const t::Error&) {
540 NDN_THROW(std::invalid_argument(
"Input has odd number of hexadecimal digits"));
Represents a TLV element of the NDN packet format.
element_const_iterator elements_begin() const noexcept
Equivalent to elements().begin().
element_container::const_iterator element_const_iterator
const uint8_t * data() const
Returns a raw pointer to the beginning of the encoded wire, i.e., the whole TLV.
Buffer::const_iterator const_iterator
const_iterator value_end() const noexcept
Get end iterator of TLV-VALUE.
element_const_iterator find(uint32_t type) const
Find the first sub-element of the specified TLV-TYPE.
const_iterator begin() const
Returns an iterator to the beginning of the encoded wire.
Block blockFromValue() const
Return a new Block constructed from the TLV-VALUE of this Block.
element_iterator erase(element_const_iterator position)
Erase a sub-element.
void remove(uint32_t type)
Remove all sub-elements of the specified TLV-TYPE.
size_t size() const
Returns the size of the encoded wire, i.e., of the whole TLV.
element_const_iterator elements_end() const noexcept
Equivalent to elements().end().
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
size_t m_size
Total size including Type-Length-Value.
Buffer::const_iterator m_valueEnd
void resetWire() noexcept
Reset wire buffer but keep TLV-TYPE and sub-elements (if any).
element_container m_elements
Contains the sub-elements.
static std::tuple< bool, Block > fromBuffer(ConstBufferPtr buffer, size_t offset=0)
Try to parse Block from a wire buffer.
void push_back(const Block &element)
Append a sub-element.
Block & operator=(const Block &)
Copy assignment operator.
Buffer::const_iterator m_end
Buffer::const_iterator m_valueBegin
bool hasValue() const noexcept
Check if the Block has a non-empty TLV-VALUE.
bool isValid() const noexcept
Check if the Block is valid.
element_container::iterator element_iterator
void encode()
Encode sub-elements into TLV-VALUE.
span< const uint8_t > value_bytes() const noexcept
Return a read-only view of TLV-VALUE as a contiguous range of bytes.
const_iterator end() const
Returns an iterator past-the-end of the encoded wire.
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
static Block fromStream(std::istream &is)
Parse Block from an input stream.
void reset() noexcept
Reset the Block to a default-constructed state.
Buffer::const_iterator m_begin
shared_ptr< const Buffer > m_buffer
Underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields.
void parse() const
Parse TLV-VALUE into sub-elements.
const_iterator value_begin() const noexcept
Get begin iterator of TLV-VALUE.
const Block & get(uint32_t type) const
Return the first sub-element of the specified TLV-TYPE.
size_t value_size() const noexcept
Return the size of TLV-VALUE, i.e., the TLV-LENGTH.
Block()
Create an invalid Block.
element_iterator insert(element_const_iterator pos, const Block &element)
Insert a sub-element.
const uint8_t * value() const noexcept
Return a raw pointer to the beginning of TLV-VALUE.
An output stream that writes to a Buffer.
std::shared_ptr< Buffer > buf()
Return a shared pointer to the underlying buffer.
EncodingImpl< EstimatorTag > EncodingEstimator
EncodingImpl< EncoderTag > EncodingBuffer
std::string to_string(const errinfo_stacktrace &x)
constexpr size_t sizeOfVarNumber(uint64_t number) noexcept
Get the number of bytes necessary to hold the value of number encoded as VAR-NUMBER.
constexpr bool readVarNumber(Iterator &begin, Iterator end, uint64_t &number) noexcept
Read VAR-NUMBER in NDN-TLV encoding.
constexpr bool readType(Iterator &begin, Iterator end, uint32_t &type) noexcept
Read TLV-TYPE.
void printHex(std::ostream &os, uint64_t num, bool wantUpperCase)
Output the hex representation of num to the output stream os.
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
std::shared_ptr< const Buffer > ConstBufferPtr
constexpr size_t MAX_SIZE_OF_BLOCK_FROM_STREAM
constexpr size_t MAX_NDN_PACKET_SIZE
Practical size limit of a network-layer packet.
Backport of ostream_joiner from the Library Fundamentals v2 TS.