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/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