forked from cawka/ndn.cxx
diff --git a/ndn-cpp/fields/blob.h b/ndn-cpp/fields/blob.h
new file mode 100644
index 0000000..85fd71b
--- /dev/null
+++ b/ndn-cpp/fields/blob.h
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ * Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BLOB_H
+#define NDN_BLOB_H
+
+#include <vector>
+#include <cstddef>
+
+namespace ndn {
+
+/**
+ * @brief Class representing a general-use binary blob
+ */
+class Blob : public std::vector<char>
+{
+public:
+ /**
+ * @brief Creates an empty blob
+ */
+ Blob ()
+ {
+ }
+
+ Blob (const void *buf, size_t length)
+ : std::vector<char> (reinterpret_cast<const char*> (buf), reinterpret_cast<const char*> (buf) + length)
+ {
+ }
+
+ /**
+ * @brief Get pointer to the first byte of the binary blob
+ */
+ inline char*
+ buf ()
+ {
+ return &front ();
+ }
+
+ /**
+ * @brief Get const pointer to the first byte of the binary blob
+ */
+ inline const char*
+ buf () const
+ {
+ return &front ();
+ }
+};
+
+} // ndn
+
+#endif // NDN_BLOB_H
diff --git a/ndn-cpp/fields/content.cc b/ndn-cpp/fields/content.cc
new file mode 100644
index 0000000..0216bd2
--- /dev/null
+++ b/ndn-cpp/fields/content.cc
@@ -0,0 +1,53 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "content.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+const name::Component Content::noFinalBlock = name::Component ();
+const TimeInterval Content::noFreshness;
+const TimeInterval Content::maxFreshness = time::Seconds (2147);
+
+Content::Content ()
+{
+}
+
+Content::Content (const void *buffer, size_t size,
+ const Time ×tamp,
+ Type type/* = DATA*/,
+ const TimeInterval &freshness/* = maxFreshness*/,
+ const name::Component &finalBlock/* = noFinalBlock*/)
+ : m_timestamp (timestamp)
+ , m_type (type)
+ , m_freshness (freshness)
+ , m_finalBlockId (finalBlock)
+
+ , m_content (buffer, size)
+{
+}
+
+Content::Content (const void *buffer, size_t size,
+ Type type/* = DATA*/,
+ const TimeInterval &freshness/* = maxFreshness*/,
+ const name::Component &finalBlock/* = noFinalBlock*/)
+ : m_timestamp (time::Now ())
+ , m_type (type)
+ , m_freshness (freshness)
+ , m_finalBlockId (finalBlock)
+
+ , m_content (buffer, size)
+{
+}
+
+
+} // ndn
diff --git a/ndn-cpp/fields/content.h b/ndn-cpp/fields/content.h
new file mode 100644
index 0000000..752f24c
--- /dev/null
+++ b/ndn-cpp/fields/content.h
@@ -0,0 +1,306 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_CONTENT_H
+#define NDN_CONTENT_H
+
+#include "ndn-cpp/common.h"
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/name-component.h"
+
+namespace ndn {
+
+/**
+ * @brief Class providing an interface to work with content NDN data packets
+ *
+ * Content of data packets consists of two parts: information about content
+ * (timestamp, freshness, type, etc.) and raw content itself
+ *
+ * @code
+ * Content ::= ContentInfo
+ * ContentData
+ *
+ * ContentInfo ::= Timestamp
+ * Type?
+ * Freshness?
+ * FinalBlockID?
+ * @endcode
+ */
+class Content
+{
+public:
+ /**
+ * @brief Enum of content types
+ */
+ enum Type
+ {
+ DATA = 0, ///< @brief No semantics is defined for the content
+ ENCR, ///< @brief Indicate that the content is encrypted
+ GONE, ///< @brief ?
+ KEY, ///< @brief Content is a key object
+ LINK, ///< @brief Content contains a LINK object
+ NACK ///< @brief Negative acknowledgment by the content producer, indicating that there is no data with the requested name
+ };
+
+ /**
+ * @brief Create an empty content
+ */
+ Content ();
+
+ /**
+ * @brief Create a content from a memory buffer
+ * @param buffer pointer to first byte of the memory buffer
+ * @param size size of the memory buffer
+ * @param timestamp content generation timestamp
+ * @param type type of content (default is Content::DATA)
+ * @param freshness amount of time the content is considered "fresh" (default is 2147 seconds, maximum possible value for CCNx)
+ * @param finalBlock name of the final DATA
+ *
+ * Use the other version of the constructor, if timestamp needs to be automatically generated
+ */
+ Content (const void *buffer, size_t size,
+ const Time ×tamp,
+ Type type = DATA,
+ const TimeInterval &freshness = maxFreshness,
+ const name::Component &finalBlock = noFinalBlock);
+
+ /**
+ * @brief Create a content from a memory buffer
+ * @param buffer pointer to first byte of the memory buffer
+ * @param size size of the memory buffer
+ * @param type type of content (default is Content::DATA)
+ * @param freshness amount of time the content is considered "fresh" (default is 2147 seconds, maximum possible value for CCNx)
+ * @param finalBlock name of the final DATA
+ *
+ * This method automatically sets timestamp of the created content to the current time (UTC clock)
+ */
+ Content (const void *buffer, size_t size,
+ Type type = DATA,
+ const TimeInterval &freshness = maxFreshness,
+ const name::Component &finalBlock = noFinalBlock);
+
+ /**
+ * @brief Get content timestamp (const reference)
+ */
+ inline const Time &
+ getTimestamp () const;
+
+ /**
+ * @brief Get content timestamp (reference)
+ */
+ inline Time &
+ getTimestamp ();
+
+ /**
+ * @brief Set content timestamp
+ * @param timestamp content timestamp (default is empty ptime object)
+ *
+ * If parameter is omitted, then the current time (UTC clock) is used
+ */
+ inline void
+ setTimeStamp (const Time ×tamp = Time ());
+
+ /**
+ * @brief Get type of content
+ */
+ inline Type
+ getType () const;
+
+ /**
+ * @brief Set type of content
+ * @param type content type @see Content::Type
+ */
+ inline void
+ setType (Type type);
+
+ /**
+ * @brief Get content freshness (const reference)
+ */
+ inline const TimeInterval &
+ getFreshness () const;
+
+ /**
+ * @brief Get content freshness (reference)
+ */
+ inline TimeInterval &
+ getFreshness ();
+
+ /**
+ * @brief Set content freshness
+ * @param freshness content freshness (default value is Content::maxFreshness = 2147 seconds)
+ */
+ inline void
+ setFreshness (const TimeInterval &freshness = maxFreshness);
+
+ /**
+ * @brief Get final block ID of the content (const reference)
+ */
+ inline const name::Component &
+ getFinalBlockId () const;
+
+ /**
+ * @brief Get final block ID of the content (reference)
+ */
+ inline name::Component &
+ getFinalBlockId ();
+
+ /**
+ * @brief Set final block ID of the content
+ * @param finalBlock component name of the final block
+ */
+ inline void
+ setFinalBlockId (const name::Component &finalBlock);
+
+ /**
+ * @brief Get const reference to content bits
+ */
+ inline const Blob &
+ getContent () const;
+
+ /**
+ * @brief Get reference to content bits
+ */
+ inline Blob &
+ getContent ();
+
+ /**
+ * @brief Set content bits from blob
+ * @param content blob that holds content bits
+ *
+ * In certain cases, getContent ().swap (content); is more appropriate,
+ * since it would avoid object copying
+ */
+ inline void
+ setContent (const Blob &content);
+
+ /**
+ * @brief Set content bits from memory buffer
+ * @param buf pointer to first byte of memory buffer
+ * @param length size of memory buffer
+ */
+ inline void
+ setContent (const void *buf, size_t length);
+
+public:
+ static const name::Component noFinalBlock; ///< @brief Not a final block == name::Component ()
+ static const TimeInterval noFreshness; ///< @brief Minimum freshness == seconds (0)
+ static const TimeInterval maxFreshness; ///< @brief Maximum freshnes == seconds (2147)
+
+private:
+ // ContentInfo
+ Time m_timestamp;
+ Type m_type;
+ TimeInterval m_freshness;
+ name::Component m_finalBlockId;
+
+ // ContentData
+ Blob m_content;
+};
+
+inline const Time &
+Content::getTimestamp () const
+{
+ return m_timestamp;
+}
+
+inline Time &
+Content::getTimestamp ()
+{
+ return m_timestamp;
+}
+
+inline void
+Content::setTimeStamp (const Time ×tamp/* = Time ()*/)
+{
+ if (timestamp != Time ())
+ {
+ m_timestamp = timestamp;
+ }
+ else
+ {
+ m_timestamp = time::Now ();
+ }
+}
+
+inline Content::Type
+Content::getType () const
+{
+ return m_type;
+}
+
+inline void
+Content::setType (Content::Type type)
+{
+ m_type = type;
+}
+
+inline const TimeInterval &
+Content::getFreshness () const
+{
+ return m_freshness;
+}
+
+inline TimeInterval &
+Content::getFreshness ()
+{
+ return m_freshness;
+}
+
+inline void
+Content::setFreshness (const TimeInterval &freshness/* = Content::maxFreshness*/)
+{
+ m_freshness = freshness;
+}
+
+inline const name::Component &
+Content::getFinalBlockId () const
+{
+ return m_finalBlockId;
+}
+
+inline name::Component &
+Content::getFinalBlockId ()
+{
+ return m_finalBlockId;
+}
+
+inline void
+Content::setFinalBlockId (const name::Component &finalBlock)
+{
+ m_finalBlockId = finalBlock;
+}
+
+inline const Blob &
+Content::getContent () const
+{
+ return m_content;
+}
+
+inline Blob &
+Content::getContent ()
+{
+ return m_content;
+}
+
+inline void
+Content::setContent (const Blob &content)
+{
+ m_content = content;
+}
+
+inline void
+Content::setContent (const void *buf, size_t length)
+{
+ Blob (buf, length).swap (m_content);
+}
+
+} // ndn
+
+#endif // NDN_SIGNATURE_H
diff --git a/ndn-cpp/fields/exclude.cc b/ndn-cpp/fields/exclude.cc
new file mode 100644
index 0000000..b637c01
--- /dev/null
+++ b/ndn-cpp/fields/exclude.cc
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "exclude.h"
+
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+Exclude::Exclude ()
+{
+}
+
+// example: ANY /b /d ANY /f
+//
+// ordered in map as:
+//
+// /f (false); /d (true); /b (false); / (true)
+//
+// lower_bound (/) -> / (true) <-- excluded (equal)
+// lower_bound (/a) -> / (true) <-- excluded (any)
+// lower_bound (/b) -> /b (false) <--- excluded (equal)
+// lower_bound (/c) -> /b (false) <--- not excluded (not equal and no ANY)
+// lower_bound (/d) -> /d (true) <- excluded
+// lower_bound (/e) -> /d (true) <- excluded
+bool
+Exclude::isExcluded (const name::Component &comp) const
+{
+ const_iterator lowerBound = m_exclude.lower_bound (comp);
+ if (lowerBound == end ())
+ return false;
+
+ if (lowerBound->second)
+ return true;
+ else
+ return lowerBound->first == comp;
+
+ return false;
+}
+
+Exclude &
+Exclude::excludeOne (const name::Component &comp)
+{
+ if (!isExcluded (comp))
+ {
+ m_exclude.insert (std::make_pair (comp, false));
+ }
+ return *this;
+}
+
+
+// example: ANY /b0 /d0 ANY /f0
+//
+// ordered in map as:
+//
+// /f0 (false); /d0 (true); /b0 (false); / (true)
+//
+// lower_bound (/) -> / (true) <-- excluded (equal)
+// lower_bound (/a0) -> / (true) <-- excluded (any)
+// lower_bound (/b0) -> /b0 (false) <--- excluded (equal)
+// lower_bound (/c0) -> /b0 (false) <--- not excluded (not equal and no ANY)
+// lower_bound (/d0) -> /d0 (true) <- excluded
+// lower_bound (/e0) -> /d0 (true) <- excluded
+
+
+// examples with desired outcomes
+// excludeRange (/, /f0) -> ANY /f0
+// /f0 (false); / (true)
+// excludeRange (/, /f1) -> ANY /f1
+// /f1 (false); / (true)
+// excludeRange (/a0, /e0) -> ANY /f0
+// /f0 (false); / (true)
+// excludeRange (/a0, /e0) -> ANY /f0
+// /f0 (false); / (true)
+
+// excludeRange (/b1, /c0) -> ANY /b0 /b1 ANY /c0 /d0 ANY /f0
+// /f0 (false); /d0 (true); /c0 (false); /b1 (true); /b0 (false); / (true)
+
+Exclude &
+Exclude::excludeRange (const name::Component &from, const name::Component &to)
+{
+ if (from >= to)
+ {
+ BOOST_THROW_EXCEPTION (error::Exclude ()
+ << error::msg ("Invalid exclude range (for single name exclude use Exclude::excludeOne)")
+ << error::msg (from.toUri ())
+ << error::msg (to.toUri ()));
+ }
+
+ iterator newFrom = m_exclude.lower_bound (from);
+ if (newFrom == end () || !newFrom->second /*without ANY*/)
+ {
+ std::pair<iterator, bool> fromResult = m_exclude.insert (std::make_pair (from, true));
+ newFrom = fromResult.first;
+ if (!fromResult.second)
+ {
+ // this means that the lower bound is equal to the item itself. So, just update ANY flag
+ newFrom->second = true;
+ }
+ }
+ // else
+ // nothing special if start of the range already exists with ANY flag set
+
+ iterator newTo = m_exclude.lower_bound (to); // !newTo cannot be end ()
+ if (newTo == newFrom || !newTo->second)
+ {
+ std::pair<iterator, bool> toResult = m_exclude.insert (std::make_pair (to, false));
+ newTo = toResult.first;
+ ++ newTo;
+ }
+ else
+ {
+ // nothing to do really
+ }
+
+ m_exclude.erase (newTo, newFrom); // remove any intermediate node, since all of the are excluded
+
+ return *this;
+}
+
+Exclude &
+Exclude::excludeAfter (const name::Component &from)
+{
+ iterator newFrom = m_exclude.lower_bound (from);
+ if (newFrom == end () || !newFrom->second /*without ANY*/)
+ {
+ std::pair<iterator, bool> fromResult = m_exclude.insert (std::make_pair (from, true));
+ newFrom = fromResult.first;
+ if (!fromResult.second)
+ {
+ // this means that the lower bound is equal to the item itself. So, just update ANY flag
+ newFrom->second = true;
+ }
+ }
+ // else
+ // nothing special if start of the range already exists with ANY flag set
+
+ if (newFrom != m_exclude.begin ())
+ {
+ m_exclude.erase (m_exclude.begin (), newFrom); // remove any intermediate node, since all of the are excluded
+ }
+
+ return *this;
+}
+
+
+std::ostream&
+operator << (std::ostream &os, const Exclude &exclude)
+{
+ for (Exclude::const_reverse_iterator i = exclude.rbegin (); i != exclude.rend (); i++)
+ {
+ os << i->first.toUri () << " ";
+ if (i->second)
+ os << "----> ";
+ }
+ return os;
+}
+
+
+} // ndn
diff --git a/ndn-cpp/fields/exclude.h b/ndn-cpp/fields/exclude.h
new file mode 100644
index 0000000..265a809
--- /dev/null
+++ b/ndn-cpp/fields/exclude.h
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_EXCLUDE_H
+#define NDN_EXCLUDE_H
+
+#include "ndn-cpp/fields/name-component.h"
+
+#include <map>
+
+namespace ndn {
+
+/**
+ * @brief Class to represent Exclude component in NDN interests
+ */
+class Exclude
+{
+public:
+ typedef std::map< name::Component, bool /*any*/, std::greater<name::Component> > exclude_type;
+
+ typedef exclude_type::iterator iterator;
+ typedef exclude_type::const_iterator const_iterator;
+ typedef exclude_type::reverse_iterator reverse_iterator;
+ typedef exclude_type::const_reverse_iterator const_reverse_iterator;
+
+ /**
+ * @brief Default constructor an empty exclude
+ */
+ Exclude ();
+
+ /**
+ * @brief Check if name component is excluded
+ * @param comp Name component to check against exclude filter
+ */
+ bool
+ isExcluded (const name::Component &comp) const;
+
+ /**
+ * @brief Exclude specific name component
+ * @param comp component to exclude
+ * @returns *this to allow chaining
+ */
+ Exclude &
+ excludeOne (const name::Component &comp);
+
+ /**
+ * @brief Exclude components from range [from, to]
+ * @param from first element of the range
+ * @param to last element of the range
+ * @returns *this to allow chaining
+ */
+ Exclude &
+ excludeRange (const name::Component &from, const name::Component &to);
+
+ /**
+ * @brief Exclude all components from range [/, to]
+ * @param to last element of the range
+ * @returns *this to allow chaining
+ */
+ inline Exclude &
+ excludeBefore (const name::Component &to);
+
+ /**
+ * @brief Exclude all components from range [from, +Inf]
+ * @param to last element of the range
+ * @returns *this to allow chaining
+ */
+ Exclude &
+ excludeAfter (const name::Component &from);
+
+ /**
+ * @brief Method to directly append exclude element
+ * @param name excluded name component
+ * @param any flag indicating if there is a postfix ANY component after the name
+ *
+ * This method is used during conversion from wire format of exclude filter
+ *
+ * If there is an error with ranges (e.g., order of components is wrong) an exception is thrown
+ */
+ void
+ appendExclude (const name::Component &name, bool any);
+
+ /**
+ * @brief Get number of exclude terms
+ */
+ inline size_t
+ size () const;
+
+ /**
+ * @brief Get begin iterator of the exclude terms
+ */
+ inline const_iterator
+ begin () const;
+
+ /**
+ * @brief Get end iterator of the exclude terms
+ */
+ inline const_iterator
+ end () const;
+
+ /**
+ * @brief Get begin iterator of the exclude terms
+ */
+ inline const_reverse_iterator
+ rbegin () const;
+
+ /**
+ * @brief Get end iterator of the exclude terms
+ */
+ inline const_reverse_iterator
+ rend () const;
+
+private:
+ Exclude &
+ excludeRange (iterator fromLowerBound, iterator toLowerBound);
+
+private:
+ exclude_type m_exclude;
+};
+
+std::ostream&
+operator << (std::ostream &os, const Exclude &name);
+
+inline Exclude &
+Exclude::excludeBefore (const name::Component &to)
+{
+ return excludeRange (name::Component (), to);
+}
+
+inline size_t
+Exclude::size () const
+{
+ return m_exclude.size ();
+}
+
+inline Exclude::const_iterator
+Exclude::begin () const
+{
+ return m_exclude.begin ();
+}
+
+inline Exclude::const_iterator
+Exclude::end () const
+{
+ return m_exclude.end ();
+}
+
+inline Exclude::const_reverse_iterator
+Exclude::rbegin () const
+{
+ return m_exclude.rbegin ();
+}
+
+inline Exclude::const_reverse_iterator
+Exclude::rend () const
+{
+ return m_exclude.rend ();
+}
+
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/key-locator.cc b/ndn-cpp/fields/key-locator.cc
new file mode 100644
index 0000000..84fd60c
--- /dev/null
+++ b/ndn-cpp/fields/key-locator.cc
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "key-locator.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn {
+
+KeyLocator::KeyLocator ()
+ : m_type (NOTSET)
+ , m_data (0)
+{
+}
+
+KeyLocator::KeyLocator (const KeyLocator &keyLocator)
+ : m_type (keyLocator.getType ())
+ , m_data (0)
+{
+ switch (m_type)
+ {
+ case NOTSET:
+ break;
+ case KEY:
+ m_data = new Blob (keyLocator.getKey ());
+ break;
+ case CERTIFICATE:
+ m_data = new Blob (keyLocator.getCertificate ());
+ break;
+ case KEYNAME:
+ m_data = new Name (keyLocator.getKeyName ());
+ break;
+ }
+}
+
+KeyLocator::~KeyLocator ()
+{
+ deleteData ();
+}
+
+KeyLocator &
+KeyLocator::operator = (const KeyLocator &keyLocator)
+{
+ if (this == &keyLocator)
+ return *this;
+
+ deleteData ();
+ m_type = keyLocator.getType ();
+
+ switch (m_type)
+ {
+ case NOTSET:
+ break;
+ case KEY:
+ m_data = new Blob (keyLocator.getKey ());
+ break;
+ case CERTIFICATE:
+ m_data = new Blob (keyLocator.getCertificate ());
+ break;
+ case KEYNAME:
+ m_data = new Name (keyLocator.getKeyName ());
+ break;
+ }
+
+ return *this;
+}
+
+void
+KeyLocator::deleteData ()
+{
+ switch (m_type)
+ {
+ case NOTSET: // nothing to clean up
+ break;
+ case KEY:
+ delete reinterpret_cast<Blob*> (m_data);
+ break;
+ case CERTIFICATE:
+ delete reinterpret_cast<Blob*> (m_data);
+ break;
+ case KEYNAME:
+ delete reinterpret_cast<Name*> (m_data);
+ break;
+ }
+}
+
+void
+KeyLocator::setType (KeyLocator::Type type)
+{
+ if (m_type == type)
+ return;
+
+ deleteData ();
+ m_type = type;
+
+ switch (m_type)
+ {
+ case NOTSET:
+ m_data = 0;
+ case KEY:
+ m_data = new Blob;
+ break;
+ case CERTIFICATE:
+ m_data = new Blob;
+ break;
+ case KEYNAME:
+ m_data = new Name;
+ break;
+ }
+}
+
+const Blob &
+KeyLocator::getKey () const
+{
+ if (m_type != KEY)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getKey called, but KeyLocator is not of type KeyLocator::KEY"));
+ return *reinterpret_cast<const Blob*> (m_data);
+}
+
+Blob &
+KeyLocator::getKey ()
+{
+ if (m_type != KEY)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getKey called, but KeyLocator is not of type KeyLocator::KEY"));
+ return *reinterpret_cast<Blob*> (m_data);
+}
+
+void
+KeyLocator::setKey (const Blob &key)
+{
+ if (m_type != KEY)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("setKey called, but KeyLocator is not of type KeyLocator::KEY"));
+ *reinterpret_cast<Blob*> (m_data) = key;
+}
+
+const Blob &
+KeyLocator::getCertificate () const
+{
+ if (m_type != CERTIFICATE)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+ return *reinterpret_cast<const Blob*> (m_data);
+}
+
+Blob &
+KeyLocator::getCertificate ()
+{
+ if (m_type != CERTIFICATE)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+ return *reinterpret_cast<Blob*> (m_data);
+}
+
+void
+KeyLocator::setCertificate (const Blob &certificate)
+{
+ if (m_type != CERTIFICATE)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("setCertificate called, but KeyLocator is not of type KeyLocator::CERTIFICATE"));
+ *reinterpret_cast<Blob*> (m_data) = certificate;
+}
+
+const Name &
+KeyLocator::getKeyName () const
+{
+ if (m_type != KEYNAME)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+ return *reinterpret_cast<const Name*> (m_data);
+}
+
+Name &
+KeyLocator::getKeyName ()
+{
+ if (m_type != KEYNAME)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("getKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+ return *reinterpret_cast<Name*> (m_data);
+}
+
+
+void
+KeyLocator::setKeyName (const Name &name)
+{
+ if (m_type != KEYNAME)
+ BOOST_THROW_EXCEPTION (error::KeyLocator ()
+ << error::msg ("setKeyName called, but KeyLocator is not of type KeyLocator::KEYNAME"));
+ *reinterpret_cast<Name*> (m_data) = name;
+}
+
+}
diff --git a/ndn-cpp/fields/key-locator.h b/ndn-cpp/fields/key-locator.h
new file mode 100644
index 0000000..cf1c6ea
--- /dev/null
+++ b/ndn-cpp/fields/key-locator.h
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_KEY_LOCATOR_H
+#define NDN_KEY_LOCATOR_H
+
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/name.h"
+
+namespace ndn {
+
+/**
+ * @brief Class providing an interface to work with key locators in NDN data packets
+ */
+class KeyLocator
+{
+public:
+ /**
+ * @brief Key locator type
+ *
+ * Key locator can be only of the defined types, i.e., it cannot contain key bits and key name
+ */
+ enum Type
+ {
+ NOTSET=-1, ///< @brief Unset key locator type, any attempt to use KeyLocator of NOTSET type will cause an exception
+ KEY, ///< @brief Key locator contains key bits
+ CERTIFICATE, ///< @brief Key locator contains certificate bits
+ KEYNAME ///< @brief key locator contains name of the key
+ };
+
+ /**
+ * @brief Default constructor
+ */
+ KeyLocator ();
+
+ /**
+ * @brief Copy constructor
+ */
+ KeyLocator (const KeyLocator &keyLocator);
+
+ /**
+ * @brief Destructor
+ */
+ ~KeyLocator ();
+
+ /**
+ * @brief Copy operator
+ */
+ KeyLocator &
+ operator = (const KeyLocator &keyLocator);
+
+ /**
+ * @brief Set type of the key locator
+ * @param type key locator type, @see Type
+ *
+ * If type of the key locator changes, setType will delete any previously allocated
+ * data, allocate appropriate type and store it in m_data
+ */
+ void
+ setType (Type type);
+
+ /**
+ * @brief Get type of the key locator
+ */
+ inline Type
+ getType () const;
+
+ /**
+ * @brief Get const reference to key bits, associated with key locator
+ *
+ * If key locator type is not KEY, then an exception will be thrown
+ */
+ const Blob &
+ getKey () const;
+
+ /**
+ * @brief Get reference to key bits, associated with key locator
+ *
+ * If key locator type is not KEY, then an exception will be thrown
+ */
+ Blob &
+ getKey ();
+
+ /**
+ * @brief Set key bits, associated with key locator
+ * @param key const reference to key bits
+ *
+ * If key locator type is not KEY, then an exception will be thrown
+ */
+ void
+ setKey (const Blob &key);
+
+ /**
+ * @brief Get const reference to certificated bits, associated with key locator
+ *
+ * If key locator type is not CERTIFICATE, then an exception will be thrown
+ */
+ const Blob &
+ getCertificate () const;
+
+ /**
+ * @brief Get reference to certificated bits, associated with key locator
+ *
+ * If key locator type is not CERTIFICATE, then an exception will be thrown
+ */
+ Blob &
+ getCertificate ();
+
+ /**
+ * @brief Set certificated bits, associated with key locator
+ * @param certificate const reference to certificate bits
+ *
+ * If key locator type is not CERTIFICATE, then an exception will be thrown
+ */
+ void
+ setCertificate (const Blob &certificate);
+
+ /**
+ * @brief Get const reference to key name, associated with key locator
+ *
+ * If key locator type is not KEYNAME, then an exception will be thrown
+ */
+ const Name &
+ getKeyName () const;
+
+ /**
+ * @brief Get reference to key name, associated with key locator
+ *
+ * If key locator type is not KEYNAME, then an exception will be thrown
+ */
+ Name &
+ getKeyName ();
+
+ /**
+ * @brief Set key name, associated with key locator
+ * @param name const reference to key name
+ *
+ * If key locator type is not KEYNAME, then an exception will be thrown
+ */
+ void
+ setKeyName (const Name &name);
+
+private:
+ void
+ deleteData ();
+
+private:
+ Type m_type;
+ void *m_data;
+};
+
+inline KeyLocator::Type
+KeyLocator::getType () const
+{
+ return m_type;
+}
+
+
+} // ndn
+
+#endif // NDN_KEY_LOCATOR_H
diff --git a/ndn-cpp/fields/name-component.cc b/ndn-cpp/fields/name-component.cc
new file mode 100644
index 0000000..ecc87b1
--- /dev/null
+++ b/ndn-cpp/fields/name-component.cc
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "name-component.h"
+
+#include "ndn-cpp/error.h"
+#include "ndn-cpp/helpers/uri.h"
+
+using namespace std;
+
+namespace ndn
+{
+namespace name
+{
+
+Component::Component ()
+{
+}
+
+Component::Component (const std::string &uri)
+{
+ try
+ {
+ Uri::fromEscaped (uri.begin (), uri.end (), back_inserter (*this));
+ }
+ catch (error::Uri &err)
+ {
+ // re-throwing different exception
+ BOOST_THROW_EXCEPTION (error::name::Component ()
+ << error::msg (uri)
+ << error::pos (error::get_pos (err)));
+ }
+}
+
+Component::Component (std::string::const_iterator begin, std::string::const_iterator end)
+{
+ try
+ {
+ Uri::fromEscaped (begin, end, back_inserter (*this));
+ }
+ catch (error::Uri &err)
+ {
+ // re-throwing different exception
+ BOOST_THROW_EXCEPTION (error::name::Component ()
+ << error::msg (string (begin, end))
+ << error::pos (error::get_pos (err)));
+ }
+}
+
+Component::Component (const void *buf, size_t length)
+{
+ copy (static_cast<const char*> (buf),
+ static_cast<const char*> (buf)+length,
+ back_inserter (*this));
+}
+
+int
+Component::compare (const Component &other) const
+{
+ if (size () < other.size ())
+ return -1;
+
+ if (size () > other.size ())
+ return +1;
+
+ // now we know that sizes are equal
+
+ pair<const_iterator, const_iterator> diff = mismatch (begin (), end (), other.begin ());
+ if (diff.first == end ()) // components are actually equal
+ return 0;
+
+ return (std::lexicographical_compare (diff.first, end (), diff.second, other.end ())) ? -1 : +1;
+}
+
+Component
+Component::fromNumber (uint64_t number)
+{
+ Component comp;
+ while (number > 0)
+ {
+ comp.push_back (static_cast<unsigned char> (number & 0xFF));
+ number >>= 8;
+ }
+ std::reverse (comp.begin (), comp.end ());
+ return comp;
+}
+
+Component
+Component::fromNumberWithMarker (uint64_t number, unsigned char marker)
+{
+ Component comp;
+ comp.push_back (marker);
+
+ while (number > 0)
+ {
+ comp.push_back (static_cast<unsigned char> (number & 0xFF));
+ number >>= 8;
+ }
+
+ std::reverse (comp.begin () + 1, comp.end ());
+ return comp;
+}
+
+std::string
+Component::toBlob () const
+{
+ return std::string (begin (), end ());
+}
+
+void
+Component::toBlob (std::ostream &os) const
+{
+ os.write (buf (), size ());
+}
+
+std::string
+Component::toUri () const
+{
+ ostringstream os;
+ toUri (os);
+ return os.str ();
+}
+
+void
+Component::toUri (std::ostream &os) const
+{
+ Uri::toEscaped (begin (), end (), ostream_iterator<char> (os));
+}
+
+uint64_t
+Component::toNumber () const
+{
+ uint64_t ret = 0;
+ for (const_iterator i = begin (); i != end (); i++)
+ {
+ ret <<= 8;
+ ret |= static_cast<unsigned char> (*i);
+ }
+ return ret;
+}
+
+uint64_t
+Component::toNumberWithMarker (unsigned char marker) const
+{
+ if (empty () ||
+ static_cast<unsigned char> (*(begin ())) != marker)
+ {
+ BOOST_THROW_EXCEPTION (error::name::Component ()
+ << error::msg ("Name component does not have required marker [" + toUri () + "]"));
+ }
+
+ uint64_t ret = 0;
+ for (const_iterator i = begin () + 1; i != end (); i++)
+ {
+ ret <<= 8;
+ ret |= static_cast<unsigned char> (*i);
+ }
+ return ret;
+}
+
+
+} // name
+} // ndn
diff --git a/ndn-cpp/fields/name-component.h b/ndn-cpp/fields/name-component.h
new file mode 100644
index 0000000..0bcf862
--- /dev/null
+++ b/ndn-cpp/fields/name-component.h
@@ -0,0 +1,282 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_NAME_COMPONENT_H
+#define NDN_NAME_COMPONENT_H
+
+#include <string>
+#include <vector>
+
+#include "blob.h"
+#include <stdint.h>
+
+namespace ndn {
+
+namespace name {
+
+/**
+ * @brief Class to representing binary blob of NDN name component
+ *
+ * This class is based on std::vector<char> and just provides several helpers
+ * to work with name components, as well as operator to apply canonical
+ * ordering on name components
+ */
+class Component : public Blob
+{
+public:
+ /**
+ * @brief Default constructor an empty exclude
+ */
+ Component ();
+
+ /**
+ * @brief Create component from URI encoded string
+ * @param uri URI encoded name component (convert escaped with % characters)
+ */
+ Component (const std::string &uri);
+
+ /**
+ * @brief Create component from URI encoded string, with string specified by a pair of iterators
+ * @param begin begin iterator pointing to the URI encoded name
+ * @param end end iterator
+ */
+ Component (std::string::const_iterator begin, std::string::const_iterator end);
+
+ /**
+ * @brief Create component using a binary blob
+ * @param buf pointer to first byte of binary blob to store as a name component
+ * @param length length of the binary blob
+ */
+ Component (const void *buf, size_t length);
+
+ /**
+ * @brief Apply canonical ordering on component comparison
+ * @return 0 They compare equal
+ * <0 If *this comes before other in the canonical ordering
+ * >0 If *this comes after in the canonical ordering
+ *
+ * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+ */
+ int
+ compare (const Component &other) const;
+
+ /**
+ * @brief Apply canonical ordering on component comparison (less or equal)
+ *
+ * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+ */
+ inline bool
+ operator <= (const Component &other) const;
+
+ /**
+ * @brief Apply canonical ordering on component comparison (less)
+ *
+ * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+ */
+ inline bool
+ operator < (const Component &other) const;
+
+ /**
+ * @brief Apply canonical ordering on component comparison (greater or equal)
+ *
+ * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+ */
+ inline bool
+ operator >= (const Component &other) const;
+
+ /**
+ * @brief Apply canonical ordering on component comparison (greater)
+ *
+ * @see http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
+ */
+ inline bool
+ operator > (const Component &other) const;
+
+ ////////////////////////////////////
+ // Component construction helpers //
+ ////////////////////////////////////
+
+ /**
+ * @brief Create network-ordered numeric component
+ *
+ * @param number number to be encoded and added as a component
+ *
+ * Number is encoded and added in network order. Tail zero-bytes are not included.
+ * For example, if the number is 1, then 1-byte binary blob will be added 0x01.
+ * If the number is 256, then 2 binary blob will be added: 0x01 0x01
+ *
+ * If the number is zero, an empty component will be created
+ */
+ static Component
+ fromNumber (uint64_t number);
+
+ /**
+ * @brief Create network-ordered numeric component to the name with marker
+ *
+ * @param number number to be encoded and added as a component
+ * @param marker byte marker, specified by the desired naming convention
+ *
+ * Currently defined naming conventions of the marker:
+ * - 0x00 sequence number
+ * - 0xC1 control number
+ * - 0xFB block id
+ * - 0xFD version number
+ *
+ * This version is almost exactly as appendNumber, with exception that it adds initial marker.
+ * The number is formatted in the exactly the same way.
+ *
+ * @see fromNumber
+ */
+ static Component
+ fromNumberWithMarker (uint64_t number, unsigned char marker);
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // helpers
+ //////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Convert binary blob name component to std::string (no conversion is made)
+ * @param comp name component to be converted
+ * @see asUriString
+ */
+ std::string
+ toBlob () const;
+
+ /**
+ * @brief Write blob of the name component to the specified output stream
+ * @param os output stream
+ */
+ void
+ toBlob (std::ostream &os) const;
+
+ /**
+ * @brief Convert binary blob name component to std::string, escaping all non-printable characters in URI format
+ * @param comp name component to be converted
+ * @see asString
+ */
+ std::string
+ toUri () const;
+
+ /**
+ * @brief Write name as URI to the specified output stream
+ * @param os output stream
+ */
+ void
+ toUri (std::ostream &os) const;
+
+ /**
+ * @brief Convert binary blob name component (network-ordered number) to number
+ * @param comp name component to be converted
+ */
+ uint64_t
+ toNumber () const;
+
+ /**
+ * @brief Convert binary blob name component (network-ordered number) to number, using appropriate marker from the naming convention
+ * @param comp name component to be converted
+ * @param marker required marker from the naming convention
+ *
+ * If the required marker does not exist, an exception will be thrown
+ */
+ uint64_t
+ toNumberWithMarker (unsigned char marker) const;
+
+ /**
+ * @brief Convert binary blob name component, assuming sequence number naming convention (marker = 0x00)
+ * @param comp name component to be converted
+ * @see asNumberWithMarker
+ */
+ inline uint64_t
+ toSeqNum () const;
+
+ /**
+ * @brief Convert binary blob name component, assuming control number naming convention (marker = 0xC1)
+ * @param comp name component to be converted
+ * @see asNumberWithMarker
+ */
+ inline uint64_t
+ toControlNum () const;
+
+ /**
+ * @brief Convert binary blob name component, assuming block ID naming convention (marker = 0xFB)
+ * @param comp name component to be converted
+ * @see asNumberWithMarker
+ */
+ inline uint64_t
+ toBlkId () const;
+
+ /**
+ * @brief Convert binary blob name component, assuming time-stamping version naming convention (marker = 0xFD)
+ * @param comp name component to be converted
+ * @see asNumberWithMarker
+ */
+ inline uint64_t
+ toVersion () const;
+};
+
+bool
+Component::operator <= (const Component &other) const
+{
+ return (compare (other) <= 0);
+}
+
+bool
+Component::operator < (const Component &other) const
+{
+ return (compare (other) < 0);
+}
+
+bool
+Component::operator >= (const Component &other) const
+{
+ return (compare (other) >= 0);
+}
+
+bool
+Component::operator > (const Component &other) const
+{
+ return (compare (other) > 0);
+}
+
+inline uint64_t
+Component::toSeqNum () const
+{
+ return toNumberWithMarker (0x00);
+}
+
+inline uint64_t
+Component::toControlNum () const
+{
+ return toNumberWithMarker (0xC1);
+}
+
+inline uint64_t
+Component::toBlkId () const
+{
+ return toNumberWithMarker (0xFB);
+}
+
+inline uint64_t
+Component::toVersion () const
+{
+ return toNumberWithMarker (0xFD);
+}
+
+/**
+ * @brief Stream output operator (output in escaped URI format)
+ */
+std::ostream&
+operator <<(std::ostream &os, const Component &name);
+
+} // name
+
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/name.cc b/ndn-cpp/fields/name.cc
new file mode 100644
index 0000000..d3e2ec6
--- /dev/null
+++ b/ndn-cpp/fields/name.cc
@@ -0,0 +1,264 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ * Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#include "name.h"
+
+#include "ndn-cpp/error.h"
+#include <boost/algorithm/string.hpp>
+
+#include <ctype.h>
+
+using namespace std;
+
+namespace ndn
+{
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTRUCTORS //
+///////////////////////////////////////////////////////////////////////////////
+
+Name::Name ()
+{
+}
+
+Name::Name (const string &uri)
+{
+ string::const_iterator i = uri.begin ();
+ string::const_iterator end = uri.end ();
+
+ string::const_iterator firstSlash = std::find (i, end, '/');
+ if (firstSlash == end)
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("Name should include at least one slash (did you forget to specify initial /?)"));
+ }
+
+ if (firstSlash != i)
+ {
+ string schema (i, firstSlash);
+ if (*schema.rbegin () != ':')
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("First component of the name does not start with a slash (did you forget to specify initial /?)"));
+ }
+
+ i = firstSlash;
+
+ if (!boost::iequals (schema, "ccnx:") &&
+ !boost::iequals (schema, "ndn:"))
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("URI schema is not supported (only ccnx: or ndn: is allowed)")
+ << error::msg (schema));
+ }
+ }
+
+ string::const_iterator secondSlash = i;
+ secondSlash ++;
+ if (secondSlash != end && *secondSlash == '/')
+ {
+ // The authority component (the part after the initial "//" in the familiar http and ftp URI schemes) is present,
+ // but it is not relevant to NDN name.
+ // skipping it
+ secondSlash ++;
+ i = std::find (secondSlash, end, '/');
+ }
+
+ if (i == end)
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("Invalid URI")
+ << error::msg (uri));
+ }
+
+ while (i != end)
+ {
+ // skip any extra slashes
+ while (i != end && *i == '/')
+ {
+ i ++;
+ }
+ if (i == end)
+ break;
+
+ string::const_iterator endOfComponent = std::find (i, end, '/');
+ append (name::Component (i, endOfComponent));
+
+ i = endOfComponent;
+ }
+}
+
+Name::Name (const Name &other)
+{
+ m_comps = other.m_comps;
+}
+
+Name &
+Name::operator= (const Name &other)
+{
+ m_comps = other.m_comps;
+ return *this;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SETTERS //
+///////////////////////////////////////////////////////////////////////////////
+
+Name &
+Name::appendVersion (uint64_t version/* = Name::nversion*/)
+{
+ if (version != Name::nversion)
+ return appendNumberWithMarker (version, 0xFD);
+ else
+ {
+ TimeInterval now = time::NowUnixTimestamp ();
+ version = (now.total_seconds () << 12) | (0xFFF & (now.fractional_seconds () / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
+ return appendNumberWithMarker (version, 0xFD);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// GETTERS //
+///////////////////////////////////////////////////////////////////////////////
+
+const name::Component &
+Name::get (int index) const
+{
+ if (index < 0)
+ {
+ index = size () - (-index);
+ }
+
+ if (static_cast<unsigned int> (index) >= size ())
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("Index out of range")
+ << error::pos (index));
+ }
+ return m_comps [index];
+}
+
+name::Component &
+Name::get (int index)
+{
+ if (index < 0)
+ {
+ index = size () - (-index);
+ }
+
+ if (static_cast<unsigned int> (index) >= size())
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("Index out of range")
+ << error::pos (index));
+ }
+ return m_comps [index];
+}
+
+
+/////
+///// Static helpers to convert name component to appropriate value
+/////
+
+
+Name
+Name::getSubName (size_t pos/* = 0*/, size_t len/* = Name::npos*/) const
+{
+ Name retval;
+
+ if (len == npos)
+ {
+ len = size () - pos;
+ }
+
+ if (pos + len > size ())
+ {
+ BOOST_THROW_EXCEPTION (error::Name ()
+ << error::msg ("getSubName parameter out of range")
+ << error::pos (pos)
+ << error::pos (len));
+ }
+
+ for (size_t i = pos; i < pos + len; i++)
+ {
+ retval.append (get (i));
+ }
+
+ return retval;
+}
+
+Name
+Name::operator+ (const Name &name) const
+{
+ Name newName;
+ newName
+ .append (*this)
+ .append (name);
+
+ return newName;
+}
+
+std::string
+Name::toUri () const
+{
+ ostringstream os;
+ toUri (os);
+ return os.str ();
+}
+
+void
+Name::toUri (std::ostream &os) const
+{
+ for (Name::const_iterator comp = begin (); comp != end (); comp++)
+ {
+ os << "/";
+ comp->toUri (os);
+ }
+ if (size () == 0)
+ os << "/";
+}
+
+// ostream &
+// operator << (ostream &os, const Name &name)
+// {
+// for (Name::const_iterator comp = name.begin (); comp != name.end (); comp++)
+// {
+// os << "/" << *comp;
+// }
+// if (name.size () == 0)
+// os << "/";
+// return os;
+// }
+
+int
+Name::compare (const Name &name) const
+{
+ Name::const_iterator i = this->begin ();
+ Name::const_iterator j = name.begin ();
+
+ for (; i != this->end () && j != name.end (); i++, j++)
+ {
+ int res = i->compare (*j);
+ if (res == 0)
+ continue;
+ else
+ return res;
+ }
+
+ if (i == this->end () && j == name.end ())
+ return 0; // prefixes are equal
+
+ return (i == this->end ()) ? -1 : +1;
+}
+
+} // ndn
diff --git a/ndn-cpp/fields/name.h b/ndn-cpp/fields/name.h
new file mode 100644
index 0000000..18e2412
--- /dev/null
+++ b/ndn-cpp/fields/name.h
@@ -0,0 +1,637 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ * Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ * Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ */
+
+#ifndef NDN_NAME_H
+#define NDN_NAME_H
+
+#include "ndn-cpp/fields/name-component.h"
+#include "ndn-cpp/common.h"
+
+namespace ndn {
+
+/**
+ * @brief Class for NDN Name
+ */
+class Name
+{
+public:
+ typedef std::vector<name::Component>::iterator iterator;
+ typedef std::vector<name::Component>::const_iterator const_iterator;
+ typedef std::vector<name::Component>::reverse_iterator reverse_iterator;
+ typedef std::vector<name::Component>::const_reverse_iterator const_reverse_iterator;
+ typedef std::vector<name::Component>::reference reference;
+ typedef std::vector<name::Component>::const_reference const_reference;
+
+ typedef name::Component partial_type;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // CONSTRUCTORS //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Default constructor to create an empty name (zero components, or "/")
+ */
+ Name ();
+
+ /**
+ * @brief Copy constructor
+ *
+ * @param other reference to a NDN name object
+ */
+ Name (const Name &other);
+
+ /**
+ * @brief Create a name from URL string
+ *
+ * @param url URI-represented name
+ */
+ Name (const std::string &url);
+
+ /**
+ * @brief Create a name from a container of elements [begin, end)
+ *
+ * @param begin begin iterator of the container
+ * @param end end iterator of the container
+ */
+ template<class Iterator>
+ Name (Iterator begin, Iterator end);
+
+ /**
+ * @brief Assignment operator
+ */
+ Name &
+ operator= (const Name &other);
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // SETTERS //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Append a binary blob as a name component
+ *
+ * @param comp a binary blob
+ * @returns reference to self (to allow chaining of append methods)
+ */
+ inline Name &
+ append (const name::Component &comp);
+
+ /**
+ * @brief Append a binary blob as a name component
+ * @param comp a binary blob
+ *
+ * This version is a little bit more efficient, since it swaps contents of comp and newly added component
+ *
+ * Attention!!! This method has an intended side effect: content of comp becomes empty
+ */
+ inline Name &
+ appendBySwap (name::Component &comp);
+
+ /**
+ * @brief Append components a container of elements [begin, end)
+ *
+ * @param begin begin iterator of the container
+ * @param end end iterator of the container
+ * @returns reference to self (to allow chaining of append methods)
+ */
+ template<class Iterator>
+ inline Name &
+ append (Iterator begin, Iterator end);
+
+ /**
+ * @brief Append components from another ndn::Name object
+ *
+ * @param comp reference to Name object
+ * @returns reference to self (to allow chaining of append methods)
+ */
+ inline Name &
+ append (const Name &comp);
+
+ /**
+ * @brief Append a string as a name component
+ *
+ * @param compStr a string
+ * @returns reference to self (to allow chaining of append methods)
+ *
+ * No conversions will be done to the string. The string is included in raw form,
+ * without any leading '\0' symbols.
+ */
+ inline Name &
+ append (const std::string &compStr);
+
+ /**
+ * @brief Append a binary blob as a name component
+ *
+ * @param buf pointer to the first byte of the binary blob
+ * @param size length of the binary blob
+ * @returns reference to self (to allow chaining of append methods)
+ */
+ inline Name &
+ append (const void *buf, size_t size);
+
+ /**
+ * @brief Append network-ordered numeric component to the name
+ *
+ * @param number number to be encoded and added as a component
+ *
+ * Number is encoded and added in network order. Tail zero-bytes are not included.
+ * For example, if the number is 1, then 1-byte binary blob will be added 0x01.
+ * If the number is 256, then 2 binary blob will be added: 0x01 0x01
+ *
+ * If the number is zero, an empty component will be added
+ */
+ inline Name &
+ appendNumber (uint64_t number);
+
+ /**
+ * @brief Append network-ordered numeric component to the name with marker
+ *
+ * @param number number to be encoded and added as a component
+ * @param marker byte marker, specified by the desired naming convention
+ *
+ * Currently defined naming conventions of the marker:
+ * - 0x00 sequence number
+ * - 0xC1 control number
+ * - 0xFB block id
+ * - 0xFD version number
+ *
+ * This version is almost exactly as appendNumber, with exception that it adds initial marker.
+ * The number is formatted in the exactly the same way.
+ *
+ * @see appendNumber
+ */
+ inline Name &
+ appendNumberWithMarker (uint64_t number, unsigned char marker);
+
+ /**
+ * @brief Helper method to add sequence number to the name (marker = 0x00)
+ * @param seqno sequence number
+ * @see appendNumberWithMarker
+ */
+ inline Name &
+ appendSeqNum (uint64_t seqno);
+
+ /**
+ * @brief Helper method to add control number to the name (marker = 0xC1)
+ * @param control control number
+ * @see appendNumberWithMarker
+ */
+ inline Name &
+ appendControlNum (uint64_t control);
+
+ /**
+ * @brief Helper method to add block ID to the name (marker = 0xFB)
+ * @param blkid block ID
+ * @see appendNumberWithMarker
+ */
+ inline Name &
+ appendBlkId (uint64_t blkid);
+
+ /**
+ * @brief Helper method to add version to the name (marker = 0xFD)
+ * @param version fully formatted version in a desired format (e.g., timestamp).
+ * If version is Name::nversion, then the version number is automatically
+ * assigned based on UTC timestamp
+ * @see appendNumberWithMarker
+ */
+ Name &
+ appendVersion (uint64_t version = Name::nversion);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // GETTERS //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @brief Get number of the name components
+ * @return number of name components
+ */
+ inline size_t
+ size () const;
+
+ /**
+ * @brief Get binary blob of name component
+ * @param index index of the name component. If less than 0, then getting component from the back:
+ * get(-1) getting the last component, get(-2) is getting second component from back, etc.
+ * @returns const reference to binary blob of the requested name component
+ *
+ * If index is out of range, an exception will be thrown
+ */
+ const name::Component &
+ get (int index) const;
+
+ /**
+ * @brief Get binary blob of name component
+ * @param index index of the name component. If less than 0, then getting component from the back
+ * @returns reference to binary blob of the requested name component
+ *
+ * If index is out of range, an exception will be thrown
+ */
+ name::Component &
+ get (int index);
+
+ /////
+ ///// Iterator interface to name components
+ /////
+ inline Name::const_iterator
+ begin () const; ///< @brief Begin iterator (const)
+
+ inline Name::iterator
+ begin (); ///< @brief Begin iterator
+
+ inline Name::const_iterator
+ end () const; ///< @brief End iterator (const)
+
+ inline Name::iterator
+ end (); ///< @brief End iterator
+
+ inline Name::const_reverse_iterator
+ rbegin () const; ///< @brief Reverse begin iterator (const)
+
+ inline Name::reverse_iterator
+ rbegin (); ///< @brief Reverse begin iterator
+
+ inline Name::const_reverse_iterator
+ rend () const; ///< @brief Reverse end iterator (const)
+
+ inline Name::reverse_iterator
+ rend (); ///< @brief Reverse end iterator
+
+
+ /////
+ ///// Static helpers to convert name component to appropriate value
+ /////
+
+ /**
+ * @brief Get a new name, constructed as a subset of components
+ * @param pos Position of the first component to be copied to the subname
+ * @param len Number of components to be copied. Value Name::npos indicates that all components till the end of the name.
+ */
+ Name
+ getSubName (size_t pos = 0, size_t len = npos) const;
+
+ /**
+ * @brief Get prefix of the name
+ * @param len length of the prefix
+ * @param skip number of components to skip from beginning of the name
+ */
+ inline Name
+ getPrefix (size_t len, size_t skip = 0) const;
+
+ /**
+ * @brief Get postfix of the name
+ * @param len length of the postfix
+ * @param skip number of components to skip from end of the name
+ */
+ inline Name
+ getPostfix (size_t len, size_t skip = 0) const;
+
+ /**
+ * @brief Get text representation of the name (URI)
+ */
+ std::string
+ toUri () const;
+
+ /**
+ * @brief Write name as URI to the specified output stream
+ * @param os output stream
+ */
+ void
+ toUri (std::ostream &os) const;
+
+ /////////////////////////////////////////////////
+ // Helpers and compatibility wrappers
+ /////////////////////////////////////////////////
+
+ /**
+ * @brief Compare two names, using canonical ordering for each component
+ * @return 0 They compare equal
+ * <0 If *this comes before other in the canonical ordering
+ * >0 If *this comes after in the canonical ordering
+ */
+ int
+ compare (const Name &name) const;
+
+ /**
+ * @brief Check if to Name objects are equal (have the same number of components with the same binary data)
+ */
+ inline bool
+ operator == (const Name &name) const;
+
+ /**
+ * @brief Check if two Name objects are not equal
+ */
+ inline bool
+ operator != (const Name &name) const;
+
+ /**
+ * @brief Less or equal comparison of two name objects
+ */
+ inline bool
+ operator <= (const Name &name) const;
+
+ /**
+ * @brief Less comparison of two name objects
+ */
+ inline bool
+ operator < (const Name &name) const;
+
+ /**
+ * @brief Great or equal comparison of two name objects
+ */
+ inline bool
+ operator >= (const Name &name) const;
+
+ /**
+ * @brief Great comparison of two name objects
+ */
+ inline bool
+ operator > (const Name &name) const;
+
+ /**
+ * @brief Operator [] to simplify access to name components
+ * @see get
+ */
+ inline name::Component &
+ operator [] (int index);
+
+ /**
+ * @brief Operator [] to simplify access to name components
+ * @see get
+ */
+ inline const name::Component &
+ operator [] (int index) const;
+
+ /**
+ * @brief Create a new Name object, by copying components from first and second name
+ */
+ Name
+ operator + (const Name &name) const;
+
+ /**
+ * @brief A wrapper for append method
+ */
+ template<class T>
+ inline void
+ push_back (const T &comp);
+
+public:
+ // Data Members (public):
+ /// Value returned by various member functions when they fail.
+ const static size_t npos = static_cast<size_t> (-1);
+ const static uint64_t nversion = static_cast<uint64_t> (-1);
+
+private:
+ std::vector<name::Component> m_comps;
+};
+
+typedef boost::shared_ptr<Name> NamePtr;
+
+inline std::ostream &
+operator << (std::ostream &os, const Name &name)
+{
+ name.toUri (os);
+ return os;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+// Definition of inline methods
+/////////////////////////////////////////////////////////////////////////////////////
+
+template<class Iterator>
+Name::Name (Iterator begin, Iterator end)
+{
+ append (begin, end);
+}
+
+inline Name &
+Name::append (const name::Component &comp)
+{
+ if (comp.size () != 0)
+ m_comps.push_back (comp);
+ return *this;
+}
+
+inline Name &
+Name::appendBySwap (name::Component &comp)
+{
+ if (comp.size () != 0)
+ {
+ Name::iterator newComp = m_comps.insert (end (), name::Component ());
+ newComp->swap (comp);
+ }
+ return *this;
+}
+
+template<class Iterator>
+inline Name &
+Name::append (Iterator begin, Iterator end)
+{
+ for (Iterator i = begin; i != end; i++)
+ {
+ append (*i);
+ }
+ return *this;
+}
+
+Name &
+Name::append (const Name &comp)
+{
+ if (this == &comp)
+ {
+ // have to double-copy if the object is self, otherwise results very frustrating (because we use vector...)
+ return append (Name (comp.begin (), comp.end ()));
+ }
+ return append (comp.begin (), comp.end ());
+}
+
+Name &
+Name::append (const std::string &compStr)
+{
+ name::Component comp (compStr);
+ return appendBySwap (comp);
+}
+
+Name &
+Name::append (const void *buf, size_t size)
+{
+ name::Component comp (buf, size);
+ return appendBySwap (comp);
+}
+
+Name &
+Name::appendNumber (uint64_t number)
+{
+ name::Component comp;
+ name::Component::fromNumber (number).swap (comp);
+ return appendBySwap (comp);
+}
+
+Name &
+Name::appendNumberWithMarker (uint64_t number, unsigned char marker)
+{
+ name::Component comp;
+ name::Component::fromNumberWithMarker (number, marker).swap (comp);
+ return appendBySwap (comp);
+}
+
+inline Name &
+Name::appendSeqNum (uint64_t seqno)
+{
+ return appendNumberWithMarker (seqno, 0x00);
+}
+
+inline Name &
+Name::appendControlNum (uint64_t control)
+{
+ return appendNumberWithMarker (control, 0xC1);
+}
+
+inline Name &
+Name::appendBlkId (uint64_t blkid)
+{
+ return appendNumberWithMarker (blkid, 0xFB);
+}
+
+inline size_t
+Name::size () const
+{
+ return m_comps.size ();
+}
+
+/////
+///// Iterator interface to name components
+/////
+inline Name::const_iterator
+Name::begin () const
+{
+ return m_comps.begin ();
+}
+
+inline Name::iterator
+Name::begin ()
+{
+ return m_comps.begin ();
+}
+
+inline Name::const_iterator
+Name::end () const
+{
+ return m_comps.end ();
+}
+
+inline Name::iterator
+Name::end ()
+{
+ return m_comps.end ();
+}
+
+inline Name::const_reverse_iterator
+Name::rbegin () const
+{
+ return m_comps.rbegin ();
+}
+
+inline Name::reverse_iterator
+Name::rbegin ()
+{
+ return m_comps.rbegin ();
+}
+
+inline Name::const_reverse_iterator
+Name::rend () const
+{
+ return m_comps.rend ();
+}
+
+
+inline Name::reverse_iterator
+Name::rend ()
+{
+ return m_comps.rend ();
+}
+
+
+//// helpers
+
+
+inline Name
+Name::getPrefix (size_t len, size_t skip/* = 0*/) const
+{
+ return getSubName (skip, len);
+}
+
+inline Name
+Name::getPostfix (size_t len, size_t skip/* = 0*/) const
+{
+ return getSubName (size () - len - skip, len);
+}
+
+
+template<class T>
+inline void
+Name::push_back (const T &comp)
+{
+ append (comp);
+}
+
+inline bool
+Name::operator ==(const Name &name) const
+{
+ return (compare (name) == 0);
+}
+
+inline bool
+Name::operator !=(const Name &name) const
+{
+ return (compare (name) != 0);
+}
+
+inline bool
+Name::operator <= (const Name &name) const
+{
+ return (compare (name) <= 0);
+}
+
+inline bool
+Name::operator < (const Name &name) const
+{
+ return (compare (name) < 0);
+}
+
+inline bool
+Name::operator >= (const Name &name) const
+{
+ return (compare (name) >= 0);
+}
+
+inline bool
+Name::operator > (const Name &name) const
+{
+ return (compare (name) > 0);
+}
+
+inline name::Component &
+Name::operator [] (int index)
+{
+ return get (index);
+}
+
+inline const name::Component &
+Name::operator [] (int index) const
+{
+ return get (index);
+}
+
+} // ndn
+
+#endif
diff --git a/ndn-cpp/fields/signature-sha256-with-rsa.cc b/ndn-cpp/fields/signature-sha256-with-rsa.cc
new file mode 100644
index 0000000..c84ef5a
--- /dev/null
+++ b/ndn-cpp/fields/signature-sha256-with-rsa.cc
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "signature-sha256-with-rsa.h"
+#include "ndn-cpp/wire/base.h"
+
+namespace ndn {
+namespace signature {
+
+const std::string Sha256WithRsa::s_oid = "2.16.840.1.101.3.4.2.1";
+
+Sha256WithRsa::~Sha256WithRsa ()
+{
+}
+
+void
+Sha256WithRsa::doubleDispatch (std::ostream &os, wire::Base &wire, void *userData) const
+{
+ wire.appendSignature (os, *this, userData);
+}
+
+} // signature
+} // ndn
diff --git a/ndn-cpp/fields/signature-sha256-with-rsa.h b/ndn-cpp/fields/signature-sha256-with-rsa.h
new file mode 100644
index 0000000..be6766b
--- /dev/null
+++ b/ndn-cpp/fields/signature-sha256-with-rsa.h
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNATURE_SHA256_WITH_RSA_H
+#define NDN_SIGNATURE_SHA256_WITH_RSA_H
+
+#include "signature.h"
+
+#include "ndn-cpp/fields/blob.h"
+#include "ndn-cpp/fields/key-locator.h"
+
+#include <string>
+
+namespace ndn {
+
+namespace signature {
+
+/**
+ * @brief Class providing operations to work with SHA256withRSA (OID: "2.16.840.1.101.3.4.2.1")
+ */
+class Sha256WithRsa : public virtual Signature
+{
+public:
+ /**
+ * @brief Virtual destructor
+ */
+ virtual
+ ~Sha256WithRsa ();
+
+ /**
+ * @brief Get OID of the signature algorithm
+ */
+ inline const std::string &
+ getDigestAlgorithm () const;
+
+ /**
+ * @brief Get reference to signature bits
+ */
+ inline Blob &
+ getSignatureBits ();
+
+ /**
+ * @brief Get const reference to signature bits
+ */
+ inline const Blob &
+ getSignatureBits () const;
+
+ /**
+ * @brief Set signature bits
+ */
+ inline void
+ setSignatureBits (const Blob &signatureBits);
+
+ /**
+ * @brief Get reference to publisher key digest bits
+ */
+ inline Blob &
+ getPublisherKeyDigest ();
+
+ /**
+ * @brief Get const reference to publisher key digest bits
+ */
+ inline const Blob &
+ getPublisherKeyDigest () const;
+
+ /**
+ * @brief Set publisher key digest bits
+ */
+ inline void
+ setPublisherKeyDigest (const Blob &publisherKeyDigest);
+
+ /**
+ * @brief Get reference to key locator object
+ */
+ inline KeyLocator &
+ getKeyLocator ();
+
+ /**
+ * @brief Get const reference to key locator object
+ */
+ inline const KeyLocator &
+ getKeyLocator () const;
+
+ /**
+ * @brief Set key locator object
+ */
+ inline void
+ setKeyLocator (const KeyLocator &keyLocator);
+
+ // from Signature
+ virtual void
+ doubleDispatch (std::ostream &os, wire::Base &wire, void *userData) const;
+
+private:
+ static const std::string s_oid;
+
+ Blob m_signatureBits;
+ Blob m_publisherKeyDigest;
+ KeyLocator m_keyLocator;
+};
+
+const std::string &
+Sha256WithRsa::getDigestAlgorithm () const
+{
+ return s_oid;
+}
+
+inline Blob &
+Sha256WithRsa::getSignatureBits ()
+{
+ return m_signatureBits;
+}
+
+inline const Blob &
+Sha256WithRsa::getSignatureBits () const
+{
+ return m_signatureBits;
+}
+
+inline void
+Sha256WithRsa::setSignatureBits (const Blob &signatureBits)
+{
+ m_signatureBits = signatureBits;
+}
+
+inline Blob &
+Sha256WithRsa::getPublisherKeyDigest ()
+{
+ return m_publisherKeyDigest;
+}
+
+inline const Blob &
+Sha256WithRsa::getPublisherKeyDigest () const
+{
+ return m_publisherKeyDigest;
+}
+
+inline void
+Sha256WithRsa::setPublisherKeyDigest (const Blob &publisherKeyDigest)
+{
+ m_publisherKeyDigest = publisherKeyDigest;
+}
+
+inline KeyLocator &
+Sha256WithRsa::getKeyLocator ()
+{
+ return m_keyLocator;
+}
+
+inline const KeyLocator &
+Sha256WithRsa::getKeyLocator () const
+{
+ return m_keyLocator;
+}
+
+inline void
+Sha256WithRsa::setKeyLocator (const KeyLocator &keyLocator)
+{
+ m_keyLocator = keyLocator;
+}
+
+} // signature
+} // ndn
+
+#endif // NDN_EXCLUDE_H
diff --git a/ndn-cpp/fields/signature.cc b/ndn-cpp/fields/signature.cc
new file mode 100644
index 0000000..4c7a3a5
--- /dev/null
+++ b/ndn-cpp/fields/signature.cc
@@ -0,0 +1,18 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "signature.h"
+#include "ndn-cpp/error.h"
+
+namespace ndn
+{
+
+
+} // ndn
diff --git a/ndn-cpp/fields/signature.h b/ndn-cpp/fields/signature.h
new file mode 100644
index 0000000..a9fb39a
--- /dev/null
+++ b/ndn-cpp/fields/signature.h
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNATURE_H
+#define NDN_SIGNATURE_H
+
+#include <iostream>
+
+namespace ndn {
+
+namespace wire { class Base; }
+
+/**
+ * @brief Pure virtual class providing an interface to work with signatures for NDN data packets
+ */
+class Signature
+{
+public:
+ /**
+ * @brief Virtual destructor
+ */
+ virtual
+ ~Signature () { }
+
+ /**
+ * @brief A double dispatch pattern to call the right wireFormatter method to format signature
+ * @param os reference to output stream
+ * @param wireFormatter a reference to a wireFormatter object
+ * @param userData any user-specific data
+ */
+ virtual void
+ doubleDispatch (std::ostream &os, wire::Base &wireFormatter, void *userData) const = 0;
+};
+
+} // ndn
+
+#endif // NDN_SIGNATURE_H
diff --git a/ndn-cpp/fields/signed-blob.h b/ndn-cpp/fields/signed-blob.h
new file mode 100644
index 0000000..2686977
--- /dev/null
+++ b/ndn-cpp/fields/signed-blob.h
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ * Alexander Afanasyev
+ * Zhenkai Zhu
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_SIGNED_BLOB_H
+#define NDN_SIGNED_BLOB_H
+
+#include "blob.h"
+
+namespace ndn {
+
+/**
+ * @brief Class representing a blob, which has a signed portion (e.g., bytes of DATA packet)
+ */
+class SignedBlob : public Blob
+{
+public:
+ /**
+ * @brief Set signed portion of the blob
+ * @param offset An offset from the beginning of the blob
+ * @param size Size of the signed portion of the blob
+ */
+ inline void
+ setSignedPortion (size_t offset, size_t size);
+
+ /**
+ * @brief Get begin iterator to a signed portion of the blob
+ */
+ inline const_iterator
+ signed_begin () const;
+
+ /**
+ * @brief Get end iterator of a signed portion of the blob
+ */
+ inline const_iterator
+ signed_end () const;
+
+ /**
+ * @brief Get pointer to a first byte of the signed blob
+ */
+ inline const char*
+ signed_buf () const;
+
+ /**
+ * @brief Get size of the signed blob
+ */
+ inline size_t
+ signed_size () const;
+
+private:
+ const_iterator m_signedBegin;
+ const_iterator m_signedEnd;
+};
+
+
+inline void
+SignedBlob::setSignedPortion (size_t offset, size_t size)
+{
+ m_signedBegin = begin () + offset;
+ m_signedEnd = begin () + offset + size;
+}
+
+inline SignedBlob::const_iterator
+SignedBlob::signed_begin () const
+{
+ return m_signedBegin;
+}
+
+inline SignedBlob::const_iterator
+SignedBlob::signed_end () const
+{
+ return m_signedEnd;
+}
+
+inline const char*
+SignedBlob::signed_buf () const
+{
+ return &*m_signedBegin;
+}
+
+inline size_t
+SignedBlob::signed_size () const
+{
+ return m_signedEnd - m_signedBegin;
+}
+
+
+} // ndn
+
+#endif // NDN_SIGNED_BLOB_H