blob: ad644248dfd87815ad97bcd8f12180357d58b670 [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/*
Junxiao Shia36f15d2018-04-04 02:22:11 +00003 * Copyright (c) 2013-2018 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
Junxiao Shia36f15d2018-04-04 02:22:11 +000092 * @sa https://named-data.net/doc/NDN-packet-spec/current/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
Junxiao Shia36f15d2018-04-04 02:22:11 +000098 * @sa https://named-data.net/doc/NDN-packet-spec/current/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
Junxiao Shia36f15d2018-04-04 02:22:11 +0000104 * @sa https://named-data.net/doc/NDN-packet-spec/current/name.html#ndn-uri-scheme
Junxiao Shi71ff2312017-07-12 13:32:50 +0000105 * @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
Junxiao Shia36f15d2018-04-04 02:22:11 +0000252 /** @brief Append a component.
253 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000254 */
255 Name&
256 append(const Component& component)
257 {
258 m_wire.push_back(component);
259 return *this;
260 }
261
Junxiao Shia36f15d2018-04-04 02:22:11 +0000262 /** @brief Append a NameComponent of TLV-TYPE @p type, copying @p count bytes at @p value as
263 * TLV-VALUE.
264 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000265 */
266 Name&
Junxiao Shia36f15d2018-04-04 02:22:11 +0000267 append(uint32_t type, const uint8_t* value, size_t count)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000268 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000269 return append(Component(type, value, count));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000270 }
271
Junxiao Shia36f15d2018-04-04 02:22:11 +0000272 /** @brief Append a GenericNameComponent, copying @p count bytes at @p value as TLV-VALUE.
273 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000274 */
275 Name&
Junxiao Shia36f15d2018-04-04 02:22:11 +0000276 append(const uint8_t* value, size_t count)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000277 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000278 return append(Component(value, count));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000279 }
280
Junxiao Shia36f15d2018-04-04 02:22:11 +0000281 /** @brief Append a NameComponent of TLV-TYPE @p type, copying TLV-VALUE from a range.
282 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
283 * implementation is available when it is a @c RandomAccessIterator.
284 * @param type the TLV-TYPE.
285 * @param first beginning of the range.
286 * @param last past-end of the range.
287 * @return a reference to this name, to allow chaining.
288 */
289 template<class Iterator>
290 Name&
291 append(uint32_t type, Iterator first, Iterator last)
292 {
293 return append(Component(type, first, last));
294 }
295
296 /** @brief Append a GenericNameComponent, copying TLV-VALUE from a range.
297 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
298 * implementation is available when it is a @c RandomAccessIterator.
299 * @param first beginning of the range.
300 * @param last past-end of the range.
301 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000302 */
303 template<class Iterator>
304 Name&
305 append(Iterator first, Iterator last)
306 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000307 return append(Component(first, last));
308 }
309
Junxiao Shia36f15d2018-04-04 02:22:11 +0000310 /** @brief Append a GenericNameComponent, copying TLV-VALUE from a null-terminated string.
311 * @param str a null-terminated string. Bytes from the string are copied as is, and not
312 * interpreted as URI component.
313 * @return a reference to this name, to allow chaining.
314 */
315 Name&
316 append(const char* str)
317 {
318 return append(Component(str));
319 }
320
321 /** @brief Append a GenericNameComponent from a TLV element.
322 * @param value a TLV element. If its type is @c tlv::GenericNameComponent, it is used as is.
323 * Otherwise, it is encapsulated into a GenericNameComponent.
324 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000325 */
326 Name&
327 append(const Block& value)
328 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000329 if (value.type() == tlv::GenericNameComponent) {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000330 m_wire.push_back(value);
331 }
332 else {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000333 m_wire.push_back(Block(tlv::GenericNameComponent, value));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000334 }
Junxiao Shi71ff2312017-07-12 13:32:50 +0000335 return *this;
336 }
337
338 /** @brief Append a component with a nonNegativeInteger
339 * @sa number the number
340 * @return a reference to this name, to allow chaining
Junxiao Shia36f15d2018-04-04 02:22:11 +0000341 * @sa https://named-data.net/doc/NDN-packet-spec/current/tlv.html#non-negative-integer-encoding
Junxiao Shi71ff2312017-07-12 13:32:50 +0000342 */
343 Name&
344 appendNumber(uint64_t number)
345 {
346 return append(Component::fromNumber(number));
347 }
348
349 /** @brief Append a component with a marked number
350 * @param marker 1-octet marker
351 * @param number the number
352 *
353 * The component is encoded as a 1-octet marker, followed by a nonNegativeInteger.
354 *
355 * @return a reference to this name, to allow chaining
356 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
357 */
358 Name&
359 appendNumberWithMarker(uint8_t marker, uint64_t number)
360 {
361 return append(Component::fromNumberWithMarker(marker, number));
362 }
363
364 /** @brief Append a version 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 appendVersion(uint64_t version)
370 {
371 return append(Component::fromVersion(version));
372 }
373
374 /** @brief Append a version component based on current time
375 *
376 * The version number is the current UNIX timestamp in milliseconds
377 *
378 * @return a reference to this name, to allow chaining
379 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
380 */
381 Name&
382 appendVersion();
383
384 /** @brief Append a segment number (sequential) 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 appendSegment(uint64_t segmentNo)
390 {
391 return append(Component::fromSegment(segmentNo));
392 }
393
394 /** @brief Append a segment byte offset component
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 appendSegmentOffset(uint64_t offset)
400 {
401 return append(Component::fromSegmentOffset(offset));
402 }
403
404 /** @brief Append a timestamp component
405 * @return a reference to this name, to allow chaining
406 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
407 */
408 Name&
409 appendTimestamp(const time::system_clock::TimePoint& timePoint)
410 {
411 return append(Component::fromTimestamp(timePoint));
412 }
413
414 /** @brief Append a timestamp component based on current time
415 * @return a reference to this name, to allow chaining
416 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
417 */
418 Name&
419 appendTimestamp();
420
421 /** @brief Append a sequence number component
422 * @return a reference to this name, to allow chaining
423 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
424 */
425 Name&
426 appendSequenceNumber(uint64_t seqNo)
427 {
428 return append(Component::fromSequenceNumber(seqNo));
429 }
430
431 /** @brief Append an ImplicitSha256Digest component
432 * @return a reference to this name, to allow chaining
433 */
434 Name&
435 appendImplicitSha256Digest(const ConstBufferPtr& digest)
436 {
437 return append(Component::fromImplicitSha256Digest(digest));
438 }
439
440 /** @brief Append an ImplicitSha256Digest component
441 * @return a reference to this name, to allow chaining
442 */
443 Name&
444 appendImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
445 {
446 return append(Component::fromImplicitSha256Digest(digest, digestSize));
447 }
448
449 /** @brief Append a PartialName
450 * @param name the components to append
451 * @return a reference to this name, to allow chaining
452 */
453 Name&
454 append(const PartialName& name);
455
456 /** @brief Append a component
457 * @note This makes push_back an alias of append, giving Name a similar API as STL vector.
458 */
459 template<class T>
460 void
461 push_back(const T& component)
462 {
463 append(component);
464 }
465
466 /** @brief Remove all components
467 * @post empty() == true
468 */
469 void
470 clear()
471 {
472 m_wire = Block(tlv::Name);
473 }
474
475public: // algorithms
476 /** @brief Get the successor of a name
477 *
478 * The successor of a name is defined as follows:
479 *
480 * N represents the set of NDN Names, and X,Y ∈ N.
481 * Operator < is defined by canonical order on N.
482 * Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
483 *
484 * In plain words, successor of a name is the same name, but with its last component
485 * advanced to a next possible value.
486 *
487 * Examples:
488 *
489 * - successor for / is /%00
490 * - successor for /%00%01/%01%02 is /%00%01/%01%03
491 * - successor for /%00%01/%01%FF is /%00%01/%02%00
492 * - successor for /%00%01/%FF%FF is /%00%01/%00%00%00
493 *
494 * @return a new Name containing the successor
495 */
496 Name
497 getSuccessor() const;
498
499 /** @brief Check if this name is a prefix of another name
500 *
501 * This name is a prefix of @p other if the N components of this name are same as the first N
502 * components of @p other.
503 *
504 * @retval true this name is a prefix of @p other
505 * @retval false this name is not a prefix of @p other
506 */
507 bool
508 isPrefixOf(const Name& other) const;
509
510 /** @brief Check if this name equals another name
511 *
512 * Two names are equal if they have the same number of components, and components at each index
513 * are equal.
514 */
515 bool
516 equals(const Name& other) const;
517
518 /** @brief Compare this to the other Name using NDN canonical ordering.
519 *
520 * If the first components of each name are not equal, this returns a negative value if
521 * the first comes before the second using the NDN canonical ordering for name
522 * components, or a positive value if it comes after. If they are equal, this compares
523 * the second components of each name, etc. If both names are the same up to the size
524 * of the shorter name, this returns a negative value if the first name is shorter than
525 * the second or a positive value if it is longer. For example, if you std::sort gives:
526 * /a/b/d /a/b/cc /c /c/a /bb .
527 * This is intuitive because all names with the prefix /a are next to each other.
528 * But it may be also be counter-intuitive because /c comes before /bb according
529 * to NDN canonical ordering since it is shorter.
530 *
531 * @param other The other Name to compare with.
532 *
533 * @retval negative this comes before other in canonical ordering
534 * @retval zero this equals other
535 * @retval positive this comes after other in canonical ordering
536 *
Junxiao Shia36f15d2018-04-04 02:22:11 +0000537 * @sa https://named-data.net/doc/NDN-packet-spec/current/name.html#canonical-order
Junxiao Shi71ff2312017-07-12 13:32:50 +0000538 */
539 int
540 compare(const Name& other) const
541 {
542 return this->compare(0, npos, other);
543 }
544
545 /** @brief compares [pos1, pos1+count1) components in this Name
546 * to [pos2, pos2+count2) components in @p other
547 *
548 * This is equivalent to this->getSubName(pos1, count1).compare(other.getSubName(pos2, count2));
549 */
550 int
551 compare(size_t pos1, size_t count1,
552 const Name& other, size_t pos2 = 0, size_t count2 = npos) const;
553
Junxiao Shia6452ac2015-01-23 11:21:06 -0700554public:
Junxiao Shiadc334e2017-07-14 20:28:28 +0000555 /** @brief indicates "until the end" in getSubName and compare
Junxiao Shia6452ac2015-01-23 11:21:06 -0700556 */
557 static const size_t npos;
558
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700559private:
Junxiao Shi71ff2312017-07-12 13:32:50 +0000560 mutable Block m_wire;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800561};
562
Davide Pesavento88a0d812017-08-19 21:31:42 -0400563NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Name);
564
Junxiao Shi71ff2312017-07-12 13:32:50 +0000565inline bool
566operator==(const Name& lhs, const Name& rhs)
567{
568 return lhs.equals(rhs);
569}
570
571inline bool
572operator!=(const Name& lhs, const Name& rhs)
573{
574 return !lhs.equals(rhs);
575}
576
577inline bool
578operator<=(const Name& lhs, const Name& rhs)
579{
580 return lhs.compare(rhs) <= 0;
581}
582
583inline bool
584operator<(const Name& lhs, const Name& rhs)
585{
586 return lhs.compare(rhs) < 0;
587}
588
589inline bool
590operator>=(const Name& lhs, const Name& rhs)
591{
592 return lhs.compare(rhs) >= 0;
593}
594
595inline bool
596operator>(const Name& lhs, const Name& rhs)
597{
598 return lhs.compare(rhs) > 0;
599}
600
601/** @brief Print URI representation of a name
Junxiao Shia36f15d2018-04-04 02:22:11 +0000602 * @sa https://named-data.net/doc/NDN-packet-spec/current/name.html#ndn-uri-scheme
Junxiao Shi71ff2312017-07-12 13:32:50 +0000603 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700604std::ostream&
605operator<<(std::ostream& os, const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700606
Junxiao Shi71ff2312017-07-12 13:32:50 +0000607/** @brief Parse URI from stream as Name
Junxiao Shia36f15d2018-04-04 02:22:11 +0000608 * @sa https://named-data.net/doc/NDN-packet-spec/current/name.html#ndn-uri-scheme
Junxiao Shi71ff2312017-07-12 13:32:50 +0000609 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700610std::istream&
611operator>>(std::istream& is, Name& name);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800612
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800613} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700614
Yingdi Yu90e23582014-11-06 14:21:04 -0800615namespace std {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000616
Yingdi Yu90e23582014-11-06 14:21:04 -0800617template<>
618struct hash<ndn::Name>
619{
620 size_t
621 operator()(const ndn::Name& name) const;
622};
623
624} // namespace std
625
Junxiao Shi8609bf22017-07-12 13:02:55 +0000626#endif // NDN_NAME_HPP