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