encoding: reorganize Block class code

* Improve Doxygen.
* Consolidate and simplify constructors.
* Reorder class methods in cpp file to match hpp.
* Make operator== and operator!= non-member functions.
* Improve exception messages.
* Update code style.

refs #4171

Change-Id: I4cc0393f43a24a500b0efff90108ad1b42f5fa47
diff --git a/src/encoding/block.cpp b/src/encoding/block.cpp
index 16c05c5..82b1110 100644
--- a/src/encoding/block.cpp
+++ b/src/encoding/block.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,10 +23,9 @@
 
 #include "block.hpp"
 #include "block-helpers.hpp"
-
-#include "tlv.hpp"
-#include "encoding-buffer.hpp"
 #include "buffer-stream.hpp"
+#include "encoding-buffer.hpp"
+#include "tlv.hpp"
 
 #include <boost/lexical_cast.hpp>
 #include <boost/asio/buffer.hpp>
@@ -45,176 +44,122 @@
 
 const size_t MAX_SIZE_OF_BLOCK_FROM_STREAM = MAX_NDN_PACKET_SIZE;
 
+// ---- constructor, creation, assignment ----
+
 Block::Block()
   : m_type(std::numeric_limits<uint32_t>::max())
+  , m_size(0)
 {
 }
 
 Block::Block(const EncodingBuffer& buffer)
-  : m_buffer(const_cast<EncodingBuffer&>(buffer).getBuffer())
-  , m_begin(buffer.begin())
-  , m_end(buffer.end())
-  , m_size(m_end - m_begin)
-{
-  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);
-  if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
-    {
-      BOOST_THROW_EXCEPTION(tlv::Error("TLV length doesn't match buffer length"));
-    }
-}
-
-Block::Block(const ConstBufferPtr& wire,
-             uint32_t type,
-             const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
-             const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd)
-  : m_buffer(wire)
-  , m_type(type)
-  , m_begin(begin)
-  , m_end(end)
-  , m_size(m_end - m_begin)
-  , m_value_begin(valueBegin)
-  , m_value_end(valueEnd)
+  : Block(const_cast<EncodingBuffer&>(buffer).getBuffer(), buffer.begin(), buffer.end(), true)
 {
 }
 
 Block::Block(const ConstBufferPtr& buffer)
-  : m_buffer(buffer)
-  , m_begin(m_buffer->begin())
-  , m_end(m_buffer->end())
-  , m_size(m_end - m_begin)
+  : Block(buffer, buffer->begin(), buffer->end(), true)
 {
-  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);
-  if (length != static_cast<uint64_t>(m_value_end - m_value_begin))
-    {
-      BOOST_THROW_EXCEPTION(tlv::Error("TLV length doesn't match buffer length"));
-    }
 }
 
-Block::Block(const ConstBufferPtr& buffer,
-             const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
-             bool verifyLength/* = true*/)
-  : m_buffer(buffer)
+Block::Block(ConstBufferPtr buffer, Buffer::const_iterator begin, Buffer::const_iterator end,
+             bool verifyLength)
+  : m_buffer(std::move(buffer))
   , m_begin(begin)
   , m_end(end)
+  , m_valueBegin(m_begin)
+  , m_valueEnd(m_end)
   , m_size(m_end - m_begin)
 {
-  m_value_begin = m_begin;
-  m_value_end   = m_end;
+  if (m_buffer->size() == 0) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("buffer is empty"));
+  }
 
-  m_type = tlv::readType(m_value_begin, m_value_end);
-  uint64_t length = tlv::readVarNumber(m_value_begin, m_value_end);
-  if (verifyLength) {
-    if (length != static_cast<uint64_t>(std::distance(m_value_begin, m_value_end))) {
-      BOOST_THROW_EXCEPTION(tlv::Error("TLV length doesn't match buffer length"));
-    }
+  const uint8_t* bufferBegin = &m_buffer->front();
+  const uint8_t* bufferEnd = bufferBegin + m_buffer->size();
+  if (&*begin < bufferBegin || &*begin > bufferEnd ||
+      &*end   < bufferBegin || &*end   > bufferEnd) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("begin/end iterators points out of the buffer"));
+  }
+
+  m_type = tlv::readType(m_valueBegin, m_valueEnd);
+  uint64_t length = tlv::readVarNumber(m_valueBegin, m_valueEnd);
+  // m_valueBegin now points to TLV-VALUE
+
+  if (verifyLength && length != static_cast<uint64_t>(m_valueEnd - m_valueBegin)) {
+    BOOST_THROW_EXCEPTION(Error("TLV-LENGTH doesn't match buffer size"));
   }
 }
 
-Block::Block(const Block& block,
-             const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
-             bool verifyLength/* = true*/)
-  : m_buffer(block.m_buffer)
+Block::Block(const Block& block, Buffer::const_iterator begin, Buffer::const_iterator end,
+             bool verifyLength)
+  : Block(block.m_buffer, begin, end, verifyLength)
+{
+}
+
+Block::Block(ConstBufferPtr buffer, uint32_t type,
+             Buffer::const_iterator begin, Buffer::const_iterator end,
+             Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd)
+  : m_buffer(std::move(buffer))
   , m_begin(begin)
   , m_end(end)
+  , m_valueBegin(valueBegin)
+  , m_valueEnd(valueEnd)
+  , m_type(type)
   , m_size(m_end - m_begin)
 {
-  if (!(m_buffer->begin() <= begin && begin <= m_buffer->end()) ||
-      !(m_buffer->begin() <= end   && end   <= m_buffer->end())) {
-    BOOST_THROW_EXCEPTION(Error("begin/end iterators do not point to the underlying buffer of the block"));
-  }
-
-  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);
-  if (verifyLength) {
-    if (length != static_cast<uint64_t>(std::distance(m_value_begin, m_value_end))) {
-      BOOST_THROW_EXCEPTION(tlv::Error("TLV length doesn't match buffer length"));
-    }
-  }
 }
 
