blob: 3bb241650db544395be6005df0f67636b14735d3 [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, '/');
95 append (name::Component (i, endOfComponent));
96
97 i = endOfComponent;
98 }
99}
100
101Name::Name (const Name &other)
102{
103 m_comps = other.m_comps;
104}
105
106Name &
107Name::operator= (const Name &other)
108{
109 m_comps = other.m_comps;
110 return *this;
111}
112
113///////////////////////////////////////////////////////////////////////////////
114// SETTERS //
115///////////////////////////////////////////////////////////////////////////////
116
117Name &
118Name::appendVersion (uint64_t version/* = Name::nversion*/)
119{
120 if (version != Name::nversion)
121 return appendNumberWithMarker (version, 0xFD);
122 else
123 {
124 TimeInterval now = time::NowUnixTimestamp ();
125#ifdef NDNSIM_MODE
126 int64_t seconds = now.GetSeconds ();
127 int64_t microseconds = now.GetMicroSeconds () - seconds * 1000000;
128
129 version = (seconds << 12) | (0xFFF & (microseconds / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
130#else
131 version = (now.total_seconds () << 12) | (0xFFF & (now.fractional_seconds () / 244 /*( 1000,000 microseconds / 4096.0 resolution = last 12 bits)*/));
132#endif
133 return appendNumberWithMarker (version, 0xFD);
134 }
135}
136
137
138///////////////////////////////////////////////////////////////////////////////
139// GETTERS //
140///////////////////////////////////////////////////////////////////////////////
141
142const name::Component &
143Name::get (int index) const
144{
145 if (index < 0)
146 {
147 index = size () - (-index);
148 }
149
150 if (static_cast<unsigned int> (index) >= size ())
151 {
152 BOOST_THROW_EXCEPTION (error::Name ()
153 << error::msg ("Index out of range")
154 << error::pos (index));
155 }
156 return m_comps [index];
157}
158
159name::Component &
160Name::get (int index)
161{
162 if (index < 0)
163 {
164 index = size () - (-index);
165 }
166
167 if (static_cast<unsigned int> (index) >= size())
168 {
169 BOOST_THROW_EXCEPTION (error::Name ()
170 << error::msg ("Index out of range")
171 << error::pos (index));
172 }
173 return m_comps [index];
174}
175
176
177/////
178///// Static helpers to convert name component to appropriate value
179/////
180
181
182Name
183Name::getSubName (size_t pos/* = 0*/, size_t len/* = Name::npos*/) const
184{
185 Name retval;
186
187 if (len == npos)
188 {
189 len = size () - pos;
190 }
191
192 if (pos + len > size ())
193 {
194 BOOST_THROW_EXCEPTION (error::Name ()
195 << error::msg ("getSubName parameter out of range")
196 << error::pos (pos)
197 << error::pos (len));
198 }
199
200 for (size_t i = pos; i < pos + len; i++)
201 {
202 retval.append (get (i));
203 }
204
205 return retval;
206}
207
208Name
209Name::operator+ (const Name &name) const
210{
211 Name newName;
212 newName
213 .append (*this)
214 .append (name);
215
216 return newName;
217}
218
219std::string
220Name::toUri () const
221{
222 ostringstream os;
223 toUri (os);
224 return os.str ();
225}
226
227void
228Name::toUri (std::ostream &os) const
229{
230 for (Name::const_iterator comp = begin (); comp != end (); comp++)
231 {
232 os << "/";
233 comp->toUri (os);
234 }
235 if (size () == 0)
236 os << "/";
237}
238
239// ostream &
240// operator << (ostream &os, const Name &name)
241// {
242// for (Name::const_iterator comp = name.begin (); comp != name.end (); comp++)
243// {
244// os << "/" << *comp;
245// }
246// if (name.size () == 0)
247// os << "/";
248// return os;
249// }
250
251int
252Name::compare (const Name &name) const
253{
254 Name::const_iterator i = this->begin ();
255 Name::const_iterator j = name.begin ();
256
257 for (; i != this->end () && j != name.end (); i++, j++)
258 {
259 int res = i->compare (*j);
260 if (res == 0)
261 continue;
262 else
263 return res;
264 }
265
266 if (i == this->end () && j == name.end ())
267 return 0; // prefixes are equal
268
269 return (i == this->end ()) ? -1 : +1;
270}
271
272NDN_NAMESPACE_END