blob: fde6ebe49cd8d6f00043b3695cbd859080bfa156 [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/*
Davide Pesavento46cdf902020-06-08 16:38:23 -04003 * Copyright (c) 2013-2020 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
Davide Pesavento905d40f2020-06-09 21:33:25 -040026#ifndef NDN_CXX_NAME_HPP
27#define NDN_CXX_NAME_HPP
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070028
Davide Pesavento7e780642018-11-24 15:51:34 -050029#include "ndn-cxx/name-component.hpp"
30
Junxiao Shiadc334e2017-07-14 20:28:28 +000031#include <iterator>
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080032
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070033namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080034
Joao Pereira6f7cfd02015-06-15 11:36:26 -040035class Name;
36
Junxiao Shi71ff2312017-07-12 13:32:50 +000037/** @brief Represents an arbitrary sequence of name components
Joao Pereira6f7cfd02015-06-15 11:36:26 -040038 */
Junxiao Shi71ff2312017-07-12 13:32:50 +000039using PartialName = Name;
Joao Pereira6f7cfd02015-06-15 11:36:26 -040040
Junxiao Shi71ff2312017-07-12 13:32:50 +000041/** @brief Represents an absolute name
Davide Pesavento905d40f2020-06-09 21:33:25 -040042 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html
Jeff Thompsonc7d65502013-11-06 17:22:26 -080043 */
Junxiao Shi8609bf22017-07-12 13:02:55 +000044class Name
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070045{
Junxiao Shi71ff2312017-07-12 13:32:50 +000046public: // nested types
Junxiao Shi68b53852018-07-25 13:56:38 -060047 using Error = name::Component::Error;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080048
Junxiao Shi71ff2312017-07-12 13:32:50 +000049 using Component = name::Component;
50 using component_container = std::vector<Component>;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080051
Junxiao Shi71ff2312017-07-12 13:32:50 +000052 // Name appears as a container of name components
53 using value_type = Component;
54 using allocator_type = void;
55 using reference = Component&;
Junxiao Shiadc334e2017-07-14 20:28:28 +000056 using const_reference = const Component&;
Junxiao Shi71ff2312017-07-12 13:32:50 +000057 using pointer = Component*;
58 using const_pointer = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000059 using iterator = const Component*; // disallow modifying via iterator
Junxiao Shi71ff2312017-07-12 13:32:50 +000060 using const_iterator = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000061 using reverse_iterator = std::reverse_iterator<iterator>;
62 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Junxiao Shi71ff2312017-07-12 13:32:50 +000063 using difference_type = component_container::difference_type;
64 using size_type = component_container::size_type;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080065
Junxiao Shi71ff2312017-07-12 13:32:50 +000066public: // constructors, encoding, decoding
67 /** @brief Create an empty name
68 * @post empty() == true
Jeff Thompson443398d2013-07-02 19:45:46 -070069 */
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080070 Name();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080071
Junxiao Shi71ff2312017-07-12 13:32:50 +000072 /** @brief Decode Name from wire encoding
73 * @throw tlv::Error wire encoding is invalid
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080074 *
Junxiao Shi71ff2312017-07-12 13:32:50 +000075 * This is a more efficient equivalent for
76 * @code
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080077 * Name name;
78 * name.wireDecode(wire);
Junxiao Shi71ff2312017-07-12 13:32:50 +000079 * @endcode
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080080 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080081 explicit
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080082 Name(const Block& wire);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070083
Junxiao Shi71ff2312017-07-12 13:32:50 +000084 /** @brief Parse name from NDN URI
85 * @param uri a null-terminated URI string
Davide Pesavento905d40f2020-06-09 21:33:25 -040086 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Jeff Thompson443398d2013-07-02 19:45:46 -070087 */
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080088 Name(const char* uri);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070089
Junxiao Shi71ff2312017-07-12 13:32:50 +000090 /** @brief Create name from NDN URI
91 * @param uri a URI string
Davide Pesavento905d40f2020-06-09 21:33:25 -040092 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Jeff Thompson3549ef32013-09-25 14:05:17 -070093 */
Junxiao Shi3188c4032016-07-18 20:53:56 +000094 Name(std::string uri);
Jeff Thompsonec39fbd2013-10-04 10:56:23 -070095
Junxiao Shia39c0b52019-12-31 15:13:15 -070096 /** @brief Write URI representation of the name to the output stream
Davide Pesavento905d40f2020-06-09 21:33:25 -040097 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shia39c0b52019-12-31 15:13:15 -070098 */
99 void
100 toUri(std::ostream& os, name::UriFormat format = name::UriFormat::DEFAULT) const;
101
Junxiao Shi71ff2312017-07-12 13:32:50 +0000102 /** @brief Get URI representation of the name
Davide Pesavento905d40f2020-06-09 21:33:25 -0400103 * @return URI representation; the "ndn:" scheme identifier is not included
104 * @note To print URI representation into a stream, it is more efficient to use `os << name`.
105 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700106 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000107 std::string
Junxiao Shia39c0b52019-12-31 15:13:15 -0700108 toUri(name::UriFormat format = name::UriFormat::DEFAULT) const;
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700109
Davide Pesavento905d40f2020-06-09 21:33:25 -0400110 /** @brief Check if this instance already has wire encoding
Junxiao Shi71ff2312017-07-12 13:32:50 +0000111 */
112 bool
Davide Pesavento905d40f2020-06-09 21:33:25 -0400113 hasWire() const noexcept
Junxiao Shi71ff2312017-07-12 13:32:50 +0000114 {
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
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400143 /** @brief Checks if the name is empty, i.e. has no components.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800144 */
Davide Pesavento140e9cb2019-08-19 00:02:05 -0400145 NDN_CXX_NODISCARD 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
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400151 /** @brief Returns the 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
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400159 /** @brief Returns an immutable reference to the component at the specified index.
160 * @param i zero-based index of the component to return;
161 * if negative, it is interpreted as offset from the end of the name
162 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
Alexander Afanasyevc89efb42015-02-10 18:26:42 -0800163 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000164 const Component&
165 get(ssize_t i) const
Jeff Thompson21eb7212013-09-26 09:05:40 -0700166 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000167 if (i < 0) {
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400168 i += static_cast<ssize_t>(size());
Junxiao Shi71ff2312017-07-12 13:32:50 +0000169 }
170 return reinterpret_cast<const Component&>(m_wire.elements()[i]);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700171 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800172
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400173 /** @brief Equivalent to `get(i)`.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000174 */
175 const Component&
176 operator[](ssize_t i) const
177 {
178 return get(i);
179 }
180
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400181 /** @brief Returns an immutable reference to the component at the specified index,
182 * with bounds checking.
183 * @param i zero-based index of the component to return;
184 * if negative, it is interpreted as offset from the end of the name
185 * @throws Error The index is out of bounds.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000186 */
187 const Component&
188 at(ssize_t i) const;
189
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400190 /** @brief Extracts some components as a sub-name (PartialName).
Junxiao Shi71ff2312017-07-12 13:32:50 +0000191 * @param iStartComponent zero-based index of the first component;
192 * if negative, size()+iStartComponent is used instead
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400193 * @param nComponents number of desired components, starting at @p iStartComponent;
194 * use @c npos to return all components until the end of the name
Junxiao Shi71ff2312017-07-12 13:32:50 +0000195 * @return a new PartialName containing the extracted components
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800196 *
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400197 * If @p iStartComponent is positive and indexes out of bounds, returns an empty PartialName.
198 * If @p iStartComponent is negative and indexes out of bounds, the sub-name will start from
199 * the beginning of the name instead. If @p nComponents is out of bounds, returns all components
200 * until the end of the name.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700201 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400202 PartialName
203 getSubName(ssize_t iStartComponent, size_t nComponents = npos) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700204
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400205 /** @brief Returns a prefix of the name.
206 * @param nComponents number of components; if negative, size()+nComponents is used instead
207 *
208 * Returns a new PartialName containing a prefix of this name up to `size() - nComponents`.
209 * For example, `getPrefix(-1)` returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700210 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400211 PartialName
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700212 getPrefix(ssize_t nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700213 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800214 if (nComponents < 0)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000215 return getSubName(0, size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800216 else
217 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700218 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700219
Junxiao Shi71ff2312017-07-12 13:32:50 +0000220public: // iterators
221 /** @brief Begin iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700222 */
223 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800224 begin() const
225 {
Junxiao Shif0bf9992017-07-15 15:51:52 +0000226 return reinterpret_cast<const_iterator>(m_wire.elements().data());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800227 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700228
Junxiao Shi71ff2312017-07-12 13:32:50 +0000229 /** @brief End iterator
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700230 */
231 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800232 end() const
233 {
Junxiao Shif0bf9992017-07-15 15:51:52 +0000234 return reinterpret_cast<const_iterator>(m_wire.elements().data() + m_wire.elements().size());
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
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400254 /** @brief Replace the component at the specified index.
255 * @param i zero-based index of the component to replace;
256 * if negative, it is interpreted as offset from the end of the name
257 * @param component the new component to use as a replacement
258 * @return a reference to this name, to allow chaining.
259 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
260 */
261 Name&
262 set(ssize_t i, const Component& component);
263
264 /** @brief Replace the component at the specified index.
265 * @param i zero-based index of the component to replace;
266 * if negative, it is interpreted as offset from the end of the name
267 * @param component the new component to use as a replacement
268 * @return a reference to this name, to allow chaining.
269 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
270 */
271 Name&
272 set(ssize_t i, Component&& component);
273
Junxiao Shia36f15d2018-04-04 02:22:11 +0000274 /** @brief Append a component.
275 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000276 */
277 Name&
278 append(const Component& component)
279 {
280 m_wire.push_back(component);
281 return *this;
282 }
283
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400284 /** @brief Append a component.
285 * @return a reference to this name, to allow chaining.
286 */
287 Name&
288 append(Component&& component)
289 {
290 m_wire.push_back(std::move(component));
291 return *this;
292 }
293
Junxiao Shia36f15d2018-04-04 02:22:11 +0000294 /** @brief Append a NameComponent of TLV-TYPE @p type, copying @p count bytes at @p value as
295 * TLV-VALUE.
296 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000297 */
298 Name&
Junxiao Shia36f15d2018-04-04 02:22:11 +0000299 append(uint32_t type, const uint8_t* value, size_t count)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000300 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000301 return append(Component(type, value, count));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000302 }
303
Junxiao Shia36f15d2018-04-04 02:22:11 +0000304 /** @brief Append a GenericNameComponent, copying @p count bytes at @p value as TLV-VALUE.
305 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000306 */
307 Name&
Junxiao Shia36f15d2018-04-04 02:22:11 +0000308 append(const uint8_t* value, size_t count)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000309 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000310 return append(Component(value, count));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000311 }
312
Junxiao Shia36f15d2018-04-04 02:22:11 +0000313 /** @brief Append a NameComponent of TLV-TYPE @p type, copying TLV-VALUE from a range.
314 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
315 * implementation is available when it is a @c RandomAccessIterator.
316 * @param type the TLV-TYPE.
317 * @param first beginning of the range.
318 * @param last past-end of the range.
319 * @return a reference to this name, to allow chaining.
320 */
321 template<class Iterator>
322 Name&
323 append(uint32_t type, Iterator first, Iterator last)
324 {
325 return append(Component(type, first, last));
326 }
327
328 /** @brief Append a GenericNameComponent, copying TLV-VALUE from a range.
329 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
330 * implementation is available when it is a @c RandomAccessIterator.
331 * @param first beginning of the range.
332 * @param last past-end of the range.
333 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000334 */
335 template<class Iterator>
336 Name&
337 append(Iterator first, Iterator last)
338 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000339 return append(Component(first, last));
340 }
341
Junxiao Shia36f15d2018-04-04 02:22:11 +0000342 /** @brief Append a GenericNameComponent, copying TLV-VALUE from a null-terminated string.
343 * @param str a null-terminated string. Bytes from the string are copied as is, and not
344 * interpreted as URI component.
345 * @return a reference to this name, to allow chaining.
346 */
347 Name&
348 append(const char* str)
349 {
350 return append(Component(str));
351 }
352
353 /** @brief Append a GenericNameComponent from a TLV element.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400354 * @param value a TLV element. If its TLV-TYPE is tlv::GenericNameComponent, it is
355 * appended as is. Otherwise, it is nested into a GenericNameComponent.
Junxiao Shia36f15d2018-04-04 02:22:11 +0000356 * @return a reference to this name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000357 */
358 Name&
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400359 append(Block value)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000360 {
Junxiao Shia36f15d2018-04-04 02:22:11 +0000361 if (value.type() == tlv::GenericNameComponent) {
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400362 m_wire.push_back(std::move(value));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000363 }
364 else {
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400365 m_wire.push_back(Block(tlv::GenericNameComponent, std::move(value)));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000366 }
Junxiao Shi71ff2312017-07-12 13:32:50 +0000367 return *this;
368 }
369
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400370 /** @brief Append a PartialName.
371 * @param name the components to append
372 * @return a reference to this name, to allow chaining
373 */
374 Name&
375 append(const PartialName& name);
376
Junxiao Shi71ff2312017-07-12 13:32:50 +0000377 /** @brief Append a component with a nonNegativeInteger
Junxiao Shi71ff2312017-07-12 13:32:50 +0000378 * @return a reference to this name, to allow chaining
Davide Pesavento905d40f2020-06-09 21:33:25 -0400379 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/tlv.html#non-negative-integer-encoding
Junxiao Shi71ff2312017-07-12 13:32:50 +0000380 */
381 Name&
382 appendNumber(uint64_t number)
383 {
384 return append(Component::fromNumber(number));
385 }
386
387 /** @brief Append a component with a marked number
388 * @param marker 1-octet marker
389 * @param number the number
390 *
391 * The component is encoded as a 1-octet marker, followed by a nonNegativeInteger.
392 *
393 * @return a reference to this name, to allow chaining
394 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
395 */
396 Name&
397 appendNumberWithMarker(uint8_t marker, uint64_t number)
398 {
399 return append(Component::fromNumberWithMarker(marker, number));
400 }
401
402 /** @brief Append a version component
Chavoosh Ghasemi6b99b6f2018-10-26 12:08:33 -0700403 * @param version the version number to append; if nullopt, the current UNIX time
404 * in milliseconds is used
Junxiao Shi71ff2312017-07-12 13:32:50 +0000405 * @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&
Chavoosh Ghasemi6b99b6f2018-10-26 12:08:33 -0700409 appendVersion(optional<uint64_t> version = nullopt);
Junxiao Shi71ff2312017-07-12 13:32:50 +0000410
411 /** @brief Append a segment number (sequential) component
412 * @return a reference to this name, to allow chaining
413 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
414 */
415 Name&
416 appendSegment(uint64_t segmentNo)
417 {
418 return append(Component::fromSegment(segmentNo));
419 }
420
Junxiao Shie2099612019-02-15 14:46:27 +0000421 /** @brief Append a byte offset component
Junxiao Shi71ff2312017-07-12 13:32:50 +0000422 * @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&
Junxiao Shie2099612019-02-15 14:46:27 +0000426 appendByteOffset(uint64_t offset)
427 {
428 return append(Component::fromByteOffset(offset));
429 }
430
Junxiao Shi71ff2312017-07-12 13:32:50 +0000431 /** @brief Append a timestamp component
Chavoosh Ghasemi6b99b6f2018-10-26 12:08:33 -0700432 * @param timestamp the timestamp to append; if nullopt, the current system time is used
Junxiao Shi71ff2312017-07-12 13:32:50 +0000433 * @return a reference to this name, to allow chaining
434 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
435 */
436 Name&
Chavoosh Ghasemi6b99b6f2018-10-26 12:08:33 -0700437 appendTimestamp(optional<time::system_clock::TimePoint> timestamp = nullopt);
Junxiao Shi71ff2312017-07-12 13:32:50 +0000438
439 /** @brief Append a sequence number component
440 * @return a reference to this name, to allow chaining
441 * @sa NDN Naming Conventions https://named-data.net/doc/tech-memos/naming-conventions.pdf
442 */
443 Name&
444 appendSequenceNumber(uint64_t seqNo)
445 {
446 return append(Component::fromSequenceNumber(seqNo));
447 }
448
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400449 /** @brief Append an ImplicitSha256Digest component.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000450 * @return a reference to this name, to allow chaining
451 */
452 Name&
Davide Pesavento3b101d02018-07-21 22:44:09 -0400453 appendImplicitSha256Digest(ConstBufferPtr digest)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000454 {
Davide Pesavento3b101d02018-07-21 22:44:09 -0400455 return append(Component::fromImplicitSha256Digest(std::move(digest)));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000456 }
457
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400458 /** @brief Append an ImplicitSha256Digest component.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000459 * @return a reference to this name, to allow chaining
460 */
461 Name&
462 appendImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
463 {
464 return append(Component::fromImplicitSha256Digest(digest, digestSize));
465 }
466
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400467 /** @brief Append a ParametersSha256Digest component.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000468 * @return a reference to this name, to allow chaining
469 */
470 Name&
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400471 appendParametersSha256Digest(ConstBufferPtr digest)
472 {
473 return append(Component::fromParametersSha256Digest(std::move(digest)));
474 }
475
476 /** @brief Append a ParametersSha256Digest component.
477 * @return a reference to this name, to allow chaining
478 */
479 Name&
480 appendParametersSha256Digest(const uint8_t* digest, size_t digestSize)
481 {
482 return append(Component::fromParametersSha256Digest(digest, digestSize));
483 }
484
485 /** @brief Append a placeholder for a ParametersSha256Digest component.
486 * @return a reference to this name, to allow chaining
487 */
488 Name&
489 appendParametersSha256DigestPlaceholder();
Junxiao Shi71ff2312017-07-12 13:32:50 +0000490
491 /** @brief Append a component
492 * @note This makes push_back an alias of append, giving Name a similar API as STL vector.
493 */
494 template<class T>
495 void
496 push_back(const T& component)
497 {
498 append(component);
499 }
500
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400501 /** @brief Erase the component at the specified index.
502 * @param i zero-based index of the component to replace;
503 * if negative, it is interpreted as offset from the end of the name
504 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000505 */
506 void
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400507 erase(ssize_t i);
508
509 /** @brief Remove all components.
510 * @post `empty() == true`
511 */
512 void
513 clear();
Junxiao Shi71ff2312017-07-12 13:32:50 +0000514
515public: // algorithms
516 /** @brief Get the successor of a name
517 *
518 * The successor of a name is defined as follows:
519 *
520 * N represents the set of NDN Names, and X,Y ∈ N.
521 * Operator < is defined by canonical order on N.
522 * Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
523 *
524 * In plain words, successor of a name is the same name, but with its last component
525 * advanced to a next possible value.
526 *
527 * Examples:
528 *
Junxiao Shicf0aff82018-07-23 06:42:13 -0600529 * - successor of `/` is
530 * `/sha256digest=0000000000000000000000000000000000000000000000000000000000000000`.
531 * - successor of `/sha256digest=0000000000000000000000000000000000000000000000000000000000000000`
532 * is `/sha256digest=0000000000000000000000000000000000000000000000000000000000000001`.
533 * - successor of `/sha256digest=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`
534 * is `/2=...`.
535 * - successor of `/P/A` is `/P/B`.
536 * - successor of `/Q/%FF` is `/Q/%00%00`.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000537 *
538 * @return a new Name containing the successor
539 */
540 Name
541 getSuccessor() const;
542
543 /** @brief Check if this name is a prefix of another name
544 *
545 * This name is a prefix of @p other if the N components of this name are same as the first N
546 * components of @p other.
547 *
548 * @retval true this name is a prefix of @p other
549 * @retval false this name is not a prefix of @p other
550 */
551 bool
552 isPrefixOf(const Name& other) const;
553
554 /** @brief Check if this name equals another name
555 *
556 * Two names are equal if they have the same number of components, and components at each index
557 * are equal.
558 */
559 bool
560 equals(const Name& other) const;
561
562 /** @brief Compare this to the other Name using NDN canonical ordering.
563 *
564 * If the first components of each name are not equal, this returns a negative value if
565 * the first comes before the second using the NDN canonical ordering for name
566 * components, or a positive value if it comes after. If they are equal, this compares
567 * the second components of each name, etc. If both names are the same up to the size
568 * of the shorter name, this returns a negative value if the first name is shorter than
569 * the second or a positive value if it is longer. For example, if you std::sort gives:
570 * /a/b/d /a/b/cc /c /c/a /bb .
571 * This is intuitive because all names with the prefix /a are next to each other.
572 * But it may be also be counter-intuitive because /c comes before /bb according
573 * to NDN canonical ordering since it is shorter.
574 *
575 * @param other The other Name to compare with.
576 *
577 * @retval negative this comes before other in canonical ordering
578 * @retval zero this equals other
579 * @retval positive this comes after other in canonical ordering
580 *
Davide Pesavento905d40f2020-06-09 21:33:25 -0400581 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#canonical-order
Junxiao Shi71ff2312017-07-12 13:32:50 +0000582 */
583 int
584 compare(const Name& other) const
585 {
586 return this->compare(0, npos, other);
587 }
588
589 /** @brief compares [pos1, pos1+count1) components in this Name
590 * to [pos2, pos2+count2) components in @p other
591 *
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400592 * Equivalent to `getSubName(pos1, count1).compare(other.getSubName(pos2, count2))`.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000593 */
594 int
595 compare(size_t pos1, size_t count1,
596 const Name& other, size_t pos2 = 0, size_t count2 = npos) const;
597
Davide Pesaventoecfb3912019-07-02 23:08:22 -0400598private: // non-member operators
599 // NOTE: the following "hidden friend" operators are available via
600 // argument-dependent lookup only and must be defined inline.
601
602 friend bool
603 operator==(const Name& lhs, const Name& rhs)
604 {
605 return lhs.equals(rhs);
606 }
607
608 friend bool
609 operator!=(const Name& lhs, const Name& rhs)
610 {
611 return !lhs.equals(rhs);
612 }
613
614 friend bool
615 operator<(const Name& lhs, const Name& rhs)
616 {
617 return lhs.compare(rhs) < 0;
618 }
619
620 friend bool
621 operator<=(const Name& lhs, const Name& rhs)
622 {
623 return lhs.compare(rhs) <= 0;
624 }
625
626 friend bool
627 operator>(const Name& lhs, const Name& rhs)
628 {
629 return lhs.compare(rhs) > 0;
630 }
631
632 friend bool
633 operator>=(const Name& lhs, const Name& rhs)
634 {
635 return lhs.compare(rhs) >= 0;
636 }
637
Davide Pesavento905d40f2020-06-09 21:33:25 -0400638 /** @brief Print the URI representation of a name.
639 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shia39c0b52019-12-31 15:13:15 -0700640 */
641 friend std::ostream&
642 operator<<(std::ostream& os, const Name& name)
643 {
644 name.toUri(os);
645 return os;
646 }
647
Junxiao Shia6452ac2015-01-23 11:21:06 -0700648public:
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400649 /** @brief Indicates "until the end" in getSubName() and compare().
Junxiao Shia6452ac2015-01-23 11:21:06 -0700650 */
651 static const size_t npos;
652
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700653private:
Junxiao Shi71ff2312017-07-12 13:32:50 +0000654 mutable Block m_wire;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800655};
656
Davide Pesavento88a0d812017-08-19 21:31:42 -0400657NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Name);
658
Davide Pesavento905d40f2020-06-09 21:33:25 -0400659/** @brief Parse URI from stream as Name.
660 * @sa https://named-data.net/doc/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shi71ff2312017-07-12 13:32:50 +0000661 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700662std::istream&
663operator>>(std::istream& is, Name& name);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800664
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800665} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700666
Yingdi Yu90e23582014-11-06 14:21:04 -0800667namespace std {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000668
Yingdi Yu90e23582014-11-06 14:21:04 -0800669template<>
670struct hash<ndn::Name>
671{
672 size_t
673 operator()(const ndn::Name& name) const;
674};
675
676} // namespace std
677
Davide Pesavento905d40f2020-06-09 21:33:25 -0400678#endif // NDN_CXX_NAME_HPP