interest: Convert Interest to TLV

Change-Id: I9b6ccd840289d7fd22fc6f652ac4bd7d0fbee63d
diff --git a/include/ndn-cpp/interest.hpp b/include/ndn-cpp/interest.hpp
index d5d8e49..5694394 100644
--- a/include/ndn-cpp/interest.hpp
+++ b/include/ndn-cpp/interest.hpp
@@ -9,187 +9,12 @@
 #define NDN_INTEREST_HPP
 
 #include "name.hpp"
-#include "publisher-public-key-digest.hpp"
-#include "c/interest-types.h"
-#include "encoding/wire-format.hpp"
-
-struct ndn_ExcludeEntry;
-struct ndn_Exclude;
-struct ndn_Interest;
+#include "exclude.hpp"
+#include "encoding/block.hpp"
 
 namespace ndn {
   
 /**
- * An Exclude holds a vector of Exclude::Entry.
- */
-class Exclude {
-public:
-  /**
-   * Create a new Exclude with no entries.
-   */
-  Exclude() 
-  {
-  }
-
-  /**
-   * An Exclude::Entry holds an ndn_ExcludeType, and if it is a COMPONENT, it holds the component value.
-   */
-  class Entry {
-  public:
-    /**
-     * Create an Exclude::Entry of type ndn_Exclude_ANY
-     */
-    Entry()
-    : type_(ndn_Exclude_ANY)
-    {    
-    }
-
-    /**
-     * Create an Exclude::Entry of type ndn_Exclude_COMPONENT.
-     */
-    Entry(uint8_t *component, size_t componentLen) 
-    : type_(ndn_Exclude_COMPONENT), component_(component, componentLen)
-    {
-    }
-
-    /**
-     * Create an Exclude::Entry of type ndn_Exclude_COMPONENT.
-     */
-    Entry(const Blob& component) 
-    : type_(ndn_Exclude_COMPONENT), component_(component)
-    {
-    }
-
-    /**
-     * Set the type in the excludeEntryStruct and to point to this entry, without copying any memory.
-     * WARNING: The resulting pointer in excludeEntryStruct is invalid after a further use of this object which could reallocate memory.
-     * @param excludeEntryStruct the C ndn_ExcludeEntry struct to receive the pointer
-     */
-    void 
-    get(struct ndn_ExcludeEntry& excludeEntryStruct) const;
-
-    ndn_ExcludeType 
-    getType() const { return type_; }
-
-    const Name::Component& 
-    getComponent() const { return component_; }
-
-  private:
-    ndn_ExcludeType type_;
-    Name::Component component_; /**< only used if type_ is ndn_Exclude_COMPONENT */
-  }; 
-
-  /**
-   * Get the number of entries.
-   * @return The number of entries.
-   */
-  size_t 
-  size() const { return entries_.size(); }
-  
-  /**
-   * Get the entry at the given index.
-   * @param i The index of the entry, starting from 0.
-   * @return The entry at the index.
-   */
-  const Exclude::Entry& 
-  get(size_t i) const { return entries_[i]; }
-
-  /**
-   * @deprecated Use size().
-   */  
-  size_t 
-  getEntryCount() const { return entries_.size(); }
-  
-  /**
-   * @deprecated Use get(i).
-   */  
-  const Exclude::Entry& 
-  getEntry(size_t i) const { return entries_[i]; }
-  
-  /**
-   * Set the excludeStruct to point to the entries in this Exclude, without copying any memory.
-   * WARNING: The resulting pointers in excludeStruct are invalid after a further use of this object which could reallocate memory.
-   * @param excludeStruct a C ndn_Exclude struct where the entries array is already allocated
-   */
-  void 
-  get(struct ndn_Exclude& excludeStruct) const;
-  
-  /**
-   * Clear this Exclude, and set the entries by copying from the ndn_Exclude struct.
-   * @param excludeStruct a C ndn_Exclude struct
-   */
-  void 
-  set(const struct ndn_Exclude& excludeStruct);
-
-  /**
-   * Append a new entry of type ndn_Exclude_ANY.
-   * @return This Exclude so that you can chain calls to append.
-   */
-  Exclude& 
-  appendAny()
-  {    
-    entries_.push_back(Entry());
-    return *this;
-  }
-  
-  /**
-   * Append a new entry of type ndn_Exclude_COMPONENT, copying from component of length componentLength.
-   * @param component A pointer to the component byte array.
-   * @param componentLength The length of component.
-   * @return This Exclude so that you can chain calls to append.
-   */
-  Exclude& 
-  appendComponent(uint8_t *component, size_t componentLength) 
-  {
-    entries_.push_back(Entry(component, componentLength));
-    return *this;
-  }
-
-  /**
-   * Append a new entry of type ndn_Exclude_COMPONENT, taking another pointer to the Blob value.
-   * @param component A blob with a pointer to an immutable array.  The pointer is copied.
-   * @return This Exclude so that you can chain calls to append.
-   */
-  Exclude& 
-  appendComponent(const Blob &component) 
-  {
-    entries_.push_back(Entry(component));
-    return *this;
-  }
-
-  /**
-   * @deprecated Use appendAny.
-   */
-  Exclude& 
-  addAny() { return appendAny(); }
-
-  /**
-   * @deprecated Use appendComponent.
-   */
-  Exclude& 
-  addComponent(uint8_t *component, size_t componentLength) { return appendComponent(component, componentLength); }
-  
-  /**
-   * Clear all the entries.
-   */
-  void 
-  clear() 
-  {
-    entries_.clear();
-  }
-  
-  /**
-   * Encode this Exclude with elements separated by "," and ndn_Exclude_ANY shown as "*".
-   * @return the URI string
-   */
-  std::string 
-  toUri() const;
-  
-private:
-  std::vector<Entry> entries_;
-};
-
-/**
  * An Interest holds a Name and other fields for an interest.
  */
 class Interest {
@@ -199,42 +24,29 @@
    * @param name
    * @param minSuffixComponents
    * @param maxSuffixComponents
-   * @param publisherPublicKeyDigest
    * @param exclude
    * @param childSelector
-   * @param answerOriginKind
+   * @param mustBeFresh
    * @param scope
-   * @param interestLifetimeMilliseconds
+   * @param interestLifetime
    * @param nonce
    */
-  Interest(const Name& name, int minSuffixComponents, int maxSuffixComponents, 
-    const PublisherPublicKeyDigest& publisherPublicKeyDigest, const Exclude& exclude, int childSelector, int answerOriginKind, 
-    int scope, Milliseconds interestLifetimeMilliseconds, const Blob& nonce) 
-  : name_(name), minSuffixComponents_(minSuffixComponents), maxSuffixComponents_(maxSuffixComponents),
-  publisherPublicKeyDigest_(publisherPublicKeyDigest), exclude_(exclude), childSelector_(childSelector), 
-  answerOriginKind_(answerOriginKind), scope_(scope), interestLifetimeMilliseconds_(interestLifetimeMilliseconds),
-  nonce_(nonce)
-  {
-  }
-
-  /**
-   * Create a new Interest with the given name and values, and "none" for the nonce.
-   * @param name
-   * @param minSuffixComponents
-   * @param maxSuffixComponents
-   * @param publisherPublicKeyDigest
-   * @param exclude
-   * @param childSelector
-   * @param answerOriginKind
-   * @param scope
-   * @param interestLifetimeMilliseconds
-   */
-  Interest(const Name& name, int minSuffixComponents, int maxSuffixComponents, 
-    const PublisherPublicKeyDigest& publisherPublicKeyDigest, const Exclude& exclude, int childSelector, int answerOriginKind, 
-    int scope, Milliseconds interestLifetimeMilliseconds) 
-  : name_(name), minSuffixComponents_(minSuffixComponents), maxSuffixComponents_(maxSuffixComponents),
-  publisherPublicKeyDigest_(publisherPublicKeyDigest), exclude_(exclude), childSelector_(childSelector), 
-  answerOriginKind_(answerOriginKind), scope_(scope), interestLifetimeMilliseconds_(interestLifetimeMilliseconds)
+  Interest(const Name& name,
+           int minSuffixComponents, int maxSuffixComponents, 
+           const Exclude& exclude,
+           int childSelector,
+           bool mustBeFresh, 
+           int scope,
+           Milliseconds interestLifetime,
+           uint32_t nonce = 0) 
+  : name_(name)
+  , minSuffixComponents_(minSuffixComponents)
+  , maxSuffixComponents_(maxSuffixComponents)
+  , exclude_(exclude), childSelector_(childSelector)
+  , mustBeFresh_(mustBeFresh)
+  , scope_(scope)
+  , interestLifetime_(interestLifetime)
+  , nonce_(nonce)
   {
   }
 
@@ -243,11 +55,11 @@
    * @param name The name for the interest.
    * @param interestLifetimeMilliseconds The interest lifetime in milliseconds, or -1 for none.
    */
-  Interest(const Name& name, Milliseconds interestLifetimeMilliseconds) 
+  Interest(const Name& name, Milliseconds interestLifetime) 
   : name_(name)
   {
     construct();
-    interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
+    interestLifetime_ = interestLifetime;
   }
 
   /**
@@ -273,10 +85,10 @@
    * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat::getDefaultWireFormat().
    * @return The encoded byte array.
    */
-  Blob 
-  wireEncode(WireFormat& wireFormat = *WireFormat::getDefaultWireFormat()) const 
+  const Block&
+  wireEncode() const 
   {
-    return wireFormat.encodeInterest(*this);
+    return wire_;
   }
   
   /**
@@ -286,9 +98,9 @@
    * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat::getDefaultWireFormat().
    */
   void 
-  wireDecode(const uint8_t *input, size_t inputLength, WireFormat& wireFormat = *WireFormat::getDefaultWireFormat()) 
+  wireDecode(const Block &wire) 
   {
-    wireFormat.decodeInterest(*this, input, inputLength);
+    // wireFormat.decodeInterest(*this, input, inputLength);
   }
   
   /**
@@ -296,27 +108,19 @@
    * @param input The input byte array to be decoded.
    * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat::getDefaultWireFormat().
    */
-  void 
-  wireDecode(const std::vector<uint8_t>& input, WireFormat& wireFormat = *WireFormat::getDefaultWireFormat()) 
-  {
-    wireDecode(&input[0], input.size(), wireFormat);
-  }
+  // void 
+  // wireDecode(const std::vector<uint8_t>& input, WireFormat& wireFormat = *WireFormat::getDefaultWireFormat()) 
+  // {
+  //   wireDecode(&input[0], input.size(), wireFormat);
+  // }
   
   /**
    * Encode the name according to the "NDN URI Scheme".  If there are interest selectors, append "?" and
    * added the selectors as a query string.  For example "/test/name?ndn.ChildSelector=1".
    * @return The URI string.
    */
-  std::string
+  inline std::string
   toUri() const;
-  
-  /**
-   * Set the interestStruct to point to the components in this interest, without copying any memory.
-   * WARNING: The resulting pointers in interestStruct are invalid after a further use of this object which could reallocate memory.
-   * @param interestStruct a C ndn_Interest struct where the name components array is already allocated.
-   */
-  void 
-  get(struct ndn_Interest& interestStruct) const;
 
   Name& 
   getName() { return name_; }
@@ -329,12 +133,6 @@
   
   int 
   getMaxSuffixComponents() const { return maxSuffixComponents_; }
-  
-  PublisherPublicKeyDigest& 
-  getPublisherPublicKeyDigest() { return publisherPublicKeyDigest_; }
-  
-  const PublisherPublicKeyDigest& 
-  getPublisherPublicKeyDigest() const { return publisherPublicKeyDigest_; }
 
   Exclude& 
   getExclude() { return exclude_; }
@@ -346,24 +144,17 @@
   getChildSelector() const { return childSelector_; }
 
   int 
-  getAnswerOriginKind() const { return answerOriginKind_; }
+  getMustBeFresh() const { return mustBeFresh_; }
 
   int 
   getScope() const { return scope_; }
 
   Milliseconds 
-  getInterestLifetimeMilliseconds() const { return interestLifetimeMilliseconds_; }
+  getInterestLifetime() const { return interestLifetime_; }
 
-  const Blob& 
+  uint32_t
   getNonce() const { return nonce_; }
-  
-  /**
-   * Clear this interest, and set the values by copying from the interest struct.
-   * @param interestStruct a C ndn_Interest struct
-   */
-  void 
-  set(const struct ndn_Interest& interestStruct);
-  
+    
   void
   setName(const Name& name) { name_ = name; }
   
@@ -377,16 +168,32 @@
   setChildSelector(int childSelector) { childSelector_ = childSelector; }
 
   void 
-  setAnswerOriginKind(int answerOriginKind) { answerOriginKind_ = answerOriginKind; }
+  setMustBeFresh(bool mustBeFresh) { mustBeFresh_ = mustBeFresh; }
 
   void 
   setScope(int scope) { scope_ = scope; }
 
   void 
-  setInterestLifetimeMilliseconds(Milliseconds interestLifetimeMilliseconds) { interestLifetimeMilliseconds_ = interestLifetimeMilliseconds; }
+  setInterestLifetime(Milliseconds interestLifetime) { interestLifetime_ = interestLifetime; }
 
   void 
-  setNonce(const Blob& nonce) { nonce_ = nonce; }
+  setNonce(uint32_t nonce) { nonce_ = nonce; }
+
+  inline bool
+  hasSelectors() const;
+
+  inline bool
+  hasGuiders() const;
+
+  /**
+   * @brief Check if Interest name matches the given name (using ndn_Name_match) and the given name also conforms to the 
+   * interest selectors.
+   * @param self A pointer to the ndn_Interest struct.
+   * @param name A pointer to the name to check.
+   * @return 1 if the name and interest selectors match, 0 otherwise.
+   */
+  bool
+  matchesName(const Name &name) const;
   
 private:
   void 
@@ -395,23 +202,55 @@
     minSuffixComponents_ = -1;
     maxSuffixComponents_ = -1;  
     childSelector_ = -1;
-    answerOriginKind_ = -1;
+    mustBeFresh_ = false; // default
     scope_ = -1;
-    interestLifetimeMilliseconds_ = -1.0;
+    interestLifetime_ = -1.0;
+    nonce_ = 0;
   }
   
   Name name_;
   int minSuffixComponents_;
   int maxSuffixComponents_;  
-  PublisherPublicKeyDigest publisherPublicKeyDigest_;
   Exclude exclude_;
   int childSelector_;
-  int answerOriginKind_;
+  bool mustBeFresh_;
   int scope_;
-  Milliseconds interestLifetimeMilliseconds_;
-  Blob nonce_;
+  Milliseconds interestLifetime_;
+  uint32_t nonce_;
+
+  Block wire_;
 };