-Block::Block(const uint8_t* buffer, size_t maxlength)
+Block::Block(const uint8_t* buf, size_t bufSize)
 {
-  const uint8_t*  tmp_begin = buffer;
-  const uint8_t*  tmp_end   = buffer + maxlength;
+  const uint8_t* pos = buf;
+  const uint8_t* const end = buf + bufSize;
 
-  m_type = tlv::readType(tmp_begin, tmp_end);
-  uint64_t length = tlv::readVarNumber(tmp_begin, tmp_end);
+  m_type = tlv::readType(pos, end);
+  uint64_t length = tlv::readVarNumber(pos, end);
+  // pos now points to TLV-VALUE
 
-  if (length > static_cast<uint64_t>(tmp_end - tmp_begin))
-    {
-      BOOST_THROW_EXCEPTION(tlv::Error("Not enough data in the buffer to fully parse TLV"));
-    }
+  if (length > static_cast<uint64_t>(end - pos)) {
+    BOOST_THROW_EXCEPTION(tlv::Error("Not enough data in the buffer to fully parse TLV"));
+  }
+  size_t typeLengthSize = pos - buf;
+  m_size = typeLengthSize + length;
 
-  m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
-
+  m_buffer = make_shared<Buffer>(buf, m_size);
   m_begin = m_buffer->begin();
-  m_end = m_buffer->end();
-  m_size = m_end - m_begin;
-
-  m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
-  m_value_end   = m_buffer->end();
+  m_end = m_valueEnd = m_buffer->end();
+  m_valueBegin = m_begin + typeLengthSize;
 }
 
-Block::Block(const void* bufferX, size_t maxlength)
+Block::Block(const void* buf, size_t bufSize)
+  : Block(reinterpret_cast<const uint8_t*>(buf), bufSize)
 {
-  const uint8_t* buffer = reinterpret_cast<const uint8_t*>(bufferX);
-
-  const uint8_t* tmp_begin = buffer;
-  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))
-    {
-      BOOST_THROW_EXCEPTION(tlv::Error("Not enough data in the buffer to fully parse TLV"));
-    }
-
-  m_buffer = make_shared<Buffer>(buffer, (tmp_begin - buffer) + length);
-
-  m_begin = m_buffer->begin();
-  m_end = m_buffer->end();
-  m_size = m_end - m_begin;
-
-  m_value_begin = m_buffer->begin() + (tmp_begin - buffer);
-  m_value_end   = m_buffer->end();
 }
 
 Block::Block(uint32_t type)
   : m_type(type)
+  , m_size(tlv::sizeOfVarNumber(m_type) + tlv::sizeOfVarNumber(0))
 {
 }
 
-Block::Block(uint32_t type, const ConstBufferPtr& value)
-  : m_buffer(value)
-  , m_type(type)
+Block::Block(uint32_t type, ConstBufferPtr value)
+  : m_buffer(std::move(value))
   , m_begin(m_buffer->end())
   , m_end(m_buffer->end())
-  , m_value_begin(m_buffer->begin())
-  , m_value_end(m_buffer->end())
+  , m_valueBegin(m_buffer->begin())
+  , m_valueEnd(m_buffer->end())
+  , m_type(type)
 {
   m_size = tlv::sizeOfVarNumber(m_type) + tlv::sizeOfVarNumber(value_size()) + value_size();
 }
 
 Block::Block(uint32_t type, const Block& value)
   : m_buffer(value.m_buffer)
-  , m_type(type)
   , m_begin(m_buffer->end())
   , m_end(m_buffer->end())
-  , m_value_begin(value.begin())
-  , m_value_end(value.end())
+  , m_valueBegin(value.begin())
+  , m_valueEnd(value.end())
+  , m_type(type)
 {
   m_size = tlv::sizeOfVarNumber(m_type) + tlv::sizeOfVarNumber(value_size()) + value_size();
 }
@@ -229,11 +174,13 @@
   uint64_t length = tlv::readVarNumber(begin, end);
 
   if (length == 0) {
-    return makeEmptyBlock(type);
+    // XXX An extra octet is incorrectly consumed from istream (#4180)
+    return Block(type);
   }
 
-  if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM)
-    BOOST_THROW_EXCEPTION(tlv::Error("Length of block from stream is too large"));
+  if (length > MAX_SIZE_OF_BLOCK_FROM_STREAM) {
+    BOOST_THROW_EXCEPTION(tlv::Error("TLV-LENGTH from stream exceeds limit"));
+  }
 
   // We may still have some problem here, if some exception happens,
   // we may completely lose all the bytes extracted from the stream.
@@ -252,225 +199,78 @@
 std::tuple<bool, Block>
 Block::fromBuffer(ConstBufferPtr buffer, size_t offset)
 {
-  Buffer::const_iterator tempBegin = buffer->begin() + offset;
+  const Buffer::const_iterator begin = buffer->begin() + offset;
+  Buffer::const_iterator pos = begin;
 
-  uint32_t type;
-  bool isOk = tlv::readType(tempBegin, buffer->end(), type);
-  if (!isOk)
+  uint32_t type = 0;
+  bool isOk = tlv::readType(pos, buffer->end(), type);
+  if (!isOk) {
     return std::make_tuple(false, Block());
-
-  uint64_t length;
-  isOk = tlv::readVarNumber(tempBegin, buffer->end(), length);
-  if (!isOk)
+  }
+  uint64_t length = 0;
+  isOk = tlv::readVarNumber(pos, buffer->end(), length);
+  if (!isOk) {
     return std::make_tuple(false, Block());
+  }
+  // pos now points to TLV-VALUE
 
-  if (length > static_cast<uint64_t>(buffer->end() - tempBegin))
+  if (length > static_cast<uint64_t>(buffer->end() - pos)) {
     return std::make_tuple(false, Block());
+  }
 
-  return std::make_tuple(true, Block(buffer, type,
-                                     buffer->begin() + offset, tempBegin + length,
-                                     tempBegin, tempBegin + length));
+  return std::make_tuple(true, Block(buffer, type, begin, pos + length, pos, pos + length));
 }
 
 std::tuple<bool, Block>
