encoding: write nonNegativeInteger 253-255 as one octet
This commit also updates code-style and improves Doxygen in tlv.hpp
refs #4167
Change-Id: I8657feb1bfe96bfc88202d55eb7432d7ff1d5538
diff --git a/src/encoding/tlv.hpp b/src/encoding/tlv.hpp
index bcb562a..876fcb5 100644
--- a/src/encoding/tlv.hpp
+++ b/src/encoding/tlv.hpp
@@ -1,5 +1,5 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
* Copyright (c) 2013-2017 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -132,103 +132,116 @@
ContentType_Key = 2,
/** @brief indicates a producer generated NACK
- * @warning Experimental. Not defined in NDN-TLV spec.
*/
ContentType_Nack = 3
};
/**
* @brief Read VAR-NUMBER in NDN-TLV encoding
+ * @tparam InputIterator an iterator or pointer dereferencable to uint8_t
*
- * @param [in] begin Begin (pointer or iterator) of the buffer
- * @param [in] end End (pointer or iterator) of the buffer
- * @param [out] number Read number
+ * @param [inout] begin Begin of the buffer, will be incremented to point to the first byte after
+ * the read VAR-NUMBER
+ * @param [in] end End of the buffer
+ * @param [out] number Read VAR-NUMBER
*
- * @throws This call never throws exception
- *
- * @return true if number successfully read from input, false otherwise
+ * @return true if number was successfully read from input, false otherwise
+ * @note This call never throws exceptions
*/
template<class InputIterator>
-inline bool
+bool
readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number);
/**
- * @brief Read TLV Type
+ * @brief Read TLV-TYPE
+ * @tparam InputIterator an iterator or pointer dereferencable to uint8_t
*
- * @param [in] begin Begin (pointer or iterator) of the buffer
- * @param [in] end End (pointer or iterator) of the buffer
- * @param [out] type Read type number
+ * @param [inout] begin Begin of the buffer, will be incremented to point to the first byte after
+ * the read TLV-TYPE
+ * @param [in] end End of the buffer
+ * @param [out] type Read TLV-TYPE
*
- * @throws This call never throws exception
- *
- * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
- * is larger than 2^32-1 (type in this library is implemented as uint32_t)
+ * @return true if TLV-TYPE was successfully read from input, false otherwise
+ * @note This call never throws exceptions
+ * @note This call is largely equivalent to tlv::readVarNumber, but it will return false if type
+ * is larger than 2^32-1 (TLV-TYPE in this library is implemented as uint32_t)
*/
template<class InputIterator>
-inline bool
+bool
readType(InputIterator& begin, const InputIterator& end, uint32_t& type);
-
/**
* @brief Read VAR-NUMBER in NDN-TLV encoding
+ * @tparam InputIterator an iterator or pointer dereferencable to uint8_t
*
- * @throws This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
+ * @param [inout] begin Begin of the buffer, will be incremented to point to the first byte after
+ * the read VAR-NUMBER
+ * @param [in] end End of the buffer
*
- * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
+ * @throw tlv::Error VAR-NUMBER cannot be read
*/
template<class InputIterator>
-inline uint64_t
+uint64_t
readVarNumber(InputIterator& begin, const InputIterator& end);
/**
* @brief Read TLV Type
+ * @tparam InputIterator an iterator or pointer dereferencable to uint8_t
*
- * @throws This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
+ * @param [inout] begin Begin of the buffer, will be incremented to point to the first byte after
+ * the read TLV-TYPE
+ * @param [in] end End of the buffer
*
- * This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
- * is larger than 2^32-1 (type in this library is implemented as uint32_t)
+ * @throw tlv::Error VAR-NUMBER cannot be read
+ * @note This call is largely equivalent to tlv::readVarNumber, but exception will be thrown if type
+ * is larger than 2^32-1 (TLV-TYPE in this library is implemented as uint32_t)
*/
template<class InputIterator>
-inline uint32_t
+uint32_t
readType(InputIterator& begin, const InputIterator& end);
/**
* @brief Get number of bytes necessary to hold value of VAR-NUMBER
*/
-inline size_t
+constexpr size_t
sizeOfVarNumber(uint64_t varNumber);
/**
* @brief Write VAR-NUMBER to the specified stream
+ * @return length of written VAR-NUMBER
*/
-inline size_t
+size_t
writeVarNumber(std::ostream& os, uint64_t varNumber);
/**
* @brief Read nonNegativeInteger in NDN-TLV encoding
+ * @tparam InputIterator an iterator or pointer dereferencable to uint8_t
*
- * This call will throw ndn::tlv::Error (aka std::runtime_error) if number cannot be read
+ * @param [in] size size of the nonNegativeInteger
+ * @param [inout] begin Begin of the buffer, will be incremented to point to the first byte after
+ * the read nonNegativeInteger
+ * @param [in] end End of the buffer
*
- * Note that after call finished, begin will point to the first byte after the read VAR-NUMBER
- *
- * How many bytes will be read is directly controlled by the size parameter, which can be either
- * 1, 2, 4, or 8. If the value of size is different, then an exception will be thrown.
+ * @throw tlv::Error number cannot be read
+ * @note How many bytes to read is directly controlled by \p size, which can be either 1, 2, 4, or 8.
+ * If \p size differs from \p std::distance(begin, end), tlv::Error exception will be thrown.
*/
template<class InputIterator>
-inline uint64_t
+uint64_t
readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end);
/**
* @brief Get number of bytes necessary to hold value of nonNegativeInteger
*/
-inline size_t
-sizeOfNonNegativeInteger(uint64_t varNumber);
+constexpr size_t
+sizeOfNonNegativeInteger(uint64_t integer);
/**
* @brief Write nonNegativeInteger to the specified stream
+ * @return length of written nonNegativeInteger
*/
-inline size_t
-writeNonNegativeInteger(std::ostream& os, uint64_t varNumber);
+size_t
+writeNonNegativeInteger(std::ostream& os, uint64_t integer);
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
@@ -241,7 +254,7 @@
/////////////////////////////////////////////////////////////////////////////////
template<class InputIterator>
-inline bool
+bool
readVarNumber(InputIterator& begin, const InputIterator& end, uint64_t& number)
{
if (begin == end)
@@ -249,59 +262,54 @@
uint8_t firstOctet = *begin;
++begin;
- if (firstOctet < 253)
- {
- number = firstOctet;
- }
- else if (firstOctet == 253)
- {
- if (end - begin < 2)
- return false;
+ if (firstOctet < 253) {
+ number = firstOctet;
+ }
+ else if (firstOctet == 253) {
+ if (end - begin < 2)
+ return false;
- uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
- begin += 2;
- number = be16toh(value);
- }
- else if (firstOctet == 254)
- {
- if (end - begin < 4)
- return false;
+ uint16_t value = *reinterpret_cast<const uint16_t*>(&*begin);
+ begin += 2;
+ number = be16toh(value);
+ }
+ else if (firstOctet == 254) {
+ if (end - begin < 4)
+ return false;
- uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
- begin += 4;
- number = be32toh(value);
- }
- else // if (firstOctet == 255)
- {
- if (end - begin < 8)
- return false;
+ uint32_t value = *reinterpret_cast<const uint32_t*>(&*begin);
+ begin += 4;
+ number = be32toh(value);
+ }
+ else { // if (firstOctet == 255)
+ if (end - begin < 8)
+ return false;
- uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
- begin += 8;
+ uint64_t value = *reinterpret_cast<const uint64_t*>(&*begin);
+ begin += 8;
- number = be64toh(value);
- }
+ number = be64toh(value);
+ }
return true;
}
template<class InputIterator>
-inline bool
+bool
readType(InputIterator& begin, const InputIterator& end, uint32_t& type)
{
uint64_t number = 0;
bool isOk = readVarNumber(begin, end, number);
- if (!isOk || number > std::numeric_limits<uint32_t>::max())
- {
- return false;
- }
+ if (!isOk || number > std::numeric_limits<uint32_t>::max()) {
+ return false;
+ }
type = static_cast<uint32_t>(number);
return true;
}
template<class InputIterator>
-inline uint64_t
+uint64_t
readVarNumber(InputIterator& begin, const InputIterator& end)
{
if (begin == end)
@@ -326,81 +334,40 @@
uint8_t firstOctet = *begin;
++begin;
- if (firstOctet < 253)
- {
- value = firstOctet;
- }
- else if (firstOctet == 253)
- {
- value = 0;
- size_t count = 0;
- for (; begin != end && count < 2; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
+ if (firstOctet < 253) {
+ value = firstOctet;
+ return true;
+ }
- if (count != 2)
- return false;
- }
- else if (firstOctet == 254)
- {
- value = 0;
- size_t count = 0;
- for (; begin != end && count < 4; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
-
- if (count != 4)
- return false;
- }
- else // if (firstOctet == 255)
- {
- value = 0;
- size_t count = 0;
- for (; begin != end && count < 8; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
-
- if (count != 8)
- return false;
- }
-
- return true;
+ size_t expectedSize = firstOctet == 253 ? 2 :
+ firstOctet == 254 ? 4 : 8;
+ value = 0;
+ size_t count = 0;
+ for (; begin != end && count < expectedSize; ++count) {
+ value = (value << 8) | *begin;
+ ++begin;
+ }
+ return count == expectedSize;
}
template<class InputIterator>
-inline uint32_t
+uint32_t
readType(InputIterator& begin, const InputIterator& end)
{
uint64_t type = readVarNumber(begin, end);
- if (type > std::numeric_limits<uint32_t>::max())
- {
- BOOST_THROW_EXCEPTION(Error("TLV type code exceeds allowed maximum"));
- }
+ if (type > std::numeric_limits<uint32_t>::max()) {
+ BOOST_THROW_EXCEPTION(Error("TLV-TYPE code exceeds allowed maximum"));
+ }
return static_cast<uint32_t>(type);
}
-size_t
+constexpr size_t
sizeOfVarNumber(uint64_t varNumber)
{
- if (varNumber < 253) {
- return 1;
- }
- else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
- return 3;
- }
- else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
- return 5;
- }
- else {
- return 9;
- }
+ return varNumber < 253 ? 1 :
+ varNumber <= std::numeric_limits<uint16_t>::max() ? 3 :
+ varNumber <= std::numeric_limits<uint32_t>::max() ? 5 : 9;
}
inline size_t
@@ -431,12 +398,11 @@
}
template<class InputIterator>
-inline uint64_t
+uint64_t
readNonNegativeInteger(size_t size, InputIterator& begin, const InputIterator& end)
{
switch (size) {
- case 1:
- {
+ case 1: {
if (end - begin < 1)
BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
@@ -444,8 +410,7 @@
begin++;
return value;
}
- case 2:
- {
+ case 2: {
if (end - begin < 2)
BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
@@ -453,8 +418,7 @@
begin += 2;
return be16toh(value);
}
- case 4:
- {
+ case 4: {
if (end - begin < 4)
BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
@@ -462,8 +426,7 @@
begin += 4;
return be32toh(value);
}
- case 8:
- {
+ case 8: {
if (end - begin < 8)
BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
@@ -472,111 +435,62 @@
return be64toh(value);
}
}
- BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
+ BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
+ "(only 1, 2, 4, and 8 are allowed)"));
}
template<>
inline uint64_t
-readNonNegativeInteger<std::istream_iterator<uint8_t> >(size_t size,
- std::istream_iterator<uint8_t>& begin,
- const std::istream_iterator<uint8_t>& end)
+readNonNegativeInteger<std::istream_iterator<uint8_t>>(size_t size,
+ std::istream_iterator<uint8_t>& begin,
+ const std::istream_iterator<uint8_t>& end)
{
- switch (size) {
- case 1:
- {
- if (begin == end)
- BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
-
- uint64_t value = *begin;
- begin++;
- return value;
- }
- case 2:
- {
- uint64_t value = 0;
- size_t count = 0;
- for (; begin != end && count < 2; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
-
- if (count != 2)
- BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
-
- return value;
- }
- case 4:
- {
- uint64_t value = 0;
- size_t count = 0;
- for (; begin != end && count < 4; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
-
- if (count != 4)
- BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
-
- return value;
- }
- case 8:
- {
- uint64_t value = 0;
- size_t count = 0;
- for (; begin != end && count < 8; ++count)
- {
- value = ((value << 8) | *begin);
- begin++;
- }
-
- if (count != 8)
- BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
-
- return value;
- }
+ if (size != 1 && size != 2 && size != 4 && size != 8) {
+ BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger "
+ "(only 1, 2, 4, and 8 are allowed)"));
}
- BOOST_THROW_EXCEPTION(Error("Invalid length for nonNegativeInteger (only 1, 2, 4, and 8 are allowed)"));
+
+ uint64_t value = 0;
+ size_t count = 0;
+ for (; begin != end && count < size; ++count) {
+ value = (value << 8) | *begin;
+ begin++;
+ }
+
+ if (count != size) {
+ BOOST_THROW_EXCEPTION(Error("Insufficient data during TLV processing"));
+ }
+
+ return value;
+}
+
+constexpr size_t
+sizeOfNonNegativeInteger(uint64_t integer)
+{
+ return integer <= std::numeric_limits<uint8_t>::max() ? 1 :
+ integer <= std::numeric_limits<uint16_t>::max() ? 2 :
+ integer <= std::numeric_limits<uint32_t>::max() ? 4 : 8;
}
inline size_t
-sizeOfNonNegativeInteger(uint64_t varNumber)
+writeNonNegativeInteger(std::ostream& os, uint64_t integer)
{
- if (varNumber < 253) {
+ if (integer <= std::numeric_limits<uint8_t>::max()) {
+ os.put(static_cast<char>(integer));
return 1;
}
- else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
- return 2;
- }
- else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
- return 4;
- }
- else {
- return 8;
- }
-}
-
-
-inline size_t
-writeNonNegativeInteger(std::ostream& os, uint64_t varNumber)
-{
- if (varNumber < 253) {
- os.put(static_cast<char>(varNumber));
- return 1;
- }
- else if (varNumber <= std::numeric_limits<uint16_t>::max()) {
- uint16_t value = htobe16(static_cast<uint16_t>(varNumber));
+ else if (integer <= std::numeric_limits<uint16_t>::max()) {
+ uint16_t value = htobe16(static_cast<uint16_t>(integer));
os.write(reinterpret_cast<const char*>(&value), 2);
return 2;
}
- else if (varNumber <= std::numeric_limits<uint32_t>::max()) {
- uint32_t value = htobe32(static_cast<uint32_t>(varNumber));
+ else if (integer <= std::numeric_limits<uint32_t>::max()) {
+ uint32_t value = htobe32(static_cast<uint32_t>(integer));
os.write(reinterpret_cast<const char*>(&value), 4);
return 4;
}
else {
- uint64_t value = htobe64(varNumber);
+ uint64_t value = htobe64(integer);
os.write(reinterpret_cast<const char*>(&value), 8);
return 8;
}