encoding: Add TLV-related definitions, data structures, abstraction, and functions

Change-Id: I2dbdd5ae17f1f60cdd65b7e46e5b43b25c7f025c
diff --git a/include/ndn-cpp/encoding/buffer.hpp b/include/ndn-cpp/encoding/buffer.hpp
new file mode 100644
index 0000000..ec71112
--- /dev/null
+++ b/include/ndn-cpp/encoding/buffer.hpp
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_BUFFER_HPP
+#define NDN_BUFFER_HPP
+
+#include <ndn-cpp/common.hpp>
+
+#include <boost/iostreams/detail/ios.hpp>
+#include <boost/iostreams/categories.hpp>
+#include <boost/iostreams/stream.hpp>
+
+#include <vector>
+
+namespace ndn {
+
+class Buffer;
+typedef ptr_lib::shared_ptr<const Buffer> ConstBufferPtr;
+typedef ptr_lib::shared_ptr<Buffer> BufferPtr;
+
+/**
+ * @brief Class representing a general-use automatically managed/resized buffer
+ *
+ * In most respect, Buffer class is equivalent to std::vector<uint8_t> and is in fact
+ * uses it as a base class.  In addition to that, it provides buf() and buf<T>() helper
+ * method for easier access to the underlying data (buf<T>() casts pointer to the requested class)
+ */
+class Buffer : public std::vector<uint8_t>
+{
+public:
+  /**
+   * @brief Creates an empty buffer
+   */
+  Buffer ()
+  {
+  }
+
+  /**
+   * @brief Create a buffer by copying the supplied data from a const buffer
+   * @param buf const pointer to buffer
+   * @param length length of the buffer to copy
+   */
+  Buffer (const void *buf, size_t length)
+    : std::vector<uint8_t> (reinterpret_cast<const uint8_t*> (buf), reinterpret_cast<const uint8_t*> (buf) + length)
+  {
+  }
+
+  /**
+   * @brief Create a buffer by copying the supplied data using iterator interface
+   *
+   * Note that the supplied iterators must be compatible with std::vector<uint8_t> interface
+   *
+   * @param first iterator to a first element to copy
+   * @param last  iterator to an element immediately following the last element to copy
+   */
+  template <class InputIterator>
+  Buffer (InputIterator first, InputIterator last)
+    : std::vector<uint8_t> (first, last)
+  {
+  }
+  
+  /**
+   * @brief Get pointer to the first byte of the buffer
+   */
+  inline uint8_t*
+  get ()
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer (alternative version)
+   */
+  inline uint8_t*
+  buf ()
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer and cast
+   * it (reinterpret_cast) to the requested type T
+   */
+  template<class T>
+  inline T*
+  get ()
+  {
+    return reinterpret_cast<T *>(&front ());
+  }
+
+  /**
+   * @brief Get pointer to the first byte of the buffer (alternative version)
+   */
+  inline const uint8_t*
+  buf () const
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get const pointer to the first byte of the buffer
+   */
+  inline const uint8_t*
+  get () const
+  {
+    return &front ();
+  }
+
+  /**
+   * @brief Get const pointer to the first byte of the buffer and cast
+   * it (reinterpret_cast) to the requested type T
+   */
+  template<class T>
+  inline const T*
+  get () const
+  {
+    return reinterpret_cast<const T *>(&front ());
+  }  
+};
+
+/// @cond include_hidden
+namespace iostreams
+{
+
+class buffer_append_device {
+public:
+  typedef char  char_type;
+  typedef boost::iostreams::sink_tag       category;
+  
+  buffer_append_device (Buffer& container)
+  : m_container (container)
+  {
+  }
+  
+  std::streamsize
+  write(const char_type* s, std::streamsize n)
+  {
+    std::copy (s, s+n, std::back_inserter(m_container));
+    return n;
+  }
+  
+protected:
+  Buffer& m_container;
+};
+
+} // iostreams
+/// @endcond
+
+/**
+ * Class implementing interface similar to ostringstream, but to construct ndn::Buffer
+ *
+ * The benefit of using stream interface is that it provides automatic buffering of written data
+ * and eliminates (or reduces) overhead of resizing the underlying buffer when writing small pieces of data.
+ *
+ * Usage example:
+ * @code
+ *      OBufferStream obuf;
+ *      obuf.put(0);
+ *      obuf.write(another_buffer, another_buffer_size);
+ *      ptr_lib::shared_ptr<Buffer> buf = obuf.get();
+ * @endcode
+ */
+struct OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
+{
+  /**
+   * Default constructor
+   */
+  OBufferStream ()
+    : m_buffer (ptr_lib::make_shared<Buffer> ())
+    , m_device (*m_buffer)
+  {
+    open (m_device);
+  }
+
+  /**
+   * Flush written data to the stream and return shared pointer to the underlying buffer
+   */
+  ptr_lib::shared_ptr<Buffer>
+  buf ()
+  {
+    flush ();
+    return m_buffer;
+  }
+
+private:
+  BufferPtr m_buffer;
+  iostreams::buffer_append_device m_device;
+};
+
+
+} // ndn
+
+#endif // NDN_BUFFER_HPP