-Block::fromBuffer(const uint8_t* buffer, size_t maxSize)
+Block::fromBuffer(const uint8_t* buf, size_t bufSize)
 {
-  const uint8_t* tempBegin = buffer;
-  const uint8_t* tempEnd = buffer + maxSize;
+  const uint8_t* pos = buf;
+  const uint8_t* const end = buf + bufSize;
 
   uint32_t type = 0;
-  bool isOk = tlv::readType(tempBegin, tempEnd, type);
-  if (!isOk)
+  bool isOk = tlv::readType(pos, end, type);
+  if (!isOk) {
     return std::make_tuple(false, Block());
-
-  uint64_t length;
-  isOk = tlv::readVarNumber(tempBegin, tempEnd, length);
-  if (!isOk)
+  }
+  uint64_t length = 0;
+  isOk = tlv::readVarNumber(pos, end, length);
+  if (!isOk) {
     return std::make_tuple(false, Block());
+  }
+  // pos now points to TLV-VALUE
 
-  if (length > static_cast<uint64_t>(tempEnd - tempBegin))
+  if (length > static_cast<uint64_t>(end - pos)) {
     return std::make_tuple(false, Block());
+  }
 
-  BufferPtr sharedBuffer = make_shared<Buffer>(buffer, tempBegin + length);
-  return std::make_tuple(true,
-         Block(sharedBuffer, type,
-               sharedBuffer->begin(), sharedBuffer->end(),
-               sharedBuffer->begin() + (tempBegin - buffer), sharedBuffer->end()));
+  size_t typeLengthSize = pos - buf;
+  auto b = make_shared<Buffer>(buf, pos + length);
+  return std::make_tuple(true, Block(b, type, b->begin(), b->end(),
+                                     b->begin() + typeLengthSize, b->end()));
+}
+
+// ---- wire format ----
+
+bool
+Block::hasWire() const
+{
+  return m_buffer != nullptr && m_begin != m_end;
 }
 
 void
 Block::reset()
 {
-  m_buffer.reset(); // reset of the shared_ptr
-  m_subBlocks.clear(); // remove all parsed subelements
+  this->resetWire();
 
   m_type = std::numeric_limits<uint32_t>::max();
-  m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
+  m_elements.clear();
 }
 
 void
 Block::resetWire()
 {
-  m_buffer.reset(); // reset of the shared_ptr
-  // keep subblocks
-
-  // keep type
-  m_begin = m_end = m_value_begin = m_value_end = Buffer::const_iterator();
-}
-
-void
-Block::parse() const
-{
-  if (!m_subBlocks.empty() || value_size() == 0)
-    return;
-
-  Buffer::const_iterator begin = value_begin();
-  Buffer::const_iterator 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);
-
-      if (length > static_cast<uint64_t>(end - begin))
-        {
-          m_subBlocks.clear();
-          BOOST_THROW_EXCEPTION(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,
-                                  begin, element_end));
-
-      begin = element_end;
-      // don't do recursive parsing, just the top level
-    }
-}
-
-void
-Block::encode()
-{
-  if (hasWire())
-    return;
-
-  OBufferStream os;
-  tlv::writeVarNumber(os, type());
-
-  if (hasValue())
-    {
-      tlv::writeVarNumber(os, value_size());
-      os.write(reinterpret_cast<const char*>(value()), value_size());
-    }
-  else if (m_subBlocks.size() == 0)
-    {
-      tlv::writeVarNumber(os, 0);
-    }
-  else
-    {
-      size_t valueSize = 0;
-      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) {
-        if (i->hasWire())
-          os.write(reinterpret_cast<const char*>(i->wire()), i->size());
-        else if (i->hasValue()) {
-          tlv::writeVarNumber(os, i->type());
-          tlv::writeVarNumber(os, i->value_size());
-          os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
-        }
-        else
-          BOOST_THROW_EXCEPTION(Error("Underlying value buffer is empty"));
-      }
-    }
-
-  // now assign correct block
-
-  m_buffer = os.buf();
-  m_begin = m_buffer->begin();
-  m_end   = m_buffer->end();
-  m_size  = m_end - m_begin;
-
-  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);
-}
-
-const Block&
-Block::get(uint32_t type) const
-{
-  element_const_iterator it = this->find(type);
-  if (it != m_subBlocks.end())
-    return *it;
-
-  BOOST_THROW_EXCEPTION(Error("(Block::get) Requested a non-existed type [" +
-                              boost::lexical_cast<std::string>(type) + "] from Block"));
-}
-
-Block::element_const_iterator
-Block::find(uint32_t type) const
-{
-  return std::find_if(m_subBlocks.begin(), m_subBlocks.end(),
-                      [type] (const Block& subBlock) { return subBlock.type() == type; });
-}
-
-void
-Block::remove(uint32_t type)
-{
-  resetWire();
-
-  auto it = std::remove_if(m_subBlocks.begin(), m_subBlocks.end(),
-                           [type] (const Block& subBlock) { return subBlock.type() == type; });
-  m_subBlocks.resize(it - m_subBlocks.begin());
-}
-
-Block
-Block::blockFromValue() const
-{
-  if (value_size() == 0)
-    BOOST_THROW_EXCEPTION(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))
-    BOOST_THROW_EXCEPTION(tlv::Error("TLV length mismatches buffer length"));
-
-  return Block(m_buffer,
-               type,
-               element_begin, end,
-               begin, end);
-}
-
-Block::operator boost::asio::const_buffer() const
-{
-  return boost::asio::const_buffer(wire(), size());
-}
-
-bool
-Block::empty() const
-{
-  return m_type == std::numeric_limits<uint32_t>::max();
-}
-
-bool
-Block::hasWire() const
-{
-  return m_buffer && (m_begin != m_end);
+  m_buffer.reset(); // discard underlying buffer by resetting shared_ptr
+  m_begin = m_end = m_valueBegin = m_valueEnd = Buffer::const_iterator();
 }
 
 Buffer::const_iterator
