name: Converting Name to TLV

Change-Id: Idc44608d3f0610f7f6b07204a00a3510e8041393
diff --git a/Makefile.am b/Makefile.am
index 17f3eb6..9821775 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -136,7 +136,8 @@
   src/util/dynamic-uint8-vector.cpp \
   src/util/dynamic-uint8-vector.hpp \
   src/util/logging.cpp \
-  src/util/logging.hpp
+  src/util/logging.hpp \
+  src/util/string-helper.hpp
 
 libndn_cpp_la_LIBADD  = @OPENSSL_LIBS@ @OSX_SECURITY_LIBS@
 libndn_cpp_la_LDFLAGS = @OPENSSL_LDFLAGS@  @SQLITE3_LDFLAGS@ @BOOST_LDFLAGS@
diff --git a/include/ndn-cpp/name.hpp b/include/ndn-cpp/name.hpp
index 633593c..00f6d21 100644
--- a/include/ndn-cpp/name.hpp
+++ b/include/ndn-cpp/name.hpp
@@ -12,12 +12,9 @@
 
 #include <vector>
 #include <string>
-#include <string.h>
 #include <sstream>
-#include "util/blob.hpp"
-
-struct ndn_NameComponent;
-struct ndn_Name;
+#include <string.h>
+#include "encoding/block.hpp"
 
 namespace ndn {
     
@@ -29,7 +26,8 @@
   /**
    * A Name::Component holds a read-only name component value.
    */
-  class Component {
+  class Component : private ConstBufferPtr
+  {
   public:
     /**
      * Create a new Name::Component with a null value.
@@ -37,13 +35,24 @@
     Component() 
     {    
     }
+
+    // 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)
+    : ConstBufferPtr (buffer)
+    {
+    }
   
     /**
      * Create a new Name::Component, copying the given value.
      * @param value The value byte array.
      */
-    Component(const std::vector<uint8_t>& value) 
-    : value_(value)
+    Component(const Buffer& value) 
+      : ConstBufferPtr (new Buffer(value))
     {
     }
 
@@ -53,29 +62,18 @@
      * @param valueLen Length of value.
      */
     Component(const uint8_t *value, size_t valueLen) 
-    : value_(value, valueLen)
+      : ConstBufferPtr (new Buffer(value, valueLen))
+    {
+    }
+
+    template<class InputIterator>
+    Component(InputIterator begin, InputIterator end)
+      : ConstBufferPtr (new Buffer(begin, end))
     {
     }
     
-    /**
-     * 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 Blob &value)
-    : value_(value)
-    {
-    }
-  
-    /**
-     * Set the componentStruct to point to this component, without copying any memory.
-     * WARNING: The resulting pointer in componentStruct is invalid after a further use of this object which could reallocate memory.
-     * @param componentStruct The C ndn_NameComponent struct to receive the pointer.
-     */
-    void 
-    get(struct ndn_NameComponent& componentStruct) const;
-  
-    const Blob& 
-    getValue() const { return value_; }
+    const Buffer& 
+    getValue() const { return **this; }
 
     /**
      * Write this component value to result, escaping characters according to the NDN URI Scheme.
@@ -83,9 +81,9 @@
      * @param result the string stream to write to.
      */
     void 
-    toEscapedString(std::ostringstream& result) const
+    toEscapedString(std::ostream& result) const
     {
-      Name::toEscapedString(*value_, result);
+      Name::toEscapedString(**this, result);
     }
 
     /**
@@ -96,7 +94,7 @@
     std::string
     toEscapedString() const
     {
-      return Name::toEscapedString(*value_);
+      return Name::toEscapedString(**this);
     }
     
     /**
@@ -176,7 +174,13 @@
     bool
     equals(const Component& other) const
     {
-      return *value_ == *other.value_;
+      return **this == *other;
+    }
+
+    bool
+    empty() const
+    {
+      return !*this || (*this)->empty();
     }
     
     /**
@@ -241,11 +245,8 @@
      */
     bool
     operator > (const Component& other) const { return compare(other) > 0; }
+  };
 
-  private:
-    Blob value_;
-  }; 
-  
   /**
    * Create a new Name with no components.
    */
@@ -260,6 +261,16 @@
   : 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()));
