name: Make use of naming conventions for segment, version, timestamp, and sequence number encoding

Change-Id: I99fe3965b2a4797bd14b6966b1d1d7d8fc530aef
Refs: #1761
diff --git a/src/data.cpp b/src/data.cpp
index d095382..77fc3c9 100644
--- a/src/data.cpp
+++ b/src/data.cpp
@@ -84,6 +84,14 @@
   return totalLength;
 }
 
+
+template size_t
+Data::wireEncode<true>(EncodingImpl<true>& block, bool unsignedPortion) const;
+
+template size_t
+Data::wireEncode<false>(EncodingImpl<false>& block, bool unsignedPortion) const;
+
+
 const Block&
 Data::wireEncode(EncodingBuffer& encoder, const Block& signatureValue) const
 {
diff --git a/src/exclude.hpp b/src/exclude.hpp
index 64eb653..70b60ba 100644
--- a/src/exclude.hpp
+++ b/src/exclude.hpp
@@ -25,7 +25,9 @@
 #define NDN_EXCLUDE_H
 
 #include "name-component.hpp"
+#include "encoding/encoding-buffer.hpp"
 
+#include <sstream>
 #include <map>
 
 namespace ndn {
diff --git a/src/interest.cpp b/src/interest.cpp
index 8bf60e3..3d3d40b 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -228,6 +228,12 @@
   return totalLength;
 }
 
+template size_t
+Interest::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+Interest::wireEncode<false>(EncodingImpl<false>& block) const;
+
 const Block&
 Interest::wireEncode() const
 {
diff --git a/src/interest.hpp b/src/interest.hpp
index 89c5c24..e075ca7 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -29,6 +29,7 @@
 #include "name.hpp"
 #include "selectors.hpp"
 #include "interest-filter.hpp"
+#include "util/time.hpp"
 #include "management/nfd-local-control-header.hpp"
 
 namespace ndn {
diff --git a/src/key-locator.hpp b/src/key-locator.hpp
index 33e4584..a86275d 100644
--- a/src/key-locator.hpp
+++ b/src/key-locator.hpp
@@ -23,6 +23,8 @@
 #define NDN_KEY_LOCATOR_HPP
 
 #include "encoding/block.hpp"
+#include "encoding/encoding-buffer.hpp"
+
 #include "name.hpp"
 
 namespace ndn {
diff --git a/src/management/nfd-control-parameters.hpp b/src/management/nfd-control-parameters.hpp
index 82c08ad..0ab0f84 100644
--- a/src/management/nfd-control-parameters.hpp
+++ b/src/management/nfd-control-parameters.hpp
@@ -24,6 +24,8 @@
 
 #include "../name.hpp"
 #include "../encoding/tlv-nfd.hpp"
+#include "../encoding/block-helpers.hpp"
+#include "../util/time.hpp"
 
 namespace ndn {
 namespace nfd {
diff --git a/src/management/nfd-fib-entry.hpp b/src/management/nfd-fib-entry.hpp
index 1086707..015beba 100644
--- a/src/management/nfd-fib-entry.hpp
+++ b/src/management/nfd-fib-entry.hpp
@@ -23,11 +23,13 @@
 #define NDN_MANAGEMENT_NFD_FIB_ENTRY_HPP
 
 #include "../encoding/block.hpp"
+#include "../encoding/block-helpers.hpp"
 #include "../encoding/encoding-buffer.hpp"
 #include "../encoding/tlv-nfd.hpp"
 #include "../name.hpp"
 
 #include <list>
+#include <sstream>
 
 namespace ndn {
 namespace nfd {
diff --git a/src/management/nfd-rib-entry.hpp b/src/management/nfd-rib-entry.hpp
index 738b8f5..d426e3f 100644
--- a/src/management/nfd-rib-entry.hpp
+++ b/src/management/nfd-rib-entry.hpp
@@ -26,6 +26,7 @@
 #include "../encoding/encoding-buffer.hpp"
 #include "../encoding/tlv-nfd.hpp"
 #include "../name.hpp"
+#include "../util/time.hpp"
 
 #include <list>
 
diff --git a/src/meta-info.hpp b/src/meta-info.hpp
index 04cded1..ed5605d 100644
--- a/src/meta-info.hpp
+++ b/src/meta-info.hpp
@@ -22,7 +22,10 @@
 #ifndef NDN_META_INFO_HPP
 #define NDN_META_INFO_HPP
 
+#include "common.hpp"
+#include "encoding/block-helpers.hpp"
 #include "encoding/encoding-buffer.hpp"
+#include "util/time.hpp"
 
 namespace ndn {
 
diff --git a/src/name-component.cpp b/src/name-component.cpp
new file mode 100644
index 0000000..a045766
--- /dev/null
+++ b/src/name-component.cpp
@@ -0,0 +1,342 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
+ */
+
+#include "name-component.hpp"
+
+#include "encoding/block-helpers.hpp"
+#include "encoding/encoding-buffer.hpp"
+#include "util/string-helper.hpp"
+
+namespace ndn {
+namespace name {
+
+Component::Component()
+  : Block(tlv::NameComponent)
+{
+}
+
+Component::Component(const Block& wire)
+  : Block(wire)
+{
+  if (type() != tlv::NameComponent)
+    throw Error("Cannot construct name::Component from not a NameComponent TLV wire block");
+}
+
+Component::Component(const ConstBufferPtr& buffer)
+  : Block(tlv::NameComponent, buffer)
+{
+}
+
+Component::Component(const Buffer& value)
+  : Block(dataBlock(tlv::NameComponent, value.buf(), value.size()))
+{
+}
+
+Component::Component(const uint8_t* value, size_t valueLen)
+  : Block(dataBlock(tlv::NameComponent, value, valueLen))
+{
+}
+
+Component::Component(const char* str)
+  : Block(dataBlock(tlv::NameComponent, str, ::strlen(str)))
+{
+}
+
+Component::Component(const std::string& str)
+  : Block(dataBlock(tlv::NameComponent, str.c_str(), str.size()))
+{
+}
+
+
+Component
+Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
+{
+  std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
+  trim(trimmedString);
+  std::string value = unescape(trimmedString);
+
+  if (value.find_first_not_of(".") == std::string::npos) {
+    // Special case for component of only periods.
+    if (value.size() <= 2)
+      // Zero, one or two periods is illegal.  Ignore this component.
+      throw Error("Illegal URI (name component cannot be . or ..)");
+    else
+      // Remove 3 periods.
+      return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
+  }
+  else
+    return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
+}
+
+
+void
+Component::toUri(std::ostream& result) const
+{
+  const uint8_t* value = this->value();
+  size_t valueSize = value_size();
+
+  bool gotNonDot = false;
+  for (size_t i = 0; i < valueSize; ++i) {
+    if (value[i] != 0x2e) {
+      gotNonDot = true;
+      break;
+    }
+  }
+  if (!gotNonDot) {
+    // Special case for component of zero or more periods.  Add 3 periods.
+    result << "...";
+    for (size_t i = 0; i < valueSize; ++i)
+      result << '.';
+  }
+  else {
+    // In case we need to escape, set to upper case hex and save the previous flags.
+    std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
+
+    for (size_t i = 0; i < valueSize; ++i) {
+      uint8_t x = value[i];
+      // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
+      if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
+          (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
+          x == 0x2e || x == 0x5f)
+        result << x;
+      else {
+        result << '%';
+        if (x < 16)
+          result << '0';
+        result << static_cast<uint32_t>(x);
+      }
+    }
+
+    // Restore.
+    result.flags(saveFlags);
+  }
+}
+
+std::string
+Component::toUri() const
+{
+  std::ostringstream os;
+  toUri(os);
+  return os.str();
+}
+
+uint64_t
+Component::toNumber() const
+{
+  /// \todo Check if Component is of tlv::NumberComponent type
+  return readNonNegativeInteger(*this);
+}
+
+uint64_t
+Component::toNumberWithMarker(uint8_t marker) const
+{
+  if (empty() || value()[0] != marker)
+    throw Error("Name component does not have the requested marker");
+
+  Buffer::const_iterator valueBegin = value_begin() + 1;
+  return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
+}
+
+uint64_t
+Component::toVersion() const
+{
+  return toNumberWithMarker(VERSION_MARKER);
+}
+
+uint64_t
+Component::toSegment() const
+{
+  return toNumberWithMarker(SEGMENT_MARKER);
+}
+
+uint64_t
+Component::toSegmentOffset() const
+{
+  return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
+}
+
+time::system_clock::TimePoint
+Component::toTimestamp() const
+{
+  uint64_t value = toNumberWithMarker(TIMESTAMP_MARKER);
+  return time::getUnixEpoch() + time::microseconds(value);
+}
+
+uint64_t
+Component::toSequenceNumber() const
+{
+  return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
+}
+
+
+Component
+Component::fromNumber(uint64_t number)
+{
+  /// \todo Change to tlv::NumberComponent
+  return nonNegativeIntegerBlock(tlv::NameComponent, number);
+}
+
+Component
+Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
+{
+  EncodingEstimator estimator;
+
+  size_t valueLength = estimator.prependNonNegativeInteger(number);
+  valueLength += estimator.prependByteArray(&marker, 1);
+  size_t totalLength = valueLength;
+  totalLength += estimator.prependVarNumber(valueLength);
+  totalLength += estimator.prependVarNumber(tlv::NameComponent);
+
+  EncodingBuffer encoder(totalLength, 0);
+  encoder.prependNonNegativeInteger(number);
+  encoder.prependByteArray(&marker, 1);
+  encoder.prependVarNumber(valueLength);
+  encoder.prependVarNumber(tlv::NameComponent);
+
+  return encoder.block();
+}
+
+Component
+Component::fromVersion(uint64_t version)
+{
+  return fromNumberWithMarker(VERSION_MARKER, version);
+}
+
+Component
+Component::fromSegment(uint64_t segmentNo)
+{
+  return fromNumberWithMarker(SEGMENT_MARKER, segmentNo);
+}
+
+Component
+Component::fromSegmentOffset(uint64_t offset)
+{
+  return fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset);
+}
+
+Component
+Component::fromTimestamp(const time::system_clock::TimePoint& timePoint)
+{
+  using namespace time;
+  uint64_t value = duration_cast<microseconds>(timePoint - getUnixEpoch()).count();
+  return fromNumberWithMarker(TIMESTAMP_MARKER, value);
+}
+
+Component
+Component::fromSequenceNumber(uint64_t seqNo)
+{
+  return fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo);
+}
+
+int
+Component::compare(const Component& other) const
+{
+  // Imitate ndn_Exclude_compareComponents.
+  if (value_size() < other.value_size())
+    return -1;
+  if (value_size() > other.value_size())
+    return 1;
+
+  if (value_size() == 0)
+    return 0;
+
+  // The components are equal length.  Just do a byte compare.
+  return std::memcmp(value(), other.value(), value_size());
+}
+
+Component
+Component::getSuccessor() const
+{
+  size_t totalLength = 0;
+  EncodingBuffer encoder(size() + 1, 1); // + 1 in case there is an overflow
+                                         // in unlikely case TLV length increases,
+                                         // EncodingBuffer will take care of that
+
+  bool isOverflow = true;
+  size_t i = value_size();
+  for (; isOverflow && i > 0; i--) {
+    uint8_t newValue = static_cast<uint8_t>((value()[i - 1] + 1) & 0xFF);
+    totalLength += encoder.prependByte(newValue);
+    isOverflow = (newValue == 0);
+  }
+  totalLength += encoder.prependByteArray(value(), i);
+
+  if (isOverflow) {
+    // new name components has to be extended
+    totalLength += encoder.appendByte(0);
+  }
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::NameComponent);
+
+  return encoder.block();
+}
+
+
+template<bool T>
+size_t
+Component::wireEncode(EncodingImpl<T>& block) const
+{
+  size_t totalLength = 0;
+  if (value_size() > 0)
+    totalLength += block.prependByteArray(value(), value_size());
+  totalLength += block.prependVarNumber(value_size());
+  totalLength += block.prependVarNumber(tlv::NameComponent);
+  return totalLength;
+}
+
+template size_t
+Component::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+Component::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+Component::wireEncode() const
+{
+  if (this->hasWire())
+    return *this;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  const_cast<Component&>(*this) = buffer.block();
+  return *this;
+}
+
+void
+Component::wireDecode(const Block& wire)
+{
+  if (wire.type() != tlv::NameComponent)
+    throw Error("name::Component::wireDecode called on not a NameComponent TLV wire block");
+
+  *this = wire;
+}
+
+} // namespace name
+} // namespace ndn
diff --git a/src/name-component.hpp b/src/name-component.hpp
index a9be6a8..7213f9a 100644
--- a/src/name-component.hpp
+++ b/src/name-component.hpp
@@ -28,13 +28,22 @@
 
 #include "common.hpp"
 #include "encoding/block.hpp"
-#include "encoding/block-helpers.hpp"
-#include "encoding/encoding-buffer.hpp"
-#include "util/string-helper.hpp"
+#include "util/time.hpp"
 
 namespace ndn {
 namespace name {
 
+/// @brief Segment marker for NDN naming conventions
+static const uint8_t SEGMENT_MARKER = 0x00;
+/// @brief Segment offset marker for NDN naming conventions
+static const uint8_t SEGMENT_OFFSET_MARKER = 0xFB;
+/// @brief Version marker for NDN naming conventions
+static const uint8_t VERSION_MARKER = 0xFD;
+/// @brief Timestamp marker for NDN naming conventions
+static const uint8_t TIMESTAMP_MARKER = 0xFC;
+/// @brief Sequence number marker for NDN naming conventions
+static const uint8_t SEQUENCE_NUMBER_MARKER = 0xFE;
+
 /**
  * @brief Component holds a read-only name component value.
  */
@@ -244,12 +253,7 @@
    * @return The escaped string
    */
   std::string
-  toUri() const
-  {
-    std::ostringstream os;
-    toUri(os);
-    return os.str();
-  }
+  toUri() const;
 
   /**
    * @brief Interpret this name component as nonNegativeInteger
@@ -262,18 +266,74 @@
   toNumber() const;
 
   /**
-   * @brief An alias for toNumber()
+   * @brief Interpret this name component as NameComponentWithMarker
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @param marker 1-byte octet of the marker
+   * @return The integer number.
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
+   */
+  uint64_t
+  toNumberWithMarker(uint8_t marker) const;
+
+  /**
+   * @brief Interpret as version component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
    */
   uint64_t
   toVersion() const;
 
   /**
-   * @brief An alias for toNumber()
+   * @brief Interpret as segment number component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
    */
   uint64_t
   toSegment() const;
 
   /**
+   * @brief Interpret as segment offset component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
+   */
+  uint64_t
+  toSegmentOffset() const;
+
+  /**
+   * @brief Interpret as timestamp component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
+   */
+  time::system_clock::TimePoint
+  toTimestamp() const;
+
+  /**
+   * @brief Interpret as sequence number component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @throws Error if name component does not have the specified marker.
+   *         tlv::Error if format does not follow NameComponentWithMarker specification.
+   */
+  uint64_t
+  toSequenceNumber() const;
+
+  /**
    * @brief Create a component encoded as nonNegativeInteger
    *
    * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
@@ -284,6 +344,70 @@
   static Component
   fromNumber(uint64_t number);
 
+  /**
+   * @brief Create a component encoded as NameComponentWithMarker
+   *
+   * NameComponentWithMarker is defined as:
+   *
+   *     NameComponentWithMarker ::= NAME-COMPONENT-TYPE TLV-LEGTH
+   *                                   Marker
+   *                                   includedNonNegativeInteger
+   *     Marker ::= BYTE
+   *     includedNonNegativeInteger ::= BYTE{1,2,4,8}
+   *     NDN-TLV := TLV-TYPE TLV-LENGTH TLV-VALUE?
+   *     TLV-TYPE := VAR-NUMBER
+   *     TLV-LENGTH := VAR-NUMBER
+   *     TLV-VALUE := BYTE+
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @param marker 1-byte marker octet
+   * @param number The non-negative number
+   * @return The component value.
+   */
+  static Component
+  fromNumberWithMarker(uint8_t marker, uint64_t number);
+
+  /**
+   * @brief Create version component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  static Component
+  fromVersion(uint64_t version);
+
+  /**
+   * @brief Create segment number component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  static Component
+  fromSegment(uint64_t segmentNo);
+
+  /**
+   * @brief Create segment offset component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  static Component
+  fromSegmentOffset(uint64_t offset);
+
+  /**
+   * @brief Create sequence number component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  static Component
+  fromTimestamp(const time::system_clock::TimePoint& timePoint);
+
+  /**
+   * @brief Create sequence number component using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  static Component
+  fromSequenceNumber(uint64_t seqNo);
+
   bool
   empty() const
   {
@@ -408,38 +532,6 @@
   return os;
 }
 
-inline
-Component::Component()
-  : Block(tlv::NameComponent)
-{
-}
-
-inline
-Component::Component(const Block& wire)
-  : Block(wire)
-{
-  if (type() != tlv::NameComponent)
-    throw Error("Constructing name component from non name component TLV wire block");
-}
-
-inline
-Component::Component(const ConstBufferPtr& buffer)
-  : Block(tlv::NameComponent, buffer)
-{
-}
-
-inline
-Component::Component(const Buffer& value)
-  : Block(dataBlock(tlv::NameComponent, value.buf(), value.size()))
-{
-}
-
-inline
-Component::Component(const uint8_t* value, size_t valueLen)
-  : Block(dataBlock(tlv::NameComponent, value, valueLen))
-{
-}
-
 template<class InputIterator>
 inline
 Component::Component(InputIterator begin, InputIterator end)
@@ -447,195 +539,6 @@
 {
 }
 
-inline
-Component::Component(const char* str)
-  : Block(dataBlock(tlv::NameComponent, str, ::strlen(str)))
-{
-}
-
-inline
-Component::Component(const std::string& str)
-  : Block(dataBlock(tlv::NameComponent, str.c_str(), str.size()))
-{
-}
-
-
-inline Component
-Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
-{
-  std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
-  trim(trimmedString);
-  std::string value = unescape(trimmedString);
-
-  if (value.find_first_not_of(".") == std::string::npos) {
-    // Special case for component of only periods.
-    if (value.size() <= 2)
-      // Zero, one or two periods is illegal.  Ignore this component.
-      return Component();
-    else
-      // Remove 3 periods.
-      return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
-  }
-  else
-    return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
-}
-
-
-inline void
-Component::toUri(std::ostream& result) const
-{
-  const uint8_t* valuePtr = value();
-  size_t valueSize = value_size();
-
-  bool gotNonDot = false;
-  for (unsigned i = 0; i < valueSize; ++i) {
-    if (valuePtr[i] != 0x2e) {
-      gotNonDot = true;
-      break;
-    }
-  }
-  if (!gotNonDot) {
-    // Special case for component of zero or more periods.  Add 3 periods.
-    result << "...";
-    for (size_t i = 0; i < valueSize; ++i)
-      result << '.';
-  }
-  else {
-    // In case we need to escape, set to upper case hex and save the previous flags.
-    std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
-
-    for (size_t i = 0; i < valueSize; ++i) {
-      uint8_t x = valuePtr[i];
-      // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
-      if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
-          (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
-          x == 0x2e || x == 0x5f)
-        result << x;
-      else {
-        result << '%';
-        if (x < 16)
-          result << '0';
-        result << static_cast<unsigned int>(x);
-      }
-    }
-
-    // Restore.
-    result.flags(saveFlags);
-  }
-}
-
-
-inline Component
-Component::fromNumber(uint64_t number)
-{
-  /// \todo Change to tlv::NumberComponent
-  return nonNegativeIntegerBlock(tlv::NameComponent, number);
-}
-
-
-inline uint64_t
-Component::toNumber() const
-{
-  /// \todo Check if Component is of tlv::NumberComponent type
-  return readNonNegativeInteger(static_cast<const Block&>(*this));
-}
-
-
-inline uint64_t
-Component::toVersion() const
-{
-  return toNumber();
-}
-
-inline uint64_t
-Component::toSegment() const
-{
-  return toNumber();
-}
-
-inline int
-Component::compare(const Component& other) const
-{
-  // Imitate ndn_Exclude_compareComponents.
-  if (value_size() < other.value_size())
-    return -1;
-  if (value_size() > other.value_size())
-    return 1;
-
-  if (value_size() == 0)
-    return 0;
-
-  // The components are equal length.  Just do a byte compare.
-  return std::memcmp(value(), other.value(), value_size());
-}
-
-inline Component
-Component::getSuccessor() const
-{
-  size_t totalLength = 0;
-  EncodingBuffer encoder(size() + 1, 1); // + 1 in case there is an overflow
-                                         // in unlikely case TLV length changes more,
-                                         // EncodingBuffer will take care of that
-
-  bool isOverflow = true;
-  size_t i = value_size();
-  for (; isOverflow && i > 0; i--) {
-    uint8_t newValue = static_cast<uint8_t>((value()[i - 1] + 1) & 0xFF);
-    totalLength += encoder.prependByte(newValue);
-    isOverflow = (newValue == 0);
-  }
-  totalLength += encoder.prependByteArray(value(), i);
-
-  if (isOverflow) {
-    // new name components has to be extended
-    totalLength += encoder.appendByte(0);
-  }
-
-  totalLength += encoder.prependVarNumber(totalLength);
-  totalLength += encoder.prependVarNumber(tlv::NameComponent);
-
-  return encoder.block();
-}
-
-
-template<bool T>
-inline size_t
-Component::wireEncode(EncodingImpl<T>& block) const
-{
-  size_t totalLength = 0;
-  if (value_size() > 0)
-    totalLength += block.prependByteArray(value(), value_size());
-  totalLength += block.prependVarNumber(value_size());
-  totalLength += block.prependVarNumber(tlv::NameComponent);
-  return totalLength;
-}
-
-inline const Block&
-Component::wireEncode() const
-{
-  if (this->hasWire())
-    return *this;
-
-  EncodingEstimator estimator;
-  size_t estimatedSize = wireEncode(estimator);
-
-  EncodingBuffer buffer(estimatedSize, 0);
-  wireEncode(buffer);
-
-  const_cast<Component&>(*this) = buffer.block();
-  return *this;
-}
-
-inline void
-Component::wireDecode(const Block& wire)
-{
-  if (wire.type() != tlv::NameComponent)
-    throw Error("wireDecode name component from non name component TLV wire block");
-
-  *this = wire;
-}
-
-
 } // namespace name
 } // namespace ndn
 
diff --git a/src/name.cpp b/src/name.cpp
new file mode 100644
index 0000000..ea0015b
--- /dev/null
+++ b/src/name.cpp
@@ -0,0 +1,336 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ *
+ * @author Jeff Thompson <jefft0@remap.ucla.edu>
+ * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
+ * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
+ */
+
+#include "name.hpp"
+
+#include "util/time.hpp"
+#include "util/string-helper.hpp"
+#include "encoding/block.hpp"
+#include "encoding/encoding-buffer.hpp"
+
+namespace ndn {
+
+template<bool T>
+size_t
+Name::wireEncode(EncodingImpl<T>& encoder) const
+{
+  size_t totalLength = 0;
+
+  for (const_reverse_iterator i = rbegin(); i != rend(); ++i)
+    {
+      totalLength += i->wireEncode(encoder);
+    }
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::Name);
+  return totalLength;
+}
+
+template size_t
+Name::wireEncode<true>(EncodingImpl<true>& estimator) const;
+
+template size_t
+Name::wireEncode<false>(EncodingImpl<false>& encoder) const;
+
+const Block&
+Name::wireEncode() const
+{
+  if (m_nameBlock.hasWire())
+    return m_nameBlock;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_nameBlock = buffer.block();
+  m_nameBlock.parse();
+
+  return m_nameBlock;
+}
+
+void
+Name::wireDecode(const Block& wire)
+{
+  if (wire.type() != tlv::Name)
+    throw tlv::Error("Unexpected TLV type when decoding Name");
+
+  m_nameBlock = wire;
+  m_nameBlock.parse();
+}
+
+void
+Name::set(const char* uriOrig)
+{
+  clear();
+
+  std::string uri = uriOrig;
+  trim(uri);
+  if (uri.size() == 0)
+    return;
+
+  size_t iColon = uri.find(':');
+  if (iColon != std::string::npos) {
+    // Make sure the colon came before a '/'.
+    size_t iFirstSlash = uri.find('/');
+    if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
+      // Omit the leading protocol such as ndn:
+      uri.erase(0, iColon + 1);
+      trim(uri);
+    }
+  }
+
+  // Trim the leading slash and possibly the authority.
+  if (uri[0] == '/') {
+    if (uri.size() >= 2 && uri[1] == '/') {
+      // Strip the authority following "//".
+      size_t iAfterAuthority = uri.find('/', 2);
+      if (iAfterAuthority == std::string::npos)
+        // Unusual case: there was only an authority.
+        return;
+      else {
+        uri.erase(0, iAfterAuthority + 1);
+        trim(uri);
+      }
+    }
+    else {
+      uri.erase(0, 1);
+      trim(uri);
+    }
+  }
+
+  size_t iComponentStart = 0;
+
+  // Unescape the components.
+  while (iComponentStart < uri.size()) {
+    size_t iComponentEnd = uri.find("/", iComponentStart);
+    if (iComponentEnd == std::string::npos)
+      iComponentEnd = uri.size();
+
+    Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
+    // Ignore illegal components.  This also gets rid of a trailing '/'.
+    if (!component.empty())
+      append(Component(component));
+
+    iComponentStart = iComponentEnd + 1;
+  }
+}
+
+std::string
+Name::toUri() const
+{
+  std::ostringstream os;
+  os << *this;
+  return os.str();
+}
+
+Name&
+Name::append(const Name& name)
+{
+  if (&name == this)
+    // Copying from this name, so need to make a copy first.
+    return append(Name(name));
+
+  for (size_t i = 0; i < name.size(); ++i)
+    append(name.at(i));
+
+  return *this;
+}
+
+Name&
+Name::appendNumber(uint64_t number)
+{
+  m_nameBlock.push_back(Component::fromNumber(number));
+  return *this;
+}
+
+Name&
+Name::appendNumberWithMarker(uint8_t marker, uint64_t number)
+{
+  m_nameBlock.push_back(Component::fromNumberWithMarker(marker, number));
+  return *this;
+}
+
+Name&
+Name::appendVersion(uint64_t version)
+{
+  m_nameBlock.push_back(Component::fromVersion(version));
+  return *this;
+}
+
+Name&
+Name::appendVersion()
+{
+  appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
+  return *this;
+}
+
+Name&
+Name::appendSegment(uint64_t segmentNo)
+{
+  m_nameBlock.push_back(Component::fromSegment(segmentNo));
+  return *this;
+}
+
+Name&
+Name::appendSegmentOffset(uint64_t offset)
+{
+  m_nameBlock.push_back(Component::fromSegmentOffset(offset));
+  return *this;
+}
+
+Name&
+Name::appendTimestamp(const time::system_clock::TimePoint& timePoint)
+{
+  m_nameBlock.push_back(Component::fromTimestamp(timePoint));
+  return *this;
+}
+
+Name&
+Name::appendSequenceNumber(uint64_t seqNo)
+{
+  m_nameBlock.push_back(Component::fromSequenceNumber(seqNo));
+  return *this;
+}
+
+
+Name
+Name::getSubName(size_t iStartComponent, size_t nComponents) const
+{
+  Name result;
+
+  size_t iEnd = iStartComponent + nComponents;
+  for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
+    result.append(at(i));
+
+  return result;
+}
+
+Name
+Name::getSubName(size_t iStartComponent) const
+{
+  Name result;
+
+  for (size_t i = iStartComponent; i < size(); ++i)
+    result.append(at(i));
+
+  return result;
+}
+
+Name
+Name::getSuccessor() const
+{
+  if (empty()) {
+    static uint8_t firstValue[] = { 0 };
+    Name firstName;
+    firstName.append(firstValue, 1);
+    return firstName;
+  }
+
+  return getPrefix(-1).append(get(-1).getSuccessor());
+}
+
+bool
+Name::equals(const Name& name) const
+{
+  if (size() != name.size())
+    return false;
+
+  for (size_t i = 0; i < size(); ++i) {
+    if (at(i) != name.at(i))
+      return false;
+  }
+
+  return true;
+}
+
+bool
+Name::isPrefixOf(const Name& name) const
+{
+  // This name is longer than the name we are checking against.
+  if (size() > name.size())
+    return false;
+
+  // Check if at least one of given components doesn't match.
+  for (size_t i = 0; i < size(); ++i) {
+    if (at(i) != name.at(i))
+      return false;
+  }
+
+  return true;
+}
+
+
+int
+Name::compare(const Name& other) const
+{
+  for (size_t i = 0; i < size() && i < other.size(); ++i) {
+    int comparison = at(i).compare(other.at(i));
+    if (comparison == 0)
+      // The components at this index are equal, so check the next components.
+      continue;
+
+    // Otherwise, the result is based on the components at this index.
+    return comparison;
+  }
+
+  // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
+  if (size() < other.size())
+    return -1;
+  else if (size() > other.size())
+    return 1;
+  else
+    return 0;
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Name& name)
+{
+  if (name.empty())
+    {
+      os << "/";
+    }
+  else
+    {
+      for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
+        os << "/";
+        i->toUri(os);
+      }
+    }
+  return os;
+}
+
+std::istream&
+operator>>(std::istream& is, Name& name)
+{
+  std::string inputString;
+  is >> inputString;
+  name.set(inputString);
+
+  return is;
+}
+
+} // namespace ndn
diff --git a/src/name.hpp b/src/name.hpp
index 0e8c840..f4b1411 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -28,10 +28,6 @@
 
 #include "common.hpp"
 #include "name-component.hpp"
-#include "util/time.hpp"
-
-#include "encoding/block.hpp"
-#include "encoding/encoding-buffer.hpp"
 
 #include <boost/iterator/reverse_iterator.hpp>
 
@@ -233,7 +229,9 @@
   getSubName(size_t iStartComponent, size_t nComponents) const;
 
   /**
-   * Get a new name, constructed as a subset of components starting at iStartComponent until the end of the name.
+   * @brief Get a new name, constructed as a subset of components starting at
+   *        iStartComponent until the end of the name.
+   *
    * @param iStartComponent The index if the first component to get.
    * @return A new name.
    */
@@ -241,13 +239,15 @@
   getSubName(size_t iStartComponent) const;
 
   /**
-   * Return a new Name with the first nComponents components of this Name.
-   * @param nComponents The number of prefix components.  If nComponents is -N then return the prefix up
-   * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
+   * @brief Return a new Name with the first nComponents components of this Name.
+   *
+   * @param nComponents The number of prefix components.  If nComponents is -N then return
+   *                    the prefix up to name.size() - N. For example getPrefix(-1)
+   *                    returns the name without the final component.
    * @return A new Name.
    */
   Name
-  getPrefix(int nComponents) const
+  getPrefix(ssize_t nComponents) const
   {
     if (nComponents < 0)
       return getSubName(0, m_nameBlock.elements_size() + nComponents);
@@ -271,41 +271,87 @@
    * @return This name so that you can chain calls to append.
    */
   Name&
-  appendNumber(uint64_t number)
-  {
-    m_nameBlock.push_back(Component::fromNumber(number));
-    return *this;
-  }
+  appendNumber(uint64_t number);
 
   /**
-   * @brief An alias for appendNumber(uint64_t)
+   * @brief Create a component encoded as NameComponentWithMarker
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   *
+   * @param marker 1-byte marker octet
+   * @param number The non-negative number
    */
   Name&
-  appendVersion(uint64_t number)
-  {
-    return appendNumber(number);
-  }
+  appendNumberWithMarker(uint8_t marker, uint64_t number);
 
   /**
-   * @brief Append a component with the encoded version number (current UNIX timestamp
-   *        in milliseconds)
+   * @brief Append version using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  Name&
+  appendVersion(uint64_t version);
+
+  /**
+   * @brief Append version using NDN naming conventions based on current UNIX timestamp
+   *        in milliseconds
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
    */
   Name&
   appendVersion();
 
   /**
-   * @brief An alias for appendNumber(uint64_t)
+   * @brief Append segment number (sequential) using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
    */
   Name&
-  appendSegment(uint64_t number)
-  {
-    return appendNumber(number);
-  }
+  appendSegment(uint64_t segmentNo);
 
   /**
-   * @brief get the successor of a name
-   * successor of a name is defined that its last component is
-   * advanced next possible value of last component of original name
+   * @brief Append segment byte offset using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  Name&
+  appendSegmentOffset(uint64_t offset);
+
+  /**
+   * @brief Append timestamp using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  Name&
+  appendTimestamp(const time::system_clock::TimePoint& timePoint = time::system_clock::now());
+
+  /**
+   * @brief Append sequence number using NDN naming conventions
+   *
+   * @see http://named-data.net/doc/tech-memos/naming-conventions.pdf
+   */
+  Name&
+  appendSequenceNumber(uint64_t seqNo);
+
+  /**
+   * @brief Get the successor of a name
+   *
+   * The successor of a name is defined as follows:
+   *
+   *     N represents the set of NDN Names, and X,Y ∈ N.
+   *     Operator < is defined by canonical order on N.
+   *     Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
+   *
+   * In plain words, successor of a name is the same name, but with its last component
+   * advanced to a next possible value.
+   *
+   * Examples:
+   *
+   * - successor for / is /%00
+   * - successor for /%00%01/%01%02 is /%00%01/%01%03
+   * - successor for /%00%01/%01%FF is /%00%01/%02%00
+   * - successor for /%00%01/%FF%FF is /%00%01/%00%00%00
+   *
    * @return a new name
    */
   Name
@@ -320,9 +366,12 @@
   equals(const Name& name) const;
 
   /**
-   * Check if the N components of this name are the same as the first N components of the given name.
+   * @brief Check if the N components of this name are the same as the first N components
+   *        of the given name.
+   *
    * @param name The Name to check.
-   * @return true if this matches the given name, otherwise false.  This always returns true if this name is empty.
+   * @return true if this matches the given name, otherwise false.  This always returns
+   *              true if this name is empty.
    */
   bool
   isPrefixOf(const Name& name) const;
@@ -534,255 +583,11 @@
   mutable Block m_nameBlock;
 };
 
-inline std::ostream&
-operator<<(std::ostream& os, const Name& name)
-{
-  if (name.empty())
-    {
-      os << "/";
-    }
-  else
-    {
-      for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
-        os << "/";
-        i->toUri(os);
-      }
-    }
-  return os;
-}
+std::ostream&
+operator<<(std::ostream& os, const Name& name);
 
-inline std::string
-Name::toUri() const
-{
-  std::ostringstream os;
-  os << *this;
-  return os.str();
-}
-
-inline std::istream&
-operator>>(std::istream& is, Name& name)
-{
-  std::string inputString;
-  is >> inputString;
-  name.set(inputString);
-
-  return is;
-}
-
-
-inline void
-Name::set(const char* uri_cstr)
-{
-  clear();
-
-  std::string uri = uri_cstr;
-  trim(uri);
-  if (uri.size() == 0)
-    return;
-
-  size_t iColon = uri.find(':');
-  if (iColon != std::string::npos) {
-    // Make sure the colon came before a '/'.
-    size_t iFirstSlash = uri.find('/');
-    if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
-      // Omit the leading protocol such as ndn:
-      uri.erase(0, iColon + 1);
-      trim(uri);
-    }
-  }
-
-  // Trim the leading slash and possibly the authority.
-  if (uri[0] == '/') {
-    if (uri.size() >= 2 && uri[1] == '/') {
-      // Strip the authority following "//".
-      size_t iAfterAuthority = uri.find('/', 2);
-      if (iAfterAuthority == std::string::npos)
-        // Unusual case: there was only an authority.
-        return;
-      else {
-        uri.erase(0, iAfterAuthority + 1);
-        trim(uri);
-      }
-    }
-    else {
-      uri.erase(0, 1);
-      trim(uri);
-    }
-  }
-
-  size_t iComponentStart = 0;
-
-  // Unescape the components.
-  while (iComponentStart < uri.size()) {
-    size_t iComponentEnd = uri.find("/", iComponentStart);
-    if (iComponentEnd == std::string::npos)
-      iComponentEnd = uri.size();
-
-    Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
-    // Ignore illegal components.  This also gets rid of a trailing '/'.
-    if (!component.empty())
-      append(Component(component));
-
-    iComponentStart = iComponentEnd + 1;
-  }
-}
-
-inline Name&
-Name::append(const Name& name)
-{
-  if (&name == this)
-    // Copying from this name, so need to make a copy first.
-    return append(Name(name));
-
-  for (size_t i = 0; i < name.size(); ++i)
-    append(name.at(i));
-
-  return *this;
-}
-
-inline Name&
-Name::appendVersion()
-{
-  appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
-  return *this;
-}
-
-inline Name
-Name::getSubName(size_t iStartComponent, size_t nComponents) const
-{
-  Name result;
-
-  size_t iEnd = iStartComponent + nComponents;
-  for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
-    result.append(at(i));
-
-  return result;
-}
-
-inline Name
-Name::getSubName(size_t iStartComponent) const
-{
-  Name result;
-
-  for (size_t i = iStartComponent; i < size(); ++i)
-    result.append(at(i));
-
-  return result;
-}
-
-inline Name
-Name::getSuccessor() const
-{
-  if (empty()) {
-    static uint8_t firstValue[] = { 0 };
-    Name firstName;
-    firstName.append(firstValue, 1);
-    return firstName;
-  }
-
-  return getPrefix(-1).append(get(-1).getSuccessor());
-}
-
-inline bool
-Name::equals(const Name& name) const
-{
-  if (size() != name.size())
-    return false;
-
-  for (size_t i = 0; i < size(); ++i) {
-    if (at(i) != name.at(i))
-      return false;
-  }
-
-  return true;
-}
-
-inline bool
-Name::isPrefixOf(const Name& name) const
-{
-  // This name is longer than the name we are checking it against.
-  if (size() > name.size())
-    return false;
-
-  // Check if at least one of given components doesn't match.
-  for (size_t i = 0; i < size(); ++i) {
-    if (at(i) != name.at(i))
-      return false;
-  }
-
-  return true;
-}
-
-
-inline int
-Name::compare(const Name& other) const
-{
-  for (size_t i = 0; i < size() && i < other.size(); ++i) {
-    int comparison = at(i).compare(other.at(i));
-    if (comparison == 0)
-      // The components at this index are equal, so check the next components.
-      continue;
-
-    // Otherwise, the result is based on the components at this index.
-    return comparison;
-  }
-
-  // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
-  if (size() < other.size())
-    return -1;
-  else if (size() > other.size())
-    return 1;
-  else
-    return 0;
-}
-
-
-
-template<bool T>
-inline size_t
-Name::wireEncode(EncodingImpl<T>& blk) const
-{
-  size_t totalLength = 0;
-
-  for (const_reverse_iterator i = rbegin();
-       i != rend();
-       ++i)
-    {
-      totalLength += i->wireEncode(blk);
-    }
-
-  totalLength += blk.prependVarNumber(totalLength);
-  totalLength += blk.prependVarNumber(tlv::Name);
-  return totalLength;
-}
-
-inline const Block&
-Name::wireEncode() const
-{
-  if (m_nameBlock.hasWire())
-    return m_nameBlock;
-
-  EncodingEstimator estimator;
-  size_t estimatedSize = wireEncode(estimator);
-
-  EncodingBuffer buffer(estimatedSize, 0);
-  wireEncode(buffer);
-
-  m_nameBlock = buffer.block();
-  m_nameBlock.parse();
-
-  return m_nameBlock;
-}
-
-inline void
-Name::wireDecode(const Block& wire)
-{
-  if (wire.type() != tlv::Name)
-    throw tlv::Error("Unexpected TLV type when decoding Name");
-
-  m_nameBlock = wire;
-  m_nameBlock.parse();
-}
+std::istream&
+operator>>(std::istream& is, Name& name);
 
 inline bool
 Name::hasWire() const
diff --git a/src/selectors.hpp b/src/selectors.hpp
index e09acea..c4fcb42 100644
--- a/src/selectors.hpp
+++ b/src/selectors.hpp
@@ -26,6 +26,7 @@
 #include "key-locator.hpp"
 #include "exclude.hpp"
 #include "encoding/encoding-buffer.hpp"
+#include "encoding/block-helpers.hpp"
 
 namespace ndn {
 
diff --git a/src/signature-info.cpp b/src/signature-info.cpp
index 469bdee..1e40b1f 100644
--- a/src/signature-info.cpp
+++ b/src/signature-info.cpp
@@ -20,6 +20,8 @@
  */
 
 #include "signature-info.hpp"
+#include "encoding/block-helpers.hpp"
+
 #include <boost/lexical_cast.hpp>
 
 namespace ndn {