name: Make use of naming conventions for segment, version, timestamp, and sequence number encoding
Change-Id: I99fe3965b2a4797bd14b6966b1d1d7d8fc530aef
Refs: #1761
diff --git a/src/name-component.hpp b/src/name-component.hpp
index a9be6a8..7213f9a 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -28,13 +28,22 @@
#include "common.hpp"
#include "encoding/block.hpp"
-#include "encoding/block-helpers.hpp"
-#include "encoding/encoding-buffer.hpp"
-#include "util/string-helper.hpp"
+#include "util/time.hpp"
namespace ndn {
namespace name {
+/// @brief Segment marker for NDN naming conventions
+static const uint8_t SEGMENT_MARKER = 0x00;
+/// @brief Segment offset marker for NDN naming conventions
+static const uint8_t SEGMENT_OFFSET_MARKER = 0xFB;
+/// @brief Version marker for NDN naming conventions
+static const uint8_t VERSION_MARKER = 0xFD;
+/// @brief Timestamp marker for NDN naming conventions
+static const uint8_t TIMESTAMP_MARKER = 0xFC;
+/// @brief Sequence number marker for NDN naming conventions
+static const uint8_t SEQUENCE_NUMBER_MARKER = 0xFE;
+
/**
* @brief Component holds a read-only name component value.
*/
@@ -244,12 +253,7 @@
* @return The escaped string
*/
std::string
- toUri() const
- {
- std::ostringstream os;
- toUri(os);
- return os.str();
- }
+ toUri() const;
/**
* @brief Interpret this name component as nonNegativeInteger
@@ -262,18 +266,74 @@
toNumber() const;
/**
- * @brief An alias for toNumber()
+ * @brief Interpret this name component as NameComponentWithMarker
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @param marker 1-byte octet of the marker
+ * @return The integer number.
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
+ */
+ uint64_t
+ toNumberWithMarker(uint8_t marker) const;
+
+ /**
+ * @brief Interpret as version component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
*/
uint64_t
toVersion() const;
/**
- * @brief An alias for toNumber()
+ * @brief Interpret as segment number component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
*/
uint64_t
toSegment() const;
/**
+ * @brief Interpret as segment offset component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
+ */
+ uint64_t
+ toSegmentOffset() const;
+
+ /**
+ * @brief Interpret as timestamp component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
+ */
+ time::system_clock::TimePoint
+ toTimestamp() const;
+
+ /**
+ * @brief Interpret as sequence number component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @throws Error if name component does not have the specified marker.
+ * tlv::Error if format does not follow NameComponentWithMarker specification.
+ */
+ uint64_t
+ toSequenceNumber() const;
+
+ /**
* @brief Create a component encoded as nonNegativeInteger
*
* @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
@@ -284,6 +344,70 @@
static Component
fromNumber(uint64_t number);
+ /**
+ * @brief Create a component encoded as NameComponentWithMarker
+ *
+ * NameComponentWithMarker is defined as:
+ *
+ * NameComponentWithMarker ::= NAME-COMPONENT-TYPE TLV-LEGTH
+ * Marker
+ * includedNonNegativeInteger
+ * Marker ::= BYTE
+ * includedNonNegativeInteger ::= BYTE{1,2,4,8}
+ * NDN-TLV := TLV-TYPE TLV-LENGTH TLV-VALUE?
+ * TLV-TYPE := VAR-NUMBER
+ * TLV-LENGTH := VAR-NUMBER
+ * TLV-VALUE := BYTE+
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ *
+ * @param marker 1-byte marker octet
+ * @param number The non-negative number
+ * @return The component value.
+ */
+ static Component
+ fromNumberWithMarker(uint8_t marker, uint64_t number);
+
+ /**
+ * @brief Create version component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ */
+ static Component
+ fromVersion(uint64_t version);
+
+ /**
+ * @brief Create segment number component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ */
+ static Component
+ fromSegment(uint64_t segmentNo);
+
+ /**
+ * @brief Create segment offset component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ */
+ static Component
+ fromSegmentOffset(uint64_t offset);
+
+ /**
+ * @brief Create sequence number component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ */
+ static Component
+ fromTimestamp(const time::system_clock::TimePoint& timePoint);
+
+ /**
+ * @brief Create sequence number component using NDN naming conventions
+ *
+ * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+ */
+ static Component
+ fromSequenceNumber(uint64_t seqNo);
+
bool
empty() const
{
@@ -408,38 +532,6 @@
return os;
}
-inline
-Component::Component()
- : Block(tlv::NameComponent)
-{
-}
-
-inline
-Component::Component(const Block& wire)
- : Block(wire)
-{
- if (type() != tlv::NameComponent)
- throw Error("Constructing name component from non name component TLV wire block");
-}
-
-inline
-Component::Component(const ConstBufferPtr& buffer)
- : Block(tlv::NameComponent, buffer)
-{
-}
-
-inline
-Component::Component(const Buffer& value)
- : Block(dataBlock(tlv::NameComponent, value.buf(), value.size()))
-{
-}
-
-inline
-Component::Component(const uint8_t* value, size_t valueLen)
- : Block(dataBlock(tlv::NameComponent, value, valueLen))
-{
-}
-
template<class InputIterator>
inline
Component::Component(InputIterator begin, InputIterator end)
@@ -447,195 +539,6 @@
{
}
-inline
-Component::Component(const char* str)
- : Block(dataBlock(tlv::NameComponent, str, ::strlen(str)))
-{
-}
-
-inline
-Component::Component(const std::string& str)
- : Block(dataBlock(tlv::NameComponent, str.c_str(), str.size()))
-{
-}
-
-
-inline Component
-Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
-{
- std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
- trim(trimmedString);
- std::string value = unescape(trimmedString);
-
- if (value.find_first_not_of(".") == std::string::npos) {
- // Special case for component of only periods.
- if (value.size() <= 2)
- // Zero, one or two periods is illegal. Ignore this component.
- return Component();
- else
- // Remove 3 periods.
- return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
- }
- else
- return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
-}
-
-
-inline void
-Component::toUri(std::ostream& result) const
-{
- const uint8_t* valuePtr = value();
- size_t valueSize = value_size();
-
- bool gotNonDot = false;
- for (unsigned i = 0; i < valueSize; ++i) {
- if (valuePtr[i] != 0x2e) {
- gotNonDot = true;
- break;
- }
- }
- if (!gotNonDot) {
- // Special case for component of zero or more periods. Add 3 periods.
- result << "...";
- for (size_t i = 0; i < valueSize; ++i)
- result << '.';
- }
- else {
- // In case we need to escape, set to upper case hex and save the previous flags.
- std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
-
- for (size_t i = 0; i < valueSize; ++i) {
- uint8_t x = valuePtr[i];
- // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
- if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
- (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
- x == 0x2e || x == 0x5f)
- result << x;
- else {
- result << '%';
- if (x < 16)
- result << '0';
- result << static_cast<unsigned int>(x);
- }
- }
-
- // Restore.
- result.flags(saveFlags);
- }
-}
-
-
-inline Component
-Component::fromNumber(uint64_t number)
-{
- /// \todo Change to tlv::NumberComponent
- return nonNegativeIntegerBlock(tlv::NameComponent, number);
-}
-
-
-inline uint64_t
-Component::toNumber() const
-{
- /// \todo Check if Component is of tlv::NumberComponent type
- return readNonNegativeInteger(static_cast<const Block&>(*this));
-}
-
-
-inline uint64_t
-Component::toVersion() const
-{
- return toNumber();
-}
-
-inline uint64_t
-Component::toSegment() const
-{
- return toNumber();
-}
-
-inline int
-Component::compare(const Component& other) const
-{
- // Imitate ndn_Exclude_compareComponents.
- if (value_size() < other.value_size())
- return -1;
- if (value_size() > other.value_size())
- return 1;
-
- if (value_size() == 0)
- return 0;
-
- // The components are equal length. Just do a byte compare.
- return std::memcmp(value(), other.value(), value_size());
-}
-
-inline Component
-Component::getSuccessor() const
-{
- size_t totalLength = 0;
- EncodingBuffer encoder(size() + 1, 1); // + 1 in case there is an overflow
- // in unlikely case TLV length changes more,
- // EncodingBuffer will take care of that
-
- bool isOverflow = true;
- size_t i = value_size();
- for (; isOverflow && i > 0; i--) {
- uint8_t newValue = static_cast<uint8_t>((value()[i - 1] + 1) & 0xFF);
- totalLength += encoder.prependByte(newValue);
- isOverflow = (newValue == 0);
- }
- totalLength += encoder.prependByteArray(value(), i);
-
- if (isOverflow) {
- // new name components has to be extended
- totalLength += encoder.appendByte(0);
- }
-
- totalLength += encoder.prependVarNumber(totalLength);
- totalLength += encoder.prependVarNumber(tlv::NameComponent);
-
- return encoder.block();
-}
-
-
-template<bool T>
-inline size_t
-Component::wireEncode(EncodingImpl<T>& block) const
-{
- size_t totalLength = 0;
- if (value_size() > 0)
- totalLength += block.prependByteArray(value(), value_size());
- totalLength += block.prependVarNumber(value_size());
- totalLength += block.prependVarNumber(tlv::NameComponent);
- return totalLength;
-}
-
-inline const Block&
-Component::wireEncode() const
-{
- if (this->hasWire())
- return *this;
-
- EncodingEstimator estimator;
- size_t estimatedSize = wireEncode(estimator);
-
- EncodingBuffer buffer(estimatedSize, 0);
- wireEncode(buffer);
-
- const_cast<Component&>(*this) = buffer.block();
- return *this;
-}
-
-inline void
-Component::wireDecode(const Block& wire)
-{
- if (wire.type() != tlv::NameComponent)
- throw Error("wireDecode name component from non name component TLV wire block");
-
- *this = wire;
-}
-
-
} // namespace name
} // namespace ndn