| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (c) 2013-2014 Regents of the University of California. |
| * |
| * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions). |
| * |
| * ndn-cxx library is free software: you can redistribute it and/or modify it under the |
| * terms of the GNU Lesser General Public License as published by the Free Software |
| * Foundation, either version 3 of the License, or (at your option) any later version. |
| * |
| * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
| * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
| * |
| * You should have received copies of the GNU General Public License and GNU Lesser |
| * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see |
| * <http://www.gnu.org/licenses/>. |
| * |
| * See AUTHORS.md for complete list of ndn-cxx authors and contributors. |
| * |
| * @author Jeff Thompson <jefft0@remap.ucla.edu> |
| * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html> |
| * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/> |
| */ |
| |
| #ifndef NDN_NAME_COMPONENT_HPP |
| #define NDN_NAME_COMPONENT_HPP |
| |
| #include "common.hpp" |
| #include "encoding/block.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. |
| */ |
| class Component : public Block |
| { |
| public: |
| /** |
| * @brief Error that can be thrown from name::Component |
| */ |
| class Error : public Block::Error |
| { |
| public: |
| explicit |
| Error(const std::string& what) |
| : Block::Error(what) |
| { |
| } |
| }; |
| |
| /** |
| * Create a new name::Component with an empty value |
| */ |
| Component(); |
| |
| /** |
| * @brief Create name::Component from a wire block |
| * |
| * @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 |
| */ |
| Component(const Block& wire); |
| |
| /** |
| * @brief Create a new name::Component from the buffer pointer (buffer pointer will be copied) |
| * |
| * @param buffer A pointer to an immutable buffer |
| * |
| * 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. |
| */ |
| explicit |
| Component(const ConstBufferPtr& 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. |
| */ |
| explicit |
| Component(const Buffer& 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. |
| */ |
| Component(const uint8_t* buffer, size_t bufferSize); |
| |
| /** |
| * @brief Create a new name::Component from the buffer (data from buffer will be copied) |
| * @param begin Iterator pointing to the beginning of the buffer |
| * @param end Iterator pointing to the ending 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. |
| */ |
| template<class InputIterator> |
| Component(InputIterator begin, InputIterator end); |
| |
| /** |
| * @brief Create a new name::Component from the C string (data from string will be copied) |
| * |
| * @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. |
| */ |
| explicit |
| Component(const char* str); |
| |
| /** |
| * @brief Create a new name::Component from the STL string (data from string will be copied) |
| * |
| * @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. |
| */ |
| explicit |
| Component(const std::string& str); |
| |
| /** |
| * @brief Fast encoding or block size estimation |
| */ |
| template<bool T> |
| size_t |
| wireEncode(EncodingImpl<T>& block) const; |
| |
| /** |
| * @brief Encode to a wire format |
| */ |
| const Block& |
| wireEncode() const; |
| |
| /** |
| * @brief Decode from the wire format |
| */ |
| void |
| wireDecode(const Block& wire); |
| |
| /** |
| * @brief Create name::Component by decoding the escapedString between beginOffset and |
| * endOffset according to the NDN URI Scheme. |
| * |
| * 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. |
| * |
| * @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. |
| */ |
| 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) |
| { |
| return fromEscapedString(escapedString, 0, std::char_traits<char>::length(escapedString)); |
| } |
| |
| /** |
| * @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 std::string& escapedString) |
| { |
| return fromEscapedString(escapedString.c_str(), 0, escapedString.size()); |
| } |
| |
| /** |
| * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme |
| * |
| * @deprecated Use toUri(std::ostream&) instead |
| * |
| * This also adds "..." to a value with zero or more "." |
| * |
| * @param os The output stream to where write the URI escaped version *this |
| */ |
| DEPRECATED( |
| void |
| toEscapedString(std::ostream& os) const) |
| { |
| return toUri(os); |
| } |
| |
| /** |
| * @brief Convert *this by escaping characters according to the NDN URI Scheme |
| * |
| * @deprecated Use toUri() instead |
| * |
| * This also adds "..." to a value with zero or more "." |
| * |
| * @return The escaped string |
| */ |
| DEPRECATED( |
| std::string |
| toEscapedString() const) |
| { |
| return toUri(); |
| } |
| |
| /** |
| * @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 "." |
| * |
| * @param os The output stream to where write the URI escaped version *this |
| */ |
| void |
| toUri(std::ostream& os) const; |
| |
| /** |
| * @brief Convert *this by escaping characters according to the NDN URI Scheme |
| * |
| * This also adds "..." to a value with zero or more "." |
| * |
| * @return The escaped string |
| */ |
| std::string |
| toUri() const; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * @brief Check if the component is nonNegativeInteger |
| * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding |
| */ |
| bool |
| isNumber() const; |
| |
| /** |
| * @brief Check if the component is NameComponentWithMarker per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isNumberWithMarker(uint8_t marker) const; |
| |
| /** |
| * @brief Check if the component is version per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isVersion() const; |
| |
| /** |
| * @brief Check if the component is segment number per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isSegment() const; |
| |
| /** |
| * @brief Check if the component is segment offset per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isSegmentOffset() const; |
| |
| /** |
| * @brief Check if the component is timestamp per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isTimestamp() const; |
| |
| /** |
| * @brief Check if the component is sequence number per NDN naming conventions |
| * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf |
| */ |
| bool |
| isSequenceNumber() const; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * @brief Interpret this name component as nonNegativeInteger |
| * |
| * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding |
| * |
| * @return The integer number. |
| */ |
| uint64_t |
| toNumber() const; |
| |
| /** |
| * @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 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 |
| * |
| * @param number The non-negative number |
| * @return The component value. |
| */ |
| 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); |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * @brief Check if the component is GenericComponent |
| */ |
| bool |
| isGeneric() const; |
| |
| /** |
| * @brief Check if the component is ImplicitSha256DigestComponent |
| */ |
| bool |
| isImplicitSha256Digest() const; |
| |
| /** |
| * @brief Create ImplicitSha256DigestComponent component |
| */ |
| static Component |
| fromImplicitSha256Digest(const ConstBufferPtr& digest); |
| |
| /** |
| * @brief Create ImplicitSha256DigestComponent component |
| */ |
| static Component |
| fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize); |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| bool |
| empty() const |
| { |
| return !hasValue(); |
| } |
| |
| Component |
| getSuccessor() const; |
| |
| /** |
| * @brief Check if this is the same component as other |
| * |
| * @param other The other Component to compare with |
| * @return true if the components are equal, otherwise false. |
| */ |
| bool |
| equals(const Component& other) const |
| { |
| if (value_size() != other.value_size()) |
| return false; |
| if (value_size() == 0 /* == other.value_size()*/) |
| return true; |
| |
| // somehow, behavior is wrong on OSX 10.9 when component is empty |
| // (probably some bug in STL...) |
| return std::equal(value_begin(), value_end(), other.value_begin()); |
| } |
| |
| /** |
| * @brief Compare this to the other Component using NDN canonical ordering |
| * |
| * @param other The other Component to compare with. |
| * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or |
| * 1 if *this comes after other in the canonical ordering. |
| * |
| * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order |
| */ |
| int |
| compare(const Component& other) const; |
| |
| /** |
| * @brief Check if this is the same component as other |
| * |
| * @param other The other Component to compare with. |
| * @return true if the components are equal, otherwise false. |
| */ |
| bool |
| operator==(const Component& other) const |
| { |
| return equals(other); |
| } |
| |
| /** |
| * @brief Check if this is not the same component as other |
| * @param other The other Component to compare with |
| * @return true if the components are not equal, otherwise false |
| */ |
| bool |
| operator!=(const Component& other) const |
| { |
| return !equals(other); |
| } |
| |
| /** |
| * @brief Check if the *this is less than or equal to the other in NDN canonical ordering |
| * @param other The other Component to compare with |
| * |
| * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order |
| */ |
| bool |
| operator<=(const Component& other) const |
| { |
| return compare(other) <= 0; |
| } |
| |
| /** |
| * @brief Check if the *this is less than the other in NDN canonical ordering |
| * @param other The other Component to compare with |
| * |
| * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order |
| */ |
| bool |
| operator<(const Component& other) const |
| { |
| return compare(other) < 0; |
| } |
| |
| /** |
| * @brief Check if the *this is greater or equal than the other in NDN canonical ordering |
| * @param other The other Component to compare with |
| * |
| * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order |
| */ |
| bool |
| operator>=(const Component& other) const |
| { |
| return compare(other) >= 0; |
| } |
| |
| /** |
| * @brief Check if the *this is greater than the other in NDN canonical ordering |
| * @param other The other Component to compare with |
| * |
| * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order |
| */ |
| bool |
| operator>(const Component& other) const |
| { |
| return compare(other) > 0; |
| } |
| |
| // !!! NOTE TO IMPLEMENTOR !!! |
| // |
| // This class MUST NOT contain any data fields. |
| // Block can be reinterpret_cast'ed as Component type. |
| }; |
| |
| inline std::ostream& |
| operator<<(std::ostream& os, const Component& component) |
| { |
| component.toUri(os); |
| return os; |
| } |
| |
| template<class InputIterator> |
| inline |
| Component::Component(InputIterator begin, InputIterator end) |
| : Block(dataBlock(tlv::NameComponent, begin, end)) |
| { |
| } |
| |
| } // namespace name |
| } // namespace ndn |
| |
| #endif // NDN_NAME_COMPONENT_HPP |