decoding+transport: Exception-safe Block parsing

Change-Id: I3e83b6ca4c8ca42b8bb1ddc8dc50c52ee366c55c
Refs: #1291
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index eaba9ba..07ec2f0 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -59,7 +59,7 @@
 {
   m_value_begin = m_begin;
   m_value_end   = m_end;
-  
+
   m_type = Tlv::readType(m_value_begin, m_value_end);
 
   uint64_t length = Tlv::readVarNumber(m_value_begin, m_value_end);
@@ -93,9 +93,9 @@
 
 Block::Block(std::istream& is)
 {
-  std::istream_iterator<uint8_t> tmp_begin(is);  
+  std::istream_iterator<uint8_t> tmp_begin(is);
   std::istream_iterator<uint8_t> tmp_end;
-  
+
   m_type = Tlv::readType(tmp_begin, tmp_end);
   uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
 
@@ -104,7 +104,7 @@
   OBufferStream os;
   size_t headerLength = Tlv::writeVarNumber(os, m_type);
   headerLength += Tlv::writeVarNumber(os, length);
-  
+
   char* buf = new char[length];
   buf[0] = *tmp_begin;
   is.read(buf+1, length-1);
@@ -113,7 +113,7 @@
     {
       delete [] buf;
       throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
-    } 
+    }
 
   os.write(buf, length);
   delete [] buf;
@@ -132,11 +132,11 @@
 Block::Block(const uint8_t *buffer, size_t maxlength)
 {
   const uint8_t * tmp_begin = buffer;
-  const uint8_t * tmp_end   = buffer + maxlength;  
-  
+  const uint8_t * tmp_end   = buffer + maxlength;
+
   m_type = Tlv::readType(tmp_begin, tmp_end);
   uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
-  
+
   if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
     {
       throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
@@ -155,13 +155,13 @@
 Block::Block(const void *bufferX, size_t maxlength)
 {
   const uint8_t * buffer = reinterpret_cast<const uint8_t*>(bufferX);
-  
+
   const uint8_t * tmp_begin = buffer;
-  const uint8_t * tmp_end   = buffer + maxlength;  
-  
+  const uint8_t * tmp_end   = buffer + maxlength;
+
   m_type = Tlv::readType(tmp_begin, tmp_end);
   uint64_t length = Tlv::readVarNumber(tmp_begin, tmp_end);
-  
+
   if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
     {
       throw Tlv::Error("Not enough data in the buffer to fully parse TLV");
@@ -204,19 +204,75 @@
   m_size = Tlv::sizeOfVarNumber(m_type) + Tlv::sizeOfVarNumber(value_size()) + value_size();
 }
 
+bool
+Block::fromBuffer(const ConstBufferPtr& wire, size_t offset, Block& block)
+{
+  Buffer::const_iterator tempBegin = wire->begin() + offset;
+
+  uint32_t type;
+  bool ok = Tlv::readType(tempBegin, wire->end(), type);
+  if (!ok)
+    return false;
+
+  uint64_t length;
+  ok = Tlv::readVarNumber(tempBegin, wire->end(), length);
+  if (!ok)
+    return false;
+
+  if (length > static_cast<uint64_t>(wire->end() - tempBegin))
+    {
+      return false;
+    }
+
+  block = Block(wire, type,
+                wire->begin() + offset, tempBegin + length,
+                tempBegin, tempBegin + length);
+
+  return true;
+}
+
+bool
+Block::fromBuffer(const uint8_t* buffer, size_t maxSize, Block& block)
+{
+  const uint8_t* tempBegin = buffer;
+  const uint8_t* tempEnd = buffer + maxSize;
+
+  uint32_t type;
+  bool ok = Tlv::readType(tempBegin, tempEnd, type);
+  if (!ok)
+    return false;
+
+  uint64_t length;
+  ok = Tlv::readVarNumber(tempBegin, tempEnd, length);
+  if (!ok)
+    return false;
+
+  if (length > static_cast<uint64_t>(tempEnd - tempBegin))
+    {
+      return false;
+    }
+
+  BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
+  block = Block(sharedBuffer, type,
+                sharedBuffer->begin(), sharedBuffer->end(),
+                sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end());
+
+  return true;
+}
+
 void
 Block::parse() const
 {
   if (!m_subBlocks.empty() || value_size()==0)
     return;
-  
+
   Buffer::const_iterator begin = value_begin(),
     end = value_end();
 
   while (begin != end)
     {
       Buffer::const_iterator element_begin = begin;
-      
+
       uint32_t type = Tlv::readType(begin, end);
       uint64_t length = Tlv::readVarNumber(begin, end);
 
@@ -226,7 +282,7 @@
           throw Tlv::Error("TLV length exceeds buffer length");
         }
       Buffer::const_iterator element_end = begin + length;
-      
+
       m_subBlocks.push_back(Block(m_buffer,
                                   type,
                                   element_begin, element_end,
@@ -261,7 +317,7 @@
       for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
         valueSize += i->size();
       }
-  
+
       Tlv::writeVarNumber(os, valueSize);
 
       for (element_const_iterator i = m_subBlocks.begin(); i != m_subBlocks.end(); ++i) {
@@ -286,7 +342,7 @@
 
   m_value_begin = m_buffer->begin();
   m_value_end   = m_buffer->end();
-  
+
   Tlv::readType(m_value_begin, m_value_end);
   Tlv::readVarNumber(m_value_begin, m_value_end);
 }
@@ -296,18 +352,18 @@
 {
   if (value_size()==0)
     throw Error("Underlying value buffer is empty");
-  
+
   Buffer::const_iterator begin = value_begin(),
     end = value_end();
 
   Buffer::const_iterator element_begin = begin;
-      
+
   uint32_t type = Tlv::readType(begin, end);
   uint64_t length = Tlv::readVarNumber(begin, end);
 
   if (length != static_cast<uint64_t>(end - begin))
     throw Tlv::Error("TLV length mismatches buffer length");
-      
+
   return Block(m_buffer,
                type,
                element_begin, end,