Merge branch 'dev'

Conflicts:
	include/ccnx-wrapper.h
diff --git a/include/ccnx-closure.h b/include/ccnx-closure.h
index 01358c4..a2c8b7d 100644
--- a/include/ccnx-closure.h
+++ b/include/ccnx-closure.h
@@ -2,6 +2,7 @@
 #define CCNX_CLOSURE_H
 
 #include "ccnx-common.h"
+#include "ccnx-name.h"
 
 using namespace std;
 
@@ -10,7 +11,7 @@
 class Closure
 {
 public:
-  typedef boost::function<void (const string &, const Bytes &)> DataCallback;
+  typedef boost::function<void (const Name &, const Bytes &)> DataCallback;
 
   typedef enum
   {
@@ -18,7 +19,7 @@
     RESULT_REEXPRESS
   } TimeoutCallbackReturnValue;
 
-  typedef boost::function<TimeoutCallbackReturnValue (const string &)> TimeoutCallback;
+  typedef boost::function<TimeoutCallbackReturnValue (const Name &)> TimeoutCallback;
 
   Closure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback);
   Closure(const Closure &other);
@@ -26,9 +27,9 @@
   void decRetry() { m_retry--;}
   virtual ~Closure();
   virtual void
-  runDataCallback(const string &name, const Bytes &content);
+  runDataCallback(const Name &name, const Bytes &content);
   virtual TimeoutCallbackReturnValue
-  runTimeoutCallback(const string &interest);
+  runTimeoutCallback(const Name &interest);
 
 protected:
   int m_retry;
diff --git a/include/ccnx-name.h b/include/ccnx-name.h
index 84c045f..59e34a5 100644
--- a/include/ccnx-name.h
+++ b/include/ccnx-name.h
@@ -5,6 +5,9 @@
 
 namespace Ccnx {
 
+class CcnxCharbuf;
+typedef boost::shared_ptr<CcnxCharbuf> CcnxCharbufPtr;
+
 //  This class is mostly used in CcnxWrapper; users should not be directly using this class
 // The main purpose of this class to is avoid manually create and destroy charbuf everytime
 class CcnxCharbuf
@@ -17,15 +20,16 @@
   // expose internal data structure, use with caution!!
   ccn_charbuf *
   getBuf() { return m_buf; }
+  static CcnxCharbufPtr Null;
 
 protected:
   ccn_charbuf *m_buf;
 };
 
-typedef boost::shared_ptr<CcnxCharbuf> CcnxCharbufPtr;
 
 struct NameException:
   virtual boost::exception, virtual exception {};
