name: Fixes and improvements in Name and name::Component classes

Change-Id: I4695ea252d7cd2de7d68991f5c029bd3f1b39828
diff --git a/src/name-component.hpp b/src/name-component.hpp
index c8ca77e..a74c40c 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -34,7 +34,17 @@
   {    
   }
 
-  // copy constructor OK
+  /**
+   * @brief Directly create component from wire block
+   *
+   * ATTENTION  wire MUST BE of type Tlv::Component. Any other value would cause an exception
+   */
+  Component(const Block& wire)
+    : Block(wire)
+  {
+    if (type() != Tlv::NameComponent)
+      throw Error("Constructing name component from non name component TLV wire block");
+  }
   
   /**
    * Create a new Name::Component, taking another pointer to the Blob value.
@@ -69,12 +79,19 @@
     : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(begin, end)))
   {
   }
-    
-  Component(const char *string)
-    : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(string, ::strlen(string))))
+
+  explicit
+  Component(const char *str)
+    : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(str, ::strlen(str))))
   {
   }
 
+  explicit
+  Component(const std::string& str)
+    : Block (Tlv::NameComponent, ConstBufferPtr(new Buffer(str.begin(), str.end())))
+  {
+  }
+  
   /**
    * @brief Fast encoding or block size estimation
    */
@@ -142,6 +159,18 @@
     toEscapedString(result);
     return result.str();
   }
+
+  inline void
+  toUri(std::ostream& result) const
+  {
+    return toEscapedString(result);
+  }
+
+  inline std::string
+  toUri() const
+  {
+    return toEscapedString();
+  }
     
   /**
    * Interpret this name component as a network-ordered number and return an integer.
diff --git a/src/name.cpp b/src/name.cpp
index 5f4a018..5c267d7 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -187,45 +187,4 @@
   return os;
 }
 
-const Block &
-Name::wireEncode() const
-{
-  if (m_nameBlock.hasWire())
-    return m_nameBlock;
-
-  for (Block::element_iterator i = m_nameBlock.element_begin();
-       i != m_nameBlock.element_end();
-       ++i)
-    {
-      i->encode();
-    }
-        
-  m_nameBlock.encode();
-  return m_nameBlock;
-}
-
-void
-Name::wireDecode(const Block &wire)
-{
-  m_nameBlock = wire;
-  m_nameBlock.parse();
-}
-
-size_t
-Name::wireEncode (EncodingBuffer& blk)
-{
-  size_t total_len = 0;
-  
-  for (reverse_iterator i = rbegin (); 
-       i != rend ();
-       ++i)
-    {
-      total_len += i->wireEncode (blk);
-    }
-
-  total_len += blk.prependVarNumber (total_len);
-  total_len += blk.prependVarNumber (Tlv::Name);
-  return total_len;
-}
-
 } // namespace ndn
diff --git a/src/name.hpp b/src/name.hpp
index 78b3b9d..18d4252 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -54,16 +54,21 @@
     : m_nameBlock(Tlv::Name)
   {
   }
-  
-  // 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()));
-  //     }
-  // }
+
+  /**
+   * @brief Create Name object from wire block
+   *
+   * This is a more efficient equivalent for
+   * @code
+   *    Name name;
+   *    name.wireDecode(wire);
+   * @endcode
+   */
+  Name(const Block &wire)
+  {
+    m_nameBlock = wire;
+    m_nameBlock.parse();
+  }
   
   /**
    * Parse the uri according to the NDN URI Scheme and create the name with the components.
@@ -472,6 +477,48 @@
   return os.str();
 }
 
+inline const Block &
+Name::wireEncode() const
+{
+  if (m_nameBlock.hasWire())
+    return m_nameBlock;
+
+  for (Block::element_iterator i = m_nameBlock.element_begin();
+       i != m_nameBlock.element_end();
+       ++i)
+    {
+      i->encode();
+    }
+        
+  m_nameBlock.encode();
+  return m_nameBlock;
+}
+
+inline void
+Name::wireDecode(const Block &wire)
+{
+  m_nameBlock = wire;
+  m_nameBlock.parse();
+}
+
+inline size_t
+Name::wireEncode (EncodingBuffer& blk)
+{
+  size_t total_len = 0;
+  
+  for (reverse_iterator i = rbegin (); 
+       i != rend ();
+       ++i)
+    {
+      total_len += i->wireEncode (blk);
+    }
+
+  total_len += blk.prependVarNumber (total_len);
+  total_len += blk.prependVarNumber (Tlv::Name);
+  return total_len;
+}
+
+
 } // namespace ndn
 
 #endif
diff --git a/tests/test-encode-decode-interest.cpp b/tests/test-encode-decode-interest.cpp
index db193e8..09057fb 100644
--- a/tests/test-encode-decode-interest.cpp
+++ b/tests/test-encode-decode-interest.cpp
@@ -70,7 +70,9 @@
   i.setMaxSuffixComponents(1);
   i.setChildSelector(1);
   i.setMustBeFresh(false);
-  i.getExclude().excludeOne("alex").excludeRange("xxxx", "yyyy");
+  i.getExclude()
+    .excludeOne(name::Component("alex"))
+    .excludeRange(name::Component("xxxx"), name::Component("yyyy"));
   i.setNonce(1);
 
   const Block &wire = i.wireEncode();
diff --git a/tests/test-name.cpp b/tests/test-name.cpp
new file mode 100644
index 0000000..a4e86d0
--- /dev/null
+++ b/tests/test-name.cpp
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * @author: Jeff Thompson <jefft0@remap.ucla.edu>
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <boost/test/unit_test.hpp>
+
+#include "name.hpp"
+
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestName)
+
+static const uint8_t TestName[] = {
+        0x3,  0x14, // Name
+          0x4,  0x5, // NameComponent
+              0x6c,  0x6f,  0x63,  0x61,  0x6c,
+          0x4,  0x3, // NameComponent
+              0x6e,  0x64,  0x6e,
+          0x4,  0x6, // NameComponent
+              0x70,  0x72,  0x65,  0x66,  0x69,  0x78
+};
+
+BOOST_AUTO_TEST_CASE (Encode)
+{
+  Name name("/local/ndn/prefix");
+
+  const Block &wire = name.wireEncode();
+
+  // for (Buffer::const_iterator i = wire.begin();
+  //      i != wire.end();
+  //      ++i)
+  //   {
+  //     std::ios::fmtflags saveFlags = std::cout.flags(std::ios::hex);
+
+  //     if (i != wire.begin())
+  //       std::cout << ", ";
+  //     std::cout << "0x" << static_cast<uint32_t>(*i);
+      
+  //     std::cout.flags(saveFlags);
+  //   }
+  // std::cout << std::endl;
+  
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(TestName, TestName+sizeof(TestName),
+                                  wire.begin(), wire.end());
+}
+
+
+BOOST_AUTO_TEST_CASE (Decode)
+{
+  Block block(TestName, sizeof(TestName));
+
+  Name name(block);
+
+  BOOST_CHECK_EQUAL(name.toUri(), "/local/ndn/prefix");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn