blob: 764bdacbb247e21938032f40acc45966670dd171 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi8609bf22017-07-12 13:02:55 +00002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * 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.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
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/>
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070024 */
25
26#ifndef NDN_NAME_HPP
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070027#define NDN_NAME_HPP
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070028
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080029#include "name-component.hpp"
Junxiao Shiadc334e2017-07-14 20:28:28 +000030#include <iterator>
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080031
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070032namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080033
Joao Pereira6f7cfd02015-06-15 11:36:26 -040034class Name;
35
Junxiao Shi71ff2312017-07-12 13:32:50 +000036/** @brief Represents an arbitrary sequence of name components
Joao Pereira6f7cfd02015-06-15 11:36:26 -040037 */
Junxiao Shi71ff2312017-07-12 13:32:50 +000038using PartialName = Name;
Joao Pereira6f7cfd02015-06-15 11:36:26 -040039
Junxiao Shi71ff2312017-07-12 13:32:50 +000040/** @brief Represents an absolute name
Jeff Thompsonc7d65502013-11-06 17:22:26 -080041 */
Junxiao Shi8609bf22017-07-12 13:02:55 +000042class Name
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070043{
Junxiao Shi71ff2312017-07-12 13:32:50 +000044public: // nested types
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070045 class Error : public name::Component::Error
46 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070047 public:
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070048 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070049 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070050 : name::Component::Error(what)
51 {
52 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070053 };
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080054
Junxiao Shi71ff2312017-07-12 13:32:50 +000055 using Component = name::Component;
56 using component_container = std::vector<Component>;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080057
Junxiao Shi71ff2312017-07-12 13:32:50 +000058 // Name appears as a container of name components
59 using value_type = Component;
60 using allocator_type = void;
61 using reference = Component&;
Junxiao Shiadc334e2017-07-14 20:28:28 +000062 using const_reference = const Component&;
Junxiao Shi71ff2312017-07-12 13:32:50 +000063 using pointer = Component*;
64 using const_pointer = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000065 using iterator = const Component*; // disallow modifying via iterator
Junxiao Shi71ff2312017-07-12 13:32:50 +000066 using const_iterator = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000067 using reverse_iterator = std::reverse_iterator<iterator>;
68 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Junxiao Shi71ff2312017-07-12 13:32:50 +000069 using difference_type = component_container::difference_type;
70 using size_type = component_container::size_type;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080071
Junxiao Shi71ff2312017-07-12 13:32:50 +000072public: // constructors, encoding, decoding
73 /** @brief Create an empty name
74 * @post empty() == true
Jeff Thompson443398d2013-07-02 19:45:46 -070075 */
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080076 Name();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080077
Junxiao Shi71ff2312017-07-12 13:32:50 +000078 /** @brief Decode Name from wire encoding
79 * @throw tlv::Error wire encoding is invalid
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080080 *
Junxiao Shi71ff2312017-07-12 13:32:50 +000081 * This is a more efficient equivalent for
82 * @code
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080083 * Name name;
84 * name.wireDecode(wire);
Junxiao Shi71ff2312017-07-12 13:32:50 +000085 * @endcode
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080086 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080087 explicit
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080088 Name(const Block& wire);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070089
Junxiao Shi71ff2312017-07-12 13:32:50 +000090 /** @brief Parse name from NDN URI
91 * @param uri a null-terminated URI string
92 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
Jeff Thompson443398d2013-07-02 19:45:46 -070093 */
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080094 Name(const char* uri);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070095
Junxiao Shi71ff2312017-07-12 13:32:50 +000096 /** @brief Create name from NDN URI
97 * @param uri a URI string
98 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
Jeff Thompson3549ef32013-09-25 14:05:17 -070099 */
Junxiao Shi3188c4032016-07-18 20:53:56 +0000100 Name(std::string uri);
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700101
Junxiao Shi71ff2312017-07-12 13:32:50 +0000102 /** @brief Get URI representation of the name
103 * @return URI representation; "ndn:" scheme identifier is not included
104 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
105 * @note To print URI representation into a stream, it is more efficient to use ``os << name``.
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700106 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000107 std::string
108 toUri() const;
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700109
Junxiao Shi71ff2312017-07-12 13:32:50 +0000110 /** @brief Check if this Name instance already has wire encoding
111 */
112 bool
113 hasWire() const
114 {
115 return m_wire.hasWire();
116 }
117
118 /** @brief Fast encoding or block size estimation
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800119 */
Alexander Afanasyev74633892015-02-08 18:08:46 -0800120 template<encoding::Tag TAG>
Wentao Shang77949212014-02-01 23:42:24 -0800121 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700122 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700123
Junxiao Shi71ff2312017-07-12 13:32:50 +0000124 /** @brief Perform wire encoding, or return existing wire encoding
125 * @post hasWire() == true
126 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700127 const Block&
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800128 wireEncode() const;
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800129
Junxiao Shi71ff2312017-07-12 13:32:50 +0000130 /** @brief Decode name from wire encoding
131 * @throw tlv::Error wire encoding is invalid
132 * @post hasWire() == true
133 */
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800134 void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700135 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800136
Junxiao Shi71ff2312017-07-12 13:32:50 +0000137 /** @brief Make a deep copy of the name, reallocating the underlying memory buffer
138 */
139 Name
140 deepCopy() const;
141
142public: // access
143 /** @brief Check if name is empty
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800144 */
145 bool
Junxiao Shi71ff2312017-07-12 13:32:50 +0000146 empty() const
Jeff Thompson0f743452013-09-12 14:23:18 -0700147 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000148 return m_wire.elements().empty();
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700149 }
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700150
Junxiao Shi71ff2312017-07-12 13:32:50 +0000151 /** @brief Get number of components
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800152 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000153 size_t
154 size() const
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800155 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000156 return m_wire.elements_size();
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800157 }
158
Junxiao Shi71ff2312017-07-12 13:32:50 +0000159 /** @brief Get the component at the given index
160 * @param i zero-based index; if negative, it starts at the end of this name
161 * @warning Indexing out of bounds triggers undefined behavior.
Alexander Afanasyevc89efb42015-02-10 18:26:42 -0800162 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000163 const Component&
164 get(ssize_t i) const
Jeff Thompson21eb7212013-09-26 09:05:40 -0700165 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000166 if (i < 0) {
167 i += size();
168 }
169 return reinterpret_cast<const Component&>(m_wire.elements()[i]);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700170 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800171
Junxiao Shi71ff2312017-07-12 13:32:50 +0000172 /** @brief Equivalent to get(i)
173 */
174 const Component&
175 operator[](ssize_t i) const
176 {
177 return get(i);
178 }
179
180 /** @brief Get the component at the given index
181 * @param i zero-based index; if negative, size()+i is used instead
182 * @throws Name::Error index is out of bounds
183 */
184 const Component&
185 at(ssize_t i) const;
186
187 /** @brief Extract some components as a sub-name (PartialName)
188 * @param iStartComponent zero-based index of the first component;
189 * if negative, size()+iStartComponent is used instead
190 * @param nComponents Number of components starting at iStartComponent.
191 * Use @p npos to get the PartialName until the end of this Name.
192 * @return a new PartialName containing the extracted components
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800193 *
Junxiao Shi71ff2312017-07-12 13:32:50 +0000194 * If iStartComponent is positive and indexes out of bounds, returns an empty PartialName.
195 * If iStartComponent is negative and indexes out of bounds, returns components starting from the
196 * beginning of the Name. If nComponents is out of bounds, returns the components until the end
197 * of this Name.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700198 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400199 PartialName
200 getSubName(ssize_t iStartComponent, size_t nComponents = npos) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700201
Junxiao Shi71ff2312017-07-12 13:32:50 +0000202 /** @brief Extract a prefix of the name
203 * @param nComponents Number of components; if negative, size()+nComponents is used instead
204 * @return a new Name containing the prefix
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700205 * the prefix up to name.size() - N. For example getPrefix(-1)
206 * returns the name without the final component.
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400207 * @return A new partial name
Jeff Thompsond0159d72013-09-23 13:34:15 -0700208 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400209 PartialName
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700210 getPrefix(ssize_t nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700211 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800212 if (nComponents < 0)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000213 return getSubName(0, size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800214 else
215 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700216 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700217
Junxiao Shi71ff2312017-07-12 13:32:50 +0000218public: // iterators
219 /** @brief Begin iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700220 */
221 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800222 begin() const
223 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000224 // XXX This triggers undefined behavior if name is empty (#4181)
225 return reinterpret_cast<const_iterator>(&*m_wire.elements().begin());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800226 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700227
Junxiao Shi71ff2312017-07-12 13:32:50 +0000228 /** @brief End iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700229 */
230 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800231 end() const
232 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000233 // XXX This triggers undefined behavior if name is empty (#4181)
234 return reinterpret_cast<const_iterator>(&*m_wire.elements().end());
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800235 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700236
Junxiao Shi71ff2312017-07-12 13:32:50 +0000237 /** @brief Reverse begin iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700238 */
239 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800240 rbegin() const
241 {
242 return const_reverse_iterator(end());
243 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700244
Junxiao Shi71ff2312017-07-12 13:32:50 +0000245 /** @brief Reverse end iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700246 */
247 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800248 rend() const
249 {
250 return const_reverse_iterator(begin());
251 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700252
Junxiao Shi71ff2312017-07-12 13:32:50 +0000253public: // modifiers
254 /** @brief Append a component
255 * @return a reference to this name, to allow chaining
256 */
257 Name&
258 append(const Component& component)
259 {
260 m_wire.push_back(component);
261 return *this;
262 }
263
264 /** @brief Append a component, copying from a zero-terminated byte string
265 * @param value a zero-terminated string; it will be constructed as a component as is
266 * and will not be interpreted as a URI
267 * @note This overload is necessary to ensure unambiguity of ``append("string")``, because both
268 * Component and PartialName are implicitly convertible from zero-terminated byte string.
269 * This overload ensures the string is constructed as a Component.
270 */
271 Name&
272 append(const char* value)
273 {
274 return append(Component(value));
275 }
276
277 /** @brief Append a component, copying from [@p value, @p value + @p valueLength)
278 * @return a reference to this name, to allow chaining
279 */
280 Name&
281 append(const uint8_t* value, size_t valueLength)
282 {
283 return append(Component(value, valueLength));
284 }
285
286 /** @brief Append a component, copying from [@p first, @p last)
287 * @tparam Iterator an InputIterator dereferencing to a one-octet value type. More efficient
288 * implementation is available when @p Iterator additionally satisfies
289 * RandomAccessIterator concept.
290 * @param first begin position of the value
291 * @param last end position of the value
292 * @return a reference to this name, to allow chaining
293 */
294 template<class Iterator>
295 Name&
296 append(Iterator first, Iterator last)
297 {
298 static_assert(sizeof(std::iterator_traits<Iterator>::value_type) == 1,
299 "iterator does not dereference to one-octet value type");
300 return append(Component(first, last));
301 }
302
303 /** @brief Append a component, decoding from a Block
304 * @param value a Block; if its TLV-TYPE is not NameComponent, it is nested into a NameComponent
305 * @return a reference to this name, to allow chaining
306 */
307 Name&
308 append(const Block& value)
309 {
310 if (value.type() == tlv::NameComponent) {
311 m_wire.push_back(value);
312 }
313 else {
314 m_wire.push_back(Block(tlv::NameComponent, value));
315 }
316
317 return *this;
318 }
319
320 /** @brief Append a component with a nonNegativeInteger
321 * @sa number the number
322 * @return a reference to this name, to allow chaining
323 * @sa https://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
324 */
325 Name&
326 appendNumber(uint64_t number)
327 {
328 return append(Component::fromNumber(number));
329 }
330
331 /** @brief Append a component with a marked number
332 * @param marker 1-octet marker
333 * @param number the number
334 *
335 * The component is encoded as a 1-octet marker, followed by a nonNegativeInteger.
336 *
337 * @return a reference to this name, to allow chaining
338 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
339 */
340 Name&
341 appendNumberWithMarker(uint8_t marker, uint64_t number)
342 {
343 return append(Component::fromNumberWithMarker(marker, number));
344 }
345
346 /** @brief Append a version component
347 * @return a reference to this name, to allow chaining
348 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
349 */
350 Name&
351 appendVersion(uint64_t version)
352 {
353 return append(Component::fromVersion(version));
354 }
355
356 /** @brief Append a version component based on current time
357 *
358 * The version number is the current UNIX timestamp in milliseconds
359 *
360 * @return a reference to this name, to allow chaining
361 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
362 */
363 Name&
364 appendVersion();
365
366 /** @brief Append a segment number (sequential) component
367 * @return a reference to this name, to allow chaining
368 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
369 */
370 Name&
371 appendSegment(uint64_t segmentNo)
372 {
373 return append(Component::fromSegment(segmentNo));
374 }
375
376 /** @brief Append a segment byte offset component
377 * @return a reference to this name, to allow chaining
378 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
379 */
380 Name&
381 appendSegmentOffset(uint64_t offset)
382 {
383 return append(Component::fromSegmentOffset(offset));
384 }
385
386 /** @brief Append a timestamp component
387 * @return a reference to this name, to allow chaining
388 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
389 */
390 Name&
391 appendTimestamp(const time::system_clock::TimePoint& timePoint)
392 {
393 return append(Component::fromTimestamp(timePoint));
394 }
395
396 /** @brief Append a timestamp component based on current time
397 * @return a reference to this name, to allow chaining
398 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
399 */
400 Name&
401 appendTimestamp();
402
403 /** @brief Append a sequence number component
404 * @return a reference to this name, to allow chaining
405 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
406 */
407 Name&
408 appendSequenceNumber(uint64_t seqNo)
409 {
410 return append(Component::fromSequenceNumber(seqNo));
411 }
412
413 /** @brief Append an ImplicitSha256Digest component
414 * @return a reference to this name, to allow chaining
415 */
416 Name&
417 appendImplicitSha256Digest(const ConstBufferPtr& digest)
418 {
419 return append(Component::fromImplicitSha256Digest(digest));
420 }
421
422 /** @brief Append an ImplicitSha256Digest component
423 * @return a reference to this name, to allow chaining
424 */
425 Name&
426 appendImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
427 {
428 return append(Component::fromImplicitSha256Digest(digest, digestSize));
429 }
430
431 /** @brief Append a PartialName
432 * @param name the components to append
433 * @return a reference to this name, to allow chaining
434 */
435 Name&
436 append(const PartialName& name);
437
438 /** @brief Append a component
439 * @note This makes push_back an alias of append, giving Name a similar API as STL vector.
440 */
441 template<class T>
442 void
443 push_back(const T& component)
444 {
445 append(component);
446 }
447
448 /** @brief Remove all components
449 * @post empty() == true
450 */
451 void
452 clear()
453 {
454 m_wire = Block(tlv::Name);
455 }
456
457public: // algorithms
458 /** @brief Get the successor of a name
459 *
460 * The successor of a name is defined as follows:
461 *
462 * N represents the set of NDN Names, and X,Y ∈ N.
463 * Operator < is defined by canonical order on N.
464 * Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
465 *
466 * In plain words, successor of a name is the same name, but with its last component
467 * advanced to a next possible value.
468 *
469 * Examples:
470 *
471 * - successor for / is /%00
472 * - successor for /%00%01/%01%02 is /%00%01/%01%03
473 * - successor for /%00%01/%01%FF is /%00%01/%02%00
474 * - successor for /%00%01/%FF%FF is /%00%01/%00%00%00
475 *
476 * @return a new Name containing the successor
477 */
478 Name
479 getSuccessor() const;
480
481 /** @brief Check if this name is a prefix of another name
482 *
483 * This name is a prefix of @p other if the N components of this name are same as the first N
484 * components of @p other.
485 *
486 * @retval true this name is a prefix of @p other
487 * @retval false this name is not a prefix of @p other
488 */
489 bool
490 isPrefixOf(const Name& other) const;
491
492 /** @brief Check if this name equals another name
493 *
494 * Two names are equal if they have the same number of components, and components at each index
495 * are equal.
496 */
497 bool
498 equals(const Name& other) const;
499
500 /** @brief Compare this to the other Name using NDN canonical ordering.
501 *
502 * If the first components of each name are not equal, this returns a negative value if
503 * the first comes before the second using the NDN canonical ordering for name
504 * components, or a positive value if it comes after. If they are equal, this compares
505 * the second components of each name, etc. If both names are the same up to the size
506 * of the shorter name, this returns a negative value if the first name is shorter than
507 * the second or a positive value if it is longer. For example, if you std::sort gives:
508 * /a/b/d /a/b/cc /c /c/a /bb .
509 * This is intuitive because all names with the prefix /a are next to each other.
510 * But it may be also be counter-intuitive because /c comes before /bb according
511 * to NDN canonical ordering since it is shorter.
512 *
513 * @param other The other Name to compare with.
514 *
515 * @retval negative this comes before other in canonical ordering
516 * @retval zero this equals other
517 * @retval positive this comes after other in canonical ordering
518 *
519 * @sa https://named-data.net/doc/ndn-tlv/name.html#canonical-order
520 */
521 int
522 compare(const Name& other) const
523 {
524 return this->compare(0, npos, other);
525 }
526
527 /** @brief compares [pos1, pos1+count1) components in this Name
528 * to [pos2, pos2+count2) components in @p other
529 *
530 * This is equivalent to this->getSubName(pos1, count1).compare(other.getSubName(pos2, count2));
531 */
532 int
533 compare(size_t pos1, size_t count1,
534 const Name& other, size_t pos2 = 0, size_t count2 = npos) const;
535
Junxiao Shia6452ac2015-01-23 11:21:06 -0700536public:
Junxiao Shiadc334e2017-07-14 20:28:28 +0000537 /** @brief indicates "until the end" in getSubName and compare
Junxiao Shia6452ac2015-01-23 11:21:06 -0700538 */
539 static const size_t npos;
540
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700541private:
Junxiao Shi71ff2312017-07-12 13:32:50 +0000542 mutable Block m_wire;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800543};
544
Junxiao Shi71ff2312017-07-12 13:32:50 +0000545inline bool
546operator==(const Name& lhs, const Name& rhs)
547{
548 return lhs.equals(rhs);
549}
550
551inline bool
552operator!=(const Name& lhs, const Name& rhs)
553{
554 return !lhs.equals(rhs);
555}
556
557inline bool
558operator<=(const Name& lhs, const Name& rhs)
559{
560 return lhs.compare(rhs) <= 0;
561}
562
563inline bool
564operator<(const Name& lhs, const Name& rhs)
565{
566 return lhs.compare(rhs) < 0;
567}
568
569inline bool
570operator>=(const Name& lhs, const Name& rhs)
571{
572 return lhs.compare(rhs) >= 0;
573}
574
575inline bool
576operator>(const Name& lhs, const Name& rhs)
577{
578 return lhs.compare(rhs) > 0;
579}
580
581/** @brief Print URI representation of a name
582 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
583 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700584std::ostream&
585operator<<(std::ostream& os, const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700586
Junxiao Shi71ff2312017-07-12 13:32:50 +0000587/** @brief Parse URI from stream as Name
588 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
589 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700590std::istream&
591operator>>(std::istream& is, Name& name);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800592
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800593} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700594
Yingdi Yu90e23582014-11-06 14:21:04 -0800595namespace std {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000596
Yingdi Yu90e23582014-11-06 14:21:04 -0800597template<>
598struct hash<ndn::Name>
599{
600 size_t
601 operator()(const ndn::Name& name) const;
602};
603
604} // namespace std
605
Junxiao Shi8609bf22017-07-12 13:02:55 +0000606#endif // NDN_NAME_HPP