+
 class Name
 {
 public:
@@ -58,8 +62,22 @@
   getCompAsString(int index) const;
 
   Name
-  getPartialName(int start, int n) const;
+  getPartialName(int start, int n = -1) const;
 
+  string
+  toString() const;
+
+  Name &
+  operator=(const Name &other);
+
+  bool
+  operator==(const string &str);
+
+  bool
+  operator!=(const string &str);
+
+  friend Name
+  operator+(const Name &n1, const Name &n2);
 
 protected:
   vector<Bytes> m_comps;
@@ -68,6 +86,16 @@
 ostream&
 operator <<(ostream &os, const Name &name);
 
+bool
+operator ==(const Name &n1, const Name &n2);
+
+bool
+operator !=(const Name &n1, const Name &n2);
+
+bool
+operator <(const Name &n1, const Name &n2);
+
+
 struct InterestSelectorException:
   virtual boost::exception, virtual exception {};
 
@@ -117,7 +145,13 @@
   publisherPublicKeyDigest(const Bytes &digest) {m_publisherPublicKeyDigest = digest; return *this;}
 
   CcnxCharbufPtr
-  toCcnxCharbuf();
+  toCcnxCharbuf() const;
+
+  bool
+  isEmpty() const;
+
+  bool
+  operator==(const Selectors &other);
 
 private:
   int m_maxSuffixComps;
diff --git a/include/ccnx-pco.h b/include/ccnx-pco.h
index 829e0cc..72a7289 100644
--- a/include/ccnx-pco.h
+++ b/include/ccnx-pco.h
@@ -3,6 +3,7 @@
 
 #include "ccnx-wrapper.h"
 #include "ccnx-common.h"
+#include "ccnx-name.h"
 
 using namespace std;
 
@@ -21,7 +22,7 @@
   Bytes
   content() const;
 
-  string
+  Name
   name() const;
 
 protected:
diff --git a/include/ccnx-tunnel.h b/include/ccnx-tunnel.h
index 15d5223..732370d 100644
--- a/include/ccnx-tunnel.h
+++ b/include/ccnx-tunnel.h
@@ -5,6 +5,7 @@
 
 #include "ccnx-common.h"
 #include "ccnx-wrapper.h"
+#include "ccnx-name.h"
 
 #define _OVERRIDE
 #ifdef __GNUC__
@@ -24,8 +25,8 @@
 class CcnxTunnel : public CcnxWrapper
 {
 public:
-  typedef multimap<string, InterestCallback> RegisteredInterestTable;
-  typedef multimap<string, InterestCallback>::iterator RitIter;
+  typedef multimap<Name, InterestCallback> RegisteredInterestTable;
+  typedef multimap<Name, InterestCallback>::iterator RitIter;
 
 
   CcnxTunnel();
@@ -33,50 +34,50 @@
 
   // name is topology-independent
   virtual int
-  publishData(const string &name, const unsigned char *buf, size_t len, int freshness) _OVERRIDE;
+  publishData(const Name &name, const unsigned char *buf, size_t len, int freshness) _OVERRIDE;
 
   int
-  publishContentObject(const string &name, const Bytes &contentObject, int freshness);
+  publishContentObject(const Name &name, const Bytes &contentObject, int freshness);
 
   virtual int
-  sendInterest (const string &interest, Closure *closure);
+  sendInterest (const Name &interest, Closure *closure, const Selectors &selectors = Selectors());
 
 
   // prefix is topology-independent
   virtual int
-  setInterestFilter(const string &prefix, const InterestCallback &interestCallback) _OVERRIDE;
+  setInterestFilter(const Name &prefix, const InterestCallback &interestCallback) _OVERRIDE;
 
   // prefix is topology-independent
   // this clears all entries with key equal to prefix
   virtual void
-  clearInterestFilter(const string &prefix) _OVERRIDE;
+  clearInterestFilter(const Name &prefix) _OVERRIDE;
 
   // subclass should provide translation service from topology-independent name
   // to routable name
-  virtual string
-  queryRoutableName(const string &name) = 0;
+  virtual Name
+  queryRoutableName(const Name &name) = 0;
 
   // subclass should implement the function to store ContentObject with topoloy-independent
   // name to the permanent storage; default does nothing
   virtual void
-  storeContentObject(const string &name, const Bytes &content) {}
+  storeContentObject(const Name &name, const Bytes &content) {}
 
   // should be called  when connect to a different network
   void
   refreshLocalPrefix();
 
   static bool
-  isPrefix(const string &prefix, const string &name);
+  isPrefix(const Name &prefix, const Name &name);
 
   void
-  handleTunneledInterest(const string &tunneldInterest);
+  handleTunneledInterest(const Name &tunneldInterest);
 
   void
-  handleTunneledData(const string &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback);
+  handleTunneledData(const Name &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback);
 
 protected:
   // need a way to update local prefix, perhaps using macports trick, but eventually we need something more portable
-  string m_localPrefix;
+  Name m_localPrefix;
   RegisteredInterestTable m_rit;
   Lock m_ritLock;
 };
@@ -84,19 +85,19 @@
 class TunnelClosure : public Closure
 {
 public:
-  TunnelClosure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const string &originalInterest);
+  TunnelClosure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const Name &originalInterest);
 
-  TunnelClosure(const Closure *closure, CcnxTunnel *tunnel, const string &originalInterest);
+  TunnelClosure(const Closure *closure, CcnxTunnel *tunnel, const Name &originalInterest);
 
   virtual void
-  runDataCallback(const string &name, const Bytes &content) _OVERRIDE;
+  runDataCallback(const Name &name, const Bytes &content) _OVERRIDE;
 
   virtual TimeoutCallbackReturnValue
-  runTimeoutCallback(const string &interest) _OVERRIDE;
+  runTimeoutCallback(const Name &interest) _OVERRIDE;
 
 private:
   CcnxTunnel *m_tunnel;
-  string m_originalInterest;
+  Name m_originalInterest;
 };
 
 };
