blob: 5a8dfcf876353d751457d63e7dfc82c1cbaafe7e [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/**
Jeff Thompson7687dc02013-09-13 11:54:07 -07003 * Copyright (C) 2013 Regents of the University of California.
4 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
Jeff Thompsonec39fbd2013-10-04 10:56:23 -07005 * @author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
6 * @author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
Jeff Thompson47eecfc2013-07-07 22:56:46 -07007 * See COPYING for copyright and distribution information.
Jeff Thompson9c41dfe2013-06-27 12:10:25 -07008 */
9
10#ifndef NDN_NAME_HPP
Jeff Thompson2d27e2f2013-08-09 12:55:00 -070011#define NDN_NAME_HPP
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070012
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080013#include "common.hpp"
14#include "name-component.hpp"
15
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080016#include "encoding/block.hpp"
Wentao Shang77949212014-02-01 23:42:24 -080017#include "encoding/encoding-buffer.hpp"
Jeff Thompson25b4e612013-10-10 16:03:24 -070018
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080019#include <boost/iterator/reverse_iterator.hpp>
20
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070021namespace ndn {
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080022
Jeff Thompsonc7d65502013-11-06 17:22:26 -080023/**
24 * A Name holds an array of Name::Component and represents an NDN name.
25 */
Alexander Afanasyevb790d952014-01-24 12:07:53 -080026class Name : public ptr_lib::enable_shared_from_this<Name> {
Jeff Thompson9c41dfe2013-06-27 12:10:25 -070027public:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080028 /// @brief Error that can be thrown from the block
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070029 class Error : public name::Component::Error {
30 public:
31 Error(const std::string& what)
32 : name::Component::Error(what) {}
33 };
Alexander Afanasyevaf283d82014-01-03 13:23:34 -080034
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080035 typedef name::Component Component;
36
37 typedef std::vector<Component> component_container;
38
39 typedef Component value_type;
40 typedef void allocator_type;
41 typedef Component& reference;
42 typedef const Component const_reference;
43 typedef Component* pointer;
44 typedef const Component* const_pointer;
45 typedef Component* iterator;
46 typedef const Component* const_iterator;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070047
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080048 typedef boost::reverse_iterator<iterator> reverse_iterator;
49 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
50
51 typedef component_container::difference_type difference_type;
52 typedef component_container::size_type size_type;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070053
Jeff Thompson443398d2013-07-02 19:45:46 -070054 /**
55 * Create a new Name with no components.
56 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080057 Name()
58 : m_nameBlock(Tlv::Name)
59 {
Jeff Thompson016ed642013-07-02 14:39:06 -070060 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080061
62 /**
63 * @brief Create Name object from wire block
64 *
65 * This is a more efficient equivalent for
66 * @code
67 * Name name;
68 * name.wireDecode(wire);
69 * @endcode
70 */
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -080071 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070072 Name(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080073 {
74 m_nameBlock = wire;
75 m_nameBlock.parse();
76 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070077
Jeff Thompson3f2175b2013-07-31 17:12:47 -070078 /**
Jeff Thompson443398d2013-07-02 19:45:46 -070079 * Parse the uri according to the NDN URI Scheme and create the name with the components.
Jeff Thompson3f2175b2013-07-31 17:12:47 -070080 * @param uri The URI string.
Jeff Thompson443398d2013-07-02 19:45:46 -070081 */
Jeff Thompson3549ef32013-09-25 14:05:17 -070082 Name(const char* uri)
Jeff Thompson67515bd2013-08-15 17:43:22 -070083 {
84 set(uri);
85 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -070086
Jeff Thompsone5f839b2013-06-28 12:50:38 -070087 /**
Jeff Thompson3549ef32013-09-25 14:05:17 -070088 * Parse the uri according to the NDN URI Scheme and create the name with the components.
89 * @param uri The URI string.
90 */
91 Name(const std::string& uri)
92 {
93 set(uri.c_str());
94 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -070095
Alexander Afanasyev380420b2014-02-09 20:52:29 -080096 /**
97 * @brief Fast encoding or block size estimation
98 */
99 template<bool T>
Wentao Shang77949212014-02-01 23:42:24 -0800100 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700101 wireEncode(EncodingImpl<T>& block) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700102
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700103 const Block&
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800104 wireEncode() const;
Alexander Afanasyev848c61a2014-01-03 13:52:04 -0800105
106 void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700107 wireDecode(const Block& wire);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800108
109 /**
110 * @brief Check if already has wire
111 */
112 bool
113 hasWire() const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700114
Jeff Thompsonb468c312013-07-01 17:50:14 -0700115 /**
Jeff Thompson67515bd2013-08-15 17:43:22 -0700116 * Parse the uri according to the NDN URI Scheme and set the name with the components.
Jeff Thompson7781b392013-12-17 11:45:59 -0800117 * @param uri The null-terminated URI string.
Jeff Thompson67515bd2013-08-15 17:43:22 -0700118 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700119 void
120 set(const char *uri);
Jeff Thompson67515bd2013-08-15 17:43:22 -0700121
122 /**
Jeff Thompson7781b392013-12-17 11:45:59 -0800123 * Parse the uri according to the NDN URI Scheme and set the name with the components.
124 * @param uri The URI string.
125 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700126 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800127 set(const std::string& uri)
128 {
129 set(uri.c_str());
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700130 }
131
Jeff Thompson7781b392013-12-17 11:45:59 -0800132 /**
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700133 * Append a new component, copying from value of length valueLength.
Jeff Thompson26b0d792013-09-23 16:19:01 -0700134 * @return This name so that you can chain calls to append.
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700135 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700136 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700137 append(const uint8_t* value, size_t valueLength)
Jeff Thompson0f743452013-09-12 14:23:18 -0700138 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800139 m_nameBlock.push_back(Component(value, valueLength));
Jeff Thompson26b0d792013-09-23 16:19:01 -0700140 return *this;
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700141 }
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700142
Alexander Afanasyevbf9671d2014-02-11 13:44:13 -0800143 /**
144 * Append a new component, copying from value of length valueLength.
145 * @return This name so that you can chain calls to append.
146 */
147 template<class InputIterator>
148 Name&
149 append(InputIterator begin, InputIterator end)
150 {
151 m_nameBlock.push_back(Component(begin, end));
152 return *this;
153 }
154
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700155 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700156 append(const ConstBufferPtr& value)
Jeff Thompson0f743452013-09-12 14:23:18 -0700157 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800158 m_nameBlock.push_back(value);
Jeff Thompson26b0d792013-09-23 16:19:01 -0700159 return *this;
Jeff Thompsonf72b1ac2013-08-16 16:44:41 -0700160 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700161
162 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700163 append(const Component& value)
Jeff Thompson21eb7212013-09-26 09:05:40 -0700164 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800165 m_nameBlock.push_back(value);
Jeff Thompson21eb7212013-09-26 09:05:40 -0700166 return *this;
167 }
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800168
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800169 /**
170 * @brief Append name component that represented as a string
171 *
172 * Note that this method is necessary to ensure correctness and unambiguity of
173 * ``append("string")`` operations (both Component and Name can be implicitly
174 * converted from string, each having different outcomes
175 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700176 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700177 append(const char* value)
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800178 {
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800179 m_nameBlock.push_back(Component(value));
Alexander Afanasyev594cdb22014-01-03 15:11:33 -0800180 return *this;
181 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700182
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800183 Name&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700184 append(const Block& value)
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800185 {
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800186 if (value.type() == Tlv::NameComponent)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800187 m_nameBlock.push_back(value);
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800188 else
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800189 m_nameBlock.push_back(Block(Tlv::NameComponent, value));
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800190
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800191 return *this;
192 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700193
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700194 /**
Jeff Thompson26b0d792013-09-23 16:19:01 -0700195 * Append the components of the given name to this name.
196 * @param name The Name with components to append.
197 * @return This name so that you can chain calls to append.
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700198 */
Jeff Thompson26b0d792013-09-23 16:19:01 -0700199 Name&
200 append(const Name& name);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700201
Jeff Thompson0aa66f22013-09-23 13:02:13 -0700202 /**
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700203 * Clear all the components.
204 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700205 void
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800206 clear()
207 {
208 m_nameBlock = Block(Tlv::Name);
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700209 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700210
Jeff Thompsone5f839b2013-06-28 12:50:38 -0700211 /**
Jeff Thompsond0159d72013-09-23 13:34:15 -0700212 * Get a new name, constructed as a subset of components.
213 * @param iStartComponent The index if the first component to get.
214 * @param nComponents The number of components starting at iStartComponent.
215 * @return A new name.
216 */
217 Name
218 getSubName(size_t iStartComponent, size_t nComponents) const;
219
220 /**
221 * Get a new name, constructed as a subset of components starting at iStartComponent until the end of the name.
222 * @param iStartComponent The index if the first component to get.
223 * @return A new name.
224 */
225 Name
226 getSubName(size_t iStartComponent) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700227
Jeff Thompsond0159d72013-09-23 13:34:15 -0700228 /**
229 * Return a new Name with the first nComponents components of this Name.
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800230 * @param nComponents The number of prefix components. If nComponents is -N then return the prefix up
231 * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
Jeff Thompsond0159d72013-09-23 13:34:15 -0700232 * @return A new Name.
233 */
234 Name
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800235 getPrefix(int nComponents) const
Jeff Thompsond0159d72013-09-23 13:34:15 -0700236 {
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800237 if (nComponents < 0)
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800238 return getSubName(0, m_nameBlock.elements_size() + nComponents);
Jeff Thompsoneb0358f2013-12-17 10:59:53 -0800239 else
240 return getSubName(0, nComponents);
Jeff Thompsond0159d72013-09-23 13:34:15 -0700241 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700242
Jeff Thompsond0159d72013-09-23 13:34:15 -0700243 /**
Jeff Thompsone6063512013-07-01 15:11:28 -0700244 * Encode this name as a URI.
Jeff Thompson3f2175b2013-07-31 17:12:47 -0700245 * @return The encoded URI.
Jeff Thompsone6063512013-07-01 15:11:28 -0700246 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700247 std::string
Jeff Thompson0050abe2013-09-17 12:50:25 -0700248 toUri() const;
Jeff Thompsond129ac12013-10-11 14:30:12 -0700249
250 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700251 * @brief Append a component with the number encoded as nonNegativeInteger
252 *
253 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
254 *
Steve DiBenedettoc145d492014-03-11 16:35:45 -0600255 * @param number The non-negative number
256 * @return This name so that you can chain calls to append.
257 */
258 Name&
259 appendNumber(uint64_t number)
260 {
261 m_nameBlock.push_back(Component::fromNumber(number));
262 return *this;
263 }
264
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700265 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700266 * @brief An alias for appendNumber(uint64_t)
267 */
268 Name&
269 appendVersion(uint64_t number)
270 {
271 return appendNumber(number);
272 }
273
274 /**
275 * @brief Append a component with the encoded version number (current UNIX timestamp
276 * in milliseconds)
277 */
278 Name&
279 appendVersion();
280
281 /**
282 * @brief An alias for appendNumber(uint64_t)
283 */
284 Name&
285 appendSegment(uint64_t number)
286 {
287 return appendNumber(number);
288 }
289
290 /**
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700291 * Check if this name has the same component count and components as the given name.
292 * @param name The Name to check.
293 * @return true if the names are equal, otherwise false.
294 */
295 bool
296 equals(const Name& name) const;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700297
Jeff Thompson3c2ab012013-10-02 14:18:16 -0700298 /**
Jeff Thompsonec7789a2013-08-21 11:08:36 -0700299 * Check if the N components of this name are the same as the first N components of the given name.
300 * @param name The Name to check.
301 * @return true if this matches the given name, otherwise false. This always returns true if this name is empty.
302 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700303 bool
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800304 isPrefixOf(const Name& name) const;
305
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700306 //
307 // vector equivalent interface.
308 //
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800309
310 /**
311 * @brief Check if name is emtpy
312 */
313 bool
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800314 empty() const { return m_nameBlock.elements().empty(); }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700315
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700316 /**
317 * Get the number of components.
318 * @return The number of components.
319 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700320 size_t
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800321 size() const { return m_nameBlock.elements_size(); }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700322
323 /**
324 * Get the component at the given index.
325 * @param i The index of the component, starting from 0.
326 * @return The name component at the index.
327 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700328 const Component&
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800329 get(ssize_t i) const
330 {
331 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800332 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800333 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800334 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
335 }
336
337 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700338 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800339 {
340 return get(i);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800341 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000342
343 /**
344 * @brief Get component at the specified index
345 *
346 * Unlike get() and operator[] methods, at() checks for out of bounds
347 * and will throw Name::Error when it happens
348 *
349 * @throws Name::Error if index out of bounds
350 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800351 const Component&
352 at(ssize_t i) const
353 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700354 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
355 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000356 throw Error("Requested component does not exist (out of bounds)");
357
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800358 return get(i);
359 }
360
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800361 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700362 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800363 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700364 * If the first components of each name are not equal, this returns -1 if the first comes
365 * before the second using the NDN canonical ordering for name components, or 1 if it
366 * comes after. If they are equal, this compares the second components of each name, etc.
367 * If both names are the same up to the size of the shorter name, this returns -1 if the
368 * first name is shorter than the second or 1 if it is longer. For example, if you
369 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
370 * the prefix /a are next to each other. But it may be also be counter-intuitive because
371 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
372 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
373 * comes before other in the canonical ordering, or 1 if *this comes after other in the
374 * canonical ordering.
375 *
376 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800377 */
378 int
379 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700380
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700381 /**
382 * Append the component
383 * @param component The component of type T.
384 */
385 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700386 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700387 {
388 append(component);
389 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700390
Jeff Thompson91737f52013-10-04 11:07:24 -0700391 /**
392 * Check if this name has the same component count and components as the given name.
393 * @param name The Name to check.
394 * @return true if the names are equal, otherwise false.
395 */
396 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700397 operator==(const Name& name) const { return equals(name); }
Jeff Thompson91737f52013-10-04 11:07:24 -0700398
399 /**
400 * Check if this name has the same component count and components as the given name.
401 * @param name The Name to check.
402 * @return true if the names are not equal, otherwise false.
403 */
404 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700405 operator!=(const Name& name) const { return !equals(name); }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700406
Jeff Thompson82568ad2013-12-17 15:17:40 -0800407 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800408 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
409 * @param other The other Name to compare with.
410 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700411 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800412 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800413 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700414 operator<=(const Name& other) const { return compare(other) <= 0; }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800415
416 /**
417 * Return true if this is less than the other Name in the NDN canonical ordering.
418 * @param other The other Name to compare with.
419 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700420 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800421 */
422 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700423 operator<(const Name& other) const { return compare(other) < 0; }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800424
425 /**
426 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
427 * @param other The other Name to compare with.
428 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700429 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800430 */
431 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700432 operator>=(const Name& other) const { return compare(other) >= 0; }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800433
434 /**
435 * Return true if this is greater than 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 Thompsonafc45a92014-01-15 12:42:45 -0800439 */
440 bool
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700441 operator>(const Name& other) const { return compare(other) > 0; }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700442
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700443 //
444 // Iterator interface to name components.
445 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700446
447 /**
448 * Begin iterator (const).
449 */
450 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800451 begin() const
452 {
453 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
454 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700455
456 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700457 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800458 *
459 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700460 */
461 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800462 end() const
463 {
464 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
465 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700466
467 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700468 * Reverse begin iterator (const).
469 */
470 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800471 rbegin() const
472 {
473 return const_reverse_iterator(end());
474 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700475
476 /**
477 * Reverse end iterator (const).
478 */
479 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800480 rend() const
481 {
482 return const_reverse_iterator(begin());
483 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700484
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700485private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800486 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800487};
488
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700489inline std::ostream&
490operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700491{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700492 if (name.empty())
493 {
494 os << "/";
495 }
496 else
497 {
498 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
499 os << "/";
500 i->toEscapedString(os);
501 }
502 }
503 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700504}
505
506inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800507Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700508{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800509 std::ostringstream os;
510 os << *this;
511 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700512}
513
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700514inline std::istream&
515operator>>(std::istream& is, Name& name)
516{
517 std::string inputString;
518 is >> inputString;
519 name.set(inputString);
520
521 return is;
522}
523
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700524
525inline void
526Name::set(const char* uri_cstr)
527{
528 clear();
529
530 std::string uri = uri_cstr;
531 trim(uri);
532 if (uri.size() == 0)
533 return;
534
535 size_t iColon = uri.find(':');
536 if (iColon != std::string::npos) {
537 // Make sure the colon came before a '/'.
538 size_t iFirstSlash = uri.find('/');
539 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
540 // Omit the leading protocol such as ndn:
541 uri.erase(0, iColon + 1);
542 trim(uri);
543 }
544 }
545
546 // Trim the leading slash and possibly the authority.
547 if (uri[0] == '/') {
548 if (uri.size() >= 2 && uri[1] == '/') {
549 // Strip the authority following "//".
550 size_t iAfterAuthority = uri.find('/', 2);
551 if (iAfterAuthority == std::string::npos)
552 // Unusual case: there was only an authority.
553 return;
554 else {
555 uri.erase(0, iAfterAuthority + 1);
556 trim(uri);
557 }
558 }
559 else {
560 uri.erase(0, 1);
561 trim(uri);
562 }
563 }
564
565 size_t iComponentStart = 0;
566
567 // Unescape the components.
568 while (iComponentStart < uri.size()) {
569 size_t iComponentEnd = uri.find("/", iComponentStart);
570 if (iComponentEnd == std::string::npos)
571 iComponentEnd = uri.size();
572
573 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
574 // Ignore illegal components. This also gets rid of a trailing '/'.
575 if (!component.empty())
576 append(Component(component));
577
578 iComponentStart = iComponentEnd + 1;
579 }
580}
581
582inline Name&
583Name::append(const Name& name)
584{
585 if (&name == this)
586 // Copying from this name, so need to make a copy first.
587 return append(Name(name));
588
589 for (size_t i = 0; i < name.size(); ++i)
590 append(name.at(i));
591
592 return *this;
593}
594
595inline Name&
596Name::appendVersion()
597{
598 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
599 return *this;
600}
601
602inline Name
603Name::getSubName(size_t iStartComponent, size_t nComponents) const
604{
605 Name result;
606
607 size_t iEnd = iStartComponent + nComponents;
608 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
609 result.append(at(i));
610
611 return result;
612}
613
614inline Name
615Name::getSubName(size_t iStartComponent) const
616{
617 Name result;
618
619 for (size_t i = iStartComponent; i < size(); ++i)
620 result.append(at(i));
621
622 return result;
623}
624
625inline bool
626Name::equals(const Name& name) const
627{
628 if (size() != name.size())
629 return false;
630
631 for (size_t i = 0; i < size(); ++i) {
632 if (at(i) != name.at(i))
633 return false;
634 }
635
636 return true;
637}
638
639inline bool
640Name::isPrefixOf(const Name& name) const
641{
642 // This name is longer than the name we are checking it against.
643 if (size() > name.size())
644 return false;
645
646 // Check if at least one of given components doesn't match.
647 for (size_t i = 0; i < size(); ++i) {
648 if (at(i) != name.at(i))
649 return false;
650 }
651
652 return true;
653}
654
655
656inline int
657Name::compare(const Name& other) const
658{
659 for (size_t i = 0; i < size() && i < other.size(); ++i) {
660 int comparison = at(i).compare(other.at(i));
661 if (comparison == 0)
662 // The components at this index are equal, so check the next components.
663 continue;
664
665 // Otherwise, the result is based on the components at this index.
666 return comparison;
667 }
668
669 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
670 if (size() < other.size())
671 return -1;
672 else if (size() > other.size())
673 return 1;
674 else
675 return 0;
676}
677
678
679
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800680template<bool T>
681inline size_t
682Name::wireEncode(EncodingImpl<T>& blk) const
683{
684 size_t total_len = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700685
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700686 for (const_reverse_iterator i = rbegin();
687 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800688 ++i)
689 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700690 total_len += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800691 }
692
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700693 total_len += blk.prependVarNumber(total_len);
694 total_len += blk.prependVarNumber(Tlv::Name);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800695 return total_len;
696}
697
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700698inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800699Name::wireEncode() const
700{
701 if (m_nameBlock.hasWire())
702 return m_nameBlock;
703
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800704 EncodingEstimator estimator;
705 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700706
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800707 EncodingBuffer buffer(estimatedSize, 0);
708 wireEncode(buffer);
709
710 m_nameBlock = buffer.block();
711 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700712
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800713 return m_nameBlock;
714}
715
716inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700717Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800718{
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800719 if (wire.type() != Tlv::Name)
720 throw Tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700721
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800722 m_nameBlock = wire;
723 m_nameBlock.parse();
724}
725
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800726inline bool
727Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800728{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800729 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800730}
731
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800732} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700733
734#endif