+      }
+  }
   
   /**
    * Parse the uri according to the NDN URI Scheme and create the name with the components.
@@ -279,20 +290,8 @@
     set(uri.c_str());
   }
 
-  /**
-   * Set the nameStruct to point to the components in this name, without copying any memory.
-   * WARNING: The resulting pointers in nameStruct are invalid after a further use of this object which could reallocate memory.
-   * @param nameStruct A C ndn_Name struct where the components array is already allocated.
-   */
-  void 
-  get(struct ndn_Name& nameStruct) const;
-  
-  /**
-   * Clear this name, and set the components by copying from the name struct.
-   * @param nameStruct A C ndn_Name struct
-   */
-  void 
-  set(const struct ndn_Name& nameStruct);
+  const Block &
+  wireEncode() const;
   
   /**
    * Parse the uri according to the NDN URI Scheme and set the name with the components.
@@ -324,14 +323,14 @@
    * @return This name so that you can chain calls to append.
    */
   Name& 
-  append(const std::vector<uint8_t>& value) 
+  append(const Buffer& value) 
   {
     components_.push_back(value);
     return *this;
   }
   
   Name& 
-  append(const Blob &value)
+  append(const ConstBufferPtr &value)
   {
     components_.push_back(value);
     return *this;
@@ -343,6 +342,13 @@
     components_.push_back(value);
     return *this;
   }
+
+  Name&
+  append(const Block &value)
+  {
+    components_.push_back(Component(value.begin(), value.end()));
+    return *this;
+  }
   
   /**
    * Append the components of the given name to this name.
@@ -365,7 +371,7 @@
    * @deprecated Use append.
    */
   Name& 
-  appendComponent(const std::vector<uint8_t>& value) 
+  appendComponent(const Buffer& value) 
   {
     return append(value);
   }
@@ -374,7 +380,7 @@
    * @deprecated Use append.
    */
   Name& 
-  appendComponent(const Blob &value)
+  appendComponent(const ConstBufferPtr &value)
   {
     return append(value);
   }
@@ -392,7 +398,7 @@
    * @deprecated Use append.
    */
   Name& 
-  addComponent(const std::vector<uint8_t>& value) 
+  addComponent(const Buffer& value) 
   {
     return append(value);
   }
@@ -401,7 +407,7 @@
    * @deprecated Use append.
    */
   Name& 
-  addComponent(const Blob &value)
+  addComponent(const ConstBufferPtr &value)
   {
     return append(value);
   }
@@ -466,15 +472,6 @@
   toUri() const;
   
   /**
-   * @deprecated Use toUri().
-   */
-  std::string 
-  to_uri() const 
-  {
-    return toUri();
-  }
-
-  /**
    * Append a component with the encoded segment number.
    * @param segment The segment number.
    * @return This name so that you can chain calls to append.
@@ -513,7 +510,13 @@
    * @return true if this matches the given name, otherwise false.  This always returns true if this name is empty.
    */
   bool 
-  match(const Name& name) const;
+  isPrefixOf(const Name& name) const;
+
+  bool
+  match(const Name& name) const
+  {
+    return isPrefixOf(name);
+  }
   
   /**
    * Make a Blob value by decoding the escapedString between beginOffset and endOffset according to the NDN URI Scheme.
@@ -524,7 +527,7 @@
    * @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 Blob 
+  static Component 
   fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset);
 
   /**
@@ -534,7 +537,7 @@
    * @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 Blob 
+  static Component 
   fromEscapedString(const char *escapedString);
 
   /**
@@ -544,7 +547,7 @@
    * @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 Blob 
+  static Component 
   fromEscapedString(const std::string& escapedString) { return fromEscapedString(escapedString.c_str()); }
 
   /**
@@ -554,7 +557,7 @@
    * @param result the string stream to write to.
    */
   static void 
