data: Optimize Data signing

As of this commit, KeyChain::sign pre-allocates EncodingBuffer, requests
unsigned portion of Data using Data::wireEncode(EncodingBuffer, true),
and then appends the resulting signature and prepends Data packet
header.  This way there is no extra memory allocation after Data packet
is signed.

Change-Id: I670e9a2f1d6f5e9b049f41b47f011af384f32c95
diff --git a/src/interest.cpp b/src/interest.cpp
index 9e5b129..590d527 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -108,6 +108,124 @@
   return true;
 }
 
+template<bool T>
+size_t
+Interest::wireEncode(EncodingImpl<T>& block) const
+{
+  size_t totalLength = 0;
+
+  // Interest ::= INTEREST-TYPE TLV-LENGTH
+  //                Name
+  //                Selectors?
+  //                Nonce
+  //                Scope?
+  //                InterestLifetime?
+
+  // (reverse encoding)
+
+  // InterestLifetime
+  if (getInterestLifetime() >= time::milliseconds::zero() &&
+      getInterestLifetime() != DEFAULT_INTEREST_LIFETIME)
+    {
+      totalLength += prependNonNegativeIntegerBlock(block,
+                                                    Tlv::InterestLifetime,
+                                                    getInterestLifetime().count());
+    }
+
+  // Scope
+  if (getScope() >= 0)
+    {
+      totalLength += prependNonNegativeIntegerBlock(block, Tlv::Scope, getScope());
+    }
+
+  // Nonce
+  getNonce(); // to ensure that Nonce is properly set
+  totalLength += block.prependBlock(m_nonce);
+
+  // Selectors
+  if (hasSelectors())
+    {
+      totalLength += getSelectors().wireEncode(block);
+    }
+
+  // Name
+  totalLength += getName().wireEncode(block);
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(Tlv::Interest);
+  return totalLength;
+}
+
+const Block&
+Interest::wireEncode() const
+{
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  // to ensure that Nonce block points to the right memory location
+  const_cast<Interest*>(this)->wireDecode(buffer.block());
+
+  return m_wire;
+}
+
+void
+Interest::wireDecode(const Block& wire)
+{
+  m_wire = wire;
+  m_wire.parse();
+
+  // Interest ::= INTEREST-TYPE TLV-LENGTH
+  //                Name
+  //                Selectors?
+  //                Nonce
+  //                Scope?
+  //                InterestLifetime?
+
+  if (m_wire.type() != Tlv::Interest)
+    throw Tlv::Error("Unexpected TLV number when decoding Interest");
+
+  // Name
+  m_name.wireDecode(m_wire.get(Tlv::Name));
+
+  // Selectors
+  Block::element_const_iterator val = m_wire.find(Tlv::Selectors);
+  if (val != m_wire.elements_end())
+    {
+      m_selectors.wireDecode(*val);
+    }
+  else
+    m_selectors = Selectors();
+
+  // Nonce
+  m_nonce = m_wire.get(Tlv::Nonce);
+
+  // Scope
+  val = m_wire.find(Tlv::Scope);
+  if (val != m_wire.elements_end())
+    {
+      m_scope = readNonNegativeInteger(*val);
+    }
+  else
+    m_scope = -1;
+
+  // InterestLifetime
+  val = m_wire.find(Tlv::InterestLifetime);
+  if (val != m_wire.elements_end())
+    {
+      m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
+    }
+  else
+    {
+      m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
+    }
+}
+
 std::ostream&
 operator<<(std::ostream& os, const Interest& interest)
 {