@@ -495,7 +295,7 @@
 Block::wire() const
 {
   if (!hasWire())
-    BOOST_THROW_EXCEPTION(Error("(Block::wire) Underlying wire buffer is empty"));
+    BOOST_THROW_EXCEPTION(Error("Underlying wire buffer is empty"));
 
   return &*m_begin;
 }
@@ -503,35 +303,144 @@
 size_t
 Block::size() const
 {
-  if (hasWire() || hasValue()) {
-    return m_size;
-  }
-  else
+  if (empty()) {
     BOOST_THROW_EXCEPTION(Error("Block size cannot be determined (undefined block size)"));
+  }
+
+  return m_size;
 }
 
-bool
-Block::hasValue() const
-{
-  return static_cast<bool>(m_buffer);
-}
+// ---- value ----
 
 const uint8_t*
 Block::value() const
 {
-  if (!hasValue())
-    return 0;
-
-  return &*m_value_begin;
+  return hasValue() ? &*m_valueBegin : nullptr;
 }
 
 size_t
 Block::value_size() const
 {
-  if (!hasValue())
-    return 0;
+  return hasValue() ? m_valueEnd - m_valueBegin : 0;
+}
 
-  return m_value_end - m_value_begin;
+Block
+Block::blockFromValue() const
+{
+  if (!hasValue())
+    BOOST_THROW_EXCEPTION(Error("Block has no TLV-VALUE"));
+
+  return Block(*this, m_valueBegin, m_valueEnd, true);
+}
+
+// ---- sub elements ----
+
+void
+Block::parse() const
+{
+  if (!m_elements.empty() || value_size() == 0)
+    return;
+
+  Buffer::const_iterator begin = value_begin();
+  Buffer::const_iterator end = value_end();
+
+  while (begin != end) {
+    Buffer::const_iterator pos = begin;
+
+    uint32_t type = tlv::readType(pos, end);
+    uint64_t length = tlv::readVarNumber(pos, end);
+    if (length > static_cast<uint64_t>(end - pos)) {
+      m_elements.clear();
+      BOOST_THROW_EXCEPTION(Error("TLV-LENGTH of sub-element of type " + to_string(type) +
+                                  " exceeds TLV-VALUE boundary of parent block"));
+    }
+    // pos now points to TLV-VALUE of sub element
+
+    Buffer::const_iterator subEnd = pos + length;
+    m_elements.emplace_back(m_buffer, type, begin, subEnd, pos, subEnd);
+
+    begin = subEnd;
+  }
+}
+
+void
+Block::encode()
+{
+  if (hasWire())
+    return;
+
+  OBufferStream os;
+  tlv::writeVarNumber(os, type());
+
+  if (hasValue()) {
+    tlv::writeVarNumber(os, value_size());
+    os.write(reinterpret_cast<const char*>(value()), value_size());
+  }
+  else if (m_elements.size() == 0) {
+    tlv::writeVarNumber(os, 0);
+  }
+  else {
+    size_t valueSize = 0;
+    for (element_const_iterator i = m_elements.begin(); i != m_elements.end(); ++i) {
+      valueSize += i->size();
+    }
+
+    tlv::writeVarNumber(os, valueSize);
+
+    for (element_const_iterator i = m_elements.begin(); i != m_elements.end(); ++i) {
+      if (i->hasWire())
+        os.write(reinterpret_cast<const char*>(i->wire()), i->size());
+      else if (i->hasValue()) {
+        tlv::writeVarNumber(os, i->type());
+        tlv::writeVarNumber(os, i->value_size());
+        os.write(reinterpret_cast<const char*>(i->value()), i->value_size());
+      }
+      else
+        BOOST_THROW_EXCEPTION(Error("Underlying value buffer is empty"));
+    }
+  }
+
+  // now assign correct block
+
+  m_buffer = os.buf();
+  m_begin = m_buffer->begin();
+  m_end   = m_buffer->end();
+  m_size  = m_end - m_begin;
+
+  m_valueBegin = m_buffer->begin();
+  m_valueEnd   = m_buffer->end();
+
+  tlv::readType(m_valueBegin, m_valueEnd);
+  tlv::readVarNumber(m_valueBegin, m_valueEnd);
+}
+
+const Block&
+Block::get(uint32_t type) const
+{
+  auto it = this->find(type);
+  if (it != m_elements.end()) {
+    return *it;
+  }
+
+  BOOST_THROW_EXCEPTION(Error("No sub-element of type " + to_string(type) +
+                              " is found in block of type " + to_string(m_type)));
+}
+
+Block::element_const_iterator
+Block::find(uint32_t type) const
+{
+  return std::find_if(m_elements.begin(), m_elements.end(),
+                      [type] (const Block& subBlock) { return subBlock.type() == type; });
+}
+
+void
+Block::remove(uint32_t type)
+{
+  resetWire();
+
+  auto it = std::remove_if(m_elements.begin(), m_elements.end(),
+                           [type] (const Block& subBlock) { return subBlock.type() == type; });
+  m_elements.resize(it - m_elements.begin());
 }
 
 Block::element_iterator
@@ -540,11 +449,11 @@
   resetWire();
 
 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR
-  return m_subBlocks.erase(position);
+  return m_elements.erase(position);
 #else
-  element_iterator it = m_subBlocks.begin();
-  std::advance(it, std::distance(m_subBlocks.cbegin(), position));
-  return m_subBlocks.erase(it);
+  element_iterator it = m_elements.begin();
+  std::advance(it, std::distance(m_elements.cbegin(), position));
+  return m_elements.erase(it);
 #endif
 }
 
@@ -554,13 +463,13 @@
   resetWire();
 
 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR
-  return m_subBlocks.erase(first, last);
+  return m_elements.erase(first, last);
 #else
