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 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  if (i < 0) {
174  i += static_cast<ssize_t>(size());
175  }
176 
177  if (i < 0 || static_cast<size_t>(i) >= size()) {
178  NDN_THROW(Error("Requested component does not exist (out of bounds)"));
179  }
180 
181  return reinterpret_cast<const Component&>(m_wire.elements()[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(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(optional<time::system_clock::TimePoint> 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  for (size_t i = 0; i < name.size(); ++i)
249  append(name.at(i));
250 
251  return *this;
252 }
253 
254 static constexpr uint8_t SHA256_OF_EMPTY_STRING[] = {
255  0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
256  0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
257  0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
258  0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
259 };
260 
261 Name&
263 {
264  static const Component placeholder(tlv::ParametersSha256DigestComponent,
266  return append(placeholder);
267 }
268 
269 void
270 Name::erase(ssize_t i)
271 {
272  if (i < 0) {
273  i += static_cast<ssize_t>(size());
274  }
275 
276  m_wire.erase(m_wire.elements_begin() + i);
277 }
278 
279 void
281 {
282  m_wire = Block(tlv::Name);
283 }
284 
285 // ---- algorithms ----
286 
287 Name
289 {
290  if (empty()) {
291  static const Name n("/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");
292  return n;
293  }
294 
295  return getPrefix(-1).append(get(-1).getSuccessor());
296 }
297 
298 bool
299 Name::isPrefixOf(const Name& other) const
300 {
301  // This name is longer than the name we are checking against.
302  if (size() > other.size())
303  return false;
304 
305  // Check if at least one of given components doesn't match.
306  for (size_t i = 0; i < size(); ++i) {
307  if (get(i) != other.get(i))
308  return false;
309  }
310 
311  return true;
312 }
313 
314 bool
315 Name::equals(const Name& other) const
316 {
317  if (size() != other.size())
318  return false;
319 
320  for (size_t i = 0; i < size(); ++i) {
321  if (get(i) != other.get(i))
322  return false;
323  }
324 
325  return true;
326 }
327 
328 int
329 Name::compare(size_t pos1, size_t count1, const Name& other, size_t pos2, size_t count2) const
330 {
331  count1 = std::min(count1, this->size() - pos1);
332  count2 = std::min(count2, other.size() - pos2);
333  size_t count = std::min(count1, count2);
334 
335  for (size_t i = 0; i < count; ++i) {
336  int comp = get(pos1 + i).compare(other.get(pos2 + i));
337  if (comp != 0) { // i-th component differs
338  return comp;
339  }
340  }
341  // [pos1, pos1+count) of this Name equals [pos2, pos2+count) of other Name
342  return count1 - count2;
343 }
344 
345 // ---- URI representation ----
346 
347 void
348 Name::toUri(std::ostream& os, name::UriFormat format) const
349 {
350  if (empty()) {
351  os << "/";
352  return;
353  }
354 
355  for (const auto& component : *this) {
356  os << "/";
357  component.toUri(os, format);
358  }
359 }
360 
361 std::string
363 {
364  std::ostringstream os;
365  toUri(os, format);
366  return os.str();
367 }
368 
369 std::istream&
370 operator>>(std::istream& is, Name& name)
371 {
372  std::string inputString;
373  is >> inputString;
374  name = Name(inputString);
375 
376  return is;
377 }
378 
379 } // namespace ndn
380 
381 namespace std {
382 
383 size_t
385 {
386  return boost::hash_range(name.wireEncode().wire(),
387  name.wireEncode().wire() + name.wireEncode().size());
388 }
389 
390 } // namespace std
ndn::Block::elements
const element_container & elements() const
Get container of sub-elements.
Definition: block.hpp:391
ndn::operator>>
std::istream & operator>>(std::istream &is, Name &name)
Parse URI from stream as Name.
Definition: name.cpp:370
ndn::name::Component::fromTimestamp
static Component fromTimestamp(const time::system_clock::TimePoint &timePoint)
Create sequence number component using NDN naming conventions.
Definition: name-component.cpp:391
nonstd::optional_lite::std11::move
T & move(T &t)
Definition: optional.hpp:421
ndn::Name::erase
void erase(ssize_t i)
Erase the component at the specified index.
Definition: name.cpp:270
ndn::Name::compare
int compare(const Name &other) const
Compare this to the other Name using NDN canonical ordering.
Definition: name.hpp:591
ndn::Name::isPrefixOf
bool isPrefixOf(const Name &other) const
Check if this name is a prefix of another name.
Definition: name.cpp:299
ndn::Name::Name
Name()
Create an empty name.
Definition: name.cpp:54
ndn::PartialName
Name PartialName
Represents an arbitrary sequence of name components.
Definition: name.hpp:39
ndn::Name::size
size_t size() const
Returns the number of components.
Definition: name.hpp:153
ndn::tlv::ParametersSha256DigestComponent
@ ParametersSha256DigestComponent
Definition: tlv.hpp:70
ndn::SHA256_OF_EMPTY_STRING
static constexpr uint8_t SHA256_OF_EMPTY_STRING[]
Definition: name.cpp:254
ndn::Block::elements_begin
element_const_iterator elements_begin() const
Equivalent to elements().begin()
Definition: block.hpp:399
block.hpp
ndn::name::Component::compare
int compare(const Component &other) const
Compare this to the other Component using NDN canonical ordering.
Definition: name-component.cpp:463
ndn::time::system_clock::now
static time_point now() noexcept
Definition: time.cpp:46
ndn::Name::empty
NDN_CXX_NODISCARD bool empty() const
Checks if the name is empty, i.e.
Definition: name.hpp:145
name.hpp
ndn::Name::npos
static const size_t npos
Indicates "until the end" in getSubName() and compare().
Definition: name.hpp:658
ndn::WireDecodable
a concept check for TLV abstraction with .wireDecode method and constructible from Block
Definition: concepts.hpp:81
ndn::encoding::EncodingEstimator
EncodingImpl< EstimatorTag > EncodingEstimator
Definition: encoding-buffer-fwd.hpp:39
ndn::Name::getSuccessor
Name getSuccessor() const
Get the successor of a name.
Definition: name.cpp:288
ndn::Name
Represents an absolute name.
Definition: name.hpp:44
ndn::Name::Error
name::Component::Error Error
Definition: name.hpp:46
ndn::Name::wireDecode
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:150
ns3::ndn::Name
Name
Definition: ndn-common.cpp:25
ndn::Name::getSubName
PartialName getSubName(ssize_t iStartComponent, size_t nComponents=npos) const
Extracts some components as a sub-name (PartialName).
Definition: name.cpp:185
ndn::name::Component::fromVersion
static Component fromVersion(uint64_t version)
Create version component using NDN naming conventions.
Definition: name-component.cpp:367
ndn::Block::type
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:274
ndn::WireEncodable
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:45
ndn::Name::appendVersion
Name & appendVersion(optional< uint64_t > version=nullopt)
Append a version component.
Definition: name.cpp:230
ndn::Block::erase
element_iterator erase(element_const_iterator position)
Erase a sub-element.
Definition: block.cpp:443
ndn::Name::wireEncode
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:117
ndn::Name::set
Name & set(ssize_t i, const Component &component)
Replace the component at the specified index.
Definition: name.cpp:206
ndn::Block::element_container
std::vector< Block > element_container
Definition: block.hpp:45
NDN_THROW
#define NDN_THROW(e)
Definition: exception.hpp:61
ndn::Name::append
Name & append(const Component &component)
Append a component.
Definition: name.hpp:277
ndn::Name::getPrefix
PartialName getPrefix(ssize_t nComponents) const
Returns a prefix of the name.
Definition: name.hpp:211
ndn::Name::wireEncode
const Block & wireEncode() const
Perform wire encoding, or return existing wire encoding.
Definition: name.cpp:132
ndn::Block::resetWire
void resetWire() noexcept
Reset wire buffer but keep TLV-TYPE and sub-elements (if any)
Definition: block.cpp:256
ndn::tlv::Name
@ Name
Definition: tlv.hpp:67
ndn::Name::toUri
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:348
ndn::Block::parse
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:325
std::hash< ndn::Name >::operator()
size_t operator()(const ndn::Name &name) const
Definition: name.cpp:384
ndn::Name::at
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
ndn::NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS
NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Interest)
ndn::encoding::EncodingImpl
Definition: encoding-buffer-fwd.hpp:36
ndn::Name::appendParametersSha256DigestPlaceholder
Name & appendParametersSha256DigestPlaceholder()
Append a placeholder for a ParametersSha256Digest component.
Definition: name.cpp:262
ndn::name::Component
Represents a name component.
Definition: name-component.hpp:94
ndn::Block
Represents a TLV element of NDN packet format.
Definition: block.hpp:43
ndn::name
Definition: name-component-types.hpp:33
ndn::Name::clear
void clear()
Remove all components.
Definition: name.cpp:280
ndn::Name::deepCopy
Name deepCopy() const
Make a deep copy of the name, reallocating the underlying memory buffer.
Definition: name.cpp:160
ndn::Block::hasWire
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:230
ndn::time::toUnixTimestamp
milliseconds toUnixTimestamp(const system_clock::TimePoint &point)
Convert system_clock::TimePoint to UNIX timestamp.
Definition: time.cpp:113
ndn::Name::appendTimestamp
Name & appendTimestamp(optional< time::system_clock::TimePoint > timestamp=nullopt)
Append a timestamp component.
Definition: name.cpp:236
time.hpp
ndn::name::Component::fromEscapedString
static Component fromEscapedString(const char *input, size_t beginOffset, size_t endOffset)
Decode NameComponent from a URI component.
Definition: name-component.hpp:238
ndn::tlv::Error
represents an error in TLV encoding or decoding
Definition: tlv.hpp:53
ndn::Name::get
const Component & get(ssize_t i) const
Returns an immutable reference to the component at the specified index.
Definition: name.hpp:164
encoding-buffer.hpp
ndn::WireEncodableWithEncodingBuffer
a concept check for TLV abstraction with .wireEncode method
Definition: concepts.hpp:61
ndn
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-strategy-choice-helper.hpp:34
ndn::encoding::EncodingBuffer
EncodingImpl< EncoderTag > EncodingBuffer
Definition: encoding-buffer-fwd.hpp:38
ndn::Name::equals
bool equals(const Name &other) const
Check if this name equals another name.
Definition: name.cpp:315
ndn::name::UriFormat
UriFormat
Identify a format of URI representation.
Definition: name-component.hpp:35