blob: 2a07f1bff1bd7bc67a08b419616bedafcf3aafc6 [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 Pesavento5d36a522024-02-09 01:36:52 -05003 * Copyright (c) 2013-2024 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.
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070020 */
21
Davide Pesavento905d40f2020-06-09 21:33:25 -040022#ifndef NDN_CXX_NAME_HPP
23#define NDN_CXX_NAME_HPP
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "ndn-cxx/name-component.hpp"
26
Junxiao Shiadc334e2017-07-14 20:28:28 +000027#include <iterator>
Davide Pesavento05ec0be2023-03-14 21:18:06 -040028#include <limits>
Davide Pesaventof6b45892023-03-13 15:00:51 -040029#include <optional>
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080030
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070031namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080032
Joao Pereira6f7cfd02015-06-15 11:36:26 -040033class Name;
34
Davide Pesaventoc860bd12022-10-04 03:23:43 -040035/**
36 * @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
Davide Pesaventoc860bd12022-10-04 03:23:43 -040040/**
41 * @brief Represents an absolute name.
Davide Pesavento02ed3322023-02-23 19:40:22 -050042 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html
Jeff Thompsonc7d65502013-11-06 17:22:26 -080043 */
Davide Pesaventofffdd622023-08-28 22:50:43 -040044class Name : private boost::totally_ordered<Name>
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070045{
Junxiao Shi71ff2312017-07-12 13:32:50 +000046public: // nested types
Junxiao Shi71ff2312017-07-12 13:32:50 +000047 using Component = name::Component;
Davide Pesavento334516a2024-02-09 18:02:36 -050048 using Error = Component::Error;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080049
Davide Pesavento334516a2024-02-09 18:02:36 -050050 // Name appears as an ordered sequence of name components
Junxiao Shi71ff2312017-07-12 13:32:50 +000051 using value_type = Component;
52 using allocator_type = void;
53 using reference = Component&;
Junxiao Shiadc334e2017-07-14 20:28:28 +000054 using const_reference = const Component&;
Junxiao Shi71ff2312017-07-12 13:32:50 +000055 using pointer = Component*;
56 using const_pointer = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000057 using iterator = const Component*; // disallow modifying via iterator
Junxiao Shi71ff2312017-07-12 13:32:50 +000058 using const_iterator = const Component*;
Junxiao Shiadc334e2017-07-14 20:28:28 +000059 using reverse_iterator = std::reverse_iterator<iterator>;
60 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Davide Pesavento334516a2024-02-09 18:02:36 -050061 using difference_type = std::vector<Component>::difference_type;
62 using size_type = std::vector<Component>::size_type;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080063
Junxiao Shi71ff2312017-07-12 13:32:50 +000064public: // constructors, encoding, decoding
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040065 /**
66 * @brief Create an empty name.
67 * @post empty() == true
Jeff Thompson443398d2013-07-02 19:45:46 -070068 */
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080069 Name();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080070
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040071 /**
Davide Pesavento5d36a522024-02-09 01:36:52 -050072 * @brief Create Name from wire encoding.
73 * @param wire TLV element of type tlv::Name
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080074 *
Davide Pesavento5d36a522024-02-09 01:36:52 -050075 * This is equivalent to:
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040076 * @code
77 * Name name;
78 * name.wireDecode(wire);
79 * @endcode
Davide Pesavento5d36a522024-02-09 01:36:52 -050080 *
81 * @throw tlv::Error The wire encoding is invalid.
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080082 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080083 explicit
Alexander Afanasyevc89efb42015-02-10 18:26:42 -080084 Name(const Block& wire);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070085
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040086 /**
87 * @brief Create name from NDN URI.
88 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Jeff Thompson443398d2013-07-02 19:45:46 -070089 */
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040090 explicit
91 Name(std::string_view uri);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070092
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040093 /**
94 * @brief Create name from NDN URI.
95 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Davide Pesavento5d36a522024-02-09 01:36:52 -050096 * @note This constructor enables implicit conversion from a string literal.
Jeff Thompson3549ef32013-09-25 14:05:17 -070097 */
Davide Pesavento3fdb02f2023-04-12 02:32:38 -040098 Name(const char* uri)
99 : Name(std::string_view(uri))
100 {
101 }
102
103 /**
104 * @brief Create name from NDN URI.
105 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Davide Pesavento5d36a522024-02-09 01:36:52 -0500106 * @note This constructor enables implicit conversion from `std::string`.
Davide Pesavento3fdb02f2023-04-12 02:32:38 -0400107 */
108 Name(const std::string& uri)
109 : Name(std::string_view(uri))
110 {
111 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700112
Davide Pesavento5d36a522024-02-09 01:36:52 -0500113 /**
114 * @brief Write URI representation of the name to the output stream.
115 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shia39c0b52019-12-31 15:13:15 -0700116 */
117 void
118 toUri(std::ostream& os, name::UriFormat format = name::UriFormat::DEFAULT) const;
119
Davide Pesavento5d36a522024-02-09 01:36:52 -0500120 /**
121 * @brief Get URI representation of the name.
122 * @return URI representation; the "ndn:" scheme identifier is not included.
123 * @note To print the URI representation to a stream, it is more efficient to use `os << name`.
124 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700125 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000126 std::string
Junxiao Shia39c0b52019-12-31 15:13:15 -0700127 toUri(name::UriFormat format = name::UriFormat::DEFAULT) const;
Alexander Afanasyev4f512fb2016-05-18 10:47:53 -0700128
Davide Pesavento5d36a522024-02-09 01:36:52 -0500129 /**
130 * @brief Check if this instance already has wire encoding.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000131 */
132 bool
Davide Pesavento905d40f2020-06-09 21:33:25 -0400133 hasWire() const noexcept
Junxiao Shi71ff2312017-07-12 13:32:50 +0000134 {
135 return m_wire.hasWire();
136 }
137
Davide Pesavento5d36a522024-02-09 01:36:52 -0500138 /**
139 * @brief Prepend wire encoding to @p encoder.
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800140 */
Alexander Afanasyev74633892015-02-08 18:08:46 -0800141 template<encoding::Tag TAG>
Wentao Shang77949212014-02-01 23:42:24 -0800142 size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700143 wireEncode(EncodingImpl<TAG>& encoder) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700144
Davide Pesavento5d36a522024-02-09 01:36:52 -0500145 /**
146 * @brief Perform wire encoding, or return existing (cached) wire encoding.
147 * @post hasWire() == true
Junxiao Shi71ff2312017-07-12 13:32:50 +0000148 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700149 const Block&
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800150 wireEncode() const;
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800151
Davide Pesavento5d36a522024-02-09 01:36:52 -0500152 /**
153 * @brief Decode name from wire encoding.
154 * @throw tlv::Error The wire encoding is invalid.
155 * @post hasWire() == true
Junxiao Shi71ff2312017-07-12 13:32:50 +0000156 */
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800157 void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700158 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800159
Davide Pesavento5d36a522024-02-09 01:36:52 -0500160 /**
161 * @brief Make a deep copy of the name, reallocating the underlying memory buffer.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000162 */
163 Name
164 deepCopy() const;
165
166public: // access
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400167 /**
168 * @brief Checks if the name is empty, i.e., has no components.
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800169 */
Davide Pesaventofcd3e442023-03-10 18:44:11 -0500170 [[nodiscard]] bool
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400171 empty() const noexcept
Jeff Thompson0f743452013-09-12 14:23:18 -0700172 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000173 return m_wire.elements().empty();
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700174 }
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700175
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400176 /**
177 * @brief Returns the number of components.
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800178 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000179 size_t
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400180 size() const noexcept
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800181 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000182 return m_wire.elements_size();
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800183 }
184
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400185 /**
186 * @brief Returns an immutable reference to the component at the specified index.
187 * @param i zero-based index of the component to return;
188 * if negative, it is interpreted as offset from the end of the name
189 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
Alexander Afanasyevc89efb42015-02-10 18:26:42 -0800190 */
Junxiao Shi71ff2312017-07-12 13:32:50 +0000191 const Component&
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400192 get(ssize_t i) const noexcept
Jeff Thompson21eb7212013-09-26 09:05:40 -0700193 {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000194 if (i < 0) {
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400195 i += static_cast<ssize_t>(size());
Junxiao Shi71ff2312017-07-12 13:32:50 +0000196 }
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500197 return static_cast<const Component&>(m_wire.elements()[static_cast<size_t>(i)]);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700198 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800199
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400200 /**
201 * @brief Equivalent to get().
Junxiao Shi71ff2312017-07-12 13:32:50 +0000202 */
203 const Component&
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400204 operator[](ssize_t i) const noexcept
Junxiao Shi71ff2312017-07-12 13:32:50 +0000205 {
206 return get(i);
207 }
208
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400209 /**
210 * @brief Returns an immutable reference to the component at the specified index,
211 * with bounds checking.
212 * @param i zero-based index of the component to return;
213 * if negative, it is interpreted as offset from the end of the name
214 * @throws Error The index is out of bounds.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000215 */
216 const Component&
217 at(ssize_t i) const;
218
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400219 /** @brief Extracts some components as a sub-name (PartialName).
Junxiao Shi71ff2312017-07-12 13:32:50 +0000220 * @param iStartComponent zero-based index of the first component;
221 * if negative, size()+iStartComponent is used instead
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400222 * @param nComponents number of desired components, starting at @p iStartComponent;
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400223 * use #npos to return all components until the end of the name
Junxiao Shi71ff2312017-07-12 13:32:50 +0000224 * @return a new PartialName containing the extracted components
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800225 *
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400226 * If @p iStartComponent is positive and indexes out of bounds, returns an empty PartialName.
227 * If @p iStartComponent is negative and indexes out of bounds, the sub-name will start from
228 * the beginning of the name instead. If @p nComponents is out of bounds, returns all components
229 * until the end of the name.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700230 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400231 PartialName
232 getSubName(ssize_t iStartComponent, size_t nComponents = npos) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700233
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400234 /** @brief Returns a prefix of the name.
235 * @param nComponents number of components; if negative, size()+nComponents is used instead
236 *
237 * Returns a new PartialName containing a prefix of this name up to `size() - nComponents`.
238 * For example, `getPrefix(-1)` returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700239 */
Joao Pereira6f7cfd02015-06-15 11:36:26 -0400240 PartialName
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700241 getPrefix(ssize_t nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700242 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800243 if (nComponents < 0)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000244 return getSubName(0, size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800245 else
246 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700247 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700248
Junxiao Shi71ff2312017-07-12 13:32:50 +0000249public: // iterators
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400250 /** @brief Begin iterator.
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700251 */
252 const_iterator
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400253 begin() const noexcept
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800254 {
Junxiao Shif0bf9992017-07-15 15:51:52 +0000255 return reinterpret_cast<const_iterator>(m_wire.elements().data());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800256 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700257
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400258 /** @brief End iterator.
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700259 */
260 const_iterator
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400261 end() const noexcept
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800262 {
Junxiao Shif0bf9992017-07-15 15:51:52 +0000263 return reinterpret_cast<const_iterator>(m_wire.elements().data() + m_wire.elements().size());
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800264 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700265
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400266 /** @brief Reverse begin iterator.
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700267 */
268 const_reverse_iterator
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400269 rbegin() const noexcept
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800270 {
271 return const_reverse_iterator(end());
272 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700273
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400274 /** @brief Reverse end iterator.
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700275 */
276 const_reverse_iterator
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400277 rend() const noexcept
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800278 {
279 return const_reverse_iterator(begin());
280 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700281
Junxiao Shi71ff2312017-07-12 13:32:50 +0000282public: // modifiers
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400283 /** @brief Replace the component at the specified index.
284 * @param i zero-based index of the component to replace;
285 * if negative, it is interpreted as offset from the end of the name
286 * @param component the new component to use as a replacement
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400287 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400288 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
289 */
290 Name&
291 set(ssize_t i, const Component& component);
292
293 /** @brief Replace the component at the specified index.
294 * @param i zero-based index of the component to replace;
295 * if negative, it is interpreted as offset from the end of the name
296 * @param component the new component to use as a replacement
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400297 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400298 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
299 */
300 Name&
301 set(ssize_t i, Component&& component);
302
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400303 /**
304 * @brief Append a name component.
305 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000306 */
307 Name&
308 append(const Component& component)
309 {
310 m_wire.push_back(component);
311 return *this;
312 }
313
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400314 /**
315 * @brief Append a name component.
316 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400317 */
318 Name&
319 append(Component&& component)
320 {
321 m_wire.push_back(std::move(component));
322 return *this;
323 }
324
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500325 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400326 * @brief Append a `NameComponent` of TLV-TYPE @p type, copying the TLV-VALUE from @p value.
327 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000328 */
329 Name&
Davide Pesaventodf8fd8a2022-02-21 20:04:21 -0500330 append(uint32_t type, span<const uint8_t> value)
331 {
332 return append(Component(type, value));
333 }
334
335 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400336 * @brief Append a `GenericNameComponent`, copying the TLV-VALUE from @p value.
337 * @return A reference to this Name, to allow chaining.
Davide Pesavento2f92b6e2022-04-10 16:42:01 -0400338 */
339 Name&
340 append(span<const uint8_t> value)
341 {
342 return append(Component(tlv::GenericNameComponent, value));
343 }
344
Davide Pesavento334516a2024-02-09 18:02:36 -0500345 /**
346 * @brief Append a `NameComponent` of TLV-TYPE @p type, copying the TLV-VALUE from a range.
347 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
348 * implementation is available when it is a @c RandomAccessIterator.
349 * @param type the TLV-TYPE.
350 * @param first beginning of the range.
351 * @param last past-end of the range.
352 * @return A reference to this Name, to allow chaining.
Junxiao Shia36f15d2018-04-04 02:22:11 +0000353 */
354 template<class Iterator>
355 Name&
356 append(uint32_t type, Iterator first, Iterator last)
357 {
358 return append(Component(type, first, last));
359 }
360
Davide Pesavento334516a2024-02-09 18:02:36 -0500361 /**
362 * @brief Append a `GenericNameComponent`, copying the TLV-VALUE from a range.
363 * @tparam Iterator an @c InputIterator dereferencing to a one-octet value type. More efficient
364 * implementation is available when it is a @c RandomAccessIterator.
365 * @param first beginning of the range.
366 * @param last past-end of the range.
367 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000368 */
369 template<class Iterator>
370 Name&
371 append(Iterator first, Iterator last)
372 {
Davide Pesavento2f92b6e2022-04-10 16:42:01 -0400373 return append(Component(tlv::GenericNameComponent, first, last));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000374 }
375
Davide Pesavento334516a2024-02-09 18:02:36 -0500376 /**
377 * @brief Append a `GenericNameComponent`, copying the TLV-VALUE from a null-terminated string.
378 * @param str a null-terminated string. Bytes from the string are copied as is, and not
379 * interpreted as a URI component.
380 * @return A reference to this Name, to allow chaining.
Junxiao Shia36f15d2018-04-04 02:22:11 +0000381 */
382 Name&
383 append(const char* str)
384 {
385 return append(Component(str));
386 }
387
Davide Pesavento334516a2024-02-09 18:02:36 -0500388 /**
389 * @brief Append a PartialName.
390 * @param name the components to append
391 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400392 */
393 Name&
394 append(const PartialName& name);
395
Davide Pesavento5d36a522024-02-09 01:36:52 -0500396 /**
397 * @brief Append a component with a NonNegativeInteger.
398 * @return A reference to this Name, to allow chaining.
399 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/tlv.html#non-negative-integer-encoding
Junxiao Shi71ff2312017-07-12 13:32:50 +0000400 */
401 Name&
402 appendNumber(uint64_t number)
403 {
404 return append(Component::fromNumber(number));
405 }
406
Davide Pesavento334516a2024-02-09 18:02:36 -0500407 /**
408 * @brief Append a component with a marked number.
409 * @param marker 1-octet marker
410 * @param number the number
Junxiao Shi71ff2312017-07-12 13:32:50 +0000411 *
Davide Pesavento334516a2024-02-09 18:02:36 -0500412 * The component is encoded as a 1-octet marker, followed by a NonNegativeInteger.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000413 *
Davide Pesavento334516a2024-02-09 18:02:36 -0500414 * @return A reference to this Name, to allow chaining.
415 * @sa NDN Naming Conventions revision 1 (obsolete)
416 * https://named-data.net/wp-content/uploads/2014/08/ndn-tr-22-ndn-memo-naming-conventions.pdf
Junxiao Shi71ff2312017-07-12 13:32:50 +0000417 */
418 Name&
419 appendNumberWithMarker(uint8_t marker, uint64_t number)
420 {
421 return append(Component::fromNumberWithMarker(marker, number));
422 }
423
Davide Pesavento47a94d12021-10-31 16:41:05 -0400424 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400425 * @brief Append a segment number (sequential) component.
426 * @return A reference to this Name, to allow chaining.
Davide Pesavento47a94d12021-10-31 16:41:05 -0400427 * @sa NDN Naming Conventions
428 * https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
Junxiao Shi71ff2312017-07-12 13:32:50 +0000429 */
430 Name&
431 appendSegment(uint64_t segmentNo)
432 {
433 return append(Component::fromSegment(segmentNo));
434 }
435
Davide Pesavento47a94d12021-10-31 16:41:05 -0400436 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400437 * @brief Append a byte offset component.
438 * @return A reference to this Name, to allow chaining.
Davide Pesavento47a94d12021-10-31 16:41:05 -0400439 * @sa NDN Naming Conventions
440 * https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
Junxiao Shi71ff2312017-07-12 13:32:50 +0000441 */
442 Name&
Junxiao Shie2099612019-02-15 14:46:27 +0000443 appendByteOffset(uint64_t offset)
444 {
445 return append(Component::fromByteOffset(offset));
446 }
447
Davide Pesavento47a94d12021-10-31 16:41:05 -0400448 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400449 * @brief Append a version component.
Davide Pesavento21ee8992022-02-25 20:46:04 -0500450 * @param version the version number to append; if nullopt, the current UNIX time
451 * in milliseconds is used
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400452 * @return A reference to this Name, to allow chaining.
Davide Pesavento21ee8992022-02-25 20:46:04 -0500453 * @sa NDN Naming Conventions
454 * https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
455 */
456 Name&
Davide Pesaventof6b45892023-03-13 15:00:51 -0400457 appendVersion(const std::optional<uint64_t>& version = std::nullopt);
Davide Pesavento21ee8992022-02-25 20:46:04 -0500458
459 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400460 * @brief Append a timestamp component.
Davide Pesavento47a94d12021-10-31 16:41:05 -0400461 * @param timestamp the timestamp to append; if nullopt, the current system time is used
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400462 * @return A reference to this Name, to allow chaining.
Davide Pesavento47a94d12021-10-31 16:41:05 -0400463 * @sa NDN Naming Conventions
464 * https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
Junxiao Shi71ff2312017-07-12 13:32:50 +0000465 */
466 Name&
Davide Pesaventof6b45892023-03-13 15:00:51 -0400467 appendTimestamp(const std::optional<time::system_clock::time_point>& timestamp = std::nullopt);
Junxiao Shi71ff2312017-07-12 13:32:50 +0000468
Davide Pesavento47a94d12021-10-31 16:41:05 -0400469 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400470 * @brief Append a sequence number component.
471 * @return A reference to this Name, to allow chaining.
Davide Pesavento47a94d12021-10-31 16:41:05 -0400472 * @sa NDN Naming Conventions
473 * https://named-data.net/publications/techreports/ndn-tr-22-3-ndn-memo-naming-conventions/
Junxiao Shi71ff2312017-07-12 13:32:50 +0000474 */
475 Name&
476 appendSequenceNumber(uint64_t seqNo)
477 {
478 return append(Component::fromSequenceNumber(seqNo));
479 }
480
Davide Pesavento47a94d12021-10-31 16:41:05 -0400481 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400482 * @brief Append an `ImplicitSha256Digest` component.
483 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000484 */
485 Name&
Davide Pesavento3b101d02018-07-21 22:44:09 -0400486 appendImplicitSha256Digest(ConstBufferPtr digest)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000487 {
Davide Pesavento21ee8992022-02-25 20:46:04 -0500488 return append(Component(tlv::ImplicitSha256DigestComponent, std::move(digest)));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000489 }
490
Davide Pesavento47a94d12021-10-31 16:41:05 -0400491 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400492 * @brief Append an `ImplicitSha256Digest` component.
493 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000494 */
495 Name&
Davide Pesavento765abc92021-12-27 00:44:04 -0500496 appendImplicitSha256Digest(span<const uint8_t> digestBytes)
Junxiao Shi71ff2312017-07-12 13:32:50 +0000497 {
Davide Pesavento21ee8992022-02-25 20:46:04 -0500498 return append(Component(tlv::ImplicitSha256DigestComponent, digestBytes));
Junxiao Shi71ff2312017-07-12 13:32:50 +0000499 }
500
Davide Pesavento47a94d12021-10-31 16:41:05 -0400501 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400502 * @brief Append a `ParametersSha256Digest` component.
503 * @return A reference to this Name, to allow chaining.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000504 */
505 Name&
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400506 appendParametersSha256Digest(ConstBufferPtr digest)
507 {
Davide Pesavento21ee8992022-02-25 20:46:04 -0500508 return append(Component(tlv::ParametersSha256DigestComponent, std::move(digest)));
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400509 }
510
Davide Pesavento47a94d12021-10-31 16:41:05 -0400511 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400512 * @brief Append a `ParametersSha256Digest` component.
513 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400514 */
515 Name&
Davide Pesavento765abc92021-12-27 00:44:04 -0500516 appendParametersSha256Digest(span<const uint8_t> digestBytes)
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400517 {
Davide Pesavento21ee8992022-02-25 20:46:04 -0500518 return append(Component(tlv::ParametersSha256DigestComponent, digestBytes));
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400519 }
520
Davide Pesavento47a94d12021-10-31 16:41:05 -0400521 /**
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400522 * @brief Append a placeholder for a `ParametersSha256Digest` component.
523 * @return A reference to this Name, to allow chaining.
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400524 */
525 Name&
526 appendParametersSha256DigestPlaceholder();
Junxiao Shi71ff2312017-07-12 13:32:50 +0000527
Davide Pesavento21ee8992022-02-25 20:46:04 -0500528 /**
529 * @brief Append a keyword component.
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400530 * @return A reference to this Name, to allow chaining.
Davide Pesavento21ee8992022-02-25 20:46:04 -0500531 */
532 Name&
533 appendKeyword(span<const uint8_t> keyword)
534 {
535 return append(Component(tlv::KeywordNameComponent, keyword));
536 }
537
538 /**
539 * @brief Append a keyword component.
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400540 * @return A reference to this Name, to allow chaining.
Davide Pesavento21ee8992022-02-25 20:46:04 -0500541 */
542 Name&
Davide Pesavento3fdb02f2023-04-12 02:32:38 -0400543 appendKeyword(std::string_view keyword)
Davide Pesavento21ee8992022-02-25 20:46:04 -0500544 {
Davide Pesavento3fdb02f2023-04-12 02:32:38 -0400545 return append(Component(tlv::KeywordNameComponent,
546 {reinterpret_cast<const uint8_t*>(keyword.data()), keyword.size()}));
Davide Pesavento21ee8992022-02-25 20:46:04 -0500547 }
548
Davide Pesavento2f92b6e2022-04-10 16:42:01 -0400549 /**
Davide Pesavento2f92b6e2022-04-10 16:42:01 -0400550 * @brief Erase the component at the specified index.
551 * @param i zero-based index of the component to erase;
552 * if negative, it is interpreted as offset from the end of the name
553 * @warning No bounds checking is performed, using an out-of-range index is undefined behavior.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000554 */
555 void
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400556 erase(ssize_t i);
557
Davide Pesavento2f92b6e2022-04-10 16:42:01 -0400558 /**
559 * @brief Remove all components.
560 * @post `empty() == true`
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400561 */
562 void
563 clear();
Junxiao Shi71ff2312017-07-12 13:32:50 +0000564
565public: // algorithms
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400566 /** @brief Get the successor of a name.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000567 *
568 * The successor of a name is defined as follows:
569 *
570 * N represents the set of NDN Names, and X,Y ∈ N.
571 * Operator < is defined by canonical order on N.
572 * Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
573 *
574 * In plain words, successor of a name is the same name, but with its last component
575 * advanced to a next possible value.
576 *
577 * Examples:
578 *
Junxiao Shicf0aff82018-07-23 06:42:13 -0600579 * - successor of `/` is
580 * `/sha256digest=0000000000000000000000000000000000000000000000000000000000000000`.
581 * - successor of `/sha256digest=0000000000000000000000000000000000000000000000000000000000000000`
582 * is `/sha256digest=0000000000000000000000000000000000000000000000000000000000000001`.
583 * - successor of `/sha256digest=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`
584 * is `/2=...`.
585 * - successor of `/P/A` is `/P/B`.
586 * - successor of `/Q/%FF` is `/Q/%00%00`.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000587 *
588 * @return a new Name containing the successor
589 */
590 Name
591 getSuccessor() const;
592
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400593 /** @brief Check if this name is a prefix of another name.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000594 *
595 * This name is a prefix of @p other if the N components of this name are same as the first N
596 * components of @p other.
597 *
598 * @retval true this name is a prefix of @p other
599 * @retval false this name is not a prefix of @p other
600 */
601 bool
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400602 isPrefixOf(const Name& other) const noexcept;
Junxiao Shi71ff2312017-07-12 13:32:50 +0000603
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400604 /** @brief Check if this name equals another name.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000605 *
606 * Two names are equal if they have the same number of components, and components at each index
607 * are equal.
608 */
609 bool
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400610 equals(const Name& other) const noexcept;
Junxiao Shi71ff2312017-07-12 13:32:50 +0000611
612 /** @brief Compare this to the other Name using NDN canonical ordering.
613 *
614 * If the first components of each name are not equal, this returns a negative value if
615 * the first comes before the second using the NDN canonical ordering for name
616 * components, or a positive value if it comes after. If they are equal, this compares
617 * the second components of each name, etc. If both names are the same up to the size
618 * of the shorter name, this returns a negative value if the first name is shorter than
619 * the second or a positive value if it is longer. For example, if you std::sort gives:
620 * /a/b/d /a/b/cc /c /c/a /bb .
621 * This is intuitive because all names with the prefix /a are next to each other.
622 * But it may be also be counter-intuitive because /c comes before /bb according
623 * to NDN canonical ordering since it is shorter.
624 *
625 * @param other The other Name to compare with.
626 *
627 * @retval negative this comes before other in canonical ordering
628 * @retval zero this equals other
629 * @retval positive this comes after other in canonical ordering
630 *
Davide Pesavento02ed3322023-02-23 19:40:22 -0500631 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#canonical-order
Junxiao Shi71ff2312017-07-12 13:32:50 +0000632 */
633 int
634 compare(const Name& other) const
635 {
636 return this->compare(0, npos, other);
637 }
638
Davide Pesaventoc860bd12022-10-04 03:23:43 -0400639 /** @brief Compares `[pos1, pos1+count1)` components in this Name
640 * to `[pos2, pos2+count2)` components in @p other.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000641 *
Davide Pesaventoadc9aa22019-06-30 19:00:20 -0400642 * Equivalent to `getSubName(pos1, count1).compare(other.getSubName(pos2, count2))`.
Junxiao Shi71ff2312017-07-12 13:32:50 +0000643 */
644 int
645 compare(size_t pos1, size_t count1,
646 const Name& other, size_t pos2 = 0, size_t count2 = npos) const;
647
Davide Pesaventoecfb3912019-07-02 23:08:22 -0400648private: // non-member operators
649 // NOTE: the following "hidden friend" operators are available via
650 // argument-dependent lookup only and must be defined inline.
Davide Pesaventofffdd622023-08-28 22:50:43 -0400651 // boost::totally_ordered provides !=, <=, >=, and > operators.
Davide Pesaventoecfb3912019-07-02 23:08:22 -0400652
653 friend bool
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400654 operator==(const Name& lhs, const Name& rhs) noexcept
Davide Pesaventoecfb3912019-07-02 23:08:22 -0400655 {
656 return lhs.equals(rhs);
657 }
658
659 friend bool
Davide Pesaventoecfb3912019-07-02 23:08:22 -0400660 operator<(const Name& lhs, const Name& rhs)
661 {
662 return lhs.compare(rhs) < 0;
663 }
664
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400665 /**
666 * @brief Print the URI representation of a name.
Davide Pesavento02ed3322023-02-23 19:40:22 -0500667 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shia39c0b52019-12-31 15:13:15 -0700668 */
669 friend std::ostream&
670 operator<<(std::ostream& os, const Name& name)
671 {
672 name.toUri(os);
673 return os;
674 }
675
Junxiao Shia6452ac2015-01-23 11:21:06 -0700676public:
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400677 /**
678 * @brief Indicates "until the end" in getSubName() and compare().
Junxiao Shia6452ac2015-01-23 11:21:06 -0700679 */
Davide Pesavento05ec0be2023-03-14 21:18:06 -0400680 static constexpr size_t npos = std::numeric_limits<size_t>::max();
Junxiao Shia6452ac2015-01-23 11:21:06 -0700681
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700682private:
Davide Pesavento152ef442023-04-22 02:02:29 -0400683 mutable Block m_wire{tlv::Name};
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800684};
685
Davide Pesavento88a0d812017-08-19 21:31:42 -0400686NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Name);
687
Davide Pesavento5c4f3762022-10-31 14:25:25 -0400688/**
689 * @brief Parse URI from stream as Name.
Davide Pesavento02ed3322023-02-23 19:40:22 -0500690 * @sa https://docs.named-data.net/NDN-packet-spec/0.3/name.html#ndn-uri-scheme
Junxiao Shi71ff2312017-07-12 13:32:50 +0000691 */
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700692std::istream&
693operator>>(std::istream& is, Name& name);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800694
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800695} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700696
Yingdi Yu90e23582014-11-06 14:21:04 -0800697namespace std {
Junxiao Shi71ff2312017-07-12 13:32:50 +0000698
Yingdi Yu90e23582014-11-06 14:21:04 -0800699template<>
700struct hash<ndn::Name>
701{
702 size_t
703 operator()(const ndn::Name& name) const;
704};
705
706} // namespace std
707
Davide Pesavento905d40f2020-06-09 21:33:25 -0400708#endif // NDN_CXX_NAME_HPP