blob: 890451f3f357b4775e9c8690b70b7c58e7b177ce [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 Shif0bf9992017-07-15 15:51:52 +0000224 return reinterpret_cast<const_iterator>(m_wire.elements().data());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800225 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700226
Junxiao Shi71ff2312017-07-12 13:32:50 +0000227 /** @brief End iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700228 */
229 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800230 end() const
231 {
Junxiao Shif0bf9992017-07-15 15:51:52 +0000232 return reinterpret_cast<const_iterator>(m_wire.elements().data() + m_wire.elements().size());
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800233 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700234
Junxiao Shi71ff2312017-07-12 13:32:50 +0000235 /** @brief Reverse begin iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700236 */
237 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800238 rbegin() const
239 {
240 return const_reverse_iterator(end());
241 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700242
Junxiao Shi71ff2312017-07-12 13:32:50 +0000243 /** @brief Reverse end iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700244 */
245 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800246 rend() const
247 {
248 return const_reverse_iterator(begin());
249 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700250
Junxiao Shi71ff2312017-07-12 13:32:50 +0000251public: // modifiers
252 /** @brief Append a component
253 * @return a reference to this name, to allow chaining
254 */
255 Name&
256 append(const Component& component)
257 {
258 m_wire.push_back(component);
259 return *this;
260 }
261
262 /** @brief Append a component, copying from a zero-terminated byte string
263 * @param value a zero-terminated string; it will be constructed as a component as is
264 * and will not be interpreted as a URI
265 * @note This overload is necessary to ensure unambiguity of ``append("string")``, because both
266 * Component and PartialName are implicitly convertible from zero-terminated byte string.
267 * This overload ensures the string is constructed as a Component.
268 */
269 Name&
270 append(const char* value)
271 {
272 return append(Component(value));
273 }
274
275 /** @brief Append a component, copying from [@p value, @p value + @p valueLength)
276 * @return a reference to this name, to allow chaining
277 */
278 Name&
279 append(const uint8_t* value, size_t valueLength)
280 {
281 return append(Component(value, valueLength));
282 }
283
284 /** @brief Append a component, copying from [@p first, @p last)
285 * @tparam Iterator an InputIterator dereferencing to a one-octet value type. More efficient
286 * implementation is available when @p Iterator additionally satisfies
287 * RandomAccessIterator concept.
288 * @param first begin position of the value
289 * @param last end position of the value
290 * @return a reference to this name, to allow chaining
291 */
292 template<class Iterator>
293 Name&
294 append(Iterator first, Iterator last)
295 {
296 static_assert(sizeof(std::iterator_traits<Iterator>::value_type) == 1,
297 "iterator does not dereference to one-octet value type");
298 return append(Component(first, last));
299 }
300
301 /** @brief Append a component, decoding from a Block
302 * @param value a Block; if its TLV-TYPE is not NameComponent, it is nested into a NameComponent
303 * @return a reference to this name, to allow chaining
304 */
305 Name&
306 append(const Block& value)
307 {
308 if (value.type() == tlv::NameComponent) {
309 m_wire.push_back(value);
310 }
311 else {
312 m_wire.push_back(Block(tlv::NameComponent, value));
313 }
314
315 return *this;
316 }
317
318 /** @brief Append a component with a nonNegativeInteger
319 * @sa number the number
320 * @return a reference to this name, to allow chaining
321 * @sa https://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
322 */
323 Name&
324 appendNumber(uint64_t number)
325 {
326 return append(Component::fromNumber(number));
327 }
328
329 /** @brief Append a component with a marked number
330 * @param marker 1-octet marker
331 * @param number the number
332 *
333 * The component is encoded as a 1-octet marker, followed by a nonNegativeInteger.
334 *
335 * @return a reference to this name, to allow chaining
336 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
337 */
338 Name&
339 appendNumberWithMarker(uint8_t marker, uint64_t number)
340 {
341 return append(Component::fromNumberWithMarker(marker, number));
342 }
343
344 /** @brief Append a version component
345 * @return a reference to this name, to allow chaining
346 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
347 */
348 Name&
349 appendVersion(uint64_t version)
350 {
351 return append(Component::fromVersion(version));
352 }
353
354 /** @brief Append a version component based on current time
355 *
356 * The version number is the current UNIX timestamp in milliseconds
357 *
358 * @return a reference to this name, to allow chaining
359 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
360 */
361 Name&
362 appendVersion();
363
364 /** @brief Append a segment number (sequential) component
365 * @return a reference to this name, to allow chaining
366 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
367 */
368 Name&
369 appendSegment(uint64_t segmentNo)
370 {
371 return append(Component::fromSegment(segmentNo));
372 }
373
374 /** @brief Append a segment byte offset component
375 * @return a reference to this name, to allow chaining
376 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
377 */
378 Name&
379 appendSegmentOffset(uint64_t offset)
380 {
381 return append(Component::fromSegmentOffset(offset));
382 }
383
384 /** @brief Append a timestamp component
385 * @return a reference to this name, to allow chaining
386 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
387 */
388 Name&
389 appendTimestamp(const time::system_clock::TimePoint& timePoint)
390 {
391 return append(Component::fromTimestamp(timePoint));
392 }
393
394 /** @brief Append a timestamp component based on current time
395 * @return a reference to this name, to allow chaining
396 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
397 */
398 Name&
399 appendTimestamp();
400
401 /** @brief Append a sequence number component
402 * @return a reference to this name, to allow chaining
403 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
404 */
405 Name&
406 appendSequenceNumber(uint64_t seqNo)
407 {
408 return append(Component::fromSequenceNumber(seqNo));
409 }
410
411 /** @brief Append an ImplicitSha256Digest component
412 * @return a reference to this name, to allow chaining
413 */
414 Name&
415 appendImplicitSha256Digest(const ConstBufferPtr& digest)
416 {
417 return append(Component::fromImplicitSha256Digest(digest));
418 }
419
420 /** @brief Append an ImplicitSha256Digest component
421 * @return a reference to this name, to allow chaining
422 */
423 Name&
424 appendImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
425 {
426 return append(Component::fromImplicitSha256Digest(digest, digestSize));
427 }
428
429 /** @brief Append a PartialName
430 * @param name the components to append
431 * @return a reference to this name, to allow chaining
432 */
433 Name&
434 append(const PartialName& name);
435
436 /** @brief Append a component
437 * @note This makes push_back an alias of append, giving Name a similar API as STL vector.
438 */
439 template<class T>
440 void
441 push_back(const T& component)
442 {
443 append(component);
444 }
445
446 /** @brief Remove all components
447 * @post empty() == true
448 */
449 void
450 clear()
451 {
452 m_wire = Block(tlv::Name);
453 }
454
455public: // algorithms
456 /** @brief Get the successor of a name
457 *
458 * The successor of a name is defined as follows:
459 *
460 * N represents the set of NDN Names, and X,Y ∈ N.
461 * Operator < is defined by canonical order on N.
462 * Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
463 *
464 * In plain words, successor of a name is the same name, but with its last component
465 * advanced to a next possible value.
466 *
467 * Examples:
468 *
469 * - successor for / is /%00
470 * - successor for /%00%01/%01%02 is /%00%01/%01%03
471 * - successor for /%00%01/%01%FF is /%00%01/%02%00
472 * - successor for /%00%01/%FF%FF is /%00%01/%00%00%00
473 *
474 * @return a new Name containing the successor
475 */
476 Name
477 getSuccessor() const;
478
479 /** @brief Check if this name is a prefix of another name
480 *
481 * This name is a prefix of @p other if the N components of this name are same as the first N
482 * components of @p other.
483 *
484 * @retval true this name is a prefix of @p other
485 * @retval false this name is not a prefix of @p other
486 */
487 bool
488 isPrefixOf(const Name& other) const;
489
490 /** @brief Check if this name equals another name
491 *
492 * Two names are equal if they have the same number of components, and components at each index
493 * are equal.
494 */
495 bool
496 equals(const Name& other) const;
497
498 /** @brief Compare this to the other Name using NDN canonical ordering.
499 *
500 * If the first components of each name are not equal, this returns a negative value if
501 * the first comes before the second using the NDN canonical ordering for name
502 * components, or a positive value if it comes after. If they are equal, this compares
503 * the second components of each name, etc. If both names are the same up to the size
504 * of the shorter name, this returns a negative value if the first name is shorter than
505 * the second or a positive value if it is longer. For example, if you std::sort gives:
506 * /a/b/d /a/b/cc /c /c/a /bb .
507 * This is intuitive because all names with the prefix /a are next to each other.
508 * But it may be also be counter-intuitive because /c comes before /bb according
509 * to NDN canonical ordering since it is shorter.
510 *
511 * @param other The other Name to compare with.
512 *
513 * @retval negative this comes before other in canonical ordering
514 * @retval zero this equals other
515 * @retval positive this comes after other in canonical ordering
516 *
517 * @sa https://named-data.net/doc/ndn-tlv/name.html#canonical-order
518 */
519 int
520 compare(const Name& other) const
521 {
522 return this->compare(0, npos, other);
523 }
524
525 /** @brief compares [pos1, pos1+count1) components in this Name
526 * to [pos2, pos2+count2) components in @p other
527 *
528 * This is equivalent to this->getSubName(pos1, count1).compare(other.getSubName(pos2, count2));
529 */
530 int
531 compare(size_t pos1, size_t count1,
532 const Name& other, size_t pos2 = 0, size_t count2 = npos) const;
533
Junxiao Shia6452ac2015-01-23 11:21:06 -0700534public:
Junxiao Shiadc334e2017-07-14 20:28:28 +0000535 /** @brief indicates "until the end" in getSubName and compare
Junxiao Shia6452ac2015-01-23 11:21:06 -0700536 */
537 static const size_t npos;
538
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700539private:
Junxiao Shi71ff2312017-07-12 13:32:50 +0000540 mutable Block m_wire;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800541};
542
Junxiao Shi71ff2312017-07-12 13:32:50 +0000543inline bool
544operator==(const Name& lhs, const Name& rhs)
545{
546 return lhs.equals(rhs);
547}
548
549inline bool
550operator!=(const Name& lhs, const Name& rhs)
551{
552 return !lhs.equals(rhs);
553}
554
555inline bool
556operator<=(const Name& lhs, const Name& rhs)
557{
558 return lhs.compare(rhs) <= 0;
559}
560
561inline bool
562operator<(const Name& lhs, const Name& rhs)
563{
564 return lhs.compare(rhs) < 0;
565}
566
567inline bool
568operator>=(const Name& lhs, const Name& rhs)
569{
570 return lhs.compare(rhs) >= 0;
571}
572
573inline bool
574operator>(const Name& lhs, const Name& rhs)
575{
576 return lhs.compare(rhs) > 0;
577}
578
579/** @brief Print URI representation of a name
580 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
581 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700582std::ostream&
583operator<<(std::ostream& os, const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700584
Junxiao Shi71ff2312017-07-12 13:32:50 +0000585/** @brief Parse URI from stream as Name
586 * @sa https://named-data.net/doc/ndn-tlv/name.html#ndn-uri-scheme
587 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700588std::istream&
589operator>>(std::istream& is, Name& name);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800590
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800591} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700592
Yingdi Yu90e23582014-11-06 14:21:04 -0800593namespace std {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000594
Yingdi Yu90e23582014-11-06 14:21:04 -0800595template<>
596struct hash<ndn::Name>
597{
598 size_t
599 operator()(const ndn::Name& name) const;
600};
601
602} // namespace std
603
Junxiao Shi8609bf22017-07-12 13:02:55 +0000604#endif // NDN_NAME_HPP