interest: More TLV-related changes

Change-Id: I3cf300b58aaf7091cb0b27827b39bfe9e3556c78
diff --git a/include/ndn-cpp/interest.hpp b/include/ndn-cpp/interest.hpp
index 5694394..17b9b67 100644
--- a/include/ndn-cpp/interest.hpp
+++ b/include/ndn-cpp/interest.hpp
@@ -82,37 +82,17 @@
   
   /**
    * Encode this Interest for a particular wire format.
-   * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat::getDefaultWireFormat().
    * @return The encoded byte array.
    */
   const Block&
-  wireEncode() const 
-  {
-    return wire_;
-  }
+  wireEncode() const;
   
   /**
    * Decode the input using a particular wire format and update this Interest.
    * @param input The input byte array to be decoded.
-   * @param inputLength The length of input.
-   * @param wireFormat A WireFormat object used to decode the input. If omitted, use WireFormat::getDefaultWireFormat().
    */
   void 
-  wireDecode(const Block &wire) 
-  {
-    // wireFormat.decodeInterest(*this, input, inputLength);
-  }
-  
-  /**
-   * Decode the input using a particular wire format and update this Interest.
-   * @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);
-  // }
+  wireDecode(const Block &wire);
   
   /**
    * Encode the name according to the "NDN URI Scheme".  If there are interest selectors, append "?" and
@@ -218,7 +198,7 @@
   Milliseconds interestLifetime_;
   uint32_t nonce_;
 
-  Block wire_;
+  mutable Block wire_;
 };
 
 std::ostream &
diff --git a/src/interest.cpp b/src/interest.cpp
index 2caffb1..0a4c8d7 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -80,4 +80,167 @@
   return os;
 }
 
+const Block&
+Interest::wireEncode() const
+{
+  if (wire_.hasWire())
+    return wire_;
+
+  wire_ = Block(Tlv::Interest);
+  wire_.push_back(getName().wireEncode());
+
+  // selectors
+  {
+    Block selectors(Tlv::Selectors);
+    
+    if (getMinSuffixComponents() >= 0) {
+      OBufferStream os;
+      Tlv::writeVarNumber(os, Tlv::MinSuffixComponents);
+      Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getMinSuffixComponents()));
+      Tlv::writeNonNegativeInteger(os, getMinSuffixComponents());
+
+      selectors.push_back(Block(os.buf()));
+    }
+    if (getMaxSuffixComponents() >= 0) {
+      OBufferStream os;
+      Tlv::writeVarNumber(os, Tlv::MaxSuffixComponents);
+      Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getMaxSuffixComponents()));
+      Tlv::writeNonNegativeInteger(os, getMaxSuffixComponents());
+
+      selectors.push_back(Block(os.buf()));
+    }
+    if (!getExclude().empty()) {
+      selectors.push_back(getExclude().wireEncode());
+    }
+    if (getChildSelector() >= 0) {
+      OBufferStream os;
+      Tlv::writeVarNumber(os, Tlv::ChildSelector);
+      Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getChildSelector()));
+      Tlv::writeNonNegativeInteger(os, getChildSelector());
+
+      selectors.push_back(Block(os.buf()));
+    }
+    if (getMustBeFresh()) {
+      OBufferStream os;
+      Tlv::writeVarNumber(os, Tlv::MustBeFresh);
+      Tlv::writeVarNumber(os, 0);
+
+      selectors.push_back(Block(os.buf()));
+    }
+
+    selectors.encode();
+    wire_.push_back(selectors);
+  }
+
+  // Nonce
+  {
+    OBufferStream os;
+    Tlv::writeVarNumber(os, Tlv::Nonce);
+    Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getNonce()));
+    Tlv::writeNonNegativeInteger(os, getNonce());
+
+    wire_.push_back(Block(os.buf()));
+  }
+  
+  if (getScope() >= 0) {
+    OBufferStream os;
+    Tlv::writeVarNumber(os, Tlv::Scope);
+    Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getScope()));
+    Tlv::writeNonNegativeInteger(os, getScope());
+
+    wire_.push_back(Block(os.buf()));
+  }
+  if (getInterestLifetime() >= 0) {
+    OBufferStream os;
+    Tlv::writeVarNumber(os, Tlv::InterestLifetime);
+    Tlv::writeVarNumber(os, Tlv::sizeOfNonNegativeInteger(getInterestLifetime()));
+    Tlv::writeNonNegativeInteger(os, getInterestLifetime());
+
+    wire_.push_back(Block(os.buf()));
+  }
+  
+  wire_.encode();
+  return wire_;
+}
+  
+void 
+Interest::wireDecode(const Block &wire) 
+{
+  wire_ = wire;
+  wire_.parse();
+
+  // Name
+  name_.wireDecode(wire_.get(Tlv::Name));
+
+  // Selectors
+  Block::element_iterator selectors = wire_.find(Tlv::Selectors);
+  if (selectors != wire_.getAll().end())
+    {
+      selectors->parse();
+
+      // MinSuffixComponents
+      Block::element_iterator val = selectors->find(Tlv::MinSuffixComponents);
+      if (val != selectors->getAll().end())
+        {
+          Buffer::const_iterator begin = val->value_begin();
+          minSuffixComponents_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+        }
+
+      // MaxSuffixComponents
+      val = selectors->find(Tlv::MaxSuffixComponents);
+      if (val != selectors->getAll().end())
+        {
+          Buffer::const_iterator begin = val->value_begin();
+          maxSuffixComponents_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+        }
+
+      // Exclude
+      val = selectors->find(Tlv::Exclude);
+      if (val != selectors->getAll().end())
+        {
+          exclude_.wireDecode(*val);
+        }
+
+      // ChildSelector
+      val = selectors->find(Tlv::ChildSelector);
+      if (val != selectors->getAll().end())
+        {
+          Buffer::const_iterator begin = val->value_begin();
+          childSelector_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+        }
+
+      //MustBeFresh aka AnswerOriginKind
+      val = selectors->find(Tlv::MustBeFresh);
+      if (val != selectors->getAll().end())
+        {
+          mustBeFresh_ = true;
+        }
+    }
+  
+  // Nonce
+  Block::element_iterator val = wire_.find(Tlv::Nonce);
+  if (val != wire_.getAll().end())
+    {
+      Buffer::const_iterator begin = val->value_begin();
+      nonce_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+    }
+
+  // Scope
+  val = wire_.find(Tlv::Scope);
+  if (val != wire_.getAll().end())
+    {
+      Buffer::const_iterator begin = val->value_begin();
+      scope_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+    }
+  
+  // InterestLifetime
+  val = wire_.find(Tlv::InterestLifetime);
+  if (val != wire_.getAll().end())
+    {
+      Buffer::const_iterator begin = val->value_begin();
+      interestLifetime_ = Tlv::readNonNegativeInteger(val->value_size(), begin, val->value_end());
+    } 
+}
+
+
 }