blob: 03030f0b77905795d633d45e11907aaf67f9cda2 [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
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700120 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 Afanasyevfdbfc6d2014-04-14 15:12:11 -0700314 empty() const
315 {
316 return m_nameBlock.elements().empty();
317 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700318
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700319 /**
320 * Get the number of components.
321 * @return The number of components.
322 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700323 size_t
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700324 size() const
325 {
326 return m_nameBlock.elements_size();
327 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700328
329 /**
330 * Get the component at the given index.
331 * @param i The index of the component, starting from 0.
332 * @return The name component at the index.
333 */
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700334 const Component&
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800335 get(ssize_t i) const
336 {
337 if (i >= 0)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800338 return reinterpret_cast<const Component&>(m_nameBlock.elements()[i]);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800339 else
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800340 return reinterpret_cast<const Component&>(m_nameBlock.elements()[size() + i]);
341 }
342
343 const Component&
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700344 operator[](ssize_t i) const
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800345 {
346 return get(i);
Alexander Afanasyev8f9aa8b2013-12-30 15:58:57 -0800347 }
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000348
349 /**
350 * @brief Get component at the specified index
351 *
352 * Unlike get() and operator[] methods, at() checks for out of bounds
353 * and will throw Name::Error when it happens
354 *
355 * @throws Name::Error if index out of bounds
356 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800357 const Component&
358 at(ssize_t i) const
359 {
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700360 if ((i >= 0 && static_cast<size_t>(i) >= size()) ||
361 (i < 0 && static_cast<size_t>(-i) > size()))
Alexander Afanasyevc2344292014-03-02 00:08:00 +0000362 throw Error("Requested component does not exist (out of bounds)");
363
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800364 return get(i);
365 }
366
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800367 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700368 * @brief Compare this to the other Name using NDN canonical ordering.
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800369 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700370 * If the first components of each name are not equal, this returns -1 if the first comes
371 * before the second using the NDN canonical ordering for name components, or 1 if it
372 * comes after. If they are equal, this compares the second components of each name, etc.
373 * If both names are the same up to the size of the shorter name, this returns -1 if the
374 * first name is shorter than the second or 1 if it is longer. For example, if you
375 * std::sort gives: /a/b/d /a/b/cc /c /c/a /bb . This is intuitive because all names with
376 * the prefix /a are next to each other. But it may be also be counter-intuitive because
377 * /c comes before /bb according to NDN canonical ordering since it is shorter. @param
378 * other The other Name to compare with. @return 0 If they compare equal, -1 if *this
379 * comes before other in the canonical ordering, or 1 if *this comes after other in the
380 * canonical ordering.
381 *
382 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800383 */
384 int
385 compare(const Name& other) const;
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700386
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700387 /**
388 * Append the component
389 * @param component The component of type T.
390 */
391 template<class T> void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700392 push_back(const T& component)
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700393 {
394 append(component);
395 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700396
Jeff Thompson91737f52013-10-04 11:07:24 -0700397 /**
398 * Check if this name has the same component count and components as the given name.
399 * @param name The Name to check.
400 * @return true if the names are equal, otherwise false.
401 */
402 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700403 operator==(const Name& name) const
404 {
405 return equals(name);
406 }
Jeff Thompson91737f52013-10-04 11:07:24 -0700407
408 /**
409 * Check if this name has the same component count and components as the given name.
410 * @param name The Name to check.
411 * @return true if the names are not equal, otherwise false.
412 */
413 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700414 operator!=(const Name& name) const
415 {
416 return !equals(name);
417 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700418
Jeff Thompson82568ad2013-12-17 15:17:40 -0800419 /**
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800420 * Return true if this is less than or equal to the other Name in the NDN canonical ordering.
421 * @param other The other Name to compare with.
422 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700423 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompson82568ad2013-12-17 15:17:40 -0800424 */
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800425 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700426 operator<=(const Name& other) const
427 {
428 return compare(other) <= 0;
429 }
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800430
431 /**
432 * Return true if this is less than 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 Thompsonafc45a92014-01-15 12:42:45 -0800436 */
437 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 or equal to the other Name in the NDN canonical ordering.
445 * @param other The other Name to compare with.
446 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700447 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff 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 greater than the other Name in the NDN canonical ordering.
457 * @param other The other Name to compare with.
458 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700459 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Jeff Thompsonafc45a92014-01-15 12:42:45 -0800460 */
461 bool
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700462 operator>(const Name& other) const
463 {
464 return compare(other) > 0;
465 }
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700466
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700467 //
468 // Iterator interface to name components.
469 //
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700470
471 /**
472 * Begin iterator (const).
473 */
474 const_iterator
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800475 begin() const
476 {
477 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().begin());
478 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700479
480 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700481 * End iterator (const).
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800482 *
483 * @todo Check if this crash when there are no elements in the buffer
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700484 */
485 const_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800486 end() const
487 {
488 return reinterpret_cast<const_iterator>(&*m_nameBlock.elements().end());
489 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700490
491 /**
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700492 * Reverse begin iterator (const).
493 */
494 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800495 rbegin() const
496 {
497 return const_reverse_iterator(end());
498 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700499
500 /**
501 * Reverse end iterator (const).
502 */
503 const_reverse_iterator
Alexander Afanasyev29e5c3d2014-02-11 00:01:10 -0800504 rend() const
505 {
506 return const_reverse_iterator(begin());
507 }
Jeff Thompsonec39fbd2013-10-04 10:56:23 -0700508
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700509private:
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800510 mutable Block m_nameBlock;
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800511};
512
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700513inline std::ostream&
514operator<<(std::ostream& os, const Name& name)
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700515{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700516 if (name.empty())
517 {
518 os << "/";
519 }
520 else
521 {
522 for (Name::const_iterator i = name.begin(); i != name.end(); i++) {
523 os << "/";
524 i->toEscapedString(os);
525 }
526 }
527 return os;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700528}
529
530inline std::string
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800531Name::toUri() const
Jeff Thompson49e321a2013-10-04 17:35:59 -0700532{
Alexander Afanasyevaf283d82014-01-03 13:23:34 -0800533 std::ostringstream os;
534 os << *this;
535 return os.str();
Jeff Thompson49e321a2013-10-04 17:35:59 -0700536}
537
Alexander Afanasyev0df28362014-03-20 17:31:43 -0700538inline std::istream&
539operator>>(std::istream& is, Name& name)
540{
541 std::string inputString;
542 is >> inputString;
543 name.set(inputString);
544
545 return is;
546}
547
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700548
549inline void
550Name::set(const char* uri_cstr)
551{
552 clear();
553
554 std::string uri = uri_cstr;
555 trim(uri);
556 if (uri.size() == 0)
557 return;
558
559 size_t iColon = uri.find(':');
560 if (iColon != std::string::npos) {
561 // Make sure the colon came before a '/'.
562 size_t iFirstSlash = uri.find('/');
563 if (iFirstSlash == std::string::npos || iColon < iFirstSlash) {
564 // Omit the leading protocol such as ndn:
565 uri.erase(0, iColon + 1);
566 trim(uri);
567 }
568 }
569
570 // Trim the leading slash and possibly the authority.
571 if (uri[0] == '/') {
572 if (uri.size() >= 2 && uri[1] == '/') {
573 // Strip the authority following "//".
574 size_t iAfterAuthority = uri.find('/', 2);
575 if (iAfterAuthority == std::string::npos)
576 // Unusual case: there was only an authority.
577 return;
578 else {
579 uri.erase(0, iAfterAuthority + 1);
580 trim(uri);
581 }
582 }
583 else {
584 uri.erase(0, 1);
585 trim(uri);
586 }
587 }
588
589 size_t iComponentStart = 0;
590
591 // Unescape the components.
592 while (iComponentStart < uri.size()) {
593 size_t iComponentEnd = uri.find("/", iComponentStart);
594 if (iComponentEnd == std::string::npos)
595 iComponentEnd = uri.size();
596
597 Component component = Component::fromEscapedString(&uri[0], iComponentStart, iComponentEnd);
598 // Ignore illegal components. This also gets rid of a trailing '/'.
599 if (!component.empty())
600 append(Component(component));
601
602 iComponentStart = iComponentEnd + 1;
603 }
604}
605
606inline Name&
607Name::append(const Name& name)
608{
609 if (&name == this)
610 // Copying from this name, so need to make a copy first.
611 return append(Name(name));
612
613 for (size_t i = 0; i < name.size(); ++i)
614 append(name.at(i));
615
616 return *this;
617}
618
619inline Name&
620Name::appendVersion()
621{
622 appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
623 return *this;
624}
625
626inline Name
627Name::getSubName(size_t iStartComponent, size_t nComponents) const
628{
629 Name result;
630
631 size_t iEnd = iStartComponent + nComponents;
632 for (size_t i = iStartComponent; i < iEnd && i < size(); ++i)
633 result.append(at(i));
634
635 return result;
636}
637
638inline Name
639Name::getSubName(size_t iStartComponent) const
640{
641 Name result;
642
643 for (size_t i = iStartComponent; i < size(); ++i)
644 result.append(at(i));
645
646 return result;
647}
648
649inline bool
650Name::equals(const Name& name) const
651{
652 if (size() != name.size())
653 return false;
654
655 for (size_t i = 0; i < size(); ++i) {
656 if (at(i) != name.at(i))
657 return false;
658 }
659
660 return true;
661}
662
663inline bool
664Name::isPrefixOf(const Name& name) const
665{
666 // This name is longer than the name we are checking it against.
667 if (size() > name.size())
668 return false;
669
670 // Check if at least one of given components doesn't match.
671 for (size_t i = 0; i < size(); ++i) {
672 if (at(i) != name.at(i))
673 return false;
674 }
675
676 return true;
677}
678
679
680inline int
681Name::compare(const Name& other) const
682{
683 for (size_t i = 0; i < size() && i < other.size(); ++i) {
684 int comparison = at(i).compare(other.at(i));
685 if (comparison == 0)
686 // The components at this index are equal, so check the next components.
687 continue;
688
689 // Otherwise, the result is based on the components at this index.
690 return comparison;
691 }
692
693 // The components up to min(this.size(), other.size()) are equal, so the shorter name is less.
694 if (size() < other.size())
695 return -1;
696 else if (size() > other.size())
697 return 1;
698 else
699 return 0;
700}
701
702
703
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800704template<bool T>
705inline size_t
706Name::wireEncode(EncodingImpl<T>& blk) const
707{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700708 size_t totalLength = 0;
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700709
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700710 for (const_reverse_iterator i = rbegin();
711 i != rend();
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800712 ++i)
713 {
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700714 totalLength += i->wireEncode(blk);
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800715 }
716
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700717 totalLength += blk.prependVarNumber(totalLength);
718 totalLength += blk.prependVarNumber(Tlv::Name);
719 return totalLength;
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800720}
721
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700722inline const Block&
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800723Name::wireEncode() const
724{
725 if (m_nameBlock.hasWire())
726 return m_nameBlock;
727
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800728 EncodingEstimator estimator;
729 size_t estimatedSize = wireEncode(estimator);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700730
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800731 EncodingBuffer buffer(estimatedSize, 0);
732 wireEncode(buffer);
733
734 m_nameBlock = buffer.block();
735 m_nameBlock.parse();
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700736
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800737 return m_nameBlock;
738}
739
740inline void
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700741Name::wireDecode(const Block& wire)
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800742{
Alexander Afanasyevc348f832014-02-17 16:35:17 -0800743 if (wire.type() != Tlv::Name)
744 throw Tlv::Error("Unexpected TLV type when decoding Name");
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700745
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800746 m_nameBlock = wire;
747 m_nameBlock.parse();
748}
749
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800750inline bool
751Name::hasWire() const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800752{
Alexander Afanasyev6d48bc12014-02-18 00:10:51 -0800753 return m_nameBlock.hasWire();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800754}
755
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800756} // namespace ndn
Jeff Thompson9c41dfe2013-06-27 12:10:25 -0700757
758#endif