diff --git a/include/ccnx-wrapper.h b/include/ccnx-wrapper.h
index 4801bc2..42466eb 100644
--- a/include/ccnx-wrapper.h
+++ b/include/ccnx-wrapper.h
@@ -25,34 +25,31 @@
   typedef boost::recursive_mutex RecLock;
   typedef boost::unique_lock<RecLock> UniqueRecLock;
 
-  typedef boost::function<void (const string &)> InterestCallback;
+  typedef boost::function<void (const Name &)> InterestCallback;
 
   CcnxWrapper();
   virtual ~CcnxWrapper();
 
   virtual int
-  setInterestFilter (const string &prefix, const InterestCallback &interestCallback);
+  setInterestFilter (const Name &prefix, const InterestCallback &interestCallback);
 
   virtual void
-  clearInterestFilter (const string &prefix);
+  clearInterestFilter (const Name &prefix);
 
   virtual int
-  sendInterest (const string &interest, Closure *closure);
+  sendInterest (const Name &interest, Closure *closure, const Selectors &selector = Selectors());
 
   virtual int
-  publishData (const string &name, const unsigned char *buf, size_t len, int freshness);
+  publishData (const Name &name, const unsigned char *buf, size_t len, int freshness);
 
   int
-  publishData (const string &name, const Bytes &content, int freshness);
+  publishData (const Name &name, const Bytes &content, int freshness);
 
-  static string
+  static Name
   getLocalPrefix ();
 
-  static string
-  extractName(const unsigned char *data, const ccn_indexbuf *comps);
-
   Bytes
-  createContentObject(const string &name, const unsigned char *buf, size_t len, int freshness = 2147/* max value for ccnx*/);
+  createContentObject(const Name &name, const unsigned char *buf, size_t len, int freshness = 2147/* max value for ccnx*/);
 
   int
   putToCcnd (const Bytes &contentObject);
@@ -91,8 +88,7 @@
   boost::thread m_thread;
   bool m_running;
   bool m_connected;
-  map<string, InterestCallback> m_registeredInterests;
-  // std::list< std::pair<std::string, InterestCallback> > m_registeredInterests;
+  map<Name, InterestCallback> m_registeredInterests;
 };
 
 typedef boost::shared_ptr<CcnxWrapper> CcnxWrapperPtr;
diff --git a/src/ccnx-closure.cpp b/src/ccnx-closure.cpp
index 5b24f66..5b30244 100644
--- a/src/ccnx-closure.cpp
+++ b/src/ccnx-closure.cpp
@@ -23,7 +23,7 @@
 }
 
 Closure::TimeoutCallbackReturnValue
