blob: d289c096ee8102f603cba821529281403b3e92a3 [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()
80 : m_nameBlock(Tlv::Name)
81 {
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 ConstBufferPtr& value)
Jeff Thompson0f743452013-09-12 14:23:18 -0700179 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800180 m_nameBlock.push_back(value);
Jeff Thompson26b0d792013-09-23 16:19:01 -0700181 return *this;
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700182 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700183
184 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700185 append(const Component& value)
Jeff Thompson21eb7212013-09-26 09:05:40 -0700186 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800187 m_nameBlock.push_back(value);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700188 return *this;
189 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800190
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800191 /**
192 * @brief Append name component that represented as a string
193 *
194 * Note that this method is necessary to ensure correctness and unambiguity of
195 * ``append("string")`` operations (both Component and Name can be implicitly
196 * converted from string, each having different outcomes
197 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700198 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700199 append(const char* value)
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800200 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800201 m_nameBlock.push_back(Component(value));
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800202 return *this;
203 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700204
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800205 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700206 append(const Block& value)
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800207 {
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800208 if (value.type() == Tlv::NameComponent)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800209 m_nameBlock.push_back(value);
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800210 else
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800211 m_nameBlock.push_back(Block(Tlv::NameComponent, value));
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800212
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800213 return *this;
214 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700215
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700216 /**
Jeff Thompson26b0d792013-09-23 16:19:01 -0700217 * Append the components of the given name to this name.
218 * @param name The Name with components to append.
219 * @return This name so that you can chain calls to append.
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700220 */
Jeff Thompson26b0d792013-09-23 16:19:01 -0700221 Name&
222 append(const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700223
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700224 /**
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700225 * Clear all the components.
226 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700227 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800228 clear()
229 {
230 m_nameBlock = Block(Tlv::Name);
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700231 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700232
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700233 /**
Jeff Thompsond0159d72013-09-23 13:34:15 -0700234 * Get a new name, constructed as a subset of components.
235 * @param iStartComponent The index if the first component to get.
236 * @param nComponents The number of components starting at iStartComponent.
237 * @return A new name.
238 */
239 Name
240 getSubName(size_t iStartComponent, size_t nComponents) const;
241
242 /**
243 * Get a new name, constructed as a subset of components starting at iStartComponent until the end of the name.
244 * @param iStartComponent The index if the first component to get.
245 * @return A new name.
246 */
247 Name
248 getSubName(size_t iStartComponent) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700249
Jeff Thompsond0159d72013-09-23 13:34:15 -0700250 /**
251 * Return a new Name with the first nComponents components of this Name.
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800252 * @param nComponents The number of prefix components. If nComponents is -N then return the prefix up
253 * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700254 * @return A new Name.
255 */
256 Name
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800257 getPrefix(int nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700258 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800259 if (nComponents < 0)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800260 return getSubName(0, m_nameBlock.elements_size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800261 else
262 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700263 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700264
Jeff Thompsond0159d72013-09-23 13:34:15 -0700265 /**
Jeff Thompsone6063512013-07-01 15:11:28 -0700266 * Encode this name as a URI.
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700267 * @return The encoded URI.
Jeff Thompsone6063512013-07-01 15:11:28 -0700268 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700269 std::string
Jeff Thompson0050abe2013-09-17 12:50:25 -0700270 toUri() const;
Jeff Thompsond129ac12013-10-11 14:30:12 -0700271
272 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700273 * @brief Append a component with the number encoded as nonNegativeInteger
274 *
275 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
276 *
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600277 * @param number The non-negative number
278 * @return This name so that you can chain calls to append.
279 */
280 Name&
281 appendNumber(uint64_t number)
282 {
283 m_nameBlock.push_back(Component::fromNumber(number));
284 return *this;
285 }
286
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700287 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700288 * @brief An alias for appendNumber(uint64_t)
289 */
290 Name&
291 appendVersion(uint64_t number)
292 {
293 return appendNumber(number);
294 }
295
296 /**
297 * @brief Append a component with the encoded version number (current UNIX timestamp
298 * in milliseconds)
299 */
300 Name&
301 appendVersion();
302
303 /**
304 * @brief An alias for appendNumber(uint64_t)
305 */
306 Name&
307 appendSegment(uint64_t number)
308 {
309 return appendNumber(number);
310 }
311
312 /**
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700313 * Check if this name has the same component count and components as the given name.
314 * @param name The Name to check.
315 * @return true if the names are equal, otherwise false.
316 */
317 bool
318 equals(const Name& name) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700319
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700320 /**
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700321 * Check if the N components of this name are the same as the first N components of the given name.
322 * @param name The Name to check.
323 * @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
324 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700325 bool
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800326 isPrefixOf(const Name& name) const;
327
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700328 //
329 // vector equivalent interface.
330 //
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800331
332 /**
333 * @brief Check if name is emtpy
334 */
335 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700336 empty() const
337 {
338 return m_nameBlock.elements().empty();
339 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700340
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700341 /**
342 * Get the number of components.
343 * @return The number of components.
344 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700345 size_t
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700346 size() const
347 {
348 return m_nameBlock.elements_size();
349 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700350
351 /**
352 * Get the component at the given index.
353 * @param i The index of the component, starting from 0.
354 * @return The name component at the index.
355 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700356 const Component&
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800357 get(ssize_t i) const
358 {
359 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800360 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800361 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800362 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
363 }
364
365 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700366 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800367 {
368 return get(i);
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800369 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000370
371 /**
372 * @brief Get component at the specified index
373 *
374 * Unlike get() and operator[] methods, at() checks for out of bounds
375 * and will throw Name::Error when it happens
376 *
377 * @throws Name::Error if index out of bounds
378 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800379 const Component&
380 at(ssize_t i) const
381 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700382 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
383 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000384 throw Error("Requested component does not exist (out of bounds)");
385
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800386 return get(i);
387 }
388
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800389 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700390 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800391 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700392 * If the first components of each name are not equal, this returns -1 if the first comes
393 * before the second using the NDN canonical ordering for name components, or 1 if it
394 * comes after. If they are equal, this compares the second components of each name, etc.
395 * If both names are the same up to the size of the shorter name, this returns -1 if the
396 * first name is shorter than the second or 1 if it is longer. For example, if you
397 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
398 * the prefix /a are next to each other. But it may be also be counter-intuitive because
399 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
400 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
401 * comes before other in the canonical ordering, or 1 if *this comes after other in the
402 * canonical ordering.
403 *
404 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800405 */
406 int
407 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700408
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700409 /**
410 * Append the component
411 * @param component The component of type T.
412 */
413 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700414 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700415 {
416 append(component);
417 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700418
Jeff Thompson91737f52013-10-04 11:07:24 -0700419 /**
420 * Check if this name has the same component count and components as the given name.
421 * @param name The Name to check.
422 * @return true if the names are equal, otherwise false.
423 */
424 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700425 operator==(const Name& name) const
426 {
427 return equals(name);
428 }
Jeff Thompson91737f52013-10-04 11:07:24 -0700429
430 /**
431 * Check if this name has the same component count and components as the given name.
432 * @param name The Name to check.
433 * @return true if the names are not equal, otherwise false.
434 */
435 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700436 operator!=(const Name& name) const
437 {
438 return !equals(name);
439 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700440
Jeff Thompson82568ad2013-12-17 15:17:40 -0800441 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800442 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
443 * @param other The other Name to compare with.
444 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700445 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800446 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800447 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700448 operator<=(const Name& other) const
449 {
450 return compare(other) <= 0;
451 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800452
453 /**
454 * Return true if this is less than the other Name in the NDN canonical ordering.
455 * @param other The other Name to compare with.
456 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700457 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800458 */
459 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700460 operator<(const Name& other) const
461 {
462 return compare(other) < 0;
463 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800464
465 /**
466 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
467 * @param other The other Name to compare with.
468 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700469 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800470 */
471 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700472 operator>=(const Name& other) const
473 {
474 return compare(other) >= 0;
475 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800476
477 /**
478 * Return true if this is greater than the other Name in the NDN canonical ordering.
479 * @param other The other Name to compare with.
480 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700481 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800482 */
483 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700484 operator>(const Name& other) const
485 {
486 return compare(other) > 0;
487 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700488
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700489 //
490 // Iterator interface to name components.
491 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700492
493 /**
494 * Begin iterator (const).
495 */
496 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800497 begin() const
498 {
499 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
500 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700501
502 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700503 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800504 *
505 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700506 */
507 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800508 end() const
509 {
510 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
511 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700512
513 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700514 * Reverse begin iterator (const).
515 */
516 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800517 rbegin() const
518 {
519 return const_reverse_iterator(end());
520 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700521
522 /**
523 * Reverse end iterator (const).
524 */
525 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800526 rend() const
527 {
528 return const_reverse_iterator(begin());
529 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700530
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700531private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800532 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800533};
534
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700535inline std::ostream&
536operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700537{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700538 if (name.empty())
539 {
540 os << "/";
541 }
542 else
543 {
544 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
545 os << "/";
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700546 i->toUri(os);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700547 }
548 }
549 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700550}
551
552inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800553Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700554{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800555 std::ostringstream os;
556 os << *this;
557 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700558}
559
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700560inline std::istream&
561operator>>(std::istream& is, Name& name)
562{
563 std::string inputString;
564 is >> inputString;
565 name.set(inputString);
566
567 return is;
568}
569
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700570
571inline void
572Name::set(const char* uri_cstr)
573{
574 clear();
575
576 std::string uri = uri_cstr;
577 trim(uri);
578 if (uri.size() == 0)
579 return;
580
581 size_t iColon = uri.find(':');
582 if (iColon != std::string::npos) {
583 // Make sure the colon came before a '/'.
584 size_t iFirstSlash = uri.find('/');
585 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
586 // Omit the leading protocol such as ndn:
587 uri.erase(0, iColon + 1);
588 trim(uri);
589 }
590 }
591
592 // Trim the leading slash and possibly the authority.
593 if (uri[0] == '/') {
594 if (uri.size() >= 2 && uri[1] == '/') {
595 // Strip the authority following "//".
596 size_t iAfterAuthority = uri.find('/', 2);
597 if (iAfterAuthority == std::string::npos)
598 // Unusual case: there was only an authority.
599 return;
600 else {
601 uri.erase(0, iAfterAuthority + 1);
602 trim(uri);
603 }
604 }
605 else {
606 uri.erase(0, 1);
607 trim(uri);
608 }
609 }
610
611 size_t iComponentStart = 0;
612
613 // Unescape the components.
614 while (iComponentStart < uri.size()) {
615 size_t iComponentEnd = uri.find("/", iComponentStart);
616 if (iComponentEnd == std::string::npos)
617 iComponentEnd = uri.size();
618
619 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
620 // Ignore illegal components. This also gets rid of a trailing '/'.
621 if (!component.empty())
622 append(Component(component));
623
624 iComponentStart = iComponentEnd + 1;
625 }
626}
627
628inline Name&
629Name::append(const Name& name)
630{
631 if (&name == this)
632 // Copying from this name, so need to make a copy first.
633 return append(Name(name));
634
635 for (size_t i = 0; i < name.size(); ++i)
636 append(name.at(i));
637
638 return *this;
639}
640
641inline Name&
642Name::appendVersion()
643{
644 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
645 return *this;
646}
647
648inline Name
649Name::getSubName(size_t iStartComponent, size_t nComponents) const
650{
651 Name result;
652
653 size_t iEnd = iStartComponent + nComponents;
654 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
655 result.append(at(i));
656
657 return result;
658}
659
660inline Name
661Name::getSubName(size_t iStartComponent) const
662{
663 Name result;
664
665 for (size_t i = iStartComponent; i < size(); ++i)
666 result.append(at(i));
667
668 return result;
669}
670
671inline bool
672Name::equals(const Name& name) const
673{
674 if (size() != name.size())
675 return false;
676
677 for (size_t i = 0; i < size(); ++i) {
678 if (at(i) != name.at(i))
679 return false;
680 }
681
682 return true;
683}
684
685inline bool
686Name::isPrefixOf(const Name& name) const
687{
688 // This name is longer than the name we are checking it against.
689 if (size() > name.size())
690 return false;
691
692 // Check if at least one of given components doesn't match.
693 for (size_t i = 0; i < size(); ++i) {
694 if (at(i) != name.at(i))
695 return false;
696 }
697
698 return true;
699}
700
701
702inline int
703Name::compare(const Name& other) const
704{
705 for (size_t i = 0; i < size() && i < other.size(); ++i) {
706 int comparison = at(i).compare(other.at(i));
707 if (comparison == 0)
708 // The components at this index are equal, so check the next components.
709 continue;
710
711 // Otherwise, the result is based on the components at this index.
712 return comparison;
713 }
714
715 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
716 if (size() < other.size())
717 return -1;
718 else if (size() > other.size())
719 return 1;
720 else
721 return 0;
722}
723
724
725
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800726template<bool T>
727inline size_t
728Name::wireEncode(EncodingImpl<T>& blk) const
729{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700730 size_t totalLength = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700731
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700732 for (const_reverse_iterator i = rbegin();
733 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800734 ++i)
735 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700736 totalLength += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800737 }
738
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700739 totalLength += blk.prependVarNumber(totalLength);
740 totalLength += blk.prependVarNumber(Tlv::Name);
741 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800742}
743
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700744inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800745Name::wireEncode() const
746{
747 if (m_nameBlock.hasWire())
748 return m_nameBlock;
749
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800750 EncodingEstimator estimator;
751 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700752
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800753 EncodingBuffer buffer(estimatedSize, 0);
754 wireEncode(buffer);
755
756 m_nameBlock = buffer.block();
757 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700758
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800759 return m_nameBlock;
760}
761
762inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700763Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800764{
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800765 if (wire.type() != Tlv::Name)
766 throw Tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700767
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800768 m_nameBlock = wire;
769 m_nameBlock.parse();
770}
771
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800772inline bool
773Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800774{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800775 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800776}
777
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800778} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700779
780#endif