-  toEscapedString(const std::vector<uint8_t>& value, std::ostringstream& result);
+  toEscapedString(const std::vector<uint8_t>& value, std::ostream& result);
 
   /**
    * Convert the value by escaping characters according to the NDN URI Scheme.
@@ -568,6 +571,12 @@
   //
   // vector equivalent interface.
   //
+
+  /**
+   * @brief Check if name is emtpy
+   */
+  bool
+  empty() const { return components_.empty(); }
   
   /**
    * Get the number of components.
@@ -657,7 +666,7 @@
   typedef std::vector<Component>::reference reference;
   typedef std::vector<Component>::const_reference const_reference;
 
-  typedef Component partial_type;
+  typedef Component value_type;
 
   /**
    * Begin iterator (const).
@@ -709,13 +718,19 @@
 
 private:
   std::vector<Component> components_;
-};  
 
-inline std::ostream&
-operator << (std::ostream& os, const Name& name)
+  mutable Block wire_;
+};
+
+std::ostream &
+operator << (std::ostream &os, const Name &name);
+
+inline std::string 
+Name::toUri() const
 {
-  os << name.toUri();
-  return os;
+  std::ostringstream os;
+  os << *this;
+  return os.str();
 }
 
 }
diff --git a/src/name.cpp b/src/name.cpp
index b17a163..3d9b395 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -10,126 +10,33 @@
 #include <algorithm>
 #include <string.h>
 #include <ndn-cpp/name.hpp>
-#include "c/name.h"
 #include "c/util/ndn_memory.h"
 
+#include "util/string-helper.hpp"
+
 using namespace std;
 
 namespace ndn {
 
-static const char *WHITESPACE_CHARS = " \n\r\t";
-
-/**
- * Modify str in place to erase whitespace on the left.
- * @param str
- */
-static inline void 
-trimLeft(string& str)
+uint64_t
+Name::Component::toNumberWithMarker(uint8_t marker) const
 {
-  size_t found = str.find_first_not_of(WHITESPACE_CHARS);
-  if (found != string::npos) {
-    if (found > 0)
-      str.erase(0, found);
-  }
-  else
-    // All whitespace
-    str.clear();    
-}
-
-/**
- * Modify str in place to erase whitespace on the right.
- * @param str
- */
-static inline void 
-trimRight(string& str)
-{
-  size_t found = str.find_last_not_of(WHITESPACE_CHARS);
-  if (found != string::npos) {
-    if (found + 1 < str.size())
-      str.erase(found + 1);
-  }
-  else
-    // All whitespace
-    str.clear();
-}
-
-/**
- * Modify str in place to erase whitespace on the left and right.
- * @param str
- */
-static void 
-trim(string& str)
-{
-  trimLeft(str);
-  trimRight(str);
-}
-
-/**
- * Convert the hex character to an integer from 0 to 15, or -1 if not a hex character.
- * @param c
- * @return 
- */
-static int 
-fromHexChar(uint8_t c)
-{
-  if (c >= '0' && c <= '9')
-    return (int)c - (int)'0';
-  else if (c >= 'A' && c <= 'F')
-    return (int)c - (int)'A' + 10;
-  else if (c >= 'a' && c <= 'f')
-    return (int)c - (int)'a' + 10;
-  else
-    return -1;
-}
-
-/**
- * Return a copy of str, converting each escaped "%XX" to the char value.
- * @param str
- */
-static string 
-unescape(const string& str)
-{
-  ostringstream result;
+  if (empty() || *getValue().begin() != marker)
+    throw runtime_error("Name component does not begin with the expected marker");
   
-  for (size_t i = 0; i < str.size(); ++i) {
-    if (str[i] == '%' && i + 2 < str.size()) {
-      int hi = fromHexChar(str[i + 1]);
-      int lo = fromHexChar(str[i + 2]);
-      
-      if (hi < 0 || lo < 0)
-        // Invalid hex characters, so just keep the escaped string.
-        result << str[i] << str[i + 1] << str[i + 2];
-      else
-        result << (uint8_t)(16 * hi + lo);
-      
-      // Skip ahead past the escaped value.
-      i += 2;
-    }
-    else
-      // Just copy through.
-      result << str[i];
+  uint64_t result = 0;
+  for (Buffer::const_iterator i = getValue().begin()+1; i != getValue().end(); ++i) {
+    result <<= 8;
+    result |= *i;
   }
   
-  return result.str();
-}
-
-uint64_t Name::Component::toNumberWithMarker(uint8_t marker) const
-{
-  struct ndn_NameComponent componentStruct;
-  get(componentStruct);
-  uint64_t result;
-  
-  ndn_Error error;
-  if ((error = ndn_NameComponent_toNumberWithMarker(&componentStruct, marker, &result)))
-    throw runtime_error(ndn_getErrorString(error));
-    
   return result;
 }
 
 Name::Component 
 Name::Component::fromNumber(uint64_t number)
 {
-  ptr_lib::shared_ptr<vector<uint8_t> > value(new vector<uint8_t>());
+  ptr_lib::shared_ptr<Buffer> value(new Buffer);
   
   // First encode in little endian.
   while (number != 0) {
@@ -139,13 +46,13 @@
   
   // Make it big endian.
   reverse(value->begin(), value->end());
-  return Blob(value);
+  return Component(value);
 }
 
 Name::Component 
 Name::Component::fromNumberWithMarker(uint64_t number, uint8_t marker)
 {
-  ptr_lib::shared_ptr<vector<uint8_t> > value(new vector<uint8_t>());
+  ptr_lib::shared_ptr<Buffer> value(new Buffer);
   
   // Add the leading marker.
   value->push_back(marker);
@@ -158,36 +65,40 @@
   
   // Make it big endian.
   reverse(value->begin() + 1, value->end());
-  return Blob(value);
-}
-
-void 
-Name::Component::get(struct ndn_NameComponent& componentStruct) const 
-{
-  value_.get(componentStruct.value);
+  return Component(value);
 }
 
 uint64_t
 Name::Component::toNumber() const
 {
-  struct ndn_NameComponent componentStruct;
-  get(componentStruct);
-  return ndn_NameComponent_toNumber(&componentStruct);
+  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 (value_.size() < other.value_.size())
+  if (getValue().size() < other.getValue().size())
     return -1;
-  if (value_.size() > other.value_.size())
+  if (getValue().size() > other.getValue().size())
     return 1;
 
   // The components are equal length.  Just do a byte compare.  
-  return ndn_memcmp((uint8_t*)value_.buf(), (uint8_t*)other.value_.buf(), value_.size());
+  return ndn_memcmp(getValue().buf(), other.getValue().buf(), getValue().size());
 }
 
+// const Block &
+// Name::wireEncode() const
+// {
+  
+// }
+
 void 
 Name::set(const char *uri_cstr) 
 {
@@ -238,32 +149,13 @@
     
     Component component(fromEscapedString(&uri[0], iComponentStart, iComponentEnd));
     // Ignore illegal components.  This also gets rid of a trailing '/'.
-    if (component.getValue())
+    if (!component.empty())
       components_.push_back(Component(component));
     
     iComponentStart = iComponentEnd + 1;
   }
 }
 
-void 
-Name::get(struct ndn_Name& nameStruct) const
-{
-  if (nameStruct.maxComponents < components_.size())
-    throw runtime_error("nameStruct.maxComponents must be >= this name getNComponents()");
-  
-  nameStruct.nComponents = components_.size();
-  for (size_t i = 0; i < nameStruct.nComponents; ++i)
-    components_[i].get(nameStruct.components[i]);
-}
-  
-void 
-Name::set(const struct ndn_Name& nameStruct) 
-{
-  clear();
-  for (size_t i = 0; i < nameStruct.nComponents; ++i)
-    append(nameStruct.components[i].value.value, nameStruct.components[i].value.length);  
-}
-
 Name&
 Name::append(const Name& name)
 {
@@ -277,21 +169,6 @@
   return *this;
 }
 
-string 
-Name::toUri() const
-{
-  if (components_.size() == 0)
-    return "/";
-  
-  ostringstream result;
-  for (size_t i = 0; i < components_.size(); ++i) {
-    result << "/";
-    toEscapedString(*components_[i].getValue(), result);
-  }
-  
-  return result.str();
-}
-
 Name
 Name::getSubName(size_t iStartComponent, size_t nComponents) const
 {
@@ -322,7 +199,7 @@
     return false;
 
   for (size_t i = 0; i < components_.size(); ++i) {
-    if (*components_[i].getValue() != *name.components_[i].getValue())
+    if (components_[i].getValue() != name.components_[i].getValue())
       return false;
   }
 
@@ -330,7 +207,7 @@
 }
 
 bool 
-Name::match(const Name& name) const
+Name::isPrefixOf(const Name& name) const
 {
   // Imitate ndn_Name_match.
   
@@ -340,14 +217,14 @@
 
   // 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())
+    if (components_[i].getValue() != name.components_[i].getValue())
       return false;
   }
 
   return true;
 }
 