-  
+
+std::ostream &
+operator << (std::ostream &os, const Interest &interest);
+
+inline std::string
+Interest::toUri() const
+{
+  std::ostringstream os;
+  os << *this;
+  return os.str();
+}
+
+inline bool
+Interest::hasSelectors() const
+{
+  return minSuffixComponents_ >= 0 ||
+    maxSuffixComponents_ >= 0 ||
+    !exclude_.empty() ||
+    childSelector_ >= 0 ||
+    mustBeFresh_ == true ||
+    scope_ >= 0;
+}
+
+inline bool
+Interest::hasGuiders() const
+{
+  return scope_ >= 0 ||
+    interestLifetime_ >= 0 ||
+    nonce_ > 0;
+}
+
 }
 
 #endif
diff --git a/src/interest.cpp b/src/interest.cpp
index fe8faf3..2caffb1 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -8,139 +8,76 @@
 #include <stdexcept>
 #include <ndn-cpp/common.hpp>
 #include <ndn-cpp/interest.hpp>
-#include "c/interest.h"
 
 using namespace std;
 
 namespace ndn {
-  
-void 
-Exclude::Entry::get(struct ndn_ExcludeEntry& excludeEntryStruct) const 
+
+bool
+Interest::matchesName(const Name &name) const
 {
-  excludeEntryStruct.type = type_;
-  if (type_ == ndn_Exclude_COMPONENT)
-    component_.get(excludeEntryStruct.component);
+  if (!name_.isPrefixOf(name))
+    return false;
+  
+  if (minSuffixComponents_ >= 0 &&
+    // Add 1 for the implicit digest.
+      !(name.size() + 1 - name_.size() >= minSuffixComponents_))
+    return false;
+
+  if (maxSuffixComponents_ >= 0 &&
+    // Add 1 for the implicit digest.
+    !(name.size() + 1 - name_.size() <= maxSuffixComponents_))
+    return false;
+
+  if (!exclude_.empty() && name.size() > name_.size() &&
+      exclude_.isExcluded(name[name_.size()]))
+    return false;
+
+  return true;
 }
 
-void 
-Exclude::get(struct ndn_Exclude& excludeStruct) const
+std::ostream &
+operator << (std::ostream &os, const Interest &interest)
 {
-  if (excludeStruct.maxEntries < entries_.size())
-    throw runtime_error("excludeStruct.maxEntries must be >= this exclude getEntryCount()");
-  
-  excludeStruct.nEntries = entries_.size();
-  for (size_t i = 0; i < excludeStruct.nEntries; ++i)
-    entries_[i].get(excludeStruct.entries[i]);  
-}
+  os << interest.getName();
 
-void 
-Exclude::set(const struct ndn_Exclude& excludeStruct)
-{
-  entries_.clear();
-  for (size_t i = 0; i < excludeStruct.nEntries; ++i) {
-    ndn_ExcludeEntry *entry = &excludeStruct.entries[i];
-    
-    if (entry->type == ndn_Exclude_COMPONENT)
-      appendComponent(entry->component.value.value, entry->component.value.length);
-    else if (entry->type == ndn_Exclude_ANY)
-      appendAny();
-    else
-      throw runtime_error("unrecognized ndn_ExcludeType");
+  char delim = '?';
+
+  if (interest.getMinSuffixComponents() >= 0) {
+    os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
+    delim = '&';
   }
-}
-
-string 
-Exclude::toUri() const
-{
-  if (entries_.size() == 0)
-    return "";
-
-  ostringstream result;
-  for (unsigned i = 0; i < entries_.size(); ++i) {
-    if (i > 0)
-      result << ",";
-        
-    if (entries_[i].getType() == ndn_Exclude_ANY)
-      result << "*";
-    else
-      Name::toEscapedString(*entries_[i].getComponent().getValue(), result);
+  if (interest.getMaxSuffixComponents() >= 0) {
+    os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
+    delim = '&';
   }
-  
-  return result.str();  
-}
-
-void 
-Interest::set(const struct ndn_Interest& interestStruct) 
-{
-  name_.set(interestStruct.name);
-  minSuffixComponents_ = interestStruct.minSuffixComponents;
-  maxSuffixComponents_ = interestStruct.maxSuffixComponents;
-  
-  publisherPublicKeyDigest_.set(interestStruct.publisherPublicKeyDigest);
-  
-  exclude_.set(interestStruct.exclude);
-  childSelector_ = interestStruct.childSelector;
-  answerOriginKind_ = interestStruct.answerOriginKind;
-  scope_ = interestStruct.scope;
-  interestLifetimeMilliseconds_ = interestStruct.interestLifetimeMilliseconds;
-  nonce_ = Blob(interestStruct.nonce);
-}
-
-void 
-Interest::get(struct ndn_Interest& interestStruct) const 
-{
-  name_.get(interestStruct.name);
-  interestStruct.minSuffixComponents = minSuffixComponents_;
-  interestStruct.maxSuffixComponents = maxSuffixComponents_;
-  publisherPublicKeyDigest_.get(interestStruct.publisherPublicKeyDigest);
-  exclude_.get(interestStruct.exclude);
-  interestStruct.childSelector = childSelector_;
-  interestStruct.answerOriginKind = answerOriginKind_;
-  interestStruct.scope = scope_;
-  interestStruct.interestLifetimeMilliseconds = interestLifetimeMilliseconds_;
-  nonce_.get(interestStruct.nonce);
-}
-
-string 
-Interest::toUri() const
-{
-  ostringstream selectors;
-
-  if (minSuffixComponents_ >= 0)
-    selectors << "&ndn.MinSuffixComponents=" << minSuffixComponents_;
-  if (maxSuffixComponents_ >= 0)
-    selectors << "&ndn.MaxSuffixComponents=" << maxSuffixComponents_;
-  if (childSelector_ >= 0)
-    selectors << "&ndn.ChildSelector=" << childSelector_;
-  if (answerOriginKind_ >= 0)
-    selectors << "&ndn.AnswerOriginKind=" << answerOriginKind_;
-  if (scope_ >= 0)
-    selectors << "&ndn.Scope=" << scope_;
-  if (interestLifetimeMilliseconds_ >= 0)
-    selectors << "&ndn.InterestLifetime=" << interestLifetimeMilliseconds_;
-  if (publisherPublicKeyDigest_.getPublisherPublicKeyDigest().size() > 0) {
-    selectors << "&ndn.PublisherPublicKeyDigest=";
-    Name::toEscapedString(*publisherPublicKeyDigest_.getPublisherPublicKeyDigest(), selectors);
+  if (interest.getChildSelector() >= 0) {
+    os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
+    delim = '&';
   }
-  if (nonce_.size() > 0) {
-    selectors << "&ndn.Nonce=";
-    Name::toEscapedString(*nonce_, selectors);
+  if (interest.getMustBeFresh()) {
+    os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
+    delim = '&';
   }
-  if (exclude_.size() > 0)
-    selectors << "&ndn.Exclude=" << exclude_.toUri();
-
-  ostringstream result;
-
-  result << name_.toUri();
-  string selectorsString(selectors.str());
-  if (selectorsString.size() > 0) {
-    // Replace the first & with ?.
-    result << "?";
-    result.write(&selectorsString[1], selectorsString.size() - 1);
+  if (interest.getScope() >= 0) {
+    os << delim << "ndn.Scope=" << interest.getScope();
+    delim = '&';
   }
-  
-  return result.str();  
+  if (interest.getInterestLifetime() >= 0) {
+    os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime();
+    delim = '&';
+  }
+
+  if (interest.getNonce() > 0) {
+    os << delim << "ndn.Nonce=" << interest.getNonce();
+    delim = '&';
+  }
+  if (!interest.getExclude().empty()) {
+    os << delim << "ndn.Exclude=" << interest.getExclude();
+    delim = '&';
+  }
+
+  return os;
 }
 
 }
-