blob: 0e8c840b5cba2d34a215735880f508ae67c49060 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Jeff Thompson47eecfc2013-07-07 22:56:46 -07002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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 "common.hpp"
30#include "name-component.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031#include "util/time.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080032
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080033#include "encoding/block.hpp"
Wentao Shang77949212014-02-01 23:42:24 -080034#include "encoding/encoding-buffer.hpp"
Jeff Thompson25b4e612013-10-10 16:03:24 -070035
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080036#include <boost/iterator/reverse_iterator.hpp>
37
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070038namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080039
Jeff Thompsonc7d65502013-11-06 17:22:26 -080040/**
41 * A Name holds an array of Name::Component and represents an NDN name.
42 */
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070043class Name : public enable_shared_from_this<Name>
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070044{
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070045public:
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070046 /// @brief Error that can be thrown from Name
47 class Error : public name::Component::Error
48 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070049 public:
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070050 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070051 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070052 : name::Component::Error(what)
53 {
54 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070055 };
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080056
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080057 typedef name::Component Component;
58
59 typedef std::vector<Component> component_container;
60
61 typedef Component value_type;
62 typedef void allocator_type;
63 typedef Component& reference;
64 typedef const Component const_reference;
65 typedef Component* pointer;
66 typedef const Component* const_pointer;
67 typedef Component* iterator;
68 typedef const Component* const_iterator;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070069
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080070 typedef boost::reverse_iterator<iterator> reverse_iterator;
71 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
72
73 typedef component_container::difference_type difference_type;
74 typedef component_container::size_type size_type;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070075
Jeff Thompson443398d2013-07-02 19:45:46 -070076 /**
77 * Create a new Name with no components.
78 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080079 Name()
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060080 : m_nameBlock(tlv::Name)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080081 {
Jeff Thompson016ed642013-07-02 14:39:06 -070082 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080083
84 /**
85 * @brief Create Name object from wire block
86 *
87 * This is a more efficient equivalent for
88 * @code
89 * Name name;
90 * name.wireDecode(wire);
91 * @endcode
92 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080093 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070094 Name(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080095 {
96 m_nameBlock = wire;
97 m_nameBlock.parse();
98 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070099
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700100 /**
Jeff Thompson443398d2013-07-02 19:45:46 -0700101 * Parse the uri according to the NDN URI Scheme and create the name with the components.
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700102 * @param uri The URI string.
Jeff Thompson443398d2013-07-02 19:45:46 -0700103 */
Jeff Thompson3549ef32013-09-25 14:05:17 -0700104 Name(const char* uri)
Jeff Thompson67515bd2013-08-15 17:43:22 -0700105 {
106 set(uri);
107 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700108
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700109 /**
Jeff Thompson3549ef32013-09-25 14:05:17 -0700110 * Parse the uri according to the NDN URI Scheme and create the name with the components.
111 * @param uri The URI string.
112 */
113 Name(const std::string& uri)
114 {
115 set(uri.c_str());
116 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700117
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800118 /**
119 * @brief Fast encoding or block size estimation
120 */
121 template<bool T>
Wentao Shang77949212014-02-01 23:42:24 -0800122 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700123 wireEncode(EncodingImpl<T>& block) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700124
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700125 const Block&
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800126 wireEncode() const;
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800127
128 void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700129 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800130
131 /**
132 * @brief Check if already has wire
133 */
134 bool
135 hasWire() const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700136
Jeff Thompsonb468c312013-07-01 17:50:14 -0700137 /**
Jeff Thompson67515bd2013-08-15 17:43:22 -0700138 * Parse the uri according to the NDN URI Scheme and set the name with the components.
Jeff Thompson7781b392013-12-17 11:45:59 -0800139 * @param uri The null-terminated URI string.
Jeff Thompson67515bd2013-08-15 17:43:22 -0700140 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700141 void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700142 set(const char* uri);
Jeff Thompson67515bd2013-08-15 17:43:22 -0700143
144 /**
Jeff Thompson7781b392013-12-17 11:45:59 -0800145 * Parse the uri according to the NDN URI Scheme and set the name with the components.
146 * @param uri The URI string.
147 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700148 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800149 set(const std::string& uri)
150 {
151 set(uri.c_str());
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700152 }
153
Jeff Thompson7781b392013-12-17 11:45:59 -0800154 /**
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700155 * Append a new component, copying from value of length valueLength.
Jeff Thompson26b0d792013-09-23 16:19:01 -0700156 * @return This name so that you can chain calls to append.
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700157 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700158 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700159 append(const uint8_t* value, size_t valueLength)
Jeff Thompson0f743452013-09-12 14:23:18 -0700160 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800161 m_nameBlock.push_back(Component(value, valueLength));
Jeff Thompson26b0d792013-09-23 16:19:01 -0700162 return *this;
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700163 }
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700164
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800165 /**
166 * Append a new component, copying from value of length valueLength.
167 * @return This name so that you can chain calls to append.
168 */
169 template<class InputIterator>
170 Name&
171 append(InputIterator begin, InputIterator end)
172 {
173 m_nameBlock.push_back(Component(begin, end));
174 return *this;
175 }
176
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700177 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700178 append(const Component& value)
Jeff Thompson21eb7212013-09-26 09:05:40 -0700179 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800180 m_nameBlock.push_back(value);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700181 return *this;
182 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800183
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800184 /**
185 * @brief Append name component that represented as a string
186 *
187 * Note that this method is necessary to ensure correctness and unambiguity of
188 * ``append("string")`` operations (both Component and Name can be implicitly
189 * converted from string, each having different outcomes
190 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700191 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700192 append(const char* value)
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800193 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800194 m_nameBlock.push_back(Component(value));
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800195 return *this;
196 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700197
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800198 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700199 append(const Block& value)
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800200 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600201 if (value.type() == tlv::NameComponent)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800202 m_nameBlock.push_back(value);
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800203 else
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600204 m_nameBlock.push_back(Block(tlv::NameComponent, value));
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800205
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800206 return *this;
207 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700208
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700209 /**
Jeff Thompson26b0d792013-09-23 16:19:01 -0700210 * Append the components of the given name to this name.
211 * @param name The Name with components to append.
212 * @return This name so that you can chain calls to append.
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700213 */
Jeff Thompson26b0d792013-09-23 16:19:01 -0700214 Name&
215 append(const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700216
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700217 /**
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700218 * Clear all the components.
219 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700220 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800221 clear()
222 {
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600223 m_nameBlock = Block(tlv::Name);
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700224 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700225
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700226 /**
Jeff Thompsond0159d72013-09-23 13:34:15 -0700227 * Get a new name, constructed as a subset of components.
228 * @param iStartComponent The index if the first component to get.
229 * @param nComponents The number of components starting at iStartComponent.
230 * @return A new name.
231 */
232 Name
233 getSubName(size_t iStartComponent, size_t nComponents) const;
234
235 /**
236 * Get a new name, constructed as a subset of components starting at iStartComponent until the end of the name.
237 * @param iStartComponent The index if the first component to get.
238 * @return A new name.
239 */
240 Name
241 getSubName(size_t iStartComponent) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700242
Jeff Thompsond0159d72013-09-23 13:34:15 -0700243 /**
244 * Return a new Name with the first nComponents components of this Name.
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800245 * @param nComponents The number of prefix components. If nComponents is -N then return the prefix up
246 * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700247 * @return A new Name.
248 */
249 Name
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800250 getPrefix(int nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700251 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800252 if (nComponents < 0)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800253 return getSubName(0, m_nameBlock.elements_size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800254 else
255 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700256 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700257
Jeff Thompsond0159d72013-09-23 13:34:15 -0700258 /**
Jeff Thompsone6063512013-07-01 15:11:28 -0700259 * Encode this name as a URI.
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700260 * @return The encoded URI.
Jeff Thompsone6063512013-07-01 15:11:28 -0700261 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700262 std::string
Jeff Thompson0050abe2013-09-17 12:50:25 -0700263 toUri() const;
Jeff Thompsond129ac12013-10-11 14:30:12 -0700264
265 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700266 * @brief Append a component with the number encoded as nonNegativeInteger
267 *
268 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
269 *
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600270 * @param number The non-negative number
271 * @return This name so that you can chain calls to append.
272 */
273 Name&
274 appendNumber(uint64_t number)
275 {
276 m_nameBlock.push_back(Component::fromNumber(number));
277 return *this;
278 }
279
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700280 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700281 * @brief An alias for appendNumber(uint64_t)
282 */
283 Name&
284 appendVersion(uint64_t number)
285 {
286 return appendNumber(number);
287 }
288
289 /**
290 * @brief Append a component with the encoded version number (current UNIX timestamp
291 * in milliseconds)
292 */
293 Name&
294 appendVersion();
295
296 /**
297 * @brief An alias for appendNumber(uint64_t)
298 */
299 Name&
300 appendSegment(uint64_t number)
301 {
302 return appendNumber(number);
303 }
304
305 /**
Shuo Chen5aa8c742014-06-22 15:00:02 +0800306 * @brief get the successor of a name
307 * successor of a name is defined that its last component is
308 * advanced next possible value of last component of original name
309 * @return a new name
310 */
311 Name
312 getSuccessor() const;
313
314 /**
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700315 * Check if this name has the same component count and components as the given name.
316 * @param name The Name to check.
317 * @return true if the names are equal, otherwise false.
318 */
319 bool
320 equals(const Name& name) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700321
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700322 /**
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700323 * Check if the N components of this name are the same as the first N components of the given name.
324 * @param name The Name to check.
325 * @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
326 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700327 bool
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800328 isPrefixOf(const Name& name) const;
329
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700330 //
331 // vector equivalent interface.
332 //
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800333
334 /**
335 * @brief Check if name is emtpy
336 */
337 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700338 empty() const
339 {
340 return m_nameBlock.elements().empty();
341 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700342
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700343 /**
344 * Get the number of components.
345 * @return The number of components.
346 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700347 size_t
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700348 size() const
349 {
350 return m_nameBlock.elements_size();
351 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700352
353 /**
354 * Get the component at the given index.
355 * @param i The index of the component, starting from 0.
356 * @return The name component at the index.
357 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700358 const Component&
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800359 get(ssize_t i) const
360 {
361 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800362 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800363 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800364 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
365 }
366
367 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700368 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800369 {
370 return get(i);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800371 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000372
373 /**
374 * @brief Get component at the specified index
375 *
376 * Unlike get() and operator[] methods, at() checks for out of bounds
377 * and will throw Name::Error when it happens
378 *
379 * @throws Name::Error if index out of bounds
380 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800381 const Component&
382 at(ssize_t i) const
383 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700384 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
385 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000386 throw Error("Requested component does not exist (out of bounds)");
387
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800388 return get(i);
389 }
390
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800391 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700392 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800393 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700394 * If the first components of each name are not equal, this returns -1 if the first comes
395 * before the second using the NDN canonical ordering for name components, or 1 if it
396 * comes after. If they are equal, this compares the second components of each name, etc.
397 * If both names are the same up to the size of the shorter name, this returns -1 if the
398 * first name is shorter than the second or 1 if it is longer. For example, if you
399 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
400 * the prefix /a are next to each other. But it may be also be counter-intuitive because
401 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
402 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
403 * comes before other in the canonical ordering, or 1 if *this comes after other in the
404 * canonical ordering.
405 *
406 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800407 */
408 int
409 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700410
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700411 /**
412 * Append the component
413 * @param component The component of type T.
414 */
415 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700416 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700417 {
418 append(component);
419 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700420
Jeff Thompson91737f52013-10-04 11:07:24 -0700421 /**
422 * Check if this name has the same component count and components as the given name.
423 * @param name The Name to check.
424 * @return true if the names are equal, otherwise false.
425 */
426 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700427 operator==(const Name& name) const
428 {
429 return equals(name);
430 }
Jeff Thompson91737f52013-10-04 11:07:24 -0700431
432 /**
433 * Check if this name has the same component count and components as the given name.
434 * @param name The Name to check.
435 * @return true if the names are not equal, otherwise false.
436 */
437 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700438 operator!=(const Name& name) const
439 {
440 return !equals(name);
441 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700442
Jeff Thompson82568ad2013-12-17 15:17:40 -0800443 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800444 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
445 * @param other The other Name to compare with.
446 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700447 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800448 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800449 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700450 operator<=(const Name& other) const
451 {
452 return compare(other) <= 0;
453 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800454
455 /**
456 * Return true if this is less than the other Name in the NDN canonical ordering.
457 * @param other The other Name to compare with.
458 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700459 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800460 */
461 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700462 operator<(const Name& other) const
463 {
464 return compare(other) < 0;
465 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800466
467 /**
468 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
469 * @param other The other Name to compare with.
470 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700471 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800472 */
473 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700474 operator>=(const Name& other) const
475 {
476 return compare(other) >= 0;
477 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800478
479 /**
480 * Return true if this is greater than the other Name in the NDN canonical ordering.
481 * @param other The other Name to compare with.
482 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700483 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800484 */
485 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700486 operator>(const Name& other) const
487 {
488 return compare(other) > 0;
489 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700490
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700491 //
492 // Iterator interface to name components.
493 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700494
495 /**
496 * Begin iterator (const).
497 */
498 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800499 begin() const
500 {
501 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
502 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700503
504 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700505 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800506 *
507 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700508 */
509 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800510 end() const
511 {
512 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
513 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700514
515 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700516 * Reverse begin iterator (const).
517 */
518 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800519 rbegin() const
520 {
521 return const_reverse_iterator(end());
522 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700523
524 /**
525 * Reverse end iterator (const).
526 */
527 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800528 rend() const
529 {
530 return const_reverse_iterator(begin());
531 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700532
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700533private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800534 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800535};
536
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700537inline std::ostream&
538operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700539{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700540 if (name.empty())
541 {
542 os << "/";
543 }
544 else
545 {
546 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
547 os << "/";
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700548 i->toUri(os);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700549 }
550 }
551 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700552}
553
554inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800555Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700556{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800557 std::ostringstream os;
558 os << *this;
559 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700560}
561
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700562inline std::istream&
563operator>>(std::istream& is, Name& name)
564{
565 std::string inputString;
566 is >> inputString;
567 name.set(inputString);
568
569 return is;
570}
571
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700572
573inline void
574Name::set(const char* uri_cstr)
575{
576 clear();
577
578 std::string uri = uri_cstr;
579 trim(uri);
580 if (uri.size() == 0)
581 return;
582
583 size_t iColon = uri.find(':');
584 if (iColon != std::string::npos) {
585 // Make sure the colon came before a '/'.
586 size_t iFirstSlash = uri.find('/');
587 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
588 // Omit the leading protocol such as ndn:
589 uri.erase(0, iColon + 1);
590 trim(uri);
591 }
592 }
593
594 // Trim the leading slash and possibly the authority.
595 if (uri[0] == '/') {
596 if (uri.size() >= 2 && uri[1] == '/') {
597 // Strip the authority following "//".
598 size_t iAfterAuthority = uri.find('/', 2);
599 if (iAfterAuthority == std::string::npos)
600 // Unusual case: there was only an authority.
601 return;
602 else {
603 uri.erase(0, iAfterAuthority + 1);
604 trim(uri);
605 }
606 }
607 else {
608 uri.erase(0, 1);
609 trim(uri);
610 }
611 }
612
613 size_t iComponentStart = 0;
614
615 // Unescape the components.
616 while (iComponentStart < uri.size()) {
617 size_t iComponentEnd = uri.find("/", iComponentStart);
618 if (iComponentEnd == std::string::npos)
619 iComponentEnd = uri.size();
620
621 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
622 // Ignore illegal components. This also gets rid of a trailing '/'.
623 if (!component.empty())
624 append(Component(component));
625
626 iComponentStart = iComponentEnd + 1;
627 }
628}
629
630inline Name&
631Name::append(const Name& name)
632{
633 if (&name == this)
634 // Copying from this name, so need to make a copy first.
635 return append(Name(name));
636
637 for (size_t i = 0; i < name.size(); ++i)
638 append(name.at(i));
639
640 return *this;
641}
642
643inline Name&
644Name::appendVersion()
645{
646 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
647 return *this;
648}
649
650inline Name
651Name::getSubName(size_t iStartComponent, size_t nComponents) const
652{
653 Name result;
654
655 size_t iEnd = iStartComponent + nComponents;
656 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
657 result.append(at(i));
658
659 return result;
660}
661
662inline Name
663Name::getSubName(size_t iStartComponent) const
664{
665 Name result;
666
667 for (size_t i = iStartComponent; i < size(); ++i)
668 result.append(at(i));
669
670 return result;
671}
672
Shuo Chen5aa8c742014-06-22 15:00:02 +0800673inline Name
674Name::getSuccessor() const
675{
676 if (empty()) {
677 static uint8_t firstValue[] = { 0 };
678 Name firstName;
679 firstName.append(firstValue, 1);
680 return firstName;
681 }
682
683 return getPrefix(-1).append(get(-1).getSuccessor());
684}
685
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700686inline bool
687Name::equals(const Name& name) const
688{
689 if (size() != name.size())
690 return false;
691
692 for (size_t i = 0; i < size(); ++i) {
693 if (at(i) != name.at(i))
694 return false;
695 }
696
697 return true;
698}
699
700inline bool
701Name::isPrefixOf(const Name& name) const
702{
703 // This name is longer than the name we are checking it against.
704 if (size() > name.size())
705 return false;
706
707 // Check if at least one of given components doesn't match.
708 for (size_t i = 0; i < size(); ++i) {
709 if (at(i) != name.at(i))
710 return false;
711 }
712
713 return true;
714}
715
716
717inline int
718Name::compare(const Name& other) const
719{
720 for (size_t i = 0; i < size() && i < other.size(); ++i) {
721 int comparison = at(i).compare(other.at(i));
722 if (comparison == 0)
723 // The components at this index are equal, so check the next components.
724 continue;
725
726 // Otherwise, the result is based on the components at this index.
727 return comparison;
728 }
729
730 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
731 if (size() < other.size())
732 return -1;
733 else if (size() > other.size())
734 return 1;
735 else
736 return 0;
737}
738
739
740
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800741template<bool T>
742inline size_t
743Name::wireEncode(EncodingImpl<T>& blk) const
744{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700745 size_t totalLength = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700746
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700747 for (const_reverse_iterator i = rbegin();
748 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800749 ++i)
750 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700751 totalLength += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800752 }
753
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700754 totalLength += blk.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600755 totalLength += blk.prependVarNumber(tlv::Name);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700756 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800757}
758
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700759inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800760Name::wireEncode() const
761{
762 if (m_nameBlock.hasWire())
763 return m_nameBlock;
764
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800765 EncodingEstimator estimator;
766 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700767
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800768 EncodingBuffer buffer(estimatedSize, 0);
769 wireEncode(buffer);
770
771 m_nameBlock = buffer.block();
772 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700773
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800774 return m_nameBlock;
775}
776
777inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700778Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800779{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600780 if (wire.type() != tlv::Name)
781 throw tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700782
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800783 m_nameBlock = wire;
784 m_nameBlock.parse();
785}
786
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800787inline bool
788Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800789{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800790 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800791}
792
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800793} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700794
795#endif