name-component: recognize typed name components
refs #4526
Change-Id: I9d32a5dc216c6b0921d181573a4e043fccc2814e
diff --git a/src/name-component.hpp b/src/name-component.hpp
index c537eb1..4e3563c 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2013-2017 Regents of the University of California.
+ * Copyright (c) 2013-2018 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -41,15 +41,15 @@
/// @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.
+/** @brief Represents a name component.
+ *
+ * The @c Component class provides a read-only view of a @c Block interpreted as a name component.
+ * Although it inherits mutation methods from @c Block base class, they must not be used, because
+ * the enclosing @c Name would not be updated correctly.
*/
class Component : public Block
{
public:
- /**
- * @brief Error that can be thrown from name::Component
- */
class Error : public Block::Error
{
public:
@@ -60,91 +60,114 @@
}
};
+public: // constructors
/**
- * Create a new name::Component with an empty value
+ * @brief Construct a NameComponent of @p type, using empty TLV-VALUE.
+ * @throw Error the NameComponent is invalid (see @c ensureValid).
*/
- Component();
+ explicit
+ Component(uint32_t type = tlv::GenericNameComponent);
/**
- * @brief Create name::Component from a wire block
+ * @brief Construct a NameComponent from @p block.
+ * @throw Error the NameComponent is invalid (see @c ensureValid).
*
- * @param wire tlv::NameComponent Block from which to create name::Component
- * @throws Error if wire.type() is not tlv::NameComponent
- *
- * Any block can be implicitly converted to name::Component
+ * This contructor enables implicit conversion from @c Block.
*/
Component(const Block& wire);
/**
- * @brief Create a new name::Component from the buffer pointer (buffer pointer will be copied)
+ * @brief Construct a NameComponent of @p type, using TLV-VALUE from @p buffer.
+ * @throw Error the NameComponent is invalid (see @c ensureValid).
*
- * @param buffer A pointer to an immutable buffer
+ * This constructor does not copy the underlying buffer, but retains a pointer to it.
+ * Therefore, the caller must not change the underlying buffer.
+ */
+ Component(uint32_t type, ConstBufferPtr buffer);
+
+ /**
+ * @brief Construct a GenericNameComponent, using TLV-VALUE from @p buffer.
+ * @throw Error the NameComponent is invalid (see @c ensureValid).
*
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will not** allocate new memory for and copy the payload until
- * toWire() method is called.
+ * This constructor does not copy the underlying buffer, but retains a pointer to it.
+ * Therefore, the caller must not change the underlying buffer.
*/
explicit
- Component(const ConstBufferPtr& buffer);
+ Component(ConstBufferPtr buffer)
+ : Component(tlv::GenericNameComponent, std::move(buffer))
+ {
+ }
/**
- * @brief Create a new name::Component from the buffer (data from buffer will be copied)
- * @param buffer A reference to the buffer
- *
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will** allocate new memory for and copy the payload.
+ * @brief Construct a NameComponent of @p type, copying TLV-VALUE from @p buffer.
+ */
+ Component(uint32_t type, const Buffer& buffer)
+ : Component(type, buffer.data(), buffer.size())
+ {
+ }
+
+ /**
+ * @brief Construct a GenericNameComponent, copying TLV-VALUE from @p buffer.
*/
explicit
- Component(const Buffer& buffer);
+ Component(const Buffer& buffer)
+ : Component(tlv::GenericNameComponent, buffer)
+ {
+ }
/**
- * @brief Create a new name::Component from the buffer (data from buffer will be copied)
- * @param buffer A pointer to the first byte of the buffer
- * @param bufferSize Size of the buffer
- *
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will** allocate new memory for and copy the payload.
+ * @brief Construct a NameComponent of @p type, copying @p count bytes at @p value as TLV-VALUE.
*/
- Component(const uint8_t* buffer, size_t bufferSize);
+ Component(uint32_t type, const uint8_t* value, size_t count);
/**
- * @brief Create a new name::Component frome the range [@p first, @p last) of bytes
- * @param first Iterator pointing to the beginning of the buffer
- * @param last Iterator pointing to the ending of the buffer
- * @tparam Iterator iterator type satisfying at least InputIterator concept. Implementation
- * is more optimal when the iterator type satisfies RandomAccessIterator concept.
- * It is required that sizeof(std::iterator_traits<Iterator>::value_type) == 1.
- *
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will** allocate new memory for and copy the payload.
+ * @brief Construct a GenericNameComponent, copying @p count bytes at @p value as TLV-VALUE.
+ */
+ Component(const uint8_t* value, size_t count)
+ : Component(tlv::GenericNameComponent, value, count)
+ {
+ }
+
+ /**
+ * @brief Construct a NameComponent of @p type, copying TLV-VALUE from a range.
+ * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
+ * implementation is available when it is a @c RandomAccessIterator.
+ * @param type the TLV-TYPE.
+ * @param first beginning of the range.
+ * @param last past-end of the range.
*/
template<class Iterator>
- Component(Iterator first, Iterator last);
+ Component(uint32_t type, Iterator first, Iterator last)
+ : Block(makeBinaryBlock(type, first, last))
+ {
+ }
/**
- * @brief Create a new name::Component from the C string (data from string will be copied)
+ * @brief Construct a GenericNameComponent, copying TLV-VALUE from a range.
+ */
+ template<class Iterator>
+ Component(Iterator first, Iterator last)
+ : Component(tlv::GenericNameComponent, first, last)
+ {
+ }
+
+ /**
+ * @brief Construct a GenericNameComponent, copying TLV-VALUE from a null-terminated string.
*
- * @param str Zero-ended string. Note that this string will be interpreted as is (i.e.,
- * it will not be interpreted as URI)
- *
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will** allocate new memory for and copy the payload.
+ * Bytes from the string are copied as is, and not interpreted as URI component.
*/
explicit
Component(const char* str);
/**
- * @brief Create a new name::Component from the STL string (data from string will be copied)
+ * @brief Construct a GenericNameComponent, copying TLV-VALUE from a string.
*
- * @param str Const reference to STL string. Note that this string will be interpreted
- * as is (i.e., it will not be interpreted as URI)
- *
- * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
- * Note that this method **will** allocate new memory for and copy the payload.
+ * Bytes from the string are copied as is, and not interpreted as URI component.
*/
explicit
Component(const std::string& str);
+public: // encoding and URI
/**
* @brief Fast encoding or block size estimation
*/
@@ -165,45 +188,36 @@
wireDecode(const Block& wire);
/**
- * @brief Create name::Component by decoding the escapedString between beginOffset and
- * endOffset according to the NDN URI Scheme.
+ * @brief Decode NameComponent from a URI component.
*
- * If the escaped string is "", "." or ".." then return an empty name::Component. Note
- * that an empty name::Component should not be added to Name and if attempted, an
- * exception will be thrown.
+ * The URI component is read from `[input+beginOffset, input+endOffset)` range.
*
- * @param escapedString String containing NDN URI-encoded name
- * component. [escapedString+beginOffset, beginOffset+endOffset)
- * must be a valid memory buffer.
- * @param beginOffset The offset in escapedString of the beginning of the portion to decode.
- * @param endOffset The offset in escapedString of the end of the portion to decode.
+ * @throw Error URI component does not represent a valid NameComponent.
*/
static Component
- fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset);
-
- /**
- * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
- *
- * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
- */
- static Component
- fromEscapedString(const char* escapedString)
+ fromEscapedString(const char* input, size_t beginOffset, size_t endOffset)
{
- return fromEscapedString(escapedString, 0, std::char_traits<char>::length(escapedString));
+ return fromEscapedString(std::string(input + beginOffset, input + endOffset));
}
/**
- * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
- *
- * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
+ * @brief Decode NameComponent from a URI component.
+ * @throw Error URI component does not represent a valid NameComponent.
*/
static Component
- fromEscapedString(const std::string& escapedString)
+ fromEscapedString(const char* input)
{
- return fromEscapedString(escapedString.c_str(), 0, escapedString.size());
+ return fromEscapedString(std::string(input));
}
/**
+ * @brief Decode NameComponent from a URI component.
+ * @throw Error URI component does not represent a valid NameComponent.
+ */
+ static Component
+ fromEscapedString(std::string input);
+
+ /**
* @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
*
* This also adds "..." to a value with zero or more "."
@@ -223,8 +237,7 @@
std::string
toUri() const;
- ////////////////////////////////////////////////////////////////////////////////
-
+public: // naming conventions
/**
* @brief Check if the component is nonNegativeInteger
* @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
@@ -274,8 +287,6 @@
bool
isSequenceNumber() const;
- ////////////////////////////////////////////////////////////////////////////////
-
/**
* @brief Interpret this name component as nonNegativeInteger
*
@@ -354,8 +365,6 @@
uint64_t
toSequenceNumber() const;
- ////////////////////////////////////////////////////////////////////////////////
-
/**
* @brief Create a component encoded as nonNegativeInteger
*
@@ -431,8 +440,7 @@
static Component
fromSequenceNumber(uint64_t seqNo);
- ////////////////////////////////////////////////////////////////////////////////
-
+public: // commonly used TLV-TYPEs
/**
* @brief Check if the component is GenericComponent
*/
@@ -457,8 +465,7 @@
static Component
fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize);
- ////////////////////////////////////////////////////////////////////////////////
-
+public: // operators
bool
empty() const
{
@@ -561,6 +568,16 @@
Component
getSuccessor() const;
+private:
+ /**
+ * @brief Throw @c Error if this NameComponent is invalid.
+ *
+ * A NameComponent is invalid if its TLV-TYPE is outside the 1-65535 range.
+ * Additionally, if this is an ImplicitSha256DigestComponent, the TLV-LENGTH must be 32.
+ */
+ void
+ ensureValid() const;
+
// !!! NOTE TO IMPLEMENTOR !!!
//
// This class MUST NOT contain any data fields.
@@ -576,13 +593,6 @@
return os;
}
-template<class Iterator>
-inline
-Component::Component(Iterator first, Iterator last)
- : Block(makeBinaryBlock(tlv::NameComponent, first, last))
-{
-}
-
} // namespace name
} // namespace ndn