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-2022 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>));
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 template<encoding::Tag TAG>
116 size_t
118 {
119  size_t totalLength = 0;
120  for (const Component& comp : *this | boost::adaptors::reversed) {
121  totalLength += comp.wireEncode(encoder);
122  }
123 
124  totalLength += encoder.prependVarNumber(totalLength);
125  totalLength += encoder.prependVarNumber(tlv::Name);
126  return totalLength;
127 }
128 
130 
131 const Block&
133 {
134  if (m_wire.hasWire())
135  return m_wire;
136 
137  EncodingEstimator estimator;
138  size_t estimatedSize = wireEncode(estimator);
139 
140  EncodingBuffer buffer(estimatedSize, 0);
141  wireEncode(buffer);
142 
143  m_wire = buffer.block();
144  m_wire.parse();
145 
146  return m_wire;
147 }
148 
149 void
151 {
152  if (wire.type() != tlv::Name)
153  NDN_THROW(tlv::Error("Name", wire.type()));
154 
155  m_wire = wire;
156  m_wire.parse();
157 }
158 
159 Name
161 {
162  Name copiedName(*this);
163  copiedName.m_wire.resetWire();
164  copiedName.wireEncode(); // "compress" the underlying buffer
165  return copiedName;
166 }
167 
168 // ---- accessors ----
169 
170 const name::Component&
171 Name::at(ssize_t i) const
172 {
173  auto ssize = static_cast<ssize_t>(size());
174  if (i < -ssize || i >= ssize) {
175  NDN_THROW(Error("Component at offset " + to_string(i) + " does not exist (out of bounds)"));
176  }
177 
178  if (i < 0) {
179  i += ssize;
180  }
181  return static_cast<const Component&>(m_wire.elements()[static_cast<size_t>(i)]);
182 }
183 
185 Name::getSubName(ssize_t iStartComponent, size_t nComponents) const
186 {
187  PartialName result;
188 
189  if (iStartComponent < 0)
190  iStartComponent += static_cast<ssize_t>(size());
191  size_t iStart = iStartComponent < 0 ? 0 : static_cast<size_t>(iStartComponent);
192 
193  size_t iEnd = size();
194  if (nComponents != npos)
195  iEnd = std::min(size(), iStart + nComponents);
196 
197  for (size_t i = iStart; i < iEnd; ++i)
198  result.append(at(i));
199 
200  return result;
201 }
202 
203 // ---- modifiers ----
204 
205 Name&
206 Name::set(ssize_t i, const Component& component)
207 {
208  if (i < 0) {
209  i += static_cast<ssize_t>(size());
210  }
211 
212  const_cast<Block::element_container&>(m_wire.elements())[i] = component;
213  m_wire.resetWire();
214  return *this;
215 }
216 
217 Name&
218 Name::set(ssize_t i, Component&& component)
219 {
220  if (i < 0) {
221  i += static_cast<ssize_t>(size());
222  }
223 
224  const_cast<Block::element_container&>(m_wire.elements())[i] = std::move(component);
225  m_wire.resetWire();
226  return *this;
227 }
228 
229 Name&
230 Name::appendVersion(const optional<uint64_t>& version)
231 {
232  return append(Component::fromVersion(version.value_or(time::toUnixTimestamp(time::system_clock::now()).count())));
233 }
234 
235 Name&
236 Name::appendTimestamp(const optional<time::system_clock::time_point>& timestamp)
237 {
238  return append(Component::fromTimestamp(timestamp.value_or(time::system_clock::now())));
239 }
240 
241 Name&
243 {
244  if (&name == this) {
245  // Copying from this name, so need to make a copy first.
246  return append(PartialName(name));
247  }
248 
249  for (const auto& c : name) {
250  append(c);
251  }
252  return *this;
253 }
254 
255 static constexpr uint8_t SHA256_OF_EMPTY_STRING[] = {
256  0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
257  0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
258  0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
259  0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
260 };
261 
262 Name&
264 {
265  static const Component placeholder(tlv::ParametersSha256DigestComponent, SHA256_OF_EMPTY_STRING);
266  return append(placeholder);
267 }
268 
269 void
270 Name::erase(ssize_t i)
271 {
272  if (i >= 0) {
273  m_wire.erase(std::next(m_wire.elements_begin(), i));
274  }
275  else {
276  m_wire.erase(std::prev(m_wire.elements_end(), -i));
277  }
278 }
279 
280 void
282 {
283  m_wire = Block(tlv::Name);
284 }
285 
286 // ---- algorithms ----
287 
288 Name
290 {
291  if (empty()) {
292  static const Name n("/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");
293  return n;
294  }
295 
296  return getPrefix(-1).append(get(-1).getSuccessor());
297 }
298 
299 bool
300 Name::isPrefixOf(const Name& other) const
301 {
302  // This name is longer than the name we are checking against.
303  if (size() > other.size())
304  return false;
305 
306  // Check if at least one of given components doesn't match.
307  for (size_t i = 0; i < size(); ++i) {
308  if (get(i) != other.get(i))
309  return false;
310  }
311 
312  return true;
313 }
314 
315 bool
316 Name::equals(const Name& other) const
317 {
318  if (size() != other.size())
319  return false;
320 
321  for (size_t i = 0; i < size(); ++i) {
322  if (get(i) != other.get(i))
323  return false;
324  }
325 
326  return true;
327 }
328 
329 int
330 Name::compare(size_t pos1, size_t count1, const Name& other, size_t pos2, size_t count2) const
331 {
332  count1 = std::min(count1, this->size() - pos1);
333  count2 = std::min(count2, other.size() - pos2);
334  size_t count = std::min(count1, count2);
335 
336  for (size_t i = 0; i < count; ++i) {
337  int comp = get(pos1 + i).compare(other.get(pos2 + i));
338  if (comp != 0) { // i-th component differs
339  return comp;
340  }
341  }
342  // [pos1, pos1+count) of this Name equals [pos2, pos2+count) of other Name
343  return count1 - count2;
344 }
345 
346 // ---- URI representation ----
347 
348 void
349 Name::toUri(std::ostream& os, name::UriFormat format) const
350 {
351  if (empty()) {
352  os << "/";
353  return;
354  }
355 
356  for (const auto& component : *this) {
357  os << "/";
358  component.toUri(os, format);
359  }
360 }
361 
362 std::string
364 {
365  std::ostringstream os;
366  toUri(os, format);
367  return os.str();
368 }
369 
370 std::istream&
371 operator>>(std::istream& is, Name& name)
372 {
373  std::string inputString;
374  is >> inputString;
375  name = Name(inputString);
376 
377  return is;
378 }
379 
380 } // namespace ndn
381 
382 namespace std {
383 
384 size_t
385 hash<ndn::Name>::operator()(const ndn::Name& name) const
386 {
387  return boost::hash_range(name.wireEncode().begin(), name.wireEncode().end());
388 }
389 
390 } // namespace std
name::Component::Error Error
Definition: name.hpp:44
PartialName getPrefix(ssize_t nComponents) const
Returns a prefix of the name.
Definition: name.hpp:209
Copyright (c) 2011-2015 Regents of the University of California.
bool equals(const Name &other) const
Check if this name equals another name.
Definition: name.cpp:316
const Block & wireEncode() const
Perform wire encoding, or return existing wire encoding.
Definition: name.cpp:132
UriFormat
Format used for the URI representation of a name.
std::string to_string(const T &val)
Definition: backports.hpp:86
const Component & get(ssize_t i) const
Returns an immutable reference to the component at the specified index.
Definition: name.hpp:162
span_constexpr std::ptrdiff_t ssize(span< T, Extent > const &spn)
Definition: span-lite.hpp:1541
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
Definition: name.cpp:300
Name getSuccessor() const
Get the successor of a name.
Definition: name.cpp:289
static const size_t npos
Indicates "until the end" in getSubName() and compare().
Definition: name.hpp:696
STL namespace.
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:324
Represents a TLV element of the NDN packet format.
Definition: block.hpp:44
void resetWire() noexcept
Reset wire buffer but keep TLV-TYPE and sub-elements (if any)
Definition: block.cpp:260
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:221
element_const_iterator elements_begin() const
Equivalent to elements().begin()
Definition: block.hpp:433
static time_point now() noexcept
Definition: time.cpp:46
milliseconds toUnixTimestamp(const system_clock::time_point &point)
Convert system_clock::time_point to UNIX timestamp.
Definition: time.cpp:113
element_iterator erase(element_const_iterator position)
Erase a sub-element.
Definition: block.cpp:441
Name & append(const Component &component)
Append a component.
Definition: name.hpp:275
Name & appendVersion(const optional< uint64_t > &version=nullopt)
Append a version component.
Definition: name.cpp:230
const element_container & elements() const
Get container of sub-elements.
Definition: block.hpp:425
static constexpr uint8_t SHA256_OF_EMPTY_STRING[]
Definition: name.cpp:255
#define NDN_THROW(e)
Definition: exception.hpp:61
const Component & at(ssize_t i) const
Returns an immutable reference to the component at the specified index, with bounds checking...
Definition: name.cpp:171
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:60
element_const_iterator elements_end() const
Equivalent to elements().end()
Definition: block.hpp:441
int compare(const Name &other) const
Compare this to the other Name using NDN canonical ordering.
Definition: name.hpp:629
NDN_CXX_NODISCARD bool empty() const
Checks if the name is empty, i.e.
Definition: name.hpp:143
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:36
std::istream & operator>>(std::istream &is, Name &name)
Parse URI from stream as Name.
Definition: name.cpp:371
Represents an absolute name.
Definition: name.hpp:41
NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Interest)
size_t size() const
Returns the number of components.
Definition: name.hpp:151
Represents a name component.
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:277
static Component fromTimestamp(const time::system_clock::time_point &timePoint)
Create a timestamp component using NDN naming conventions.
void erase(ssize_t i)
Erase the component at the specified index.
Definition: name.cpp:270
Name & set(ssize_t i, const Component &component)
Replace the component at the specified index.
Definition: name.cpp:206
Name & appendTimestamp(const optional< time::system_clock::time_point > &timestamp=nullopt)
Append a timestamp component.
Definition: name.cpp:236
void toUri(std::ostream &os, name::UriFormat format=name::UriFormat::DEFAULT) const
Write URI representation of the name to the output stream.
Definition: name.cpp:349
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:117
static Component fromVersion(uint64_t version)
Create a version component using NDN naming conventions.
Name deepCopy() const
Make a deep copy of the name, reallocating the underlying memory buffer.
Definition: name.cpp:160
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:150
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
void clear()
Remove all components.
Definition: name.cpp:281
Name & appendParametersSha256DigestPlaceholder()
Append a placeholder for a ParametersSha256Digest component.
Definition: name.cpp:263
std::vector< Block > element_container
Definition: block.hpp:49
PartialName getSubName(ssize_t iStartComponent, size_t nComponents=npos) const
Extracts some components as a sub-name (PartialName).
Definition: name.cpp:185
EncodingImpl< EncoderTag > EncodingBuffer
Name()
Create an empty name.
Definition: name.cpp:54
represents an error in TLV encoding or decoding
Definition: tlv.hpp:52
EncodingImpl< EstimatorTag > EncodingEstimator