blob: d3e2ec61df8f6cb89d8c2bdcf3781a46358326f4 [file] [log] [blame]
Jeff Thompsonfa306642013-06-17 15:06:57 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 * Alexander Afanasyev
5 * Zhenkai Zhu
6 *
7 * BSD license, See the LICENSE file for more information
8 *
9 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
10 * Zhenkai Zhu <zhenkai@cs.ucla.edu>
11 */
12
13#include "name.h"
14
15#include "ndn-cpp/error.h"
16#include <boost/algorithm/string.hpp>
17
18#include <ctype.h>
19
20using namespace std;
21
22namespace ndn
23{
24
25///////////////////////////////////////////////////////////////////////////////
26// CONSTRUCTORS //
27///////////////////////////////////////////////////////////////////////////////
28
29Name::Name ()
30{
31}
32
33Name::Name (const string &uri)
34{
35 string::const_iterator i = uri.begin ();
36 string::const_iterator end = uri.end ();
37
38 string::const_iterator firstSlash = std::find (i, end, '/');
39 if (firstSlash == end)
40 {
41 BOOST_THROW_EXCEPTION (error::Name ()
42 << error::msg ("Name should include at least one slash (did you forget to specify initial /?)"));
43 }
44
45 if (firstSlash != i)
46 {
47 string schema (i, firstSlash);
48 if (*schema.rbegin () != ':')
49 {
50 BOOST_THROW_EXCEPTION (error::Name ()
51 << error::msg ("First component of the name does not start with a slash (did you forget to specify initial /?)"));
52 }
53
54 i = firstSlash;
55
56 if (!boost::iequals (schema, "ccnx:") &&
57 !boost::iequals (schema, "ndn:"))
58 {
59 BOOST_THROW_EXCEPTION (error::Name ()
60 << error::msg ("URI schema is not supported (only ccnx: or ndn: is allowed)")
61 << error::msg (schema));
62 }
63 }
64
65 string::const_iterator secondSlash = i;
66 secondSlash ++;
67 if (secondSlash != end && *secondSlash == '/')
68 {
69 // The authority component (the part after the initial "//" in the familiar http and ftp URI schemes) is present,
70 // but it is not relevant to NDN name.
71 // skipping it
72 secondSlash ++;
73 i = std::find (secondSlash, end, '/');
74 }
75
76 if (i == end)
77 {
78 BOOST_THROW_EXCEPTION (error::Name ()
79 << error::msg ("Invalid URI")
80 << error::msg (uri));
81 }
82
83 while (i != end)
84 {
85 // skip any extra slashes
86 while (i != end && *i == '/')
87 {
88 i ++;
89 }
90 if (i == end)
91 break;
92
93 string::const_iterator endOfComponent = std::find (i, end, '/');
94 append (name::Component (i, endOfComponent));
95
96 i = endOfComponent;
97 }
98}
99
100Name::Name (const Name &other)
101{
102 m_comps = other.m_comps;
103}
104
105Name &
106Name::operator= (const Name &other)
107{
108 m_comps = other.m_comps;
109 return *this;
110}
111
112///////////////////////////////////////////////////////////////////////////////
113// SETTERS //
114///////////////////////////////////////////////////////////////////////////////
115
116Name &
117Name::appendVersion (uint64_t version/* = Name::nversion*/)
118{
119 if (version != Name::nversion)
120 return appendNumberWithMarker (version, 0xFD);
121 else
122 {
123 TimeInterval now = time::NowUnixTimestamp ();
124 version = (now.total_seconds () << 12) | (0xFFF & (now.fractional_seconds () / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
125 return appendNumberWithMarker (version, 0xFD);
126 }
127}
128
129
130///////////////////////////////////////////////////////////////////////////////
131// GETTERS //
132///////////////////////////////////////////////////////////////////////////////
133
134const name::Component &
135Name::get (int index) const
136{
137 if (index < 0)
138 {
139 index = size () - (-index);
140 }
141
142 if (static_cast<unsigned int> (index) >= size ())
143 {
144 BOOST_THROW_EXCEPTION (error::Name ()
145 << error::msg ("Index out of range")
146 << error::pos (index));
147 }
148 return m_comps [index];
149}
150
151name::Component &
152Name::get (int index)
153{
154 if (index < 0)
155 {
156 index = size () - (-index);
157 }
158
159 if (static_cast<unsigned int> (index) >= size())
160 {
161 BOOST_THROW_EXCEPTION (error::Name ()
162 << error::msg ("Index out of range")
163 << error::pos (index));
164 }
165 return m_comps [index];
166}
167
168
169/////
170///// Static helpers to convert name component to appropriate value
171/////
172
173
174Name
175Name::getSubName (size_t pos/* = 0*/, size_t len/* = Name::npos*/) const
176{
177 Name retval;
178
179 if (len == npos)
180 {
181 len = size () - pos;
182 }
183
184 if (pos + len > size ())
185 {
186 BOOST_THROW_EXCEPTION (error::Name ()
187 << error::msg ("getSubName parameter out of range")
188 << error::pos (pos)
189 << error::pos (len));
190 }
191
192 for (size_t i = pos; i < pos + len; i++)
193 {
194 retval.append (get (i));
195 }
196
197 return retval;
198}
199
200Name
201Name::operator+ (const Name &name) const
202{
203 Name newName;
204 newName
205 .append (*this)
206 .append (name);
207
208 return newName;
209}
210
211std::string
212Name::toUri () const
213{
214 ostringstream os;
215 toUri (os);
216 return os.str ();
217}
218
219void
220Name::toUri (std::ostream &os) const
221{
222 for (Name::const_iterator comp = begin (); comp != end (); comp++)
223 {
224 os << "/";
225 comp->toUri (os);
226 }
227 if (size () == 0)
228 os << "/";
229}
230
231// ostream &
232// operator << (ostream &os, const Name &name)
233// {
234// for (Name::const_iterator comp = name.begin (); comp != name.end (); comp++)
235// {
236// os << "/" << *comp;
237// }
238// if (name.size () == 0)
239// os << "/";
240// return os;
241// }
242
243int
244Name::compare (const Name &name) const
245{
246 Name::const_iterator i = this->begin ();
247 Name::const_iterator j = name.begin ();
248
249 for (; i != this->end () && j != name.end (); i++, j++)
250 {
251 int res = i->compare (*j);
252 if (res == 0)
253 continue;
254 else
255 return res;
256 }
257
258 if (i == this->end () && j == name.end ())
259 return 0; // prefixes are equal
260
261 return (i == this->end ()) ? -1 : +1;
262}
263
264} // ndn