name: Converting Name to TLV

Change-Id: Idc44608d3f0610f7f6b07204a00a3510e8041393
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