-Blob 
+Name::Component 
 Name::fromEscapedString(const char *escapedString, size_t beginOffset, size_t endOffset)
 {
   string trimmedString(escapedString + beginOffset, escapedString + endOffset);
@@ -358,23 +235,23 @@
     // Special case for component of only periods.  
     if (value.size() <= 2)
       // Zero, one or two periods is illegal.  Ignore this component.
-      return Blob();
+      return Component();
     else
       // Remove 3 periods.
-      return Blob((const uint8_t *)&value[3], value.size() - 3); 
+      return Component((const uint8_t *)&value[3], value.size() - 3); 
   }
   else
-    return Blob((const uint8_t *)&value[0], value.size()); 
+    return Component((const uint8_t *)&value[0], value.size()); 
 }
 
-Blob 
+Name::Component
 Name::fromEscapedString(const char *escapedString)
 {
   return fromEscapedString(escapedString, 0, ::strlen(escapedString));
 }
 
-void 
-Name::toEscapedString(const vector<uint8_t>& value, ostringstream& result)
+void
+Name::toEscapedString(const vector<uint8_t>& value, std::ostream& result)
 {
   bool gotNonDot = false;
   for (unsigned i = 0; i < value.size(); ++i) {
@@ -437,5 +314,22 @@
   return name1.size() < name2.size();
 }
 
+std::ostream&
+operator << (std::ostream& os, const Name& name)
+{
+  if (name.empty())
+    {
+      os << "/";
+    }
+  else
+    {
+      for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
+        os << "/";
+        i->toEscapedString(os);
+      }
+    }
+  
+  return os;
+}
 
 }
