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.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);