blob: 9c33528facc2503e41e83493fbf8336e7628e283 [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 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 {
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800201 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
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800204 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 {
223 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 /**
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700306 * Check if this name has the same component count and components as the given name.
307 * @param name The Name to check.
308 * @return true if the names are equal, otherwise false.
309 */
310 bool
311 equals(const Name& name) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700312
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700313 /**
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700314 * Check if the N components of this name are the same as the first N components of the given name.
315 * @param name The Name to check.
316 * @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
317 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700318 bool
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800319 isPrefixOf(const Name& name) const;
320
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700321 //
322 // vector equivalent interface.
323 //
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800324
325 /**
326 * @brief Check if name is emtpy
327 */
328 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700329 empty() const
330 {
331 return m_nameBlock.elements().empty();
332 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700333
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700334 /**
335 * Get the number of components.
336 * @return The number of components.
337 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700338 size_t
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700339 size() const
340 {
341 return m_nameBlock.elements_size();
342 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700343
344 /**
345 * Get the component at the given index.
346 * @param i The index of the component, starting from 0.
347 * @return The name component at the index.
348 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700349 const Component&
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800350 get(ssize_t i) const
351 {
352 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800353 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800354 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800355 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
356 }
357
358 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700359 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800360 {
361 return get(i);
Alexander Afanasyev8f9aa8bed2013-12-30 15:58:57 -0800362 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000363
364 /**
365 * @brief Get component at the specified index
366 *
367 * Unlike get() and operator[] methods, at() checks for out of bounds
368 * and will throw Name::Error when it happens
369 *
370 * @throws Name::Error if index out of bounds
371 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800372 const Component&
373 at(ssize_t i) const
374 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700375 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
376 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000377 throw Error("Requested component does not exist (out of bounds)");
378
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800379 return get(i);
380 }
381
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800382 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700383 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800384 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700385 * If the first components of each name are not equal, this returns -1 if the first comes
386 * before the second using the NDN canonical ordering for name components, or 1 if it
387 * comes after. If they are equal, this compares the second components of each name, etc.
388 * If both names are the same up to the size of the shorter name, this returns -1 if the
389 * first name is shorter than the second or 1 if it is longer. For example, if you
390 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
391 * the prefix /a are next to each other. But it may be also be counter-intuitive because
392 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
393 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
394 * comes before other in the canonical ordering, or 1 if *this comes after other in the
395 * canonical ordering.
396 *
397 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800398 */
399 int
400 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700401
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700402 /**
403 * Append the component
404 * @param component The component of type T.
405 */
406 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700407 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700408 {
409 append(component);
410 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700411
Jeff Thompson91737f52013-10-04 11:07:24 -0700412 /**
413 * Check if this name has the same component count and components as the given name.
414 * @param name The Name to check.
415 * @return true if the names are equal, otherwise false.
416 */
417 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700418 operator==(const Name& name) const
419 {
420 return equals(name);
421 }
Jeff Thompson91737f52013-10-04 11:07:24 -0700422
423 /**
424 * Check if this name has the same component count and components as the given name.
425 * @param name The Name to check.
426 * @return true if the names are not equal, otherwise false.
427 */
428 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700429 operator!=(const Name& name) const
430 {
431 return !equals(name);
432 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700433
Jeff Thompson82568ad2013-12-17 15:17:40 -0800434 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800435 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
436 * @param other The other Name to compare with.
437 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700438 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800439 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800440 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700441 operator<=(const Name& other) const
442 {
443 return compare(other) <= 0;
444 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800445
446 /**
447 * Return true if this is less than the other Name in the NDN canonical ordering.
448 * @param other The other Name to compare with.
449 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700450 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800451 */
452 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700453 operator<(const Name& other) const
454 {
455 return compare(other) < 0;
456 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800457
458 /**
459 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
460 * @param other The other Name to compare with.
461 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700462 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800463 */
464 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700465 operator>=(const Name& other) const
466 {
467 return compare(other) >= 0;
468 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800469
470 /**
471 * Return true if this is greater than the other Name in the NDN canonical ordering.
472 * @param other The other Name to compare with.
473 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700474 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800475 */
476 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700477 operator>(const Name& other) const
478 {
479 return compare(other) > 0;
480 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700481
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700482 //
483 // Iterator interface to name components.
484 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700485
486 /**
487 * Begin iterator (const).
488 */
489 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800490 begin() const
491 {
492 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
493 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700494
495 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700496 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800497 *
498 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700499 */
500 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800501 end() const
502 {
503 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
504 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700505
506 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700507 * Reverse begin iterator (const).
508 */
509 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800510 rbegin() const
511 {
512 return const_reverse_iterator(end());
513 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700514
515 /**
516 * Reverse end iterator (const).
517 */
518 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800519 rend() const
520 {
521 return const_reverse_iterator(begin());
522 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700523
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700524private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800525 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800526};
527
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700528inline std::ostream&
529operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700530{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700531 if (name.empty())
532 {
533 os << "/";
534 }
535 else
536 {
537 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
538 os << "/";
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700539 i->toUri(os);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700540 }
541 }
542 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700543}
544
545inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800546Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700547{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800548 std::ostringstream os;
549 os << *this;
550 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700551}
552
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700553inline std::istream&
554operator>>(std::istream& is, Name& name)
555{
556 std::string inputString;
557 is >> inputString;
558 name.set(inputString);
559
560 return is;
561}
562
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700563
564inline void
565Name::set(const char* uri_cstr)
566{
567 clear();
568
569 std::string uri = uri_cstr;
570 trim(uri);
571 if (uri.size() == 0)
572 return;
573
574 size_t iColon = uri.find(':');
575 if (iColon != std::string::npos) {
576 // Make sure the colon came before a '/'.
577 size_t iFirstSlash = uri.find('/');
578 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
579 // Omit the leading protocol such as ndn:
580 uri.erase(0, iColon + 1);
581 trim(uri);
582 }
583 }
584
585 // Trim the leading slash and possibly the authority.
586 if (uri[0] == '/') {
587 if (uri.size() >= 2 && uri[1] == '/') {
588 // Strip the authority following "//".
589 size_t iAfterAuthority = uri.find('/', 2);
590 if (iAfterAuthority == std::string::npos)
591 // Unusual case: there was only an authority.
592 return;
593 else {
594 uri.erase(0, iAfterAuthority + 1);
595 trim(uri);
596 }
597 }
598 else {
599 uri.erase(0, 1);
600 trim(uri);
601 }
602 }
603
604 size_t iComponentStart = 0;
605
606 // Unescape the components.
607 while (iComponentStart < uri.size()) {
608 size_t iComponentEnd = uri.find("/", iComponentStart);
609 if (iComponentEnd == std::string::npos)
610 iComponentEnd = uri.size();
611
612 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
613 // Ignore illegal components. This also gets rid of a trailing '/'.
614 if (!component.empty())
615 append(Component(component));
616
617 iComponentStart = iComponentEnd + 1;
618 }
619}
620
621inline Name&
622Name::append(const Name& name)
623{
624 if (&name == this)
625 // Copying from this name, so need to make a copy first.
626 return append(Name(name));
627
628 for (size_t i = 0; i < name.size(); ++i)
629 append(name.at(i));
630
631 return *this;
632}
633
634inline Name&
635Name::appendVersion()
636{
637 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
638 return *this;
639}
640
641inline Name
642Name::getSubName(size_t iStartComponent, size_t nComponents) const
643{
644 Name result;
645
646 size_t iEnd = iStartComponent + nComponents;
647 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
648 result.append(at(i));
649
650 return result;
651}
652
653inline Name
654Name::getSubName(size_t iStartComponent) const
655{
656 Name result;
657
658 for (size_t i = iStartComponent; i < size(); ++i)
659 result.append(at(i));
660
661 return result;
662}
663
664inline bool
665Name::equals(const Name& name) const
666{
667 if (size() != name.size())
668 return false;
669
670 for (size_t i = 0; i < size(); ++i) {
671 if (at(i) != name.at(i))
672 return false;
673 }
674
675 return true;
676}
677
678inline bool
679Name::isPrefixOf(const Name& name) const
680{
681 // This name is longer than the name we are checking it against.
682 if (size() > name.size())
683 return false;
684
685 // Check if at least one of given components doesn't match.
686 for (size_t i = 0; i < size(); ++i) {
687 if (at(i) != name.at(i))
688 return false;
689 }
690
691 return true;
692}
693
694
695inline int
696Name::compare(const Name& other) const
697{
698 for (size_t i = 0; i < size() && i < other.size(); ++i) {
699 int comparison = at(i).compare(other.at(i));
700 if (comparison == 0)
701 // The components at this index are equal, so check the next components.
702 continue;
703
704 // Otherwise, the result is based on the components at this index.
705 return comparison;
706 }
707
708 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
709 if (size() < other.size())
710 return -1;
711 else if (size() > other.size())
712 return 1;
713 else
714 return 0;
715}
716
717
718
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800719template<bool T>
720inline size_t
721Name::wireEncode(EncodingImpl<T>& blk) const
722{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700723 size_t totalLength = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700724
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700725 for (const_reverse_iterator i = rbegin();
726 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800727 ++i)
728 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700729 totalLength += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800730 }
731
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700732 totalLength += blk.prependVarNumber(totalLength);
733 totalLength += blk.prependVarNumber(Tlv::Name);
734 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800735}
736
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700737inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800738Name::wireEncode() const
739{
740 if (m_nameBlock.hasWire())
741 return m_nameBlock;
742
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800743 EncodingEstimator estimator;
744 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700745
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800746 EncodingBuffer buffer(estimatedSize, 0);
747 wireEncode(buffer);
748
749 m_nameBlock = buffer.block();
750 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700751
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800752 return m_nameBlock;
753}
754
755inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700756Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800757{
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800758 if (wire.type() != Tlv::Name)
759 throw Tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700760
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800761 m_nameBlock = wire;
762 m_nameBlock.parse();
763}
764
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800765inline bool
766Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800767{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800768 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800769}
770
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800771} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700772
773#endif