blob: 1abffbce91723c0525baaeb631e7f3b62d2cd25f [file] [log] [blame]
Jeff Thompson25b4e612013-10-10 16:03:24 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
Jeff Thompson47eecfc2013-07-07 22:56:46 -07002/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Jeff Thompson <jefft0@remap.ucla.edu>
13 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
14 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070015 */
16
17#ifndef NDN_NAME_HPP
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070018#define NDN_NAME_HPP
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070019
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080020#include "common.hpp"
21#include "name-component.hpp"
22
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080023#include "encoding/block.hpp"
Wentao Shang77949212014-02-01 23:42:24 -080024#include "encoding/encoding-buffer.hpp"
Jeff Thompson25b4e612013-10-10 16:03:24 -070025
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080026#include <boost/iterator/reverse_iterator.hpp>
27
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070028namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080029
Jeff Thompsonc7d65502013-11-06 17:22:26 -080030/**
31 * A Name holds an array of Name::Component and represents an NDN name.
32 */
Alexander Afanasyevf73f0632014-05-12 18:02:37 -070033class Name : public enable_shared_from_this<Name>
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070034{
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070035public:
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070036 /// @brief Error that can be thrown from Name
37 class Error : public name::Component::Error
38 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070039 public:
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070040 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070041 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070042 : name::Component::Error(what)
43 {
44 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070045 };
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080046
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080047 typedef name::Component Component;
48
49 typedef std::vector<Component> component_container;
50
51 typedef Component value_type;
52 typedef void allocator_type;
53 typedef Component& reference;
54 typedef const Component const_reference;
55 typedef Component* pointer;
56 typedef const Component* const_pointer;
57 typedef Component* iterator;
58 typedef const Component* const_iterator;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070059
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080060 typedef boost::reverse_iterator<iterator> reverse_iterator;
61 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
62
63 typedef component_container::difference_type difference_type;
64 typedef component_container::size_type size_type;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070065
Jeff Thompson443398d2013-07-02 19:45:46 -070066 /**
67 * Create a new Name with no components.
68 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080069 Name()
70 : m_nameBlock(Tlv::Name)
71 {
Jeff Thompson016ed642013-07-02 14:39:06 -070072 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080073
74 /**
75 * @brief Create Name object from wire block
76 *
77 * This is a more efficient equivalent for
78 * @code
79 * Name name;
80 * name.wireDecode(wire);
81 * @endcode
82 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080083 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070084 Name(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080085 {
86 m_nameBlock = wire;
87 m_nameBlock.parse();
88 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070089
Jeff Thompson3f2175b2013-07-31 17:12:47 -070090 /**
Jeff Thompson443398d2013-07-02 19:45:46 -070091 * Parse the uri according to the NDN URI Scheme and create the name with the components.
Jeff Thompson3f2175b2013-07-31 17:12:47 -070092 * @param uri The URI string.
Jeff Thompson443398d2013-07-02 19:45:46 -070093 */
Jeff Thompson3549ef32013-09-25 14:05:17 -070094 Name(const char* uri)
Jeff Thompson67515bd2013-08-15 17:43:22 -070095 {
96 set(uri);
97 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070098
Jeff Thompsone5f839b2013-06-28 12:50:38 -070099 /**
Jeff Thompson3549ef32013-09-25 14:05:17 -0700100 * Parse the uri according to the NDN URI Scheme and create the name with the components.
101 * @param uri The URI string.
102 */
103 Name(const std::string& uri)
104 {
105 set(uri.c_str());
106 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700107
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800108 /**
109 * @brief Fast encoding or block size estimation
110 */
111 template<bool T>
Wentao Shang77949212014-02-01 23:42:24 -0800112 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700113 wireEncode(EncodingImpl<T>& block) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700114
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700115 const Block&
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800116 wireEncode() const;
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800117
118 void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700119 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800120
121 /**
122 * @brief Check if already has wire
123 */
124 bool
125 hasWire() const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700126
Jeff Thompsonb468c312013-07-01 17:50:14 -0700127 /**
Jeff Thompson67515bd2013-08-15 17:43:22 -0700128 * Parse the uri according to the NDN URI Scheme and set the name with the components.
Jeff Thompson7781b392013-12-17 11:45:59 -0800129 * @param uri The null-terminated URI string.
Jeff Thompson67515bd2013-08-15 17:43:22 -0700130 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700131 void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700132 set(const char* uri);
Jeff Thompson67515bd2013-08-15 17:43:22 -0700133
134 /**
Jeff Thompson7781b392013-12-17 11:45:59 -0800135 * Parse the uri according to the NDN URI Scheme and set the name with the components.
136 * @param uri The URI string.
137 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700138 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800139 set(const std::string& uri)
140 {
141 set(uri.c_str());
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700142 }
143
Jeff Thompson7781b392013-12-17 11:45:59 -0800144 /**
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700145 * Append a new component, copying from value of length valueLength.
Jeff Thompson26b0d792013-09-23 16:19:01 -0700146 * @return This name so that you can chain calls to append.
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700147 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700148 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700149 append(const uint8_t* value, size_t valueLength)
Jeff Thompson0f743452013-09-12 14:23:18 -0700150 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800151 m_nameBlock.push_back(Component(value, valueLength));
Jeff Thompson26b0d792013-09-23 16:19:01 -0700152 return *this;
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700153 }
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700154
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800155 /**
156 * Append a new component, copying from value of length valueLength.
157 * @return This name so that you can chain calls to append.
158 */
159 template<class InputIterator>
160 Name&
161 append(InputIterator begin, InputIterator end)
162 {
163 m_nameBlock.push_back(Component(begin, end));
164 return *this;
165 }
166
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700167 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700168 append(const ConstBufferPtr& value)
Jeff Thompson0f743452013-09-12 14:23:18 -0700169 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800170 m_nameBlock.push_back(value);
Jeff Thompson26b0d792013-09-23 16:19:01 -0700171 return *this;
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700172 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700173
174 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700175 append(const Component& value)
Jeff Thompson21eb7212013-09-26 09:05:40 -0700176 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800177 m_nameBlock.push_back(value);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700178 return *this;
179 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800180
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800181 /**
182 * @brief Append name component that represented as a string
183 *
184 * Note that this method is necessary to ensure correctness and unambiguity of
185 * ``append("string")`` operations (both Component and Name can be implicitly
186 * converted from string, each having different outcomes
187 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700188 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700189 append(const char* value)
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800190 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800191 m_nameBlock.push_back(Component(value));
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800192 return *this;
193 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700194
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800195 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700196 append(const Block& value)
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800197 {
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800198 if (value.type() == Tlv::NameComponent)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800199 m_nameBlock.push_back(value);
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800200 else
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800201 m_nameBlock.push_back(Block(Tlv::NameComponent, value));
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800202
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800203 return *this;
204 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700205
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700206 /**
Jeff Thompson26b0d792013-09-23 16:19:01 -0700207 * Append the components of the given name to this name.
208 * @param name The Name with components to append.
209 * @return This name so that you can chain calls to append.
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700210 */
Jeff Thompson26b0d792013-09-23 16:19:01 -0700211 Name&
212 append(const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700213
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700214 /**
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700215 * Clear all the components.
216 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700217 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800218 clear()
219 {
220 m_nameBlock = Block(Tlv::Name);
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700221 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700222
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700223 /**
Jeff Thompsond0159d72013-09-23 13:34:15 -0700224 * Get a new name, constructed as a subset of components.
225 * @param iStartComponent The index if the first component to get.
226 * @param nComponents The number of components starting at iStartComponent.
227 * @return A new name.
228 */
229 Name
230 getSubName(size_t iStartComponent, size_t nComponents) const;
231
232 /**
233 * Get a new name, constructed as a subset of components starting at iStartComponent until the end of the name.
234 * @param iStartComponent The index if the first component to get.
235 * @return A new name.
236 */
237 Name
238 getSubName(size_t iStartComponent) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700239
Jeff Thompsond0159d72013-09-23 13:34:15 -0700240 /**
241 * Return a new Name with the first nComponents components of this Name.
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800242 * @param nComponents The number of prefix components. If nComponents is -N then return the prefix up
243 * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700244 * @return A new Name.
245 */
246 Name
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800247 getPrefix(int nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700248 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800249 if (nComponents < 0)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800250 return getSubName(0, m_nameBlock.elements_size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800251 else
252 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700253 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700254
Jeff Thompsond0159d72013-09-23 13:34:15 -0700255 /**
Jeff Thompsone6063512013-07-01 15:11:28 -0700256 * Encode this name as a URI.
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700257 * @return The encoded URI.
Jeff Thompsone6063512013-07-01 15:11:28 -0700258 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700259 std::string
Jeff Thompson0050abe2013-09-17 12:50:25 -0700260 toUri() const;
Jeff Thompsond129ac12013-10-11 14:30:12 -0700261
262 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700263 * @brief Append a component with the number encoded as nonNegativeInteger
264 *
265 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
266 *
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600267 * @param number The non-negative number
268 * @return This name so that you can chain calls to append.
269 */
270 Name&
271 appendNumber(uint64_t number)
272 {
273 m_nameBlock.push_back(Component::fromNumber(number));
274 return *this;
275 }
276
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700277 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700278 * @brief An alias for appendNumber(uint64_t)
279 */
280 Name&
281 appendVersion(uint64_t number)
282 {
283 return appendNumber(number);
284 }
285
286 /**
287 * @brief Append a component with the encoded version number (current UNIX timestamp
288 * in milliseconds)
289 */
290 Name&
291 appendVersion();
292
293 /**
294 * @brief An alias for appendNumber(uint64_t)
295 */
296 Name&
297 appendSegment(uint64_t number)
298 {
299 return appendNumber(number);
300 }
301
302 /**
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700303 * Check if this name has the same component count and components as the given name.
304 * @param name The Name to check.
305 * @return true if the names are equal, otherwise false.
306 */
307 bool
308 equals(const Name& name) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700309
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700310 /**
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700311 * Check if the N components of this name are the same as the first N components of the given name.
312 * @param name The Name to check.
313 * @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
314 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700315 bool
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800316 isPrefixOf(const Name& name) const;
317
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700318 //
319 // vector equivalent interface.
320 //
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800321
322 /**
323 * @brief Check if name is emtpy
324 */
325 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700326 empty() const
327 {
328 return m_nameBlock.elements().empty();
329 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700330
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700331 /**
332 * Get the number of components.
333 * @return The number of components.
334 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700335 size_t
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700336 size() const
337 {
338 return m_nameBlock.elements_size();
339 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700340
341 /**
342 * Get the component at the given index.
343 * @param i The index of the component, starting from 0.
344 * @return The name component at the index.
345 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700346 const Component&
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800347 get(ssize_t i) const
348 {
349 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800350 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800351 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800352 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
353 }
354
355 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700356 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800357 {
358 return get(i);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800359 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000360
361 /**
362 * @brief Get component at the specified index
363 *
364 * Unlike get() and operator[] methods, at() checks for out of bounds
365 * and will throw Name::Error when it happens
366 *
367 * @throws Name::Error if index out of bounds
368 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800369 const Component&
370 at(ssize_t i) const
371 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700372 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
373 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000374 throw Error("Requested component does not exist (out of bounds)");
375
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800376 return get(i);
377 }
378
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800379 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700380 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800381 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700382 * If the first components of each name are not equal, this returns -1 if the first comes
383 * before the second using the NDN canonical ordering for name components, or 1 if it
384 * comes after. If they are equal, this compares the second components of each name, etc.
385 * If both names are the same up to the size of the shorter name, this returns -1 if the
386 * first name is shorter than the second or 1 if it is longer. For example, if you
387 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
388 * the prefix /a are next to each other. But it may be also be counter-intuitive because
389 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
390 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
391 * comes before other in the canonical ordering, or 1 if *this comes after other in the
392 * canonical ordering.
393 *
394 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800395 */
396 int
397 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700398
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700399 /**
400 * Append the component
401 * @param component The component of type T.
402 */
403 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700404 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700405 {
406 append(component);
407 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700408
Jeff Thompson91737f52013-10-04 11:07:24 -0700409 /**
410 * Check if this name has the same component count and components as the given name.
411 * @param name The Name to check.
412 * @return true if the names are equal, otherwise false.
413 */
414 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700415 operator==(const Name& name) const
416 {
417 return equals(name);
418 }
Jeff Thompson91737f52013-10-04 11:07:24 -0700419
420 /**
421 * Check if this name has the same component count and components as the given name.
422 * @param name The Name to check.
423 * @return true if the names are not equal, otherwise false.
424 */
425 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700426 operator!=(const Name& name) const
427 {
428 return !equals(name);
429 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700430
Jeff Thompson82568ad2013-12-17 15:17:40 -0800431 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800432 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
433 * @param other The other Name to compare with.
434 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700435 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800436 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800437 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700438 operator<=(const Name& other) const
439 {
440 return compare(other) <= 0;
441 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800442
443 /**
444 * Return true if this is less than 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 Thompsonafc45a92014-01-15 12:42:45 -0800448 */
449 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 or equal to 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 greater than 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 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700478
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700479 //
480 // Iterator interface to name components.
481 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700482
483 /**
484 * Begin iterator (const).
485 */
486 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800487 begin() const
488 {
489 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
490 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700491
492 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700493 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800494 *
495 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700496 */
497 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800498 end() const
499 {
500 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
501 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700502
503 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700504 * Reverse begin iterator (const).
505 */
506 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800507 rbegin() const
508 {
509 return const_reverse_iterator(end());
510 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700511
512 /**
513 * Reverse end iterator (const).
514 */
515 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800516 rend() const
517 {
518 return const_reverse_iterator(begin());
519 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700520
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700521private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800522 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800523};
524
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700525inline std::ostream&
526operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700527{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700528 if (name.empty())
529 {
530 os << "/";
531 }
532 else
533 {
534 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
535 os << "/";
536 i->toEscapedString(os);
537 }
538 }
539 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700540}
541
542inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800543Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700544{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800545 std::ostringstream os;
546 os << *this;
547 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700548}
549
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700550inline std::istream&
551operator>>(std::istream& is, Name& name)
552{
553 std::string inputString;
554 is >> inputString;
555 name.set(inputString);
556
557 return is;
558}
559
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700560
561inline void
562Name::set(const char* uri_cstr)
563{
564 clear();
565
566 std::string uri = uri_cstr;
567 trim(uri);
568 if (uri.size() == 0)
569 return;
570
571 size_t iColon = uri.find(':');
572 if (iColon != std::string::npos) {
573 // Make sure the colon came before a '/'.
574 size_t iFirstSlash = uri.find('/');
575 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
576 // Omit the leading protocol such as ndn:
577 uri.erase(0, iColon + 1);
578 trim(uri);
579 }
580 }
581
582 // Trim the leading slash and possibly the authority.
583 if (uri[0] == '/') {
584 if (uri.size() >= 2 && uri[1] == '/') {
585 // Strip the authority following "//".
586 size_t iAfterAuthority = uri.find('/', 2);
587 if (iAfterAuthority == std::string::npos)
588 // Unusual case: there was only an authority.
589 return;
590 else {
591 uri.erase(0, iAfterAuthority + 1);
592 trim(uri);
593 }
594 }
595 else {
596 uri.erase(0, 1);
597 trim(uri);
598 }
599 }
600
601 size_t iComponentStart = 0;
602
603 // Unescape the components.
604 while (iComponentStart < uri.size()) {
605 size_t iComponentEnd = uri.find("/", iComponentStart);
606 if (iComponentEnd == std::string::npos)
607 iComponentEnd = uri.size();
608
609 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
610 // Ignore illegal components. This also gets rid of a trailing '/'.
611 if (!component.empty())
612 append(Component(component));
613
614 iComponentStart = iComponentEnd + 1;
615 }
616}
617
618inline Name&
619Name::append(const Name& name)
620{
621 if (&name == this)
622 // Copying from this name, so need to make a copy first.
623 return append(Name(name));
624
625 for (size_t i = 0; i < name.size(); ++i)
626 append(name.at(i));
627
628 return *this;
629}
630
631inline Name&
632Name::appendVersion()
633{
634 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
635 return *this;
636}
637
638inline Name
639Name::getSubName(size_t iStartComponent, size_t nComponents) const
640{
641 Name result;
642
643 size_t iEnd = iStartComponent + nComponents;
644 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
645 result.append(at(i));
646
647 return result;
648}
649
650inline Name
651Name::getSubName(size_t iStartComponent) const
652{
653 Name result;
654
655 for (size_t i = iStartComponent; i < size(); ++i)
656 result.append(at(i));
657
658 return result;
659}
660
661inline bool
662Name::equals(const Name& name) const
663{
664 if (size() != name.size())
665 return false;
666
667 for (size_t i = 0; i < size(); ++i) {
668 if (at(i) != name.at(i))
669 return false;
670 }
671
672 return true;
673}
674
675inline bool
676Name::isPrefixOf(const Name& name) const
677{
678 // This name is longer than the name we are checking it against.
679 if (size() > name.size())
680 return false;
681
682 // Check if at least one of given components doesn't match.
683 for (size_t i = 0; i < size(); ++i) {
684 if (at(i) != name.at(i))
685 return false;
686 }
687
688 return true;
689}
690
691
692inline int
693Name::compare(const Name& other) const
694{
695 for (size_t i = 0; i < size() && i < other.size(); ++i) {
696 int comparison = at(i).compare(other.at(i));
697 if (comparison == 0)
698 // The components at this index are equal, so check the next components.
699 continue;
700
701 // Otherwise, the result is based on the components at this index.
702 return comparison;
703 }
704
705 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
706 if (size() < other.size())
707 return -1;
708 else if (size() > other.size())
709 return 1;
710 else
711 return 0;
712}
713
714
715
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800716template<bool T>
717inline size_t
718Name::wireEncode(EncodingImpl<T>& blk) const
719{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700720 size_t totalLength = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700721
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700722 for (const_reverse_iterator i = rbegin();
723 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800724 ++i)
725 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700726 totalLength += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800727 }
728
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700729 totalLength += blk.prependVarNumber(totalLength);
730 totalLength += blk.prependVarNumber(Tlv::Name);
731 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800732}
733
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700734inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800735Name::wireEncode() const
736{
737 if (m_nameBlock.hasWire())
738 return m_nameBlock;
739
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800740 EncodingEstimator estimator;
741 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700742
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800743 EncodingBuffer buffer(estimatedSize, 0);
744 wireEncode(buffer);
745
746 m_nameBlock = buffer.block();
747 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700748
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800749 return m_nameBlock;
750}
751
752inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700753Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800754{
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800755 if (wire.type() != Tlv::Name)
756 throw Tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700757
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800758 m_nameBlock = wire;
759 m_nameBlock.parse();
760}
761
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800762inline bool
763Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800764{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800765 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800766}
767
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800768} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700769
770#endif