-  element_iterator itStart = m_subBlocks.begin();
-  element_iterator itEnd = m_subBlocks.begin();
-  std::advance(itStart, std::distance(m_subBlocks.cbegin(), first));
-  std::advance(itEnd, std::distance(m_subBlocks.cbegin(), last));
-  return m_subBlocks.erase(itStart, itEnd);
+  element_iterator itStart = m_elements.begin();
+  element_iterator itEnd = m_elements.begin();
+  std::advance(itStart, std::distance(m_elements.cbegin(), first));
+  std::advance(itEnd, std::distance(m_elements.cbegin(), last));
+  return m_elements.erase(itStart, itEnd);
 #endif
 }
 
@@ -568,7 +477,7 @@
 Block::push_back(const Block& element)
 {
   resetWire();
-  m_subBlocks.push_back(element);
+  m_elements.push_back(element);
 }
 
 Block::element_iterator
@@ -577,43 +486,27 @@
   resetWire();
 
 #ifdef NDN_CXX_HAVE_VECTOR_INSERT_ERASE_CONST_ITERATOR
-  return m_subBlocks.insert(pos, element);
+  return m_elements.insert(pos, element);
 #else
-  element_iterator it = m_subBlocks.begin();
-  std::advance(it, std::distance(m_subBlocks.cbegin(), pos));
-  return m_subBlocks.insert(it, element);
+  element_iterator it = m_elements.begin();
+  std::advance(it, std::distance(m_elements.cbegin(), pos));
+  return m_elements.insert(it, element);
 #endif
 }
 
-Block::element_const_iterator
-Block::elements_begin() const
-{
-  return m_subBlocks.begin();
-}
+// ---- misc ----
 
-Block::element_const_iterator
-Block::elements_end() const
+Block::operator boost::asio::const_buffer() const
 {
-  return m_subBlocks.end();
-}
-
-size_t
-Block::elements_size() const
-{
-  return m_subBlocks.size();
+  return boost::asio::const_buffer(wire(), size());
 }
 
 bool
-Block::operator!=(const Block& other) const
+operator==(const Block& lhs, const Block& rhs)
 {
-  return !this->operator==(other);
-}
-
-bool
-Block::operator==(const Block& other) const
-{
-  return this->size() == other.size() &&
-         std::equal(this->begin(), this->end(), other.begin());
+  return lhs.type() == rhs.type() &&
+         lhs.value_size() == rhs.value_size() &&
+         ::memcmp(lhs.value(), rhs.value(), lhs.value_size()) == 0;
 }
 
 } // namespace ndn
