blob: 873132312d6cf959d7931650373e3e28b0ac60e3 [file] [log] [blame]
/* -*- 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 "ns3/ndn-common.h"
#include "ns3/simple-ref-count.h"
#include "ns3/attribute.h"
#include "ns3/attribute-helper.h"
#include "name-component.h"
NDN_NAMESPACE_BEGIN
/**
* @brief Class for NDN Name
*/
class Name : public SimpleRefCount<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;
};
inline std::ostream &
operator << (std::ostream &os, const Name &name)
{
name.toUri (os);
return os;
}
inline std::istream &
operator >> (std::istream &is, Name &name)
{
std::string line;
is >> line;
name = Name (line);
return is;
}
/////////////////////////////////////////////////////////////////////////////////////
// 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;
return appendBySwap (comp.fromNumber (number));
}
Name &
Name::appendNumberWithMarker (uint64_t number, unsigned char marker)
{
name::Component comp;
return appendBySwap (comp.fromNumberWithMarker (number, marker));
}
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);
}
ATTRIBUTE_HELPER_HEADER (Name);
NDN_NAMESPACE_END
#endif