name: Optimization of Name implementation
Now, Name directly uses Block as underlying storage for name components
and name::Components (aka Name::Components) class is a helper wrapped on
top of Block class.
Change-Id: I15ca58cc6dba76dd02e973709b7b153c2613de51
refs: #1171
diff --git a/src/encoding/block.hpp b/src/encoding/block.hpp
index da81e64..f515727 100644
--- a/src/encoding/block.hpp
+++ b/src/encoding/block.hpp
@@ -348,12 +348,12 @@
for (element_iterator i = m_subBlocks.begin();
i != m_subBlocks.end();
++i)
- {
+ {
if (i->type() != type)
newContainer.push_back(*i);
- }
+ }
m_subBlocks.swap(newContainer);
-}
+ }
inline Block::element_iterator
Block::erase(Block::element_iterator position)
diff --git a/src/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index eac26f9..8870941 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -24,8 +24,8 @@
namespace ndn {
namespace encoding {
-const bool Buffer = true;
-const bool Estimator = false;
+static const bool Buffer = true;
+static const bool Estimator = false;
} // encoding
template<bool isRealEncoderNotEstimator>
@@ -91,9 +91,6 @@
prependByteArray (const uint8_t *arr, size_t len);
inline size_t
- prependBuffer (const Buffer& arr);
-
- inline size_t
prependNonNegativeInteger (uint64_t varNumber);
inline size_t
@@ -106,9 +103,6 @@
appendByteArray (const uint8_t *arr, size_t len);
inline size_t
- appendBuffer (const Buffer& arr);
-
- inline size_t
appendNonNegativeInteger (uint64_t varNumber);
inline size_t
@@ -158,9 +152,6 @@
prependByteArray (const uint8_t *arr, size_t len);
inline size_t
- prependBuffer (const Buffer& arr);
-
- inline size_t
prependNonNegativeInteger (uint64_t varNumber);
inline size_t
@@ -173,9 +164,6 @@
appendByteArray (const uint8_t *arr, size_t len);
inline size_t
- appendBuffer (const Buffer& arr);
-
- inline size_t
appendNonNegativeInteger (uint64_t varNumber);
inline size_t
@@ -324,24 +312,6 @@
}
inline size_t
-EncodingImpl<encoding::Buffer>::prependBuffer (const Buffer& arr)
-{
- if ((m_buffer->begin () + arr.size ()) > m_begin)
- resize (m_buffer->size () * 2 + arr.size (), true);
-
- m_begin -= arr.size ();
- std::copy (arr.begin (), arr.end (), m_begin);
- return arr.size ();
-}
-
-inline size_t
-EncodingImpl<encoding::Estimator>::prependBuffer (const Buffer& arr)
-{
- m_size += arr.size ();
- return arr.size ();
-}
-
-inline size_t
EncodingImpl<encoding::Buffer>::prependNonNegativeInteger (uint64_t varNumber)
{
if (varNumber < 253) {
@@ -469,23 +439,6 @@
}
inline size_t
-EncodingImpl<encoding::Buffer>::appendBuffer (const Buffer& arr)
-{
- if ((m_end + arr.size ()) > m_buffer->end ())
- resize (m_buffer->size () * 2 + arr.size (), false);
-
- std::copy (arr.begin (), arr.end (), m_end);
- m_end -= arr.size ();
- return arr.size ();
-}
-
-inline size_t
-EncodingImpl<encoding::Estimator>::appendBuffer (const Buffer& arr)
-{
- return prependBuffer(arr);
-}
-
-inline size_t
EncodingImpl<encoding::Buffer>::appendNonNegativeInteger (uint64_t varNumber)
{
if (varNumber < 253) {
diff --git a/src/exclude.cpp b/src/exclude.cpp
index 677548c..11edd82 100644
--- a/src/exclude.cpp
+++ b/src/exclude.cpp
@@ -186,8 +186,8 @@
{
OBufferStream os;
Tlv::writeVarNumber(os, Tlv::NameComponent);
- Tlv::writeVarNumber(os, i->first.getValue().size());
- os.write(reinterpret_cast<const char *>(i->first.getValue().buf()), i->first.getValue().size());
+ Tlv::writeVarNumber(os, i->first.value_size());
+ os.write(reinterpret_cast<const char *>(i->first.value()), i->first.value_size());
wire_.push_back(Block(os.buf()));
diff --git a/src/name-component.cpp b/src/name-component.cpp
new file mode 100644
index 0000000..3956e80
--- /dev/null
+++ b/src/name-component.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "name-component.hpp"
+
+#include "util/time.hpp"
+#include "util/string-helper.hpp"
+
+namespace ndn {
+namespace name {
+
+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((const uint8_t *)&value[3], value.size() - 3);
+ }
+ else
+ return Component((const uint8_t *)&value[0], value.size());
+}
+
+void
+Component::toEscapedString(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 << (unsigned int)x;
+ }
+ }
+
+ // Restore.
+ result.flags(saveFlags);
+ }
+}
+
+
+uint64_t
+Component::toNumberWithMarker(uint8_t marker) const
+{
+ if (empty() || *value_begin() != marker)
+ throw Error("Name component does not begin with the expected marker");
+
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = value_begin()+1; i != value_end(); ++i) {
+ result <<= 8;
+ result |= *i;
+ }
+
+ return result;
+}
+
+Component
+Component::fromNumber(uint64_t number)
+{
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
+
+ // First encode in little endian.
+ while (number != 0) {
+ value->push_back(number & 0xff);
+ number >>= 8;
+ }
+
+ // Make it big endian.
+ reverse(value->begin(), value->end());
+ return Component(value);
+}
+
+Component
+Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
+{
+ ptr_lib::shared_ptr<Buffer> value(new Buffer);
+
+ // Add the leading marker.
+ value->push_back(marker);
+
+ // First encode in little endian.
+ while (number != 0) {
+ value->push_back(number & 0xff);
+ number >>= 8;
+ }
+
+ // Make it big endian.
+ reverse(value->begin() + 1, value->end());
+ return Component(value);
+}
+
+uint64_t
+Component::toNumber() const
+{
+ uint64_t result = 0;
+ for (Buffer::const_iterator i = value_begin(); i != value_end(); ++i) {
+ result <<= 8;
+ result |= *i;
+ }
+
+ return result;
+}
+
+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());
+}
+
+// const Block &
+// wireEncode() const
+// {
+
+// }
+
+} // namespace name
+} // namespace ndn
diff --git a/src/name-component.hpp b/src/name-component.hpp
new file mode 100644
index 0000000..c8ca77e
--- /dev/null
+++ b/src/name-component.hpp
@@ -0,0 +1,334 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_NAME_COMPONENT_HPP
+#define NDN_NAME_COMPONENT_HPP
+
+#include "common.hpp"
+#include "encoding/block.hpp"
+#include "encoding/encoding-buffer.hpp"
+
+namespace ndn {
+namespace name {
+
+/**
+ * A Name::Component holds a read-only name component value.
+ */
+class Component : public Block
+{
+public:
+ /// @brief Error that can be thrown from the block
+ struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+
+ /**
+ * Create a new Name::Component with a null value.
+ */
+ Component()
+ : Block(Tlv::NameComponent)
+ {
+ }
+
+ // copy constructor OK
+
+ /**
+ * Create a new Name::Component, taking another pointer to the Blob value.
+ * @param value A blob with a pointer to an immutable array. The pointer is copied.
+ */
+ Component(const ConstBufferPtr &buffer)
+ : Block (Tlv::NameComponent, buffer)
+ {
+ }
+
+ /**
+ * Create a new Name::Component, copying the given value.
+ * @param value The value byte array.
+ */
+ Component(const Buffer& value)
+ : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(value)))
+ {
+ }
+
+ /**
+ * Create a new Name::Component, copying the given value.
+ * @param value Pointer to the value byte array.
+ * @param valueLen Length of value.
+ */
+ Component(const uint8_t *value, size_t valueLen)
+ : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(value, valueLen)))
+ {
+ }
+
+ template<class InputIterator>
+ Component(InputIterator begin, InputIterator end)
+ : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(begin, end)))
+ {
+ }
+
+ Component(const char *string)
+ : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(string, ::strlen(string))))
+ {
+ }
+
+ /**
+ * @brief Fast encoding or block size estimation
+ */
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T> &block) const;
+
+ /**
+ * Make a Blob value by decoding the escapedString between beginOffset and endOffset according to the NDN URI Scheme.
+ * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
+ * which means the component should be skipped in a URI name.
+ * @param escapedString The escaped string. It does not need to be null-terminated because we only scan to endOffset.
+ * @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.
+ * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
+ */
+ static Component
+ fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset);
+
+ /**
+ * Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
+ * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
+ * which means the component should be skipped in a URI name.
+ * @param escapedString The null-terminated escaped string.
+ * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
+ */
+ static Component
+ fromEscapedString(const char *escapedString)
+ {
+ return fromEscapedString(escapedString, 0, ::strlen(escapedString));
+ }
+
+ /**
+ * Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
+ * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
+ * which means the component should be skipped in a URI name.
+ * @param escapedString The escaped string.
+ * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
+ */
+ static Component
+ fromEscapedString(const std::string& escapedString)
+ {
+ return fromEscapedString(escapedString.c_str());
+ }
+
+ /**
+ * Write the value to result, escaping characters according to the NDN URI Scheme.
+ * This also adds "..." to a value with zero or more ".".
+ * @param value the buffer with the value to escape
+ * @param result the string stream to write to.
+ */
+ void
+ toEscapedString(std::ostream& result) const;
+
+ /**
+ * Convert the value by escaping characters according to the NDN URI Scheme.
+ * This also adds "..." to a value with zero or more ".".
+ * @param value the buffer with the value to escape
+ * @return The escaped string.
+ */
+ inline std::string
+ toEscapedString() const
+ {
+ std::ostringstream result;
+ toEscapedString(result);
+ return result.str();
+ }
+
+ /**
+ * Interpret this name component as a network-ordered number and return an integer.
+ * @return The integer number.
+ */
+ uint64_t
+ toNumber() const;
+
+ /**
+ * Interpret this name component as a network-ordered number with a marker and return an integer.
+ * @param marker The required first byte of the component.
+ * @return The integer number.
+ * @throw runtime_error If the first byte of the component does not equal the marker.
+ */
+ uint64_t
+ toNumberWithMarker(uint8_t marker) const;
+
+ /**
+ * Interpret this name component as a segment number according to NDN name conventions (a network-ordered number
+ * where the first byte is the marker 0x00).
+ * @return The integer segment number.
+ * @throw runtime_error If the first byte of the component is not the expected marker.
+ */
+ uint64_t
+ toSegment() const
+ {
+ return toNumberWithMarker(0x00);
+ }
+
+ /**
+ * @deprecated Use toSegment.
+ */
+ uint64_t
+ toSeqNum() const
+ {
+ return toSegment();
+ }
+
+ /**
+ * Interpret this name component as a version number according to NDN name conventions (a network-ordered number
+ * where the first byte is the marker 0xFD). Note that this returns the exact number from the component
+ * without converting it to a time representation.
+ * @return The integer segment number.
+ * @throw runtime_error If the first byte of the component is not the expected marker.
+ */
+ uint64_t
+ toVersion() const
+ {
+ return toNumberWithMarker(0xFD);
+ }
+
+ /**
+ * Create a component whose value is the network-ordered encoding of the number.
+ * Note: if the number is zero, the result is empty.
+ * @param number The number to be encoded.
+ * @return The component value.
+ */
+ static Component
+ fromNumber(uint64_t number);
+
+ /**
+ * Create a component whose value is the marker appended with the network-ordered encoding of the number.
+ * Note: if the number is zero, no bytes are used for the number - the result will have only the marker.
+ * @param number The number to be encoded.
+ * @param marker The marker to use as the first byte of the component.
+ * @return The component value.
+ */
+ static Component
+ fromNumberWithMarker(uint64_t number, uint8_t marker);
+
+ /**
+ * 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;
+
+ return std::equal(value_begin(), value_end(), other.value_begin());
+ }
+
+ bool
+ empty() const
+ {
+ return !hasValue();
+ }
+
+ /**
+ * 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); }
+
+ /**
+ * 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); }
+
+ /**
+ * 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/0.2/technical/CanonicalOrder.html
+ */
+ int
+ compare(const Component& other) const;
+
+ /**
+ * Return true if this is less than or equal to the other Component in the NDN canonical ordering.
+ * @param other The other Component to compare with.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+ bool
+ operator <= (const Component& other) const { return compare(other) <= 0; }
+
+ /**
+ * Return true if this is less than the other Component in the NDN canonical ordering.
+ * @param other The other Component to compare with.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+ bool
+ operator < (const Component& other) const { return compare(other) < 0; }
+
+ /**
+ * Return true if this is less than or equal to the other Component in the NDN canonical ordering.
+ * @param other The other Component to compare with.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+ bool
+ operator >= (const Component& other) const { return compare(other) >= 0; }
+
+ /**
+ * Return true if this is greater than the other Component in the NDN canonical ordering.
+ * @param other The other Component to compare with.
+ *
+ * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
+ */
+ bool
+ operator > (const Component& other) const { return compare(other) > 0; }
+
+ //
+ // !!! MUST NOT INCLUDE ANY DATA HERE !!!
+ //
+ // This class is just a helper and is directly reinterpret_cast'ed from Block
+};
+
+inline std::ostream &
+operator << (std::ostream &os, const Component &component)
+{
+ component.toEscapedString(os);
+ return os;
+}
+
+template<bool T>
+inline size_t
+Component::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t total_len = 0;
+ total_len += block.prependByteArray (value(), value_size());
+ total_len += block.prependVarNumber (value_size());
+ total_len += block.prependVarNumber (Tlv::NameComponent);
+ return total_len;
+}
+
+template
+size_t
+Component::wireEncode<true>(EncodingBuffer& block) const;
+
+template
+size_t
+Component::wireEncode<false>(EncodingEstimator& block) const;
+
+
+} // namespace name
+} // namespace ndn
+
+#endif // NDN_NAME_COMPONENT_HPP
diff --git a/src/name.cpp b/src/name.cpp
index fe1f739..5f4a018 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -6,124 +6,31 @@
* See COPYING for copyright and distribution information.
*/
-#include <stdexcept>
+#include "name.hpp"
+
#include <algorithm>
#include <cstring>
-#include "name.hpp"
-#include "util/time.hpp"
+#include "util/time.hpp"
#include "util/string-helper.hpp"
-using namespace std;
-
namespace ndn {
-uint64_t
-Name::Component::toNumberWithMarker(uint8_t marker) const
-{
- if (empty() || *getValue().begin() != marker)
- throw runtime_error("Name component does not begin with the expected marker");
-
- uint64_t result = 0;
- for (Buffer::const_iterator i = getValue().begin()+1; i != getValue().end(); ++i) {
- result <<= 8;
- result |= *i;
- }
-
- return result;
-}
-
-Name::Component
-Name::Component::fromNumber(uint64_t number)
-{
- ptr_lib::shared_ptr<Buffer> value(new Buffer);
-
- // First encode in little endian.
- while (number != 0) {
- value->push_back(number & 0xff);
- number >>= 8;
- }
-
- // Make it big endian.
- reverse(value->begin(), value->end());
- return Component(value);
-}
-
-Name::Component
-Name::Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
-{
- ptr_lib::shared_ptr<Buffer> value(new Buffer);
-
- // Add the leading marker.
- value->push_back(marker);
-
- // First encode in little endian.
- while (number != 0) {
- value->push_back(number & 0xff);
- number >>= 8;
- }
-
- // Make it big endian.
- reverse(value->begin() + 1, value->end());
- return Component(value);
-}
-
-uint64_t
-Name::Component::toNumber() const
-{
- uint64_t result = 0;
- for (Buffer::const_iterator i = getValue().begin(); i != getValue().end(); ++i) {
- result <<= 8;
- result |= *i;
- }
-
- return result;
-}
-
-int
-Name::Component::compare(const Name::Component& other) const
-{
- // Imitate ndn_Exclude_compareComponents.
- if (getValue().size() < other.getValue().size())
- return -1;
- if (getValue().size() > other.getValue().size())
- return 1;
-
- // The components are equal length. Just do a byte compare.
- return std::memcmp(getValue().buf(), other.getValue().buf(), getValue().size());
-}
-
-inline size_t
-Name::Component::wireEncode (EncodingBuffer& blk)
-{
- size_t total_len = 0;
- total_len += blk.prependBuffer (*value_);
- total_len += blk.prependVarNumber (value_->size ());
- total_len += blk.prependVarNumber (Tlv::NameComponent);
- return total_len;
-}
-
-// const Block &
-// Name::wireEncode() const
-// {
-
-// }
-
void
Name::set(const char *uri_cstr)
{
- components_.clear();
+ clear();
- string uri = uri_cstr;
+ std::string uri = uri_cstr;
trim(uri);
if (uri.size() == 0)
return;
size_t iColon = uri.find(':');
- if (iColon != string::npos) {
+ if (iColon != std::string::npos) {
// Make sure the colon came before a '/'.
size_t iFirstSlash = uri.find('/');
- if (iFirstSlash == string::npos || iColon < iFirstSlash) {
+ if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
// Omit the leading protocol such as ndn:
uri.erase(0, iColon + 1);
trim(uri);
@@ -135,7 +42,7 @@
if (uri.size() >= 2 && uri[1] == '/') {
// Strip the authority following "//".
size_t iAfterAuthority = uri.find('/', 2);
- if (iAfterAuthority == string::npos)
+ if (iAfterAuthority == std::string::npos)
// Unusual case: there was only an authority.
return;
else {
@@ -154,13 +61,13 @@
// Unescape the components.
while (iComponentStart < uri.size()) {
size_t iComponentEnd = uri.find("/", iComponentStart);
- if (iComponentEnd == string::npos)
+ if (iComponentEnd == std::string::npos)
iComponentEnd = uri.size();
- Component component(fromEscapedString(&uri[0], iComponentStart, iComponentEnd));
+ Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
// Ignore illegal components. This also gets rid of a trailing '/'.
if (!component.empty())
- components_.push_back(Component(component));
+ append(Component(component));
iComponentStart = iComponentEnd + 1;
}
@@ -173,8 +80,8 @@
// Copying from this name, so need to make a copy first.
return append(Name(name));
- for (size_t i = 0; i < name.components_.size(); ++i)
- components_.push_back(name.components_[i]);
+ for (size_t i = 0; i < name.size(); ++i)
+ append(name.at(i));
return *this;
}
@@ -192,8 +99,8 @@
Name result;
size_t iEnd = iStartComponent + nComponents;
- for (size_t i = iStartComponent; i < iEnd && i < components_.size(); ++i)
- result.components_.push_back(components_[i]);
+ for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
+ result.append(at(i));
return result;
}
@@ -203,8 +110,8 @@
{
Name result;
- for (size_t i = iStartComponent; i < components_.size(); ++i)
- result.components_.push_back(components_[i]);
+ for (size_t i = iStartComponent; i < size(); ++i)
+ result.append(at(i));
return result;
}
@@ -212,11 +119,11 @@
bool
Name::equals(const Name& name) const
{
- if (components_.size() != name.components_.size())
+ if (size() != name.size())
return false;
- for (size_t i = 0; i < components_.size(); ++i) {
- if (components_[i].getValue() != name.components_[i].getValue())
+ for (size_t i = 0; i < size(); ++i) {
+ if (at(i) != name.at(i))
return false;
}
@@ -226,92 +133,25 @@
bool
Name::isPrefixOf(const Name& name) const
{
- // Imitate ndn_Name_match.
-
// This name is longer than the name we are checking it against.
- if (components_.size() > name.components_.size())
+ if (size() > name.size())
return false;
// Check if at least one of given components doesn't match.
- for (size_t i = 0; i < components_.size(); ++i) {
- if (components_[i].getValue() != name.components_[i].getValue())
+ for (size_t i = 0; i < size(); ++i) {
+ if (at(i) != name.at(i))
return false;
}
return true;
}
-Name::Component
-Name::fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
-{
- string trimmedString(escapedString + beginOffset, escapedString + endOffset);
- trim(trimmedString);
- string value = unescape(trimmedString);
-
- if (value.find_first_not_of(".") == 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((const uint8_t *)&value[3], value.size() - 3);
- }
- else
- return Component((const uint8_t *)&value[0], value.size());
-}
-
-Name::Component
-Name::fromEscapedString(const char *escapedString)
-{
- return fromEscapedString(escapedString, 0, ::strlen(escapedString));
-}
-
-void
-Name::toEscapedString(const uint8_t *value, size_t valueSize, std::ostream& result)
-{
- bool gotNonDot = false;
- for (unsigned i = 0; i < valueSize; ++i) {
- if (value[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.
- ios::fmtflags saveFlags = result.flags(ios::hex | ios::uppercase);
-
- for (size_t i = 0; i < valueSize; ++i) {
- uint8_t x = value[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 << (unsigned int)x;
- }
- }
-
- // Restore.
- result.flags(saveFlags);
- }
-}
int
Name::compare(const Name& other) const
{
for (size_t i = 0; i < size() && i < other.size(); ++i) {
- int comparison = components_[i].compare(other.components_[i]);
+ int comparison = at(i).compare(other.at(i));
if (comparison == 0)
// The components at this index are equal, so check the next components.
continue;
@@ -350,50 +190,34 @@
const Block &
Name::wireEncode() const
{
- if (wire_.hasWire())
- return wire_;
+ if (m_nameBlock.hasWire())
+ return m_nameBlock;
- wire_ = Block(Tlv::Name);
- for (Name::const_iterator i = begin(); i != end(); i++) {
- OBufferStream os;
- Tlv::writeVarNumber(os, Tlv::NameComponent);
- Tlv::writeVarNumber(os, i->getValue().size());
- os.write(reinterpret_cast<const char*>(i->getValue().buf()), i->getValue().size());
-
- wire_.push_back(Block(os.buf()));
- }
+ for (Block::element_iterator i = m_nameBlock.element_begin();
+ i != m_nameBlock.element_end();
+ ++i)
+ {
+ i->encode();
+ }
- wire_.encode();
- return wire_;
+ m_nameBlock.encode();
+ return m_nameBlock;
}
void
Name::wireDecode(const Block &wire)
{
- clear();
-
- wire_ = wire;
- wire_.parse();
-
- components_.clear();
- components_.reserve(wire_.getAll().size());
-
- for (Block::element_const_iterator i = wire_.getAll().begin();
- i != wire_.getAll().end();
- ++i)
- {
- append(i->value(), i->value_size());
- }
+ m_nameBlock = wire;
+ m_nameBlock.parse();
}
-
size_t
Name::wireEncode (EncodingBuffer& blk)
{
size_t total_len = 0;
- for (std::vector<Component>::reverse_iterator i = components_.rbegin ();
- i != components_.rend ();
+ for (reverse_iterator i = rbegin ();
+ i != rend ();
++i)
{
total_len += i->wireEncode (blk);
diff --git a/src/name.hpp b/src/name.hpp
index 78bdfd7..78b3b9d 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -10,279 +10,60 @@
#ifndef NDN_NAME_HPP
#define NDN_NAME_HPP
-#include <vector>
-#include <string>
-#include <sstream>
-#include <string.h>
+#include "common.hpp"
+#include "name-component.hpp"
+
#include "encoding/block.hpp"
#include "encoding/encoding-buffer.hpp"
+#include <boost/iterator/reverse_iterator.hpp>
+
namespace ndn {
-
+
/**
* A Name holds an array of Name::Component and represents an NDN name.
*/
class Name : public ptr_lib::enable_shared_from_this<Name> {
public:
- /**
- * A Name::Component holds a read-only name component value.
- */
- class Component
- {
- public:
- /**
- * Create a new Name::Component with a null value.
- */
- Component()
- {
- }
+ /// @brief Error that can be thrown from the block
+ struct Error : public name::Component::Error { Error(const std::string &what) : name::Component::Error(what) {} };
- // copy constructor OK
+ typedef name::Component Component;
+
+ typedef std::vector<Component> component_container;
+
+ typedef Component value_type;
+ typedef void allocator_type;
+ typedef Component& reference;
+ typedef const Component const_reference;
+ typedef Component* pointer;
+ typedef const Component* const_pointer;
+ typedef Component* iterator;
+ typedef const Component* const_iterator;
- /**
- * Create a new Name::Component, taking another pointer to the Blob value.
- * @param value A blob with a pointer to an immutable array. The pointer is copied.
- */
- Component(const ConstBufferPtr &buffer)
- : value_ (buffer)
- {
- }
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ typedef component_container::difference_type difference_type;
+ typedef component_container::size_type size_type;
- /**
- * Create a new Name::Component, copying the given value.
- * @param value The value byte array.
- */
- Component(const Buffer& value)
- : value_ (new Buffer(value))
- {
- }
-
- /**
- * Create a new Name::Component, copying the given value.
- * @param value Pointer to the value byte array.
- * @param valueLen Length of value.
- */
- Component(const uint8_t *value, size_t valueLen)
- : value_ (new Buffer(value, valueLen))
- {
- }
-
- template<class InputIterator>
- Component(InputIterator begin, InputIterator end)
- : value_ (new Buffer(begin, end))
- {
- }
-
- Component(const char *string)
- : value_ (new Buffer(string, ::strlen(string)))
- {
- }
-
- const Buffer&
- getValue() const { return *value_; }
-
- /**
- * Write this component value to result, escaping characters according to the NDN URI Scheme.
- * This also adds "..." to a value with zero or more ".".
- * @param result the string stream to write to.
- */
- void
- toEscapedString(std::ostream& result) const
- {
- Name::toEscapedString(*value_, result);
- }
-
- /**
- * Convert this component value 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
- toEscapedString() const
- {
- return Name::toEscapedString(*value_);
- }
-
- /**
- * Interpret this name component as a network-ordered number and return an integer.
- * @return The integer number.
- */
- uint64_t
- toNumber() const;
-
- /**
- * Interpret this name component as a network-ordered number with a marker and return an integer.
- * @param marker The required first byte of the component.
- * @return The integer number.
- * @throw runtime_error If the first byte of the component does not equal the marker.
- */
- uint64_t
- toNumberWithMarker(uint8_t marker) const;
-
- /**
- * Interpret this name component as a segment number according to NDN name conventions (a network-ordered number
- * where the first byte is the marker 0x00).
- * @return The integer segment number.
- * @throw runtime_error If the first byte of the component is not the expected marker.
- */
- uint64_t
- toSegment() const
- {
- return toNumberWithMarker(0x00);
- }
-
- /**
- * @deprecated Use toSegment.
- */
- uint64_t
- toSeqNum() const
- {
- return toSegment();
- }
-
- /**
- * Interpret this name component as a version number according to NDN name conventions (a network-ordered number
- * where the first byte is the marker 0xFD). Note that this returns the exact number from the component
- * without converting it to a time representation.
- * @return The integer segment number.
- * @throw runtime_error If the first byte of the component is not the expected marker.
- */
- uint64_t
- toVersion() const
- {
- return toNumberWithMarker(0xFD);
- }
-
- /**
- * Create a component whose value is the network-ordered encoding of the number.
- * Note: if the number is zero, the result is empty.
- * @param number The number to be encoded.
- * @return The component value.
- */
- static Component
- fromNumber(uint64_t number);
-
- /**
- * Create a component whose value is the marker appended with the network-ordered encoding of the number.
- * Note: if the number is zero, no bytes are used for the number - the result will have only the marker.
- * @param number The number to be encoded.
- * @param marker The marker to use as the first byte of the component.
- * @return The component value.
- */
- static Component
- fromNumberWithMarker(uint64_t number, uint8_t marker);
-
- /**
- * 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
- {
- return *value_ == *other.value_;
- }
-
- bool
- empty() const
- {
- return !value_ || value_->empty();
- }
-
- /**
- * 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); }
-
- /**
- * 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); }
-
- /**
- * 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/0.2/technical/CanonicalOrder.html
- */
- int
- compare(const Component& other) const;
-
- /**
- * Return true if this is less than or equal to the other Component in the NDN canonical ordering.
- * @param other The other Component to compare with.
- *
- * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
- */
- bool
- operator <= (const Component& other) const { return compare(other) <= 0; }
-
- /**
- * Return true if this is less than the other Component in the NDN canonical ordering.
- * @param other The other Component to compare with.
- *
- * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
- */
- bool
- operator < (const Component& other) const { return compare(other) < 0; }
-
- /**
- * Return true if this is less than or equal to the other Component in the NDN canonical ordering.
- * @param other The other Component to compare with.
- *
- * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
- */
- bool
- operator >= (const Component& other) const { return compare(other) >= 0; }
-
- /**
- * Return true if this is greater than the other Component in the NDN canonical ordering.
- * @param other The other Component to compare with.
- *
- * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
- */
- bool
- operator > (const Component& other) const { return compare(other) > 0; }
-
- inline size_t
- wireEncode (EncodingBuffer& blk);
-
- private:
- ConstBufferPtr value_;
- };
-
/**
* Create a new Name with no components.
*/
- Name() {
+ Name()
+ : m_nameBlock(Tlv::Name)
+ {
}
- /**
- * Create a new Name, copying the name components.
- * @param components A vector of Component
- */
- Name(const std::vector<Component>& components)
- : components_(components)
- {
- }
-
- Name(const Block &name)
- {
- for (Block::element_const_iterator i = name.getAll().begin();
- i != name.getAll().end();
- ++i)
- {
- append(Component(i->value_begin(), i->value_end()));
- }
- }
+ // Name(const Block &name)
+ // {
+ // for (Block::element_const_iterator i = name.getAll().begin();
+ // i != name.getAll().end();
+ // ++i)
+ // {
+ // append(Component(i->value_begin(), i->value_end()));
+ // }
+ // }
/**
* Parse the uri according to the NDN URI Scheme and create the name with the components.
@@ -323,7 +104,10 @@
* @param uri The URI string.
*/
void
- set(const std::string& uri) { set(uri.c_str()); }
+ set(const std::string& uri)
+ {
+ set(uri.c_str());
+ }
/**
* Append a new component, copying from value of length valueLength.
@@ -332,32 +116,32 @@
Name&
append(const uint8_t *value, size_t valueLength)
{
- components_.push_back(Component(value, valueLength));
+ m_nameBlock.elements().push_back(Component(value, valueLength));
return *this;
}
- /**
- * Append a new component, copying from value.
- * @return This name so that you can chain calls to append.
- */
- Name&
- append(const Buffer& value)
- {
- components_.push_back(value);
- return *this;
- }
+ // /**
+ // * Append a new component, copying from value.
+ // * @return This name so that you can chain calls to append.
+ // */
+ // Name&
+ // append(const Buffer& value)
+ // {
+ // m_nameBlock.elements().push_back(value);
+ // return *this;
+ // }
Name&
append(const ConstBufferPtr &value)
{
- components_.push_back(value);
+ m_nameBlock.elements().push_back(value);
return *this;
}
Name&
append(const Component &value)
{
- components_.push_back(value);
+ m_nameBlock.elements().push_back(value);
return *this;
}
@@ -371,14 +155,14 @@
Name&
append(const char *value)
{
- components_.push_back(Component(value));
+ m_nameBlock.elements().push_back(Component(value));
return *this;
}
Name&
append(const Block &value)
{
- components_.push_back(Component(value.begin(), value.end()));
+ m_nameBlock.elements().push_back(Component(value.begin(), value.end()));
return *this;
}
@@ -389,82 +173,17 @@
*/
Name&
append(const Name& name);
-
- /**
- * @deprecated Use append.
- */
- Name&
- appendComponent(const uint8_t *value, size_t valueLength)
- {
- return append(value, valueLength);
- }
-
- /**
- * @deprecated Use append.
- */
- Name&
- appendComponent(const Buffer& value)
- {
- return append(value);
- }
-
- /**
- * @deprecated Use append.
- */
- Name&
- appendComponent(const ConstBufferPtr &value)
- {
- return append(value);
- }
-
- /**
- * @deprecated Use append.
- */
- Name&
- addComponent(const uint8_t *value, size_t valueLength)
- {
- return append(value, valueLength);
- }
-
- /**
- * @deprecated Use append.
- */
- Name&
- addComponent(const Buffer& value)
- {
- return append(value);
- }
-
- /**
- * @deprecated Use append.
- */
- Name&
- addComponent(const ConstBufferPtr &value)
- {
- return append(value);
- }
-
+
/**
* Clear all the components.
*/
void
- clear() {
- components_.clear();
+ clear()
+ {
+ m_nameBlock = Block(Tlv::Name);
}
/**
- * @deprecated use size().
- */
- size_t
- getComponentCount() const { return size(); }
-
- /**
- * @deprecated Use get(i).
- */
- const Component&
- getComponent(size_t i) const { return get(i); }
-
- /**
* Get a new name, constructed as a subset of components.
* @param iStartComponent The index if the first component to get.
* @param nComponents The number of components starting at iStartComponent.
@@ -491,7 +210,7 @@
getPrefix(int nComponents) const
{
if (nComponents < 0)
- return getSubName(0, components_.size() + nComponents);
+ return getSubName(0, m_nameBlock.elements().size() + nComponents);
else
return getSubName(0, nComponents);
}
@@ -511,7 +230,7 @@
Name&
appendSegment(uint64_t segment)
{
- components_.push_back(Component::fromNumberWithMarker(segment, 0x00));
+ m_nameBlock.elements().push_back(Component::fromNumberWithMarker(segment, 0x00));
return *this;
}
@@ -524,7 +243,7 @@
Name&
appendVersion(uint64_t version)
{
- components_.push_back(Component::fromNumberWithMarker(version, 0xFD));
+ m_nameBlock.elements().push_back(Component::fromNumberWithMarker(version, 0xFD));
return *this;
}
@@ -559,73 +278,6 @@
return isPrefixOf(name);
}
- /**
- * Make a Blob value by decoding the escapedString between beginOffset and endOffset according to the NDN URI Scheme.
- * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
- * which means the component should be skipped in a URI name.
- * @param escapedString The escaped string. It does not need to be null-terminated because we only scan to endOffset.
- * @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.
- * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
- */
- static Component
- fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset);
-
- /**
- * Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
- * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
- * which means the component should be skipped in a URI name.
- * @param escapedString The null-terminated escaped string.
- * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
- */
- static Component
- fromEscapedString(const char *escapedString);
-
- /**
- * Make a Blob value by decoding the escapedString according to the NDN URI Scheme.
- * If the escaped string is "", "." or ".." then return a Blob with a null pointer,
- * which means the component should be skipped in a URI name.
- * @param escapedString The escaped string.
- * @return The Blob value. If the escapedString is not a valid escaped component, then the Blob is a null pointer.
- */
- static Component
- fromEscapedString(const std::string& escapedString) { return fromEscapedString(escapedString.c_str()); }
-
- /**
- * Write the value to result, escaping characters according to the NDN URI Scheme.
- * This also adds "..." to a value with zero or more ".".
- * @param value the buffer with the value to escape
- * @param result the string stream to write to.
- */
- static void
- toEscapedString(const uint8_t *value, size_t valueSize, std::ostream& result);
-
- inline static void
- toEscapedString(const std::vector<uint8_t>& value, std::ostream& result)
- {
- toEscapedString(&*value.begin(), value.size(), result);
- }
-
- /**
- * Convert the value by escaping characters according to the NDN URI Scheme.
- * This also adds "..." to a value with zero or more ".".
- * @param value the buffer with the value to escape
- * @return The escaped string.
- */
- inline static std::string
- toEscapedString(const uint8_t *value, size_t valueSize)
- {
- std::ostringstream result;
- toEscapedString(value, valueSize, result);
- return result.str();
- }
-
- static inline std::string
- toEscapedString(const std::vector<uint8_t>& value)
- {
- return toEscapedString(&*value.begin(), value.size());
- }
-
//
// vector equivalent interface.
//
@@ -634,14 +286,14 @@
* @brief Check if name is emtpy
*/
bool
- empty() const { return components_.empty(); }
+ empty() const { return m_nameBlock.elements().empty(); }
/**
* Get the number of components.
* @return The number of components.
*/
size_t
- size() const { return components_.size(); }
+ size() const { return m_nameBlock.elements().size(); }
/**
* Get the component at the given index.
@@ -652,11 +304,23 @@
get(ssize_t i) const
{
if (i >= 0)
- return components_[i];
+ return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
else
- return components_[size() + i];
+ return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
+ }
+
+ const Component&
+ operator [] (ssize_t i) const
+ {
+ return get(i);
}
+ const Component&
+ at(ssize_t i) const
+ {
+ return get(i);
+ }
+
/**
* Compare this to the other Name using NDN canonical ordering. If the first components of each name are not equal,
* this returns -1 if the first comes before the second using the NDN canonical ordering for name components, or 1 if it comes after.
@@ -674,12 +338,6 @@
int
compare(const Name& other) const;
- const Component&
- operator [] (int i) const
- {
- return get(i);
- }
-
/**
* Append the component
* @param component The component of type T.
@@ -745,82 +403,67 @@
//
// Iterator interface to name components.
//
- typedef std::vector<Component>::iterator iterator;
- typedef std::vector<Component>::const_iterator const_iterator;
- typedef std::vector<Component>::reverse_iterator reverse_iterator;
- typedef std::vector<Component>::const_reverse_iterator const_reverse_iterator;
- typedef std::vector<Component>::reference reference;
- typedef std::vector<Component>::const_reference const_reference;
-
- typedef std::vector<Component>::difference_type difference_type;
- typedef std::vector<Component>::size_type size_type;
-
- typedef std::vector<Component>::value_type value_type;
/**
* Begin iterator (const).
*/
const_iterator
- begin() const { return components_.begin(); }
+ begin() const
+ {
+ return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
+ }
/**
* Begin iterator.
*/
iterator
- begin() { return components_.begin(); }
+ begin() { return reinterpret_cast<iterator>(&*m_nameBlock.elements().begin()); }
/**
* End iterator (const).
+ *
+ * @todo Check if this crash when there are no elements in the buffer
*/
const_iterator
- end() const { return components_.end(); }
+ end() const { return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end()); }
/**
* End iterator.
*/
iterator
- end() { return components_.end(); }
-
+ end() { return reinterpret_cast<iterator>(&*m_nameBlock.elements().end()); }
+
/**
* Reverse begin iterator (const).
*/
const_reverse_iterator
- rbegin() const { return components_.rbegin(); }
+ rbegin() const { return const_reverse_iterator(end()); }
/**
* Reverse begin iterator.
*/
reverse_iterator
- rbegin() { return components_.rbegin(); }
+ rbegin() { return reverse_iterator(end()); }
/**
* Reverse end iterator (const).
*/
const_reverse_iterator
- rend() const { return components_.rend(); }
+ rend() const { return const_reverse_iterator(begin()); }
/**
* Reverse end iterator.
*/
reverse_iterator
- rend() { return components_.rend(); }
+ rend() { return reverse_iterator(begin()); }
private:
- std::vector<Component> components_;
-
- mutable Block wire_;
+ mutable Block m_nameBlock;
};
std::ostream &
operator << (std::ostream &os, const Name &name);
-inline std::ostream &
-operator << (std::ostream &os, const Name::Component &component)
-{
- component.toEscapedString(os);
- return os;
-}
-
inline std::string
Name::toUri() const
{
@@ -829,7 +472,7 @@
return os.str();
}
-}
+} // namespace ndn
#endif
diff --git a/src/util/string-helper.hpp b/src/util/string-helper.hpp
index ee3f5bd..de0c41f 100644
--- a/src/util/string-helper.hpp
+++ b/src/util/string-helper.hpp
@@ -13,7 +13,7 @@
namespace ndn {
-const char *WHITESPACE_CHARS = " \n\r\t";
+static const char *WHITESPACE_CHARS = " \n\r\t";
/**
* Modify str in place to erase whitespace on the left.