diff --git a/src/encoding/block.hpp b/src/encoding/block.hpp
index 7ade6e3..a5f1e1a 100644
--- a/src/encoding/block.hpp
+++ b/src/encoding/block.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -43,9 +43,9 @@
 class Block
 {
 public:
-  typedef std::vector<Block>                 element_container;
-  typedef element_container::iterator        element_iterator;
-  typedef element_container::const_iterator  element_const_iterator;
+  using element_container      = std::vector<Block>;
+  using element_iterator       = element_container::iterator;
+  using element_const_iterator = element_container::const_iterator;
 
   class Error : public tlv::Error
   {
@@ -62,286 +62,366 @@
    */
   Block();
 
-  /** @brief Create a Block based on EncodingBuffer object
+  /** @brief Parse Block from an EncodingBuffer
+   *  @param buffer an EncodingBuffer containing one TLV element
+   *  @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
    */
   explicit
   Block(const EncodingBuffer& buffer);
 
-  /** @brief Create a Block from the raw buffer with Type-Length parsing
+  /** @brief Parse Block from a wire Buffer
+   *  @param buffer a Buffer containing one TLV element
+   *  @note This constructor takes shared ownership of @p buffer.
+   *  @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
    */
   explicit
   Block(const ConstBufferPtr& buffer);
 
-  /** @brief Create a Block from a buffer, directly specifying boundaries
-   *         of the block within the buffer
-   *
-   *  This overload will automatically detect type and position of the value within the block
+  /** @brief Parse Block within boundaries of a wire Buffer
+   *  @param buffer a Buffer containing an TLV element at [@p begin,@p end)
+   *  @param begin begin position of the TLV element within @p buffer
+   *  @param end end position of the TLV element within @p buffer
+   *  @param verifyLength if true, check TLV-LENGTH equals size of TLV-VALUE
+   *  @throw std::invalid_argument @p buffer is empty, or [@p begin,@p end) range are not within @p buffer
+   *  @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
+   *  @note This overload automatically detects TLV-TYPE and position of TLV-VALUE.
    */
-  Block(const ConstBufferPtr& buffer,
-        const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
+  Block(ConstBufferPtr buffer, Buffer::const_iterator begin, Buffer::const_iterator end,
         bool verifyLength = true);
 
-  /** @brief Create a Block from existing block (reusing the underlying buffer), directly
-   *         specifying boundaries of the block within the buffer
-   *
-   *  This overload will automatically detect type and position of the value within the block
+  /** @brief Parse Block within boundaries of an existing Block, reusing underlying wire Buffer
+   *  @param block a Block whose buffer contains an TLV element at [@p begin,@p end)
+   *  @param begin begin position of the TLV element within @p block
+   *  @param end end position of the TLV element within @p block
+   *  @param verifyLength if true, check TLV-LENGTH equals size of TLV-VALUE
+   *  @throw std::invalid_argument [@p begin,@p end) range are not within @p block
+   *  @throw tlv::Error Type-Length parsing fails, or TLV-LENGTH does not match size of TLV-VALUE
    */
-  Block(const Block& block,
-        const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
+  Block(const Block& block, Buffer::const_iterator begin, Buffer::const_iterator end,
         bool verifyLength = true);
 
-  /** @brief Create a Block from the raw buffer with Type-Length parsing
+  /** @brief Create a Block from a wire Buffer without parsing
+   *  @param buffer a Buffer containing an TLV element at [@p begin,@p end)
+   *  @param type TLV-TYPE
+   *  @param begin begin position of the TLV element within @p buffer
+   *  @param end end position of the TLV element within @p buffer
+   *  @param valueBegin begin position of TLV-VALUE within @p buffer
+   *  @param valueEnd end position of TLV-VALUE within @p buffer
    */
-  Block(const uint8_t* buffer, size_t maxlength);
+  Block(ConstBufferPtr buffer, uint32_t type,
+        Buffer::const_iterator begin, Buffer::const_iterator end,
+        Buffer::const_iterator valueBegin, Buffer::const_iterator valueEnd);
 
-  /** @brief Create a Block from the raw buffer with Type-Length parsing
+  /** @brief Parse Block from a raw buffer
+   *  @param buf pointer to the first octet of an TLV element
+   *  @param bufSize size of the raw buffer; may be more than size of the TLV element
+   *  @throw tlv::Error Type-Length parsing fails, or size of TLV-VALUE exceeds @p bufSize
+   *  @note This overload copies the TLV element into an internal wire buffer.
    */
-  Block(const void* buffer, size_t maxlength);
+  Block(const uint8_t* buf, size_t bufSize);
 
-  /** @brief Create a Block from the wire buffer (no parsing)
-   *
-   *  This overload does not do any parsing
+  /** @brief Parse Block from a raw buffer
+   *  @deprecated use Block(const uint8_t*, size_t)
    */
-  Block(const ConstBufferPtr& wire,
-        uint32_t type,
-        const Buffer::const_iterator& begin, const Buffer::const_iterator& end,
-        const Buffer::const_iterator& valueBegin, const Buffer::const_iterator& valueEnd);
+  Block(const void* buf, size_t bufSize);
 
-  /** @brief Create Block of a specific type with empty wire buffer
+  /** @brief Create an empty Block with specified TLV-TYPE
+   *  @param type TLV-TYPE
    */
   explicit
   Block(uint32_t type);
 
-  /** @brief Create a Block of a specific type with the specified value
-   *
-   *  The underlying buffer holds only value Additional operations are needed
-   *  to construct wire encoding, one need to prepend the wire buffer with type
-   *  and value-length VAR-NUMBERs
+  /** @brief Create a Block with specified TLV-TYPE and TLV-VALUE
+   *  @param type TLV-TYPE
+   *  @param value a Buffer containing the TLV-VALUE
    */
-  Block(uint32_t type, const ConstBufferPtr& value);
+  Block(uint32_t type, ConstBufferPtr value);
 
-  /** @brief Create a nested Block of a specific type with the specified value
-   *
-   *  The underlying buffer holds only value. Additional operations are needed
-   *  to construct wire encoding, one need to prepend the wire buffer with type
-   *  and value-length VAR-NUMBERs
+  /** @brief Create a Block with specified TLV-TYPE and TLV-VALUE
+   *  @param type TLV-TYPE
+   *  @param value a Block to be nested as TLV-VALUE
    */
   Block(uint32_t type, const Block& value);
 
-  /** @brief Create a Block from an input stream
+  /** @brief Parse Block from an input stream
    */
   static Block
   fromStream(std::istream& is);
 
-  /** @brief Try to construct block from Buffer
-   *  @param buffer the buffer to construct block from
-   *  @note buffer is passed by value because the constructed block
-   *        takes shared ownership of the buffer
-   *  @param offset offset from beginning of \p buffer to construct Block from
-   *
-   *  This method does not throw upon decoding error.
-   *  This method does not copy the bytes.
-   *
-   *  @return true and the Block, if Block is successfully created; otherwise false
+  /** @brief Try to parse Block from a wire buffer
+   *  @param buffer a Buffer containing an TLV element at offset @p offset
+   *  @param offset begin position of the TLV element within @p buffer
+   *  @note This function does not throw exceptions upon decoding failure.
+   *  @return true and the Block if parsing succeeds; otherwise false
    */
   static std::tuple<bool, Block>
   fromBuffer(ConstBufferPtr buffer, size_t offset);
 
-  /** @brief Try to construct block from raw buffer
-   *  @param buffer the raw buffer to copy bytes from
-   *  @param maxSize the maximum size of constructed block;
-   *                 @p buffer must have a size of at least @p maxSize
-   *
-   *  This method does not throw upon decoding error.
-   *  This method copies the bytes into a new Buffer.
-   *
-   *  @return true and the Block, if Block is successfully created; otherwise false
+  /** @brief Try to parse Block from a raw buffer
+   *  @param buf pointer to the first octet of an TLV element
+   *  @param bufSize size of the raw buffer; may be more than size of the TLV element
+   *  @note This function does not throw exceptions upon decoding failure.
+   *  @note This overload copies the TLV element into an internal wire buffer.
+   *  @return true and the Block if parsing succeeds; otherwise false
    */
   static std::tuple<bool, Block>
-  fromBuffer(const uint8_t* buffer, size_t maxSize);
+  fromBuffer(const uint8_t* buf, size_t bufSize);
 
 public: // wire format
   /** @brief Check if the Block is empty
+   *
+   *  A Block is "empty" only if it is default-constructed. A Block with zero-length TLV-VALUE is
+   *  not considered empty.
    */
   bool
-  empty() const;
+  empty() const
+  {
+    return m_type == std::numeric_limits<uint32_t>::max();
+  }
 
   /** @brief Check if the Block has fully encoded wire
+   *
+   *  A Block has fully encoded wire if the underlying buffer exists and contains full
+   *  Type-Length-Value instead of just TLV-VALUE field.
    */
   bool
   hasWire() const;
 
   /** @brief Reset wire buffer of the element
+   *  @post empty() == true
    */
   void
   reset();
 
-  /** @brief Reset wire buffer but keep sub elements (if any)
+  /** @brief Reset wire buffer but keep TLV-TYPE and sub elements (if any)
+   *  @post hasWire() == false
+   *  @post hasValue() == false
    */
   void
   resetWire();
 
+  /** @brief Get begin iterator of encoded wire
+   *  @pre hasWire() == true
+   */
   Buffer::const_iterator
   begin() const;
 
+  /** @brief Get end iterator of encoded wire
+   *  @pre hasWire() == true
+   */
   Buffer::const_iterator
   end() const;
 
+  /** @brief Get pointer to encoded wire
+   *  @pre hasWire() == true
+   */
   const uint8_t*
   wire() const;
 
+  /** @brief Get size of encoded wire, including Type-Length-Value
+   *  @pre empty() == false
+   */
   size_t
   size() const;
 
-public: // type and value
-  uint32_t
-  type() const;
+  /** @brief Get underlying buffer
+   */
+  shared_ptr<const Buffer>
+  getBuffer() const
+  {
+    return m_buffer;
+  }
 
-  /** @brief Check if the Block has value block (no type and length are encoded)
+public: // type and value
+  /** @brief Get TLV-TYPE
+   */
+  uint32_t
+  type() const
+  {
+    return m_type;
+  }
+
+  /** @brief Get begin iterator of TLV-VALUE
+   *
+   *  This property reflects whether the underlying buffer contains TLV-VALUE. If this is false,
+   *  TLV-VALUE has zero-length. If this is true, TLV-VALUE may be zero-length.
    */
   bool
-  hasValue() const;
+  hasValue() const
+  {
+    return m_buffer != nullptr;
+  }
 
+  /** @brief Get begin iterator of TLV-VALUE
+   *  @pre hasValue() == true
+   */
   Buffer::const_iterator
-  value_begin() const;
+  value_begin() const
+  {
+    return m_valueBegin;
+  }
 
+  /** @brief Get end iterator of TLV-VALUE
+   *  @pre hasValue() == true
+   */
   Buffer::const_iterator
-  value_end() const;
+  value_end() const
+  {
+    return m_valueEnd;
+  }
 
+  /** @brief Get pointer to TLV-VALUE
+   */
   const uint8_t*
   value() const;
 
+  /** @brief Get size of TLV-VALUE aka TLV-LENGTH
+   */
   size_t
   value_size() const;
 
-public: // sub elements
-  /** @brief Parse wire buffer into subblocks
-   *
-   *  This method is not really const, but it does not modify any data.  It simply
-   *  parses contents of the buffer into subblocks
-   */
-  void
-  parse() const;
-
-  /** @brief Encode subblocks into wire buffer
-   */
-  void
-  encode();
-
-  /** @brief Get the first subelement of the requested type
-   */
-  const Block&
-  get(uint32_t type) const;
-
-  element_const_iterator
-  find(uint32_t type) const;
-
-  /**
-   * @brief remove all subelements of \p type
-   * @param type TLV-TYPE of subelements to remove
-   * @pre parse() has been invoked
-   */
-  void
-  remove(uint32_t type);
-
-  element_iterator
-  erase(element_const_iterator position);
-
-  element_iterator
-  erase(element_const_iterator first, element_const_iterator last);
-
-  void
-  push_back(const Block& element);
-
-  /**
-   * @brief insert Insert a new element in a specific position
-   * @param pos Position to insert the new element
-   * @param element Element to be inserted
-   * @return An iterator that points to the first of the newly inserted elements.
-   */
-  element_iterator
-  insert(element_const_iterator pos, const Block& element);
-
-  /** @brief Get all subelements
-   */
-  const element_container&
-  elements() const;
-
-  element_const_iterator
-  elements_begin() const;
-
-  element_const_iterator
-  elements_end() const;
-
-  size_t
-  elements_size() const;
-
   Block
   blockFromValue() const;
 
-  /**
-   * @brief Get underlying buffer
+public: // sub elements
+  /** @brief Parse TLV-VALUE into sub elements
+   *  @post elements() reflects sub elements found in TLV-VALUE
+   *  @throw tlv::Error TLV-VALUE is not a sequence of TLV elements
+   *  @note This method does not perform recursive parsing.
+   *  @note This method has no effect if elements() is already populated.
+   *  @note This method is not really const, but it does not modify any data.
    */
-  shared_ptr<const Buffer>
-  getBuffer() const;
+  void
+  parse() const;
 
-public: // EqualityComparable concept
-  bool
-  operator==(const Block& other) const;
+  /** @brief Encode sub elements into TLV-VALUE
+   *  @post TLV-VALUE contains sub elements from elements()
+   */
+  void
+  encode();
 
-  bool
-  operator!=(const Block& other) const;
+  /** @brief Get the first sub element of specified TLV-TYPE
+   *  @pre parse() has been executed
+   *  @throw Error sub element of @p type does not exist
+   */
+  const Block&
+  get(uint32_t type) const;
 
-public: // ConvertibleToConstBuffer
+  /** @brief Find the first sub element of specified TLV-TYPE
+   *  @pre parse() has been executed
+   *  @return iterator in elements() to the found sub element, otherwise elements_end()
+   */
+  element_const_iterator
+  find(uint32_t type) const;
+
+  /** @brief Remove all sub elements of specified TLV-TYPE
+   *  @pre parse() has been executed
+   *  @post find(type) == elements_end()
+   */
+  void
+  remove(uint32_t type);
+
+  /** @brief Erase a sub element
+   */
+  element_iterator
+  erase(element_const_iterator position);
+
+  /** @brief Erase a range of sub elements
+   */
+  element_iterator
+  erase(element_const_iterator first, element_const_iterator last);
+
+  /** @brief Append a sub element
+   */
+  void
+  push_back(const Block& element);
+
+  /** @brief Insert a sub element
+   *  @param pos position of new sub element
+   *  @param element new sub element
+   *  @return iterator in elements() to the new sub element
+   */
+  element_iterator
+  insert(element_const_iterator pos, const Block& element);
+
+  /** @brief Get container of sub elements
+   *  @pre parse() has been executed
+   */
+  const element_container&
+  elements() const
+  {
+    return m_elements;
+  }
+
+  /** @brief Equivalent to elements().begin()
+   */
+  element_const_iterator
+  elements_begin() const
+  {
+    return m_elements.begin();
+  }
+
+  /** @brief Equivalent to elements().end()
+   */
+  element_const_iterator
+  elements_end() const
+  {
+    return m_elements.end();
+  }
+
+  /** @brief Equivalent to elements().size()
+   */
+  size_t
+  elements_size() const
+  {
+    return m_elements.size();
+  }
+
+public: // misc
+  /** @brief Implicit conversion to const_buffer
+   */
   operator boost::asio::const_buffer() const;
 
 protected:
+  /** @brief underlying buffer storing TLV-VALUE and possibly TLV-TYPE and TLV-LENGTH fields
+   *
+   *  If m_buffer is nullptr, this is an empty Block with TLV-TYPE given in m_type.
+   *  Otherwise,
+   *  - [m_valueBegin, m_valueEnd) point to TLV-VALUE within m_buffer.
+   *  - If m_begin != m_end, [m_begin,m_end) point to Type-Length-Value of this Block within m_buffer.
+   *    Otherwise, m_buffer does not contain TLV-TYPE and TLV-LENGTH fields.
+   */
   shared_ptr<const Buffer> m_buffer;
+  Buffer::const_iterator m_begin; ///< @sa m_buffer
+  Buffer::const_iterator m_end; ///< @sa m_buffer
 
-  uint32_t m_type;
+  Buffer::const_iterator m_valueBegin; ///< @sa m_buffer
+  Buffer::const_iterator m_valueEnd; ///< @sa m_buffer
 
-  Buffer::const_iterator m_begin;
-  Buffer::const_iterator m_end;
+  uint32_t m_type; ///< TLV-TYPE
+
+  /** @brief total size including Type-Length-Value
+   *
+   *  This field is valid only if empty() is false.
+   */
   uint32_t m_size;
 
-  Buffer::const_iterator m_value_begin;
-  Buffer::const_iterator m_value_end;
-
-  mutable element_container m_subBlocks;
+  /** @brief sub elements
+   *
+   *  This field is valid only if parse() has been executed.
+   */
+  mutable element_container m_elements;
 };
 
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
+/** @brief Compare whether two Blocks have same TLV-TYPE, TLV-LENGTH, and TLV-VALUE
+ */
+bool
+operator==(const Block& lhs, const Block& rhs);
 
-inline shared_ptr<const Buffer>
-Block::getBuffer() const
+inline bool
+operator!=(const Block& lhs, const Block& rhs)
 {
-  return m_buffer;
-}
-
-inline uint32_t
-Block::type() const
-{
-  return m_type;
-}
-
-inline Buffer::const_iterator
-Block::value_begin() const
-{
-  return m_value_begin;
-}
-
-inline Buffer::const_iterator
-Block::value_end() const
-{
-  return m_value_end;
-}
-
-inline const Block::element_container&
-Block::elements() const
-{
-  return m_subBlocks;
+  return !(lhs == rhs);
 }
 
 } // namespace ndn
diff --git a/tests/unit-tests/encoding/block.t.cpp b/tests/unit-tests/encoding/block.t.cpp
index 599f37c..02b1677 100644
--- a/tests/unit-tests/encoding/block.t.cpp
+++ b/tests/unit-tests/encoding/block.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2016 Regents of the University of California.
+/*
+ * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -187,9 +187,9 @@
   BOOST_CHECK(derivedBlock == Block(buffer + 2, 3));
 
   Buffer otherBuffer(buffer, sizeof(buffer));
-  BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), block.end()), Block::Error);
-  BOOST_CHECK_THROW(Block(block, block.begin(), otherBuffer.end()), Block::Error);
-  BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), otherBuffer.end()), Block::Error);
+  BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), block.end()), std::invalid_argument);
+  BOOST_CHECK_THROW(Block(block, block.begin(), otherBuffer.end()), std::invalid_argument);
+  BOOST_CHECK_THROW(Block(block, otherBuffer.begin(), otherBuffer.end()), std::invalid_argument);
 }
 
 BOOST_AUTO_TEST_CASE(FromBlockCopyOnWriteModifyOriginal)
diff --git a/tests/unit-tests/interest.t.cpp b/tests/unit-tests/interest.t.cpp
index d0345a4..a4c78c0 100644
--- a/tests/unit-tests/interest.t.cpp
+++ b/tests/unit-tests/interest.t.cpp
@@ -200,6 +200,7 @@
 
   Data data("ndn:/A/D");
   SignatureSha256WithRsa signature(KeyLocator("ndn:/B"));
+  signature.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
   data.setSignature(signature);
   data.wireEncode();
   BOOST_CHECK_EQUAL(interest.matchesData(data), true);
@@ -224,6 +225,7 @@
 
   Data data3 = data;
   SignatureSha256WithRsa signature3(KeyLocator("ndn:/G")); // violates PublisherPublicKeyLocator
+  signature3.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
   data3.setSignature(signature3);
   data3.wireEncode();
   BOOST_CHECK_EQUAL(interest.matchesData(data3), false);
@@ -234,6 +236,7 @@
 
   Data data4 = data;
   DigestSha256 signature4; // violates PublisherPublicKeyLocator
+  signature4.setValue(encoding::makeEmptyBlock(tlv::SignatureValue));
   data4.setSignature(signature4);
   data4.wireEncode();
   BOOST_CHECK_EQUAL(interest.matchesData(data4), false);
@@ -260,7 +263,7 @@
   data7.setName("ndn:/A/B");
   data7.wireEncode();
 
-  Interest interest7("/A/B/sha256digest=D548DECEFC4B880720DC9257A8D815E9DF4465E63742EE55C29133055DAA67C2");
+  Interest interest7("/A/B/sha256digest=54008e240a7eea2714a161dfddf0dd6ced223b3856e9da96792151e180f3b128");
   BOOST_CHECK_EQUAL(interest7.matchesData(data7), true);
 
   Interest interest7b("/A/B/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");