forked from cawka/ndn.cxx
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