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/encoding/encoding-buffer.hpp b/src/encoding/encoding-buffer.hpp
index d3fa3ac..4c5185e 100644
--- a/src/encoding/encoding-buffer.hpp
+++ b/src/encoding/encoding-buffer.hpp
@@ -145,6 +145,9 @@
   inline size_t
   appendVarNumber(uint64_t varNumber);
 
+  inline size_t
+  appendBlock(const Block& block);
+
   // inline void
   // removeByteFromFront();
 
@@ -207,6 +210,9 @@
 
   inline size_t
   appendVarNumber(uint64_t varNumber);
+
+  inline size_t
+  appendBlock(const Block& block);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -270,6 +276,25 @@
   return encoder.prependByteArray(block.wire(), block.size());
 }
 
+template<bool P>
+inline size_t
+appendByteArrayBlock(EncodingImpl<P>& encoder, uint32_t type,
+                      const uint8_t* array, size_t arraySize)
+{
+  size_t totalLength = encoder.appendVarNumber(type);
+  totalLength += encoder.appendVarNumber(arraySize);
+  totalLength += encoder.appendByteArray(array, arraySize);
+
+  return totalLength;
+}
+
+template<bool P>
+inline size_t
+appendBlock(EncodingImpl<P>& encoder, const Block& block)
+{
+  return encoder.appendByteArray(block.wire(), block.size());
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
@@ -536,6 +561,28 @@
 }
 
 inline size_t
+EncodingImpl<encoding::Buffer>::appendBlock(const Block& block)
+{
+  if (block.hasWire()) {
+    return appendByteArray(block.wire(), block.size());
+  }
+  else {
+    return appendByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+  }
+}
+
+inline size_t
+EncodingImpl<encoding::Estimator>::appendBlock(const Block& block)
+{
+  if (block.hasWire()) {
+    return block.size();
+  }
+  else {
+    return appendByteArrayBlock(*this, block.type(), block.value(), block.value_size());
+  }
+}
+
+inline size_t
 EncodingImpl<encoding::Estimator>::appendByteArray(const uint8_t* array, size_t length)
 {
   return prependByteArray(array, length);