-Closure::runTimeoutCallback(const string &interest)
+Closure::runTimeoutCallback(const Name &interest)
 {
   if ((*m_timeoutCallback).empty())
   {
@@ -35,7 +35,7 @@
 
 
 void
-Closure::runDataCallback(const string &name, const Bytes &content)
+Closure::runDataCallback(const Name &name, const Bytes &content)
 {
   if (m_dataCallback != NULL) {
     (*m_dataCallback)(name, content);
diff --git a/src/ccnx-name.cpp b/src/ccnx-name.cpp
index bc7b9bd..ce5f270 100644
--- a/src/ccnx-name.cpp
+++ b/src/ccnx-name.cpp
@@ -4,6 +4,7 @@
 #include <boost/algorithm/string/join.hpp>
 
 namespace Ccnx{
+CcnxCharbufPtr CcnxCharbuf::Null;
 
 CcnxCharbuf::CcnxCharbuf()
             : m_buf(NULL)
@@ -66,6 +67,40 @@
   }
 }
 
+Name &
+Name::operator=(const Name &other)
+{
+  m_comps = other.m_comps;
+  return *this;
+}
+bool
+Name::operator==(const string &str)
+{
+  return this->toString() == str;
+}
+
+bool
+Name::operator!=(const string &str)
+{
+  return !(*this == str);
+}
+
+Name
+operator+(const Name &n1, const Name &n2)
+{
+  vector<Bytes> comps = n1.m_comps;
+  copy(n2.m_comps.begin(), n2.m_comps.end(), back_inserter(comps));
+  return Name(comps);
+}
+
+string
+Name::toString() const
+{
+  stringstream ss(stringstream::out);
+  ss << *this;
+  return ss.str();
+}
+
 CcnxCharbufPtr
 Name::toCcnxCharbuf() const
 {
@@ -131,7 +166,7 @@
 Name::getPartialName(int start, int n) const
 {
   int size = m_comps.size();
-  if (start < 0 || start >= size || start + n > size)
+  if (start < 0 || start >= size || n > 0 && start + n > size)
   {
     stringstream ss(stringstream::out);
     ss << "getPartialName() parameter out of range! ";
@@ -142,10 +177,21 @@
   }
 
   vector<Bytes> comps;
-  for (int i = 0; i < n; i++)
+  int end;
+  if (n > 0)
   {
-    comps.push_back(m_comps[start + i]);
+    end = start + n;
   }
+  else
+  {
+    end = size;
+  }
+
+  for (int i = start; i < end; i++)
+  {
+    comps.push_back(m_comps[i]);
+  }
+
   return Name(comps);
 }
 
@@ -163,6 +209,31 @@
   return os;
 }
 
+bool
+operator ==(const Name &n1, const Name &n2)
+{
+  stringstream ss1(stringstream::out);
+  stringstream ss2(stringstream::out);
+  ss1 << n1;
+  ss2 << n2;
+  return ss1.str() == ss2.str();
+}
+
+bool
+operator !=(const Name &n1, const Name &n2)
+{
+  return !(n1 == n2);
+}
+
+bool
+operator <(const Name &n1, const Name &n2)
+{
+  stringstream ss1(stringstream::out);
+  stringstream ss2(stringstream::out);
+  ss1 << n1;
+  ss2 << n2;
+  return ss1.str() < ss2.str();
+}
 
 Selectors::Selectors()
           : m_maxSuffixComps(-1)
@@ -185,9 +256,36 @@
   m_publisherPublicKeyDigest = other.m_publisherPublicKeyDigest;
 }
 
-CcnxCharbufPtr
-Selectors::toCcnxCharbuf()
+bool
+Selectors::operator == (const Selectors &other)
 {
+  return m_maxSuffixComps == other.m_maxSuffixComps
+         && m_minSuffixComps == other.m_minSuffixComps
+         && m_answerOriginKind == other.m_answerOriginKind
+         && (m_interestLifetime - other.m_interestLifetime) < 10e-4
+         && m_scope == other.m_scope
+         && m_childSelector == other.m_childSelector;
+}
+
+bool
+Selectors::isEmpty() const
+{
+  return m_maxSuffixComps == -1
+         && m_minSuffixComps == -1
+         && m_answerOriginKind == AOK_DEFAULT
+         && (m_interestLifetime - (-1.0)) < 10e-4
+         && m_scope == -1
+         && m_childSelector == DEFAULT;
+}
+
+
+CcnxCharbufPtr
+Selectors::toCcnxCharbuf() const
+{
+  if (isEmpty())
+  {
+    return CcnxCharbuf::Null;
+  }
   CcnxCharbufPtr ptr(new CcnxCharbuf());
   ccn_charbuf *cbuf = ptr->getBuf();
   ccn_charbuf_append_tt(cbuf, CCN_DTAG_Interest, CCN_DTAG);
diff --git a/src/ccnx-pco.cpp b/src/ccnx-pco.cpp
index 1c24891..dce3bcb 100644
--- a/src/ccnx-pco.cpp
+++ b/src/ccnx-pco.cpp
@@ -46,10 +46,10 @@
   return bytes;
 }
 
-string
+Name
 ParsedContentObject::name() const
 {
-  return CcnxWrapper::extractName(head(m_bytes), m_comps);
+  return Name(head(m_bytes), m_comps);
 }
 
 }
diff --git a/src/ccnx-tunnel.cpp b/src/ccnx-tunnel.cpp
index 037bd8a..49e28af 100644
--- a/src/ccnx-tunnel.cpp
+++ b/src/ccnx-tunnel.cpp
@@ -18,8 +18,8 @@
 void
 CcnxTunnel::refreshLocalPrefix()
 {
-  string newPrefix = getLocalPrefix();
-  if (!newPrefix.empty() && m_localPrefix != newPrefix)
+  Name newPrefix = getLocalPrefix();
+  if (!newPrefix.toString().empty() && m_localPrefix != newPrefix)
   {
     CcnxWrapper::clearInterestFilter(m_localPrefix);
     CcnxWrapper::setInterestFilter(newPrefix, bind(&CcnxTunnel::handleTunneledInterest, this, _1));
@@ -28,23 +28,22 @@
 }
 
 int
-CcnxTunnel::sendInterest (const string &interest, Closure *closure)
+CcnxTunnel::sendInterest (const Name &interest, Closure *closure, const Selectors &selectors)
 {
-  string strInterest = interest;
-  string tunneledInterest = queryRoutableName(strInterest);
-  Closure *cp = new TunnelClosure(closure, this, strInterest);
-  sendInterest(tunneledInterest, cp);
+  Name tunneledInterest = queryRoutableName(interest);
+  Closure *cp = new TunnelClosure(closure, this, interest);
+  sendInterest(tunneledInterest, cp, selectors);
 }
 
 void
-CcnxTunnel::handleTunneledData(const string &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback)
+CcnxTunnel::handleTunneledData(const Name &name, const Bytes &tunneledData, const Closure::DataCallback &originalDataCallback)
 {
   ParsedContentObject pco(tunneledData);
   originalDataCallback(pco.name(), pco.content());
 }
 
 int
-CcnxTunnel::publishData(const string &name, const unsigned char *buf, size_t len, int freshness)
+CcnxTunnel::publishData(const Name &name, const unsigned char *buf, size_t len, int freshness)
 {
   Bytes content = createContentObject(name, buf, len, freshness);
   storeContentObject(name, content);
@@ -53,20 +52,18 @@
 }
 
 int
-CcnxTunnel::publishContentObject(const string &name, const Bytes &contentObject, int freshness)
+CcnxTunnel::publishContentObject(const Name &name, const Bytes &contentObject, int freshness)
 {
-  string tunneledName = m_localPrefix + name;
+  Name tunneledName = m_localPrefix + name;
   Bytes tunneledCo = createContentObject(tunneledName, head(contentObject), contentObject.size(), freshness);
   return putToCcnd(tunneledCo);
 }
 
 void
-CcnxTunnel::handleTunneledInterest(const string &tunneledInterest)
+CcnxTunnel::handleTunneledInterest(const Name &tunneledInterest)
 {
   // The interest must have m_localPrefix as a prefix (component-wise), otherwise ccnd would not deliver it to us
-  string interest = (m_localPrefix == "/")
-                    ? tunneledInterest
-                    : tunneledInterest.substr(m_localPrefix.size());
+  Name interest = tunneledInterest.getPartialName(m_localPrefix.size());
 
   ReadLock(m_ritLock);
 
@@ -82,23 +79,27 @@
 }
 
 bool
-CcnxTunnel::isPrefix(const string &prefix, const string &name)
+CcnxTunnel::isPrefix(const Name &prefix, const Name &name)
 {
-  // prefix is literally prefix of name
-  if (name.find(prefix) == 0)
+  if (prefix.size() > name.size())
   {
-    // name and prefix are exactly the same, or the next character in name
-    // is '/'; in both case, prefix is the ccnx prefix of name (component-wise)
-    if (name.size() == prefix.size() || name.at(prefix.size()) == '/')
+    return false;
+  }
+
+  int size = prefix.size();
+  for (int i = 0; i < size; i++)
+  {
+    if (prefix.getCompAsString(i) != name.getCompAsString(i))
     {
-      return true;
+      return false;
     }
   }
-  return false;
+
+  return true;
 }
 
 int
-CcnxTunnel::setInterestFilter(const string &prefix, const InterestCallback &interestCallback)
+CcnxTunnel::setInterestFilter(const Name &prefix, const InterestCallback &interestCallback)
 {
   WriteLock(m_ritLock);
   // make sure copy constructor for boost::function works properly
@@ -107,28 +108,28 @@
 }
 
 void
-CcnxTunnel::clearInterestFilter(const string &prefix)
+CcnxTunnel::clearInterestFilter(const Name &prefix)
 {
   WriteLock(m_ritLock);
   // remove all
   m_rit.erase(prefix);
 }
 
-TunnelClosure::TunnelClosure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const string &originalInterest)
+TunnelClosure::TunnelClosure(int retry, const DataCallback &dataCallback, const TimeoutCallback &timeoutCallback, CcnxTunnel *tunnel, const Name &originalInterest)
                   : Closure(retry, dataCallback, timeoutCallback)
                   , m_tunnel(tunnel)
                   , m_originalInterest(originalInterest)
 {
 }
 
-TunnelClosure::TunnelClosure(const Closure *closure, CcnxTunnel *tunnel, const string &originalInterest)
+TunnelClosure::TunnelClosure(const Closure *closure, CcnxTunnel *tunnel, const Name &originalInterest)
                  : Closure(*closure)
                  , m_tunnel(tunnel)
 {
 }
 
 void
-TunnelClosure::runDataCallback(const string &name, const Bytes &content)
+TunnelClosure::runDataCallback(const Name &name, const Bytes &content)
 {
   if (m_tunnel != NULL)
   {
@@ -137,7 +138,7 @@
 }
 
 Closure::TimeoutCallbackReturnValue
-TunnelClosure::runTimeoutCallback(const string &interest)
+TunnelClosure::runTimeoutCallback(const Name &interest)
 {
   return Closure::runTimeoutCallback(m_originalInterest);
 }
diff --git a/src/ccnx-wrapper.cpp b/src/ccnx-wrapper.cpp
index 1980e6e..ac65cba 100644
--- a/src/ccnx-wrapper.cpp
+++ b/src/ccnx-wrapper.cpp
@@ -63,7 +63,7 @@
 
   if (!m_registeredInterests.empty())
   {
-    for (map<std::string, InterestCallback>::const_iterator it = m_registeredInterests.begin(); it != m_registeredInterests.end(); ++it)
+    for (map<Name, InterestCallback>::const_iterator it = m_registeredInterests.begin(); it != m_registeredInterests.end(); ++it)
     {
       // clearInterestFilter(it->first);
       setInterestFilter(it->first, it->second);
@@ -211,13 +211,13 @@
 }
 
 Bytes
-CcnxWrapper::createContentObject(const std::string &name, const unsigned char *buf, size_t len, int freshness)
+CcnxWrapper::createContentObject(const Name  &name, const unsigned char *buf, size_t len, int freshness)
 {
-  ccn_charbuf *pname = ccn_charbuf_create();
+  CcnxCharbufPtr ptr = name.toCcnxCharbuf();
+  ccn_charbuf *pname = ptr->getBuf();
   ccn_charbuf *signed_info = ccn_charbuf_create();
   ccn_charbuf *content = ccn_charbuf_create();
 
-  ccn_name_from_uri(pname, name.c_str());
   ccn_signed_info_create(signed_info,
 			 getPublicKeyDigest(),
 			 getPublicKeyDigestLength(),
@@ -236,7 +236,6 @@
   Bytes bytes;
   readRaw(bytes, content->buf, content->length);
 
-  ccn_charbuf_destroy (&pname);
   ccn_charbuf_destroy (&signed_info);
   ccn_charbuf_destroy (&content);
 
@@ -260,35 +259,18 @@
 }
 
 int
-CcnxWrapper::publishData (const string &name, const unsigned char *buf, size_t len, int freshness)
+CcnxWrapper::publishData (const Name &name, const unsigned char *buf, size_t len, int freshness)
 {
   Bytes co = createContentObject(name, buf, len, freshness);
   return putToCcnd(co);
 }
 
 int
-CcnxWrapper::publishData (const string &name, const Bytes &content, int freshness)
+CcnxWrapper::publishData (const Name &name, const Bytes &content, int freshness)
 {
   publishData(name, head(content), content.size(), freshness);
 }
 
-string
-CcnxWrapper::extractName(const unsigned char *data, const ccn_indexbuf *comps)
-{
-  ostringstream name (ostringstream::out);
-  for (int i = 0; i < comps->n - 1; i++)
-  {
-    char *comp;
-    size_t size;
-    name << "/";
-    ccn_name_comp_get(data, comps, i, (const unsigned char **)&comp, &size);
-    string compStr(comp, size);
-    name << compStr;
-  }
-
-  return name.str();
-}
-
 
 static ccn_upcall_res
 incomingInterest(ccn_closure *selfp,
@@ -311,7 +293,7 @@
       return CCN_UPCALL_RESULT_OK;
     }
 
-  string interest = CcnxWrapper::extractName(info->interest_ccnb, info->interest_comps);
+  Name interest(info->interest_ccnb, info->interest_comps);
 
   (*f) (interest);
   return CCN_UPCALL_RESULT_OK;
@@ -341,7 +323,7 @@
         return CCN_UPCALL_RESULT_REEXPRESS;
       }
 
-      string interest = CcnxWrapper::extractName(info->interest_ccnb, info->interest_comps);
+      Name interest(info->interest_ccnb, info->interest_comps);
       Closure::TimeoutCallbackReturnValue rv = cp->runTimeoutCallback(interest);
       switch(rv)
       {
@@ -363,7 +345,7 @@
     // BOOST_THROW_EXCEPTION(CcnxOperationException() << errmsg_info_str("decode ContentObject failed"));
   }
 
-  string name = CcnxWrapper::extractName(info->content_ccnb, info->content_comps);
+  Name name(info->content_ccnb, info->content_comps);
 
   Bytes content;
   // copy content and do processing on the copy
@@ -375,37 +357,44 @@
   return CCN_UPCALL_RESULT_OK;
 }
 
-int CcnxWrapper::sendInterest (const string &interest, Closure *closure)
+int CcnxWrapper::sendInterest (const Name &interest, Closure *closure, const Selectors &selectors)
 {
   UniqueRecLock(m_mutex);
   if (!m_running || !m_connected)
     return -1;
 
-  ccn_charbuf *pname = ccn_charbuf_create();
+  CcnxCharbufPtr namePtr = interest.toCcnxCharbuf();
+  ccn_charbuf *pname = namePtr->getBuf();
   ccn_closure *dataClosure = new ccn_closure;
 
-  ccn_name_from_uri (pname, interest.c_str());
   dataClosure->data = (void *)closure;
 
   dataClosure->p = &incomingData;
-  if (ccn_express_interest (m_handle, pname, dataClosure, NULL) < 0)
+
+  CcnxCharbufPtr selectorsPtr = selectors.toCcnxCharbuf();
+  ccn_charbuf *templ = NULL;
+  if (selectorsPtr != CcnxCharbuf::Null)
+  {
+    templ = selectorsPtr->getBuf();
+  }
+
+  if (ccn_express_interest (m_handle, pname, dataClosure, templ) < 0)
   {
   }
 
-  ccn_charbuf_destroy (&pname);
   return 0;
 }
 
-int CcnxWrapper::setInterestFilter (const string &prefix, const InterestCallback &interestCallback)
+int CcnxWrapper::setInterestFilter (const Name &prefix, const InterestCallback &interestCallback)
 {
   UniqueRecLock(m_mutex);
   if (!m_running || !m_connected)
     return -1;
 
-  ccn_charbuf *pname = ccn_charbuf_create();
+  CcnxCharbufPtr ptr = prefix.toCcnxCharbuf();
+  ccn_charbuf *pname = ptr->getBuf();
   ccn_closure *interestClosure = new ccn_closure;
 
-  ccn_name_from_uri (pname, prefix.c_str());
   interestClosure->data = new InterestCallback (interestCallback); // should be removed when closure is removed
   interestClosure->p = &incomingInterest;
   int ret = ccn_set_interest_filter (m_handle, pname, interestClosure);
@@ -413,37 +402,35 @@
   {
   }
 
-  m_registeredInterests.insert(pair<std::string, InterestCallback>(prefix, interestCallback));
-  ccn_charbuf_destroy(&pname);
+  m_registeredInterests.insert(pair<Name, InterestCallback>(prefix, interestCallback));
 }
 
 void
-CcnxWrapper::clearInterestFilter (const std::string &prefix)
+CcnxWrapper::clearInterestFilter (const Name &prefix)
 {
   UniqueRecLock(m_mutex);
   if (!m_running || !m_connected)
     return;
 
-  ccn_charbuf *pname = ccn_charbuf_create();
+  CcnxCharbufPtr ptr = prefix.toCcnxCharbuf();
+  ccn_charbuf *pname = ptr->getBuf();
 
-  ccn_name_from_uri (pname, prefix.c_str());
   int ret = ccn_set_interest_filter (m_handle, pname, 0);
   if (ret < 0)
   {
   }
 
   m_registeredInterests.erase(prefix);
-  ccn_charbuf_destroy(&pname);
 }
 
-string
+Name
 CcnxWrapper::getLocalPrefix ()
 {
   struct ccn * tmp_handle = ccn_create ();
   int res = ccn_connect (tmp_handle, NULL);
   if (res < 0)
     {
-      return "";
+      return Name();
     }
 
   string retval = "";
@@ -515,7 +502,7 @@
   ccn_disconnect (tmp_handle);
   ccn_destroy (&tmp_handle);
 
-  return retval;
+  return Name(retval);
 }
 
 }