blob: 3bb241650db544395be6005df0f67636b14735d3 [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>
*/
#include "name.h"
#include "detail/error.h"
#include <boost/algorithm/string.hpp>
#include <ctype.h>
using namespace std;
NDN_NAMESPACE_BEGIN
ATTRIBUTE_HELPER_CPP (Name);
///////////////////////////////////////////////////////////////////////////////
// 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 ();
#ifdef NDNSIM_MODE
int64_t seconds = now.GetSeconds ();
int64_t microseconds = now.GetMicroSeconds () - seconds * 1000000;
version = (seconds << 12) | (0xFFF & (microseconds / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
#else
version = (now.total_seconds () << 12) | (0xFFF & (now.fractional_seconds () / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
#endif
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_NAMESPACE_END