blob: a9be6a8eaf8ef63811dd34fd7db58192a22c91fe [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -08002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Jeff Thompson <jefft0@remap.ucla.edu>
22 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
23 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080024 */
25
26#ifndef NDN_NAME_COMPONENT_HPP
27#define NDN_NAME_COMPONENT_HPP
28
29#include "common.hpp"
30#include "encoding/block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070031#include "encoding/block-helpers.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080032#include "encoding/encoding-buffer.hpp"
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070033#include "util/string-helper.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080034
35namespace ndn {
36namespace name {
37
38/**
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070039 * @brief Component holds a read-only name component value.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080040 */
41class Component : public Block
42{
43public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070044 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070045 * @brief Error that can be thrown from name::Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070047 class Error : public Block::Error
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070048 {
49 public:
50 explicit
51 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070052 : Block::Error(what)
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070053 {
54 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070055 };
56
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080057 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070058 * Create a new name::Component with an empty value
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080059 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070060 Component();
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080061
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080062 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070063 * @brief Create name::Component from a wire block
64 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060065 * @param wire tlv::NameComponent Block from which to create name::Component
66 * @throws Error if wire.type() is not tlv::NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080067 *
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070068 * Any block can be implicitly converted to name::Component
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080069 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070070 Component(const Block& wire);
71
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080072 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070073 * @brief Create a new name::Component from the buffer pointer (buffer pointer will be copied)
74 *
75 * @param buffer A pointer to an immutable buffer
76 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060077 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -070078 * Note that this method **will not** allocate new memory for and copy the payload until
79 * toWire() method is called.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080080 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070081 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070082 Component(const ConstBufferPtr& buffer);
83
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080084 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070085 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
86 * @param buffer A reference to the buffer
87 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060088 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -070089 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080090 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091 explicit
Alexander Afanasyev770827c2014-05-13 17:42:55 -070092 Component(const Buffer& buffer);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080093
94 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070095 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
96 * @param buffer A pointer to the first byte of the buffer
97 * @param bufferSize Size of the buffer
98 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -060099 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700100 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800101 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700102 Component(const uint8_t* buffer, size_t bufferSize);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800103
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700104 /**
105 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
106 * @param begin Iterator pointing to the beginning of the buffer
107 * @param end Iterator pointing to the ending of the buffer
108 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600109 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700110 * Note that this method **will** allocate new memory for and copy the payload.
111 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800112 template<class InputIterator>
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700113 Component(InputIterator begin, InputIterator end);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800114
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700115 /**
116 * @brief Create a new name::Component from the C string (data from string will be copied)
117 *
118 * @param str Zero-ended string. Note that this string will be interpreted as is (i.e.,
119 * it will not be interpreted as URI)
120 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600121 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700122 * Note that this method **will** allocate new memory for and copy the payload.
123 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800124 explicit
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700125 Component(const char* str);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800126
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700127 /**
128 * @brief Create a new name::Component from the STL string (data from string will be copied)
129 *
130 * @param str Const reference to STL string. Note that this string will be interpreted
131 * as is (i.e., it will not be interpreted as URI)
132 *
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600133 * This constructor will create a new tlv::NameComponent Block with `buffer` as a payload.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700134 * Note that this method **will** allocate new memory for and copy the payload.
135 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800136 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700137 Component(const std::string& str);
138
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800139 /**
140 * @brief Fast encoding or block size estimation
141 */
142 template<bool T>
143 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700144 wireEncode(EncodingImpl<T>& block) const;
145
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800146 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700147 * @brief Encode to a wire format
148 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700149 const Block&
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700150 wireEncode() const;
151
152 /**
153 * @brief Decode from the wire format
154 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700155 void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700156 wireDecode(const Block& wire);
157
158 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700159 * @brief Create name::Component by decoding the escapedString between beginOffset and
160 * endOffset according to the NDN URI Scheme.
161 *
162 * If the escaped string is "", "." or ".." then return an empty name::Component. Note
163 * that an empty name::Component should not be added to Name and if attempted, an
164 * exception will be thrown.
165 *
166 * @param escapedString String containing NDN URI-encoded name
167 * component. [escapedString+beginOffset, beginOffset+endOffset)
168 * must be a valid memory buffer.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800169 * @param beginOffset The offset in escapedString of the beginning of the portion to decode.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700170 * @param endOffset The offset in escapedString of the end of the portion to decode.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800171 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700172 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700173 fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800174
175 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700176 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
177 *
178 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800179 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700180 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700181 fromEscapedString(const char* escapedString)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800182 {
183 return fromEscapedString(escapedString, 0, ::strlen(escapedString));
184 }
185
186 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700187 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
188 *
189 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800190 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700191 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800192 fromEscapedString(const std::string& escapedString)
193 {
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700194 return fromEscapedString(escapedString.c_str(), 0, escapedString.size());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800195 }
196
197 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700198 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
199 *
200 * @deprecated Use toUri(std::ostream&) instead
201 *
202 * This also adds "..." to a value with zero or more "."
203 *
204 * @param os The output stream to where write the URI escaped version *this
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800205 */
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700206 DEPRECATED(
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700207 void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700208 toEscapedString(std::ostream& os) const)
209 {
210 return toUri(os);
211 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700212
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800213 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700214 * @brief Convert *this by escaping characters according to the NDN URI Scheme
215 *
216 * @deprecated Use toUri() instead
217 *
218 * This also adds "..." to a value with zero or more "."
219 *
220 * @return The escaped string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800221 */
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700222 DEPRECATED(
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700223 std::string
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700224 toEscapedString() const)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800225 {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700226 return toUri();
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800227 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800228
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700229 /**
230 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
231 *
232 * This also adds "..." to a value with zero or more "."
233 *
234 * @param os The output stream to where write the URI escaped version *this
235 */
236 void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700237 toUri(std::ostream& os) const;
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800238
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700239 /**
240 * @brief Convert *this by escaping characters according to the NDN URI Scheme
241 *
242 * This also adds "..." to a value with zero or more "."
243 *
244 * @return The escaped string
245 */
246 std::string
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800247 toUri() const
248 {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700249 std::ostringstream os;
250 toUri(os);
251 return os.str();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800252 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700253
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800254 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700255 * @brief Interpret this name component as nonNegativeInteger
256 *
257 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
258 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800259 * @return The integer number.
260 */
261 uint64_t
262 toNumber() const;
263
264 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700265 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800266 */
267 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700268 toVersion() const;
269
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800270 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700271 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800272 */
273 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700274 toSegment() const;
275
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800276 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700277 * @brief Create a component encoded as nonNegativeInteger
278 *
279 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
280 *
281 * @param number The non-negative number
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800282 * @return The component value.
283 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700284 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800285 fromNumber(uint64_t number);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800286
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700287 bool
288 empty() const
289 {
290 return !hasValue();
291 }
292
Shuo Chen5aa8c742014-06-22 15:00:02 +0800293 Component
294 getSuccessor() const;
295
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800296 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700297 * @brief Check if this is the same component as other
298 *
299 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800300 * @return true if the components are equal, otherwise false.
301 */
302 bool
303 equals(const Component& other) const
304 {
305 if (value_size() != other.value_size())
306 return false;
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800307 if (value_size() == 0 /* == other.value_size()*/)
308 return true;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800309
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800310 // somehow, behavior is wrong on OSX 10.9 when component is empty
311 // (probably some bug in STL...)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800312 return std::equal(value_begin(), value_end(), other.value_begin());
313 }
314
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800315 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700316 * @brief Compare this to the other Component using NDN canonical ordering
317 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800318 * @param other The other Component to compare with.
319 * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700320 * 1 if *this comes after other in the canonical ordering.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800321 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700322 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800323 */
324 int
325 compare(const Component& other) const;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800326
327 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700328 * @brief Check if this is the same component as other
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800329 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700330 * @param other The other Component to compare with.
331 * @return true if the components are equal, otherwise false.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800332 */
333 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700334 operator==(const Component& other) const
335 {
336 return equals(other);
337 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700338
339 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700340 * @brief Check if this is not the same component as other
341 * @param other The other Component to compare with
342 * @return true if the components are not equal, otherwise false
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700343 */
344 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700345 operator!=(const Component& other) const
346 {
347 return !equals(other);
348 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700349
350 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700351 * @brief Check if the *this is less than or equal to the other in NDN canonical ordering
352 * @param other The other Component to compare with
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700353 *
354 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
355 */
356 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700357 operator<=(const Component& other) const
358 {
359 return compare(other) <= 0;
360 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800361
362 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700363 * @brief Check if the *this is less than the other in NDN canonical ordering
364 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800365 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700366 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800367 */
368 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700369 operator<(const Component& other) const
370 {
371 return compare(other) < 0;
372 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800373
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700374 /**
375 * @brief Check if the *this is greater or equal than the other in NDN canonical ordering
376 * @param other The other Component to compare with
377 *
378 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
379 */
380 bool
381 operator>=(const Component& other) const
382 {
383 return compare(other) >= 0;
384 }
385
386 /**
387 * @brief Check if the *this is greater than the other in NDN canonical ordering
388 * @param other The other Component to compare with
389 *
390 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
391 */
392 bool
393 operator>(const Component& other) const
394 {
395 return compare(other) > 0;
396 }
397
398 // !!! NOTE TO IMPLEMENTOR !!!
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700399 //
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700400 // This class MUST NOT contain any data fields.
401 // Block can be reinterpret_cast'ed as Component type.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800402};
403
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700404inline std::ostream&
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700405operator<<(std::ostream& os, const Component& component)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800406{
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700407 component.toUri(os);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800408 return os;
409}
410
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700411inline
412Component::Component()
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600413 : Block(tlv::NameComponent)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700414{
415}
416
417inline
418Component::Component(const Block& wire)
419 : Block(wire)
420{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600421 if (type() != tlv::NameComponent)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700422 throw Error("Constructing name component from non name component TLV wire block");
423}
424
425inline
426Component::Component(const ConstBufferPtr& buffer)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600427 : Block(tlv::NameComponent, buffer)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700428{
429}
430
431inline
432Component::Component(const Buffer& value)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600433 : Block(dataBlock(tlv::NameComponent, value.buf(), value.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700434{
435}
436
437inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700438Component::Component(const uint8_t* value, size_t valueLen)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600439 : Block(dataBlock(tlv::NameComponent, value, valueLen))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700440{
441}
442
443template<class InputIterator>
444inline
445Component::Component(InputIterator begin, InputIterator end)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600446 : Block(dataBlock(tlv::NameComponent, begin, end))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700447{
448}
449
450inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700451Component::Component(const char* str)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600452 : Block(dataBlock(tlv::NameComponent, str, ::strlen(str)))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700453{
454}
455
456inline
457Component::Component(const std::string& str)
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600458 : Block(dataBlock(tlv::NameComponent, str.c_str(), str.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700459{
460}
461
462
463inline Component
464Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
465{
466 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
467 trim(trimmedString);
468 std::string value = unescape(trimmedString);
469
470 if (value.find_first_not_of(".") == std::string::npos) {
471 // Special case for component of only periods.
472 if (value.size() <= 2)
473 // Zero, one or two periods is illegal. Ignore this component.
474 return Component();
475 else
476 // Remove 3 periods.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700477 return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700478 }
479 else
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700480 return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700481}
482
483
484inline void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700485Component::toUri(std::ostream& result) const
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700486{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700487 const uint8_t* valuePtr = value();
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700488 size_t valueSize = value_size();
489
490 bool gotNonDot = false;
491 for (unsigned i = 0; i < valueSize; ++i) {
492 if (valuePtr[i] != 0x2e) {
493 gotNonDot = true;
494 break;
495 }
496 }
497 if (!gotNonDot) {
498 // Special case for component of zero or more periods. Add 3 periods.
499 result << "...";
500 for (size_t i = 0; i < valueSize; ++i)
501 result << '.';
502 }
503 else {
504 // In case we need to escape, set to upper case hex and save the previous flags.
505 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
506
507 for (size_t i = 0; i < valueSize; ++i) {
508 uint8_t x = valuePtr[i];
509 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
510 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
511 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
512 x == 0x2e || x == 0x5f)
513 result << x;
514 else {
515 result << '%';
516 if (x < 16)
517 result << '0';
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700518 result << static_cast<unsigned int>(x);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700519 }
520 }
521
522 // Restore.
523 result.flags(saveFlags);
524 }
525}
526
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700527
528inline Component
529Component::fromNumber(uint64_t number)
530{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600531 /// \todo Change to tlv::NumberComponent
532 return nonNegativeIntegerBlock(tlv::NameComponent, number);
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700533}
534
535
536inline uint64_t
537Component::toNumber() const
538{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600539 /// \todo Check if Component is of tlv::NumberComponent type
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700540 return readNonNegativeInteger(static_cast<const Block&>(*this));
541}
542
543
544inline uint64_t
545Component::toVersion() const
546{
547 return toNumber();
548}
549
550inline uint64_t
551Component::toSegment() const
552{
553 return toNumber();
554}
555
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700556inline int
557Component::compare(const Component& other) const
558{
559 // Imitate ndn_Exclude_compareComponents.
560 if (value_size() < other.value_size())
561 return -1;
562 if (value_size() > other.value_size())
563 return 1;
564
565 if (value_size() == 0)
566 return 0;
567
568 // The components are equal length. Just do a byte compare.
569 return std::memcmp(value(), other.value(), value_size());
570}
571
Shuo Chen5aa8c742014-06-22 15:00:02 +0800572inline Component
573Component::getSuccessor() const
574{
575 size_t totalLength = 0;
576 EncodingBuffer encoder(size() + 1, 1); // + 1 in case there is an overflow
577 // in unlikely case TLV length changes more,
578 // EncodingBuffer will take care of that
579
580 bool isOverflow = true;
581 size_t i = value_size();
582 for (; isOverflow && i > 0; i--) {
583 uint8_t newValue = static_cast<uint8_t>((value()[i - 1] + 1) & 0xFF);
584 totalLength += encoder.prependByte(newValue);
585 isOverflow = (newValue == 0);
586 }
587 totalLength += encoder.prependByteArray(value(), i);
588
589 if (isOverflow) {
590 // new name components has to be extended
591 totalLength += encoder.appendByte(0);
592 }
593
594 totalLength += encoder.prependVarNumber(totalLength);
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600595 totalLength += encoder.prependVarNumber(tlv::NameComponent);
Shuo Chen5aa8c742014-06-22 15:00:02 +0800596
597 return encoder.block();
598}
599
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700600
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800601template<bool T>
602inline size_t
603Component::wireEncode(EncodingImpl<T>& block) const
604{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700605 size_t totalLength = 0;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800606 if (value_size() > 0)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700607 totalLength += block.prependByteArray(value(), value_size());
608 totalLength += block.prependVarNumber(value_size());
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600609 totalLength += block.prependVarNumber(tlv::NameComponent);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700610 return totalLength;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800611}
612
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700613inline const Block&
614Component::wireEncode() const
615{
616 if (this->hasWire())
617 return *this;
618
619 EncodingEstimator estimator;
620 size_t estimatedSize = wireEncode(estimator);
621
622 EncodingBuffer buffer(estimatedSize, 0);
623 wireEncode(buffer);
624
625 const_cast<Component&>(*this) = buffer.block();
626 return *this;
627}
628
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700629inline void
630Component::wireDecode(const Block& wire)
631{
Steve DiBenedetto54ce6682014-07-22 13:22:57 -0600632 if (wire.type() != tlv::NameComponent)
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700633 throw Error("wireDecode name component from non name component TLV wire block");
634
635 *this = wire;
636}
637
638
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800639} // namespace name
640} // namespace ndn
641
642#endif // NDN_NAME_COMPONENT_HPP