blob: b7b529f1795bdd8ee6a7acffb5badf0801d7255a [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 *
65 * @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 *
77 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
78 * 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 *
88 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
89 * 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 *
99 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
100 * 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 *
109 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
110 * 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 *
121 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
122 * 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 *
133 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
134 * 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
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800293 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700294 * @brief Check if this is the same component as other
295 *
296 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800297 * @return true if the components are equal, otherwise false.
298 */
299 bool
300 equals(const Component& other) const
301 {
302 if (value_size() != other.value_size())
303 return false;
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800304 if (value_size() == 0 /* == other.value_size()*/)
305 return true;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800306
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800307 // somehow, behavior is wrong on OSX 10.9 when component is empty
308 // (probably some bug in STL...)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800309 return std::equal(value_begin(), value_end(), other.value_begin());
310 }
311
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800312 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700313 * @brief Compare this to the other Component using NDN canonical ordering
314 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800315 * @param other The other Component to compare with.
316 * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700317 * 1 if *this comes after other in the canonical ordering.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800318 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700319 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800320 */
321 int
322 compare(const Component& other) const;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800323
324 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700325 * @brief Check if this is the same component as other
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800326 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700327 * @param other The other Component to compare with.
328 * @return true if the components are equal, otherwise false.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800329 */
330 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700331 operator==(const Component& other) const
332 {
333 return equals(other);
334 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700335
336 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700337 * @brief Check if this is not the same component as other
338 * @param other The other Component to compare with
339 * @return true if the components are not equal, otherwise false
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700340 */
341 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700342 operator!=(const Component& other) const
343 {
344 return !equals(other);
345 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700346
347 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700348 * @brief Check if the *this is less than or equal to the other in NDN canonical ordering
349 * @param other The other Component to compare with
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700350 *
351 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
352 */
353 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700354 operator<=(const Component& other) const
355 {
356 return compare(other) <= 0;
357 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800358
359 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700360 * @brief Check if the *this is less than the other in NDN canonical ordering
361 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800362 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700363 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800364 */
365 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700366 operator<(const Component& other) const
367 {
368 return compare(other) < 0;
369 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800370
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700371 /**
372 * @brief Check if the *this is greater or equal than the other in NDN canonical ordering
373 * @param other The other Component to compare with
374 *
375 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
376 */
377 bool
378 operator>=(const Component& other) const
379 {
380 return compare(other) >= 0;
381 }
382
383 /**
384 * @brief Check if the *this is greater than the other in NDN canonical ordering
385 * @param other The other Component to compare with
386 *
387 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
388 */
389 bool
390 operator>(const Component& other) const
391 {
392 return compare(other) > 0;
393 }
394
395 // !!! NOTE TO IMPLEMENTOR !!!
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700396 //
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700397 // This class MUST NOT contain any data fields.
398 // Block can be reinterpret_cast'ed as Component type.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800399};
400
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700401inline std::ostream&
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700402operator<<(std::ostream& os, const Component& component)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800403{
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700404 component.toUri(os);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800405 return os;
406}
407
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700408inline
409Component::Component()
410 : Block(Tlv::NameComponent)
411{
412}
413
414inline
415Component::Component(const Block& wire)
416 : Block(wire)
417{
418 if (type() != Tlv::NameComponent)
419 throw Error("Constructing name component from non name component TLV wire block");
420}
421
422inline
423Component::Component(const ConstBufferPtr& buffer)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700424 : Block(Tlv::NameComponent, buffer)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700425{
426}
427
428inline
429Component::Component(const Buffer& value)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700430 : Block(dataBlock(Tlv::NameComponent, value.buf(), value.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700431{
432}
433
434inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700435Component::Component(const uint8_t* value, size_t valueLen)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700436 : Block(dataBlock(Tlv::NameComponent, value, valueLen))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700437{
438}
439
440template<class InputIterator>
441inline
442Component::Component(InputIterator begin, InputIterator end)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700443 : Block(dataBlock(Tlv::NameComponent, begin, end))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700444{
445}
446
447inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700448Component::Component(const char* str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700449 : Block(dataBlock(Tlv::NameComponent, str, ::strlen(str)))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700450{
451}
452
453inline
454Component::Component(const std::string& str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700455 : Block(dataBlock(Tlv::NameComponent, str.c_str(), str.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700456{
457}
458
459
460inline Component
461Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
462{
463 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
464 trim(trimmedString);
465 std::string value = unescape(trimmedString);
466
467 if (value.find_first_not_of(".") == std::string::npos) {
468 // Special case for component of only periods.
469 if (value.size() <= 2)
470 // Zero, one or two periods is illegal. Ignore this component.
471 return Component();
472 else
473 // Remove 3 periods.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700474 return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700475 }
476 else
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700477 return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700478}
479
480
481inline void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700482Component::toUri(std::ostream& result) const
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700483{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700484 const uint8_t* valuePtr = value();
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700485 size_t valueSize = value_size();
486
487 bool gotNonDot = false;
488 for (unsigned i = 0; i < valueSize; ++i) {
489 if (valuePtr[i] != 0x2e) {
490 gotNonDot = true;
491 break;
492 }
493 }
494 if (!gotNonDot) {
495 // Special case for component of zero or more periods. Add 3 periods.
496 result << "...";
497 for (size_t i = 0; i < valueSize; ++i)
498 result << '.';
499 }
500 else {
501 // In case we need to escape, set to upper case hex and save the previous flags.
502 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
503
504 for (size_t i = 0; i < valueSize; ++i) {
505 uint8_t x = valuePtr[i];
506 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
507 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
508 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
509 x == 0x2e || x == 0x5f)
510 result << x;
511 else {
512 result << '%';
513 if (x < 16)
514 result << '0';
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700515 result << static_cast<unsigned int>(x);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700516 }
517 }
518
519 // Restore.
520 result.flags(saveFlags);
521 }
522}
523
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700524
525inline Component
526Component::fromNumber(uint64_t number)
527{
528 /// \todo Change to Tlv::NumberComponent
529 return nonNegativeIntegerBlock(Tlv::NameComponent, number);
530}
531
532
533inline uint64_t
534Component::toNumber() const
535{
536 /// \todo Check if Component is of Tlv::NumberComponent type
537 return readNonNegativeInteger(static_cast<const Block&>(*this));
538}
539
540
541inline uint64_t
542Component::toVersion() const
543{
544 return toNumber();
545}
546
547inline uint64_t
548Component::toSegment() const
549{
550 return toNumber();
551}
552
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700553inline int
554Component::compare(const Component& other) const
555{
556 // Imitate ndn_Exclude_compareComponents.
557 if (value_size() < other.value_size())
558 return -1;
559 if (value_size() > other.value_size())
560 return 1;
561
562 if (value_size() == 0)
563 return 0;
564
565 // The components are equal length. Just do a byte compare.
566 return std::memcmp(value(), other.value(), value_size());
567}
568
569
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800570template<bool T>
571inline size_t
572Component::wireEncode(EncodingImpl<T>& block) const
573{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700574 size_t totalLength = 0;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800575 if (value_size() > 0)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700576 totalLength += block.prependByteArray(value(), value_size());
577 totalLength += block.prependVarNumber(value_size());
578 totalLength += block.prependVarNumber(Tlv::NameComponent);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700579 return totalLength;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800580}
581
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700582inline const Block&
583Component::wireEncode() const
584{
585 if (this->hasWire())
586 return *this;
587
588 EncodingEstimator estimator;
589 size_t estimatedSize = wireEncode(estimator);
590
591 EncodingBuffer buffer(estimatedSize, 0);
592 wireEncode(buffer);
593
594 const_cast<Component&>(*this) = buffer.block();
595 return *this;
596}
597
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700598inline void
599Component::wireDecode(const Block& wire)
600{
601 if (wire.type() != Tlv::NameComponent)
602 throw Error("wireDecode name component from non name component TLV wire block");
603
604 *this = wire;
605}
606
607
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800608} // namespace name
609} // namespace ndn
610
611#endif // NDN_NAME_COMPONENT_HPP