diff --git a/src/util/string-helper.hpp b/src/util/string-helper.hpp
new file mode 100644
index 0000000..ee3f5bd
--- /dev/null
+++ b/src/util/string-helper.hpp
@@ -0,0 +1,114 @@
+/* -*- 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>
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_STRING_HELPER_HPP
+#define NDN_STRING_HELPER_HPP
+
+#include <string>
+#include <sstream>
+
+namespace ndn {
+
+const char *WHITESPACE_CHARS = " \n\r\t";
+
+/**
+ * Modify str in place to erase whitespace on the left.
+ * @param str
+ */
+inline void 
+trimLeft(std::string& str)
+{
+  size_t found = str.find_first_not_of(WHITESPACE_CHARS);
+  if (found != std::string::npos) {
+    if (found > 0)
+      str.erase(0, found);
+  }
+  else
+    // All whitespace
+    str.clear();    
+}
+
+/**
+ * Modify str in place to erase whitespace on the right.
+ * @param str
+ */
+inline void 
+trimRight(std::string& str)
+{
+  size_t found = str.find_last_not_of(WHITESPACE_CHARS);
+  if (found != std::string::npos) {
+    if (found + 1 < str.size())
+      str.erase(found + 1);
+  }
+  else
+    // All whitespace
+    str.clear();
+}
+
+/**
+ * Modify str in place to erase whitespace on the left and right.
+ * @param str
+ */
+inline void 
+trim(std::string& str)
+{
+  trimLeft(str);
+  trimRight(str);
+}
+
+/**
+ * Convert the hex character to an integer from 0 to 15, or -1 if not a hex character.
+ * @param c
+ * @return 
+ */
+inline int 
+fromHexChar(uint8_t c)
+{
+  if (c >= '0' && c <= '9')
+    return (int)c - (int)'0';
+  else if (c >= 'A' && c <= 'F')
+    return (int)c - (int)'A' + 10;
+  else if (c >= 'a' && c <= 'f')
+    return (int)c - (int)'a' + 10;
+  else
+    return -1;
+}
+
+/**
+ * Return a copy of str, converting each escaped "%XX" to the char value.
+ * @param str
+ */
+inline std::string 
+unescape(const std::string& str)
+{
+  std::ostringstream result;
+  
+  for (size_t i = 0; i < str.size(); ++i) {
+    if (str[i] == '%' && i + 2 < str.size()) {
+      int hi = fromHexChar(str[i + 1]);
+      int lo = fromHexChar(str[i + 2]);
+      
+      if (hi < 0 || lo < 0)
+        // Invalid hex characters, so just keep the escaped string.
+        result << str[i] << str[i + 1] << str[i + 2];
+      else
+        result << (uint8_t)(16 * hi + lo);
+      
+      // Skip ahead past the escaped value.
+      i += 2;
+    }
+    else
+      // Just copy through.
+      result << str[i];
+  }
+  
+  return result.str();
+}
+
+} // namespace ndn
+
+#endif // NDN_STRING_HELPER_HPP