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