encoding: improve documentation of Block class
Also add missing test cases for two constructor overloads
Change-Id: Iab76867b12684481ff5fc2587a3ebc8f5d176e71
diff --git a/ndn-cxx/encoding/block.cpp b/ndn-cxx/encoding/block.cpp
index e22822c..e584467 100644
--- a/ndn-cxx/encoding/block.cpp
+++ b/ndn-cxx/encoding/block.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -245,23 +245,14 @@
// ---- wire format ----
-bool
-Block::hasWire() const
+void
+Block::reset() noexcept
{
- return m_buffer != nullptr && m_begin != m_end;
+ *this = {};
}
void
-Block::reset()
-{
- this->resetWire();
-
- m_type = std::numeric_limits<uint32_t>::max();
- m_elements.clear();
-}
-
-void
-Block::resetWire()
+Block::resetWire() noexcept
{
m_buffer.reset(); // discard underlying buffer by resetting shared_ptr
m_begin = m_end = m_valueBegin = m_valueEnd = {};
@@ -307,13 +298,13 @@
// ---- value ----
const uint8_t*
-Block::value() const
+Block::value() const noexcept
{
return hasValue() ? &*m_valueBegin : nullptr;
}
size_t
-Block::value_size() const
+Block::value_size() const noexcept
{
return hasValue() ? static_cast<size_t>(m_valueEnd - m_valueBegin) : 0;
}
@@ -444,7 +435,7 @@
auto it = std::remove_if(m_elements.begin(), m_elements.end(),
[type] (const Block& subBlock) { return subBlock.type() == type; });
- m_elements.resize(it - m_elements.begin());
+ m_elements.erase(it, m_elements.end());
}
Block::element_iterator
diff --git a/ndn-cxx/encoding/block.hpp b/ndn-cxx/encoding/block.hpp
index 893d5b4..9b81bad 100644
--- a/ndn-cxx/encoding/block.hpp
+++ b/ndn-cxx/encoding/block.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -37,7 +37,7 @@
namespace ndn {
/** @brief Represents a TLV element of NDN packet format
- * @sa https://named-data.net/doc/ndn-tlv/tlv.html
+ * @sa https://named-data.net/doc/NDN-packet-spec/current/
*/
class Block
{
@@ -52,8 +52,9 @@
using tlv::Error::Error;
};
-public: // constructor, creation, assignment
+public: // construction, assignment
/** @brief Create an empty Block
+ * @sa empty()
*/
Block();
@@ -91,11 +92,11 @@
Block(const ConstBufferPtr& buffer);
/** @brief Parse Block within boundaries of a wire Buffer
- * @param buffer a Buffer containing an TLV element at [@p begin,@p end)
+ * @param buffer a Buffer containing a TLV element at [@p begin,@p end)
* @param begin begin position of the TLV element within @p buffer
* @param end end position of the TLV element within @p buffer
* @param verifyLength if true, check TLV-LENGTH equals size of TLV-VALUE
- * @throw std::invalid_argument @p buffer is empty, or [@p begin,@p end) range are not within @p buffer
+ * @throw std::invalid_argument @p buffer is empty, or [@p begin,@p end) range is not within @p buffer
* @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
* @note This overload automatically detects TLV-TYPE and position of TLV-VALUE.
*/
@@ -103,18 +104,18 @@
bool verifyLength = true);
/** @brief Parse Block within boundaries of an existing Block, reusing underlying wire Buffer
- * @param block a Block whose buffer contains an TLV element at [@p begin,@p end)
+ * @param block a Block whose buffer contains a TLV element at [@p begin,@p end)
* @param begin begin position of the TLV element within @p block
* @param end end position of the TLV element within @p block
* @param verifyLength if true, check TLV-LENGTH equals size of TLV-VALUE
- * @throw std::invalid_argument [@p begin,@p end) range are not within @p block
+ * @throw std::invalid_argument [@p begin,@p end) range is not within @p block
* @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
*/
Block(const Block& block, Buffer::const_iterator begin, Buffer::const_iterator end,
bool verifyLength = true);
/** @brief Create a Block from a wire Buffer without parsing
- * @param buffer a Buffer containing an TLV element at [@p begin,@p end)
+ * @param buffer a Buffer containing a TLV element at [@p begin,@p end)
* @param type TLV-TYPE
* @param begin begin position of the TLV element within @p buffer
* @param end end position of the TLV element within @p buffer
@@ -126,28 +127,29 @@
Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd);
/** @brief Parse Block from a raw buffer
- * @param buf pointer to the first octet of an TLV element
- * @param bufSize size of the raw buffer; may be more than size of the TLV element
+ * @param buf pointer to the first octet of a TLV element
+ * @param bufSize size of the raw buffer; may be greater than the actual size of the TLV element
* @throw tlv::Error Type-Length parsing fails, or size of TLV-VALUE exceeds @p bufSize
- * @note This overload copies the TLV element into an internal wire buffer.
+ * @note This overload copies the TLV element octets into an internal wire buffer.
*/
Block(const uint8_t* buf, size_t bufSize);
- /** @brief Create an empty Block with specified TLV-TYPE
+ /** @brief Create a zero-length Block with the specified TLV-TYPE
* @param type TLV-TYPE
+ * @post empty() == false
*/
explicit
Block(uint32_t type);
- /** @brief Create a Block with specified TLV-TYPE and TLV-VALUE
+ /** @brief Create a Block with the specified TLV-TYPE and TLV-VALUE
* @param type TLV-TYPE
- * @param value a Buffer containing the TLV-VALUE
+ * @param value a Buffer containing the TLV-VALUE, must not be nullptr
*/
Block(uint32_t type, ConstBufferPtr value);
- /** @brief Create a Block with specified TLV-TYPE and TLV-VALUE
+ /** @brief Create a Block with the specified TLV-TYPE and TLV-VALUE
* @param type TLV-TYPE
- * @param value a Block to be nested as TLV-VALUE
+ * @param value a Block to be nested as TLV-VALUE, must not be empty
*/
Block(uint32_t type, const Block& value);
@@ -159,20 +161,20 @@
fromStream(std::istream& is);
/** @brief Try to parse Block from a wire buffer
- * @param buffer a Buffer containing an TLV element at offset @p offset
+ * @param buffer a Buffer containing a TLV element at offset @p offset
* @param offset begin position of the TLV element within @p buffer
- * @note This function does not throw exceptions upon decoding failure.
- * @return true and the Block if parsing succeeds; otherwise false
+ * @note This function does not throw upon decoding failure.
+ * @return true and the parsed Block if parsing succeeds; otherwise false and an empty Block
*/
static std::tuple<bool, Block>
fromBuffer(ConstBufferPtr buffer, size_t offset);
/** @brief Try to parse Block from a raw buffer
- * @param buf pointer to the first octet of an TLV element
- * @param bufSize size of the raw buffer; may be more than size of the TLV element
- * @note This function does not throw exceptions upon decoding failure.
- * @note This overload copies the TLV element into an internal wire buffer.
- * @return true and the Block if parsing succeeds; otherwise false
+ * @param buf pointer to the first octet of a TLV element
+ * @param bufSize size of the raw buffer; may be greater than the actual size of the TLV element
+ * @note This function does not throw upon decoding failure.
+ * @note This overload copies the TLV element octets into an internal wire buffer.
+ * @return true and the parsed Block if parsing succeeds; otherwise false and an empty Block
*/
static std::tuple<bool, Block>
fromBuffer(const uint8_t* buf, size_t bufSize);
@@ -180,35 +182,40 @@
public: // wire format
/** @brief Check if the Block is empty
*
- * A Block is "empty" only if it is default-constructed. A Block with zero-length TLV-VALUE is
- * not considered empty.
+ * A Block is considered empty only if it is default-constructed. A Block with a zero-length
+ * TLV-VALUE is not considered empty.
*/
bool
- empty() const
+ empty() const noexcept
{
return m_type == std::numeric_limits<uint32_t>::max();
}
- /** @brief Check if the Block has fully encoded wire
- *
- * A Block has fully encoded wire if the underlying buffer exists and contains full
- * Type-Length-Value instead of just TLV-VALUE field.
- */
- bool
- hasWire() const;
-
/** @brief Reset wire buffer of the element
* @post empty() == true
+ * @sa resetWire()
*/
void
- reset();
+ reset() noexcept;
- /** @brief Reset wire buffer but keep TLV-TYPE and sub elements (if any)
+ /** @brief Reset wire buffer but keep TLV-TYPE and sub-elements (if any)
* @post hasWire() == false
* @post hasValue() == false
+ * @sa reset()
*/
void
- resetWire();
+ resetWire() noexcept;
+
+ /** @brief Check if the Block contains a fully encoded wire representation
+ *
+ * A Block has a fully encoded wire if the underlying buffer exists and contains the full
+ * Type-Length-Value instead of just the TLV-VALUE field.
+ */
+ bool
+ hasWire() const noexcept
+ {
+ return m_buffer != nullptr && m_begin != m_end;
+ }
/** @brief Get begin iterator of encoded wire
* @pre hasWire() == true
@@ -222,28 +229,31 @@
Buffer::const_iterator
end() const;
- /** @brief Get pointer to encoded wire
+ /** @brief Return a raw pointer to the beginning of the encoded wire
* @pre hasWire() == true
+ * @sa value()
*/
const uint8_t*
wire() const;
- /** @brief Get size of encoded wire, including Type-Length-Value
+ /** @brief Return the size of the encoded wire, i.e. of the whole TLV
* @pre empty() == false
+ * @sa value_size()
*/
size_t
size() const;
/** @brief Get underlying buffer
*/
- shared_ptr<const Buffer>
+ ConstBufferPtr
getBuffer() const
{
return m_buffer;
}
public: // type and value
- /** @brief Get TLV-TYPE
+ /** @brief Return the TLV-TYPE of the Block
+ * @pre empty() == false
*/
uint32_t
type() const
@@ -251,13 +261,15 @@
return m_type;
}
- /** @brief Get begin iterator of TLV-VALUE
+ /** @brief Check if the Block has a non-empty TLV-VALUE
*
- * This property reflects whether the underlying buffer contains TLV-VALUE. If this is false,
+ * This property reflects whether the underlying buffer contains a TLV-VALUE. If this is false,
* TLV-VALUE has zero-length. If this is true, TLV-VALUE may be zero-length.
+ *
+ * @sa value_size()
*/
bool
- hasValue() const
+ hasValue() const noexcept
{
return m_buffer != nullptr;
}
@@ -280,22 +292,24 @@
return m_valueEnd;
}
- /** @brief Get pointer to TLV-VALUE
+ /** @brief Return a raw pointer to the beginning of TLV-VALUE
+ * @sa wire()
*/
const uint8_t*
- value() const;
+ value() const noexcept;
- /** @brief Get size of TLV-VALUE aka TLV-LENGTH
+ /** @brief Return the size of TLV-VALUE, aka TLV-LENGTH
+ * @sa size()
*/
size_t
- value_size() const;
+ value_size() const noexcept;
Block
blockFromValue() const;
-public: // sub elements
- /** @brief Parse TLV-VALUE into sub elements
- * @post elements() reflects sub elements found in TLV-VALUE
+public: // sub-elements
+ /** @brief Parse TLV-VALUE into sub-elements
+ * @post elements() reflects sub-elements found in TLV-VALUE
* @throw tlv::Error TLV-VALUE is not a sequence of TLV elements
* @note This method does not perform recursive parsing.
* @note This method has no effect if elements() is already populated.
@@ -304,57 +318,58 @@
void
parse() const;
- /** @brief Encode sub elements into TLV-VALUE
- * @post TLV-VALUE contains sub elements from elements()
+ /** @brief Encode sub-elements into TLV-VALUE
+ * @post TLV-VALUE contains sub-elements from elements()
*/
void
encode();
- /** @brief Get the first sub element of specified TLV-TYPE
+ /** @brief Return the first sub-element of the specified TLV-TYPE
* @pre parse() has been executed
- * @throw Error sub element of @p type does not exist
+ * @throw tlv::Error a sub-element of the specified type does not exist
*/
const Block&
get(uint32_t type) const;
- /** @brief Find the first sub element of specified TLV-TYPE
+ /** @brief Find the first sub-element of the specified TLV-TYPE
* @pre parse() has been executed
- * @return iterator in elements() to the found sub element, otherwise elements_end()
+ * @return iterator in elements() to the found sub-element, or elements_end() if no such
+ * sub-element exists in elements()
*/
element_const_iterator
find(uint32_t type) const;
- /** @brief Remove all sub elements of specified TLV-TYPE
+ /** @brief Remove all sub-elements of the specified TLV-TYPE
* @pre parse() has been executed
* @post find(type) == elements_end()
*/
void
remove(uint32_t type);
- /** @brief Erase a sub element
+ /** @brief Erase a sub-element
*/
element_iterator
erase(element_const_iterator position);
- /** @brief Erase a range of sub elements
+ /** @brief Erase a range of sub-elements
*/
element_iterator
erase(element_const_iterator first, element_const_iterator last);
- /** @brief Append a sub element
+ /** @brief Append a sub-element
*/
void
push_back(const Block& element);
- /** @brief Insert a sub element
- * @param pos position of new sub element
- * @param element new sub element
- * @return iterator in elements() to the new sub element
+ /** @brief Insert a sub-element
+ * @param pos position of the new sub-element
+ * @param element new sub-element to insert
+ * @return iterator in elements() to the new sub-element
*/
element_iterator
insert(element_const_iterator pos, const Block& element);
- /** @brief Get container of sub elements
+ /** @brief Get container of sub-elements
* @pre parse() has been executed
*/
const element_container&
@@ -388,35 +403,35 @@
}
public: // misc
- /** @brief Implicit conversion to const_buffer
+ /** @brief Implicit conversion to `boost::asio::const_buffer`
*/
operator boost::asio::const_buffer() const;
private:
- /** @brief Estimate Block size as if sub elements are encoded into TLV-VALUE
+ /** @brief Estimate Block size as if sub-elements are encoded into TLV-VALUE
*/
size_t
encode(EncodingEstimator& estimator) const;
- /** @brief Estimate TLV-LENGTH as if sub elements are encoded into TLV-VALUE
+ /** @brief Estimate TLV-LENGTH as if sub-elements are encoded into TLV-VALUE
*/
size_t
encodeValue(EncodingEstimator& estimator) const;
- /** @brief Encode sub elements into TLV-VALUE and prepend Block to encoder
- * @post TLV-VALUE contains sub elements from elements()
+ /** @brief Encode sub-elements into TLV-VALUE and prepend Block to encoder
+ * @post TLV-VALUE contains sub-elements from elements()
* @post internal buffer and iterators point to Encoder's buffer
*/
size_t
encode(EncodingBuffer& encoder);
protected:
- /** @brief underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
+ /** @brief Underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
*
- * If m_buffer is nullptr, this is an empty Block with TLV-TYPE given in m_type.
+ * If m_buffer is nullptr, this is an empty or zero-length Block with TLV-TYPE given in m_type.
* Otherwise,
- * - [m_valueBegin, m_valueEnd) point to TLV-VALUE within m_buffer.
- * - If m_begin != m_end, [m_begin,m_end) point to Type-Length-Value of this Block within m_buffer.
+ * - [m_valueBegin, m_valueEnd) point to the TLV-VALUE inside m_buffer.
+ * - If m_begin != m_end, [m_begin, m_end) point to Type-Length-Value of this Block in m_buffer.
* Otherwise, m_buffer does not contain TLV-TYPE and TLV-LENGTH fields.
*/
shared_ptr<const Buffer> m_buffer;
@@ -428,13 +443,13 @@
uint32_t m_type = std::numeric_limits<uint32_t>::max(); ///< TLV-TYPE
- /** @brief total size including Type-Length-Value
+ /** @brief Total size including Type-Length-Value
*
* This field is valid only if empty() is false.
*/
size_t m_size = 0;
- /** @brief sub elements
+ /** @brief Contains the sub-elements
*
* This field is valid only if parse() has been executed.
*/
@@ -442,12 +457,12 @@
/** @brief Print @p block to @p os.
*
- * Default-constructed block is printed as: `[invalid]`.
- * Zero-length block is printed as: `TT[empty]`, where TT is TLV-TYPE in decimal.
- * Non-zero-length block on which @c Block::parse is not called is printed as: `TT[LL]=VVVV`,
- * where LL is TLV-LENGTH in decimal, and VVVV is TLV-VALUE is hexadecimal.
- * Block on which @c Block::parse has been called in printed as: `TT[LL]={SUB,SUB}`,
- * where SUB is a sub-element printed using this format.
+ * Default-constructed Block is printed as: `[invalid]`.
+ * Zero-length Block is printed as: `TT[empty]`, where TT is TLV-TYPE in decimal.
+ * Non-zero-length Block on which parse() has not been called is printed as: `TT[LL]=VVVV`,
+ * where LL is TLV-LENGTH in decimal, and VVVV is TLV-VALUE in hexadecimal.
+ * Block on which parse() has been called is printed as: `TT[LL]={SUB,SUB}`,
+ * where each SUB is a sub-element printed using this format.
*/
friend std::ostream&
operator<<(std::ostream& os, const Block& block);
@@ -470,18 +485,18 @@
return !(lhs == rhs);
}
-/** \brief Construct a \c Block from hexadecimal \p input.
- * \param input a string containing hexadecimal bytes and comments.
+/** @brief Construct a Block from hexadecimal @p input.
+ * @param input a string containing hexadecimal bytes and comments.
* 0-9 and upper-case A-F are input; all other characters are comments.
- * \param len length of \p input.
- * \throw std::invalid_argument input is empty or has odd number of hexadecimal digits.
- * \throw tlv::Error input cannot be parsed into valid \c Block.
+ * @param len length of @p input.
+ * @throw std::invalid_argument input is empty or has an odd number of hexadecimal digits.
+ * @throw tlv::Error @p input cannot be parsed into a valid Block.
*
* Example
- * \code
+ * @code
* Block nameBlock = "0706 080141 080142"_block;
* Block nackBlock = "FD032005 reason(no-route)=FD03210196"_block;
- * \endcode
+ * @endcode
*/
Block
operator "" _block(const char* input, std::size_t len);
diff --git a/tests/unit/encoding/block.t.cpp b/tests/unit/encoding/block.t.cpp
index dd7e3b0..18126e8 100644
--- a/tests/unit/encoding/block.t.cpp
+++ b/tests/unit/encoding/block.t.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2019 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -50,9 +50,10 @@
BOOST_AUTO_TEST_CASE(FromEncodingBuffer)
{
- const uint8_t VALUE[4] = {0x11, 0x12, 0x13, 0x14};
-
EncodingBuffer encoder;
+ BOOST_CHECK_THROW(Block{encoder}, tlv::Error);
+
+ const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
size_t length = encoder.prependByteArray(VALUE, sizeof(VALUE));
encoder.prependVarNumber(length);
encoder.prependVarNumber(0xe0);
@@ -70,17 +71,10 @@
VALUE, VALUE + sizeof(VALUE));
}
-BOOST_AUTO_TEST_CASE(FromEmptyEncodingBuffer)
-{
- EncodingBuffer encoder;
- Block b;
- BOOST_CHECK_THROW(b = Block(encoder), tlv::Error);
-}
-
BOOST_AUTO_TEST_CASE(FromBlock)
{
- static uint8_t buffer[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
- Block block(buffer, sizeof(buffer));
+ const uint8_t BUFFER[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
+ Block block(BUFFER, sizeof(BUFFER));
Block derivedBlock(block, block.begin(), block.end());
BOOST_CHECK_EQUAL(derivedBlock.wire(), block.wire()); // pointers should match
@@ -88,9 +82,9 @@
derivedBlock = Block(block, block.begin() + 2, block.begin() + 5);
BOOST_CHECK(derivedBlock.begin() == block.begin() + 2);
- BOOST_CHECK(derivedBlock == Block(buffer + 2, 3));
+ BOOST_CHECK(derivedBlock == Block(BUFFER + 2, 3));
- Buffer otherBuffer(buffer, sizeof(buffer));
+ Buffer otherBuffer(BUFFER, sizeof(BUFFER));
BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), block.end()), std::invalid_argument);
BOOST_CHECK_THROW(Block(block, block.begin(), otherBuffer.end()), std::invalid_argument);
BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), otherBuffer.end()), std::invalid_argument);
@@ -143,14 +137,43 @@
BOOST_CHECK_EQUAL(b1.empty(), false);
BOOST_CHECK_EQUAL(b1.type(), 4);
BOOST_CHECK_EQUAL(b1.size(), 2); // 1-octet TLV-TYPE and 1-octet TLV-LENGTH
+ BOOST_CHECK_EQUAL(b1.hasValue(), false);
BOOST_CHECK_EQUAL(b1.value_size(), 0);
Block b2(258);
+ BOOST_CHECK_EQUAL(b2.empty(), false);
BOOST_CHECK_EQUAL(b2.type(), 258);
BOOST_CHECK_EQUAL(b2.size(), 4); // 3-octet TLV-TYPE and 1-octet TLV-LENGTH
+ BOOST_CHECK_EQUAL(b2.hasValue(), false);
BOOST_CHECK_EQUAL(b2.value_size(), 0);
}
+BOOST_AUTO_TEST_CASE(FromTypeAndBuffer)
+{
+ const uint8_t VALUE[] = {0x11, 0x12, 0x13, 0x14};
+ auto bufferPtr = make_shared<Buffer>(VALUE, sizeof(VALUE));
+
+ Block b(42, bufferPtr);
+ BOOST_CHECK_EQUAL(b.empty(), false);
+ BOOST_CHECK_EQUAL(b.type(), 42);
+ BOOST_CHECK_EQUAL(b.size(), 6);
+ BOOST_CHECK_EQUAL(b.hasValue(), true);
+ BOOST_CHECK_EQUAL(b.value_size(), sizeof(VALUE));
+}
+
+BOOST_AUTO_TEST_CASE(FromTypeAndBlock)
+{
+ const uint8_t BUFFER[] = {0x80, 0x06, 0x81, 0x01, 0x01, 0x82, 0x01, 0x01};
+ Block nested(BUFFER, sizeof(BUFFER));
+
+ Block b(84, nested);
+ BOOST_CHECK_EQUAL(b.empty(), false);
+ BOOST_CHECK_EQUAL(b.type(), 84);
+ BOOST_CHECK_EQUAL(b.size(), 10);
+ BOOST_CHECK_EQUAL(b.hasValue(), true);
+ BOOST_CHECK_EQUAL(b.value_size(), sizeof(BUFFER));
+}
+
BOOST_AUTO_TEST_CASE(FromStream)
{
std::stringstream stream;