NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
name.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2019 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  *
21  * @author Jeff Thompson <jefft0@remap.ucla.edu>
22  * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
23  * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
24  */
25 
26 #include "ndn-cxx/name.hpp"
29 #include "ndn-cxx/util/time.hpp"
30 
31 #include <sstream>
32 #include <boost/functional/hash.hpp>
33 #include <boost/range/adaptor/reversed.hpp>
34 #include <boost/range/concepts.hpp>
35 
36 namespace ndn {
37 
38 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Name>));
39 BOOST_CONCEPT_ASSERT((WireEncodable<Name>));
40 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Name>));
41 BOOST_CONCEPT_ASSERT((WireDecodable<Name>));
42 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Name::iterator>));
43 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Name::const_iterator>));
44 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Name::reverse_iterator>));
45 BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator<Name::const_reverse_iterator>));
46 BOOST_CONCEPT_ASSERT((boost::RandomAccessRangeConcept<Name>));
47 static_assert(std::is_base_of<tlv::Error, Name::Error>::value,
48  "Name::Error must inherit from tlv::Error");
49 
50 const size_t Name::npos = std::numeric_limits<size_t>::max();
51 
52 // ---- constructors, encoding, decoding ----
53 
55  : m_wire(tlv::Name)
56 {
57 }
58 
59 Name::Name(const Block& wire)
60  : m_wire(wire)
61 {
62  m_wire.parse();
63 }
64 
65 Name::Name(const char* uri)
66  : Name(std::string(uri))
67 {
68 }
69 
70 Name::Name(std::string uri)
71 {
72  if (uri.empty())
73  return;
74 
75  size_t iColon = uri.find(':');
76  if (iColon != std::string::npos) {
77  // Make sure the colon came before a '/'.
78  size_t iFirstSlash = uri.find('/');
79  if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
80  // Omit the leading protocol such as ndn:
81  uri.erase(0, iColon + 1);
82  }
83  }
84 
85  // Trim the leading slash and possibly the authority.
86  if (uri[0] == '/') {
87  if (uri.size() >= 2 && uri[1] == '/') {
88  // Strip the authority following "//".
89  size_t iAfterAuthority = uri.find('/', 2);
90  if (iAfterAuthority == std::string::npos)
91  // Unusual case: there was only an authority.
92  return;
93  else {
94  uri.erase(0, iAfterAuthority + 1);
95  }
96  }
97  else {
98  uri.erase(0, 1);
99  }
100  }
101 
102  size_t iComponentStart = 0;
103 
104  // Unescape the components.
105  while (iComponentStart < uri.size()) {
106  size_t iComponentEnd = uri.find("/", iComponentStart);
107  if (iComponentEnd == std::string::npos)
108  iComponentEnd = uri.size();
109 
110  append(Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd));
111  iComponentStart = iComponentEnd + 1;
112  }
113 }
114 
115 std::string
116 Name::toUri() const
117 {
118  std::ostringstream os;
119  os << *this;
120  return os.str();
121 }
122 
123 template<encoding::Tag TAG>
124 size_t
126 {
127  size_t totalLength = 0;
128  for (const Component& comp : *this | boost::adaptors::reversed) {
129  totalLength += comp.wireEncode(encoder);
130  }
131 
132  totalLength += encoder.prependVarNumber(totalLength);
133  totalLength += encoder.prependVarNumber(tlv::Name);
134  return totalLength;
135 }
136 
138 
139 const Block&
141 {
142  if (m_wire.hasWire())
143  return m_wire;
144 
145  EncodingEstimator estimator;
146  size_t estimatedSize = wireEncode(estimator);
147 
148  EncodingBuffer buffer(estimatedSize, 0);
149  wireEncode(buffer);
150 
151  m_wire = buffer.block();
152  m_wire.parse();
153 
154  return m_wire;
155 }
156 
157 void
159 {
160  if (wire.type() != tlv::Name)
161  BOOST_THROW_EXCEPTION(tlv::Error("Unexpected TLV type when decoding Name"));
162 
163  m_wire = wire;
164  m_wire.parse();
165 }
166 
167 Name
169 {
170  Name copiedName(*this);
171  copiedName.m_wire.resetWire();
172  copiedName.wireEncode(); // "compress" the underlying buffer
173  return copiedName;
174 }
175 
176 // ---- accessors ----
177 
178 const name::Component&
179 Name::at(ssize_t i) const
180 {
181  if (i < 0) {
182  i = size() + i;
183  }
184 
185  if (i < 0 || static_cast<size_t>(i) >= size()) {
186  BOOST_THROW_EXCEPTION(Error("Requested component does not exist (out of bounds)"));
187  }
188 
189  return reinterpret_cast<const Component&>(m_wire.elements()[i]);
190 }
191 
193 Name::getSubName(ssize_t iStartComponent, size_t nComponents) const
194 {
195  PartialName result;
196 
197  ssize_t iStart = iStartComponent < 0 ? this->size() + iStartComponent : iStartComponent;
198  size_t iEnd = this->size();
199 
200  iStart = std::max(iStart, static_cast<ssize_t>(0));
201 
202  if (nComponents != npos)
203  iEnd = std::min(this->size(), iStart + nComponents);
204 
205  for (size_t i = iStart; i < iEnd; ++i)
206  result.append(at(i));
207 
208  return result;
209 }
210 
211 // ---- modifiers ----
212 
213 Name&
214 Name::appendVersion(optional<uint64_t> version)
215 {
216  return append(Component::fromVersion(version.value_or(time::toUnixTimestamp(time::system_clock::now()).count())));
217 }
218 
219 Name&
220 Name::appendTimestamp(optional<time::system_clock::TimePoint> timestamp)
221 {
222  return append(Component::fromTimestamp(timestamp.value_or(time::system_clock::now())));
223 }
224 
225 Name&
227 {
228  if (&name == this)
229  // Copying from this name, so need to make a copy first.
230  return append(PartialName(name));
231 
232  for (size_t i = 0; i < name.size(); ++i)
233  append(name.at(i));
234 
235  return *this;
236 }
237 
238 // ---- algorithms ----
239 
240 Name
242 {
243  if (empty()) {
244  return Name("/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");
245  }
246 
247  return getPrefix(-1).append(get(-1).getSuccessor());
248 }
249 
250 bool
251 Name::isPrefixOf(const Name& other) const
252 {
253  // This name is longer than the name we are checking against.
254  if (size() > other.size())
255  return false;
256 
257  // Check if at least one of given components doesn't match.
258  for (size_t i = 0; i < size(); ++i) {
259  if (get(i) != other.get(i))
260  return false;
261  }
262 
263  return true;
264 }
265 
266 bool
267 Name::equals(const Name& other) const
268 {
269  if (size() != other.size())
270  return false;
271 
272  for (size_t i = 0; i < size(); ++i) {
273  if (get(i) != other.get(i))
274  return false;
275  }
276 
277  return true;
278 }
279 
280 int
281 Name::compare(size_t pos1, size_t count1, const Name& other, size_t pos2, size_t count2) const
282 {
283  count1 = std::min(count1, this->size() - pos1);
284  count2 = std::min(count2, other.size() - pos2);
285  size_t count = std::min(count1, count2);
286 
287  for (size_t i = 0; i < count; ++i) {
288  int comp = get(pos1 + i).compare(other.get(pos2 + i));
289  if (comp != 0) { // i-th component differs
290  return comp;
291  }
292  }
293  // [pos1, pos1+count) of this Name equals [pos2, pos2+count) of other Name
294  return count1 - count2;
295 }
296 
297 // ---- stream operators ----
298 
299 std::ostream&
300 operator<<(std::ostream& os, const Name& name)
301 {
302  if (name.empty()) {
303  os << "/";
304  }
305  else {
306  for (const auto& component : name) {
307  os << "/";
308  component.toUri(os);
309  }
310  }
311  return os;
312 }
313 
314 std::istream&
315 operator>>(std::istream& is, Name& name)
316 {
317  std::string inputString;
318  is >> inputString;
319  name = Name(inputString);
320 
321  return is;
322 }
323 
324 } // namespace ndn
325 
326 namespace std {
327 
328 size_t
330 {
331  return boost::hash_range(name.wireEncode().wire(),
332  name.wireEncode().wire() + name.wireEncode().size());
333 }
334 
335 } // namespace std
name::Component::Error Error
Definition: name.hpp:46
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix of the name.
Definition: name.hpp:203
bool hasWire() const
Check if the Block has fully encoded wire.
Definition: block.cpp:249
Copyright (c) 2011-2015 Regents of the University of California.
std::string toUri() const
Get URI representation of the name.
Definition: name.cpp:116
bool equals(const Name &other) const
Check if this name equals another name.
Definition: name.cpp:267
const Block & wireEncode() const
Perform wire encoding, or return existing wire encoding.
Definition: name.cpp:140
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:157
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:322
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
Definition: name.cpp:251
size_t operator()(const ndn::Name &name) const
Definition: name.cpp:329
Name getSuccessor() const
Get the successor of a name.
Definition: name.cpp:241
static Component fromTimestamp(const time::system_clock::TimePoint &timePoint)
Create sequence number component using NDN naming conventions.
static const size_t npos
indicates "until the end" in getSubName and compare
Definition: name.hpp:534
void parse() const
Parse TLV-VALUE into sub elements.
Definition: block.cpp:333
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
int compare(const Component &other) const
Compare this to the other Component using NDN canonical ordering.
static time_point now() noexcept
Definition: time.cpp:46
Name & append(const Component &component)
Append a component.
Definition: name.hpp:249
void resetWire()
Reset wire buffer but keep TLV-TYPE and sub elements (if any)
Definition: block.cpp:264
Name & appendVersion(optional< uint64_t > version=nullopt)
Append a version component.
Definition: name.cpp:214
const element_container & elements() const
Get container of sub elements.
Definition: block.hpp:361
const Component & at(ssize_t i) const
Get the component at the given index.
Definition: name.cpp:179
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:60
int compare(const Name &other) const
Compare this to the other Name using NDN canonical ordering.
Definition: name.hpp:517
static Component fromEscapedString(const char *input, size_t beginOffset, size_t endOffset)
Decode NameComponent from a URI component.
Name PartialName
Represents an arbitrary sequence of name components.
Definition: name.hpp:39
NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Exclude)
std::istream & operator>>(std::istream &is, Name &name)
Parse URI from stream as Name.
Definition: name.cpp:315
Represents an absolute name.
Definition: name.hpp:43
Name & appendTimestamp(optional< time::system_clock::TimePoint > timestamp=nullopt)
Append a timestamp component.
Definition: name.cpp:220
size_t size() const
Get number of components.
Definition: name.hpp:147
Represents a name component.
milliseconds toUnixTimestamp(const system_clock::TimePoint &point)
Convert system_clock::TimePoint to UNIX timestamp.
Definition: time.cpp:113
bool empty() const
Check if name is empty.
Definition: name.hpp:139
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:125
static Component fromVersion(uint64_t version)
Create version component using NDN naming conventions.
Name deepCopy() const
Make a deep copy of the name, reallocating the underlying memory buffer.
Definition: name.cpp:168
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:158
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:44
a concept check for TLV abstraction with .wireDecode method and constructible from Block
Definition: concepts.hpp:80
PartialName getSubName(ssize_t iStartComponent, size_t nComponents=npos) const
Extract some components as a sub-name (PartialName)
Definition: name.cpp:193
EncodingImpl< EncoderTag > EncodingBuffer
uint32_t type() const
Get TLV-TYPE.
Definition: block.hpp:249
Name()
Create an empty name.
Definition: name.cpp:54
represents an error in TLV encoding or decoding
Definition: tlv.hpp:52
EncodingImpl< EstimatorTag > EncodingEstimator