blob: 751c490744679a67ba969dc6fc17920ca0343778 [file] [log] [blame]
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Jeff Thompson <jefft0@remap.ucla.edu>
13 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
14 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080015 */
16
17#ifndef NDN_NAME_COMPONENT_HPP
18#define NDN_NAME_COMPONENT_HPP
19
20#include "common.hpp"
21#include "encoding/block.hpp"
Alexander Afanasyev258ec2b2014-05-14 16:15:37 -070022#include "encoding/block-helpers.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080023#include "encoding/encoding-buffer.hpp"
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070024#include "util/string-helper.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080025
26namespace ndn {
27namespace name {
28
29/**
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070030 * @brief Component holds a read-only name component value.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080031 */
32class Component : public Block
33{
34public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070035 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070036 * @brief Error that can be thrown from name::Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070037 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070038 class Error : public Block::Error
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070039 {
40 public:
41 explicit
42 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070043 : Block::Error(what)
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070044 {
45 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070046 };
47
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080048 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070049 * Create a new name::Component with an empty value
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080050 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070051 Component();
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080052
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080053 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070054 * @brief Create name::Component from a wire block
55 *
56 * @param wire Tlv::NameComponent Block from which to create name::Component
57 * @throws Error if wire.type() is not Tlv::NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080058 *
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070059 * Any block can be implicitly converted to name::Component
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080060 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070061 Component(const Block& wire);
62
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080063 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070064 * @brief Create a new name::Component from the buffer pointer (buffer pointer will be copied)
65 *
66 * @param buffer A pointer to an immutable buffer
67 *
68 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
69 * Note that this method **will not** allocate new memory for and copy the payload until
70 * toWire() method is called.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080071 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070072 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070073 Component(const ConstBufferPtr& buffer);
74
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080075 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070076 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
77 * @param buffer A reference to the buffer
78 *
79 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
80 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080081 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070082 explicit
Alexander Afanasyev770827c2014-05-13 17:42:55 -070083 Component(const Buffer& buffer);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080084
85 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070086 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
87 * @param buffer A pointer to the first byte of the buffer
88 * @param bufferSize Size of the buffer
89 *
90 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
91 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080092 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -070093 Component(const uint8_t* buffer, size_t bufferSize);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080094
Alexander Afanasyev770827c2014-05-13 17:42:55 -070095 /**
96 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
97 * @param begin Iterator pointing to the beginning of the buffer
98 * @param end Iterator pointing to the ending of the buffer
99 *
100 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
101 * Note that this method **will** allocate new memory for and copy the payload.
102 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800103 template<class InputIterator>
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700104 Component(InputIterator begin, InputIterator end);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800105
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700106 /**
107 * @brief Create a new name::Component from the C string (data from string will be copied)
108 *
109 * @param str Zero-ended string. Note that this string will be interpreted as is (i.e.,
110 * it will not be interpreted as URI)
111 *
112 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
113 * Note that this method **will** allocate new memory for and copy the payload.
114 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800115 explicit
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700116 Component(const char* str);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800117
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700118 /**
119 * @brief Create a new name::Component from the STL string (data from string will be copied)
120 *
121 * @param str Const reference to STL string. Note that this string will be interpreted
122 * as is (i.e., it will not be interpreted as URI)
123 *
124 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
125 * Note that this method **will** allocate new memory for and copy the payload.
126 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800127 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700128 Component(const std::string& str);
129
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800130 /**
131 * @brief Fast encoding or block size estimation
132 */
133 template<bool T>
134 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700135 wireEncode(EncodingImpl<T>& block) const;
136
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800137 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700138 * @brief Encode to a wire format
139 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700140 const Block&
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141 wireEncode() const;
142
143 /**
144 * @brief Decode from the wire format
145 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700146 void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700147 wireDecode(const Block& wire);
148
149 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700150 * @brief Create name::Component by decoding the escapedString between beginOffset and
151 * endOffset according to the NDN URI Scheme.
152 *
153 * If the escaped string is "", "." or ".." then return an empty name::Component. Note
154 * that an empty name::Component should not be added to Name and if attempted, an
155 * exception will be thrown.
156 *
157 * @param escapedString String containing NDN URI-encoded name
158 * component. [escapedString+beginOffset, beginOffset+endOffset)
159 * must be a valid memory buffer.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800160 * @param beginOffset The offset in escapedString of the beginning of the portion to decode.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700161 * @param endOffset The offset in escapedString of the end of the portion to decode.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800162 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700163 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700164 fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800165
166 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700167 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
168 *
169 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800170 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700171 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700172 fromEscapedString(const char* escapedString)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800173 {
174 return fromEscapedString(escapedString, 0, ::strlen(escapedString));
175 }
176
177 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700178 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
179 *
180 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800181 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700182 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800183 fromEscapedString(const std::string& escapedString)
184 {
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700185 return fromEscapedString(escapedString.c_str(), 0, escapedString.size());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800186 }
187
188 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700189 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
190 *
191 * @deprecated Use toUri(std::ostream&) instead
192 *
193 * This also adds "..." to a value with zero or more "."
194 *
195 * @param os The output stream to where write the URI escaped version *this
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800196 */
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700197 DEPRECATED(
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700198 void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700199 toEscapedString(std::ostream& os) const)
200 {
201 return toUri(os);
202 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700203
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800204 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700205 * @brief Convert *this by escaping characters according to the NDN URI Scheme
206 *
207 * @deprecated Use toUri() instead
208 *
209 * This also adds "..." to a value with zero or more "."
210 *
211 * @return The escaped string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800212 */
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700213 DEPRECATED(
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700214 std::string
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700215 toEscapedString() const)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800216 {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700217 return toUri();
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800218 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800219
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700220 /**
221 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
222 *
223 * This also adds "..." to a value with zero or more "."
224 *
225 * @param os The output stream to where write the URI escaped version *this
226 */
227 void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700228 toUri(std::ostream& os) const;
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800229
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700230 /**
231 * @brief Convert *this by escaping characters according to the NDN URI Scheme
232 *
233 * This also adds "..." to a value with zero or more "."
234 *
235 * @return The escaped string
236 */
237 std::string
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800238 toUri() const
239 {
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700240 std::ostringstream os;
241 toUri(os);
242 return os.str();
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800243 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700244
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800245 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700246 * @brief Interpret this name component as nonNegativeInteger
247 *
248 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
249 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800250 * @return The integer number.
251 */
252 uint64_t
253 toNumber() const;
254
255 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700256 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800257 */
258 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700259 toVersion() const;
260
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800261 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700262 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800263 */
264 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700265 toSegment() const;
266
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800267 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700268 * @brief Create a component encoded as nonNegativeInteger
269 *
270 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
271 *
272 * @param number The non-negative number
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800273 * @return The component value.
274 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700275 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800276 fromNumber(uint64_t number);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800277
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700278 bool
279 empty() const
280 {
281 return !hasValue();
282 }
283
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800284 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700285 * @brief Check if this is the same component as other
286 *
287 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800288 * @return true if the components are equal, otherwise false.
289 */
290 bool
291 equals(const Component& other) const
292 {
293 if (value_size() != other.value_size())
294 return false;
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800295 if (value_size() == 0 /* == other.value_size()*/)
296 return true;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800297
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800298 // somehow, behavior is wrong on OSX 10.9 when component is empty
299 // (probably some bug in STL...)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800300 return std::equal(value_begin(), value_end(), other.value_begin());
301 }
302
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800303 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700304 * @brief Compare this to the other Component using NDN canonical ordering
305 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800306 * @param other The other Component to compare with.
307 * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700308 * 1 if *this comes after other in the canonical ordering.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800309 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700310 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800311 */
312 int
313 compare(const Component& other) const;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800314
315 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700316 * @brief Check if this is the same component as other
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800317 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700318 * @param other The other Component to compare with.
319 * @return true if the components are equal, otherwise false.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800320 */
321 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700322 operator==(const Component& other) const
323 {
324 return equals(other);
325 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700326
327 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700328 * @brief Check if this is not the same component as other
329 * @param other The other Component to compare with
330 * @return true if the components are not equal, otherwise false
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700331 */
332 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700333 operator!=(const Component& other) const
334 {
335 return !equals(other);
336 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700337
338 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700339 * @brief Check if the *this is less than or equal to the other in NDN canonical ordering
340 * @param other The other Component to compare with
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700341 *
342 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
343 */
344 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700345 operator<=(const Component& other) const
346 {
347 return compare(other) <= 0;
348 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800349
350 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700351 * @brief Check if the *this is less than the other in NDN canonical ordering
352 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800353 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700354 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800355 */
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
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700362 /**
363 * @brief Check if the *this is greater or equal than the other in NDN canonical ordering
364 * @param other The other Component to compare with
365 *
366 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
367 */
368 bool
369 operator>=(const Component& other) const
370 {
371 return compare(other) >= 0;
372 }
373
374 /**
375 * @brief Check if the *this is greater 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 // !!! NOTE TO IMPLEMENTOR !!!
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700387 //
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700388 // This class MUST NOT contain any data fields.
389 // Block can be reinterpret_cast'ed as Component type.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800390};
391
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700392inline std::ostream&
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700393operator<<(std::ostream& os, const Component& component)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800394{
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700395 component.toUri(os);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800396 return os;
397}
398
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700399inline
400Component::Component()
401 : Block(Tlv::NameComponent)
402{
403}
404
405inline
406Component::Component(const Block& wire)
407 : Block(wire)
408{
409 if (type() != Tlv::NameComponent)
410 throw Error("Constructing name component from non name component TLV wire block");
411}
412
413inline
414Component::Component(const ConstBufferPtr& buffer)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700415 : Block(Tlv::NameComponent, buffer)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700416{
417}
418
419inline
420Component::Component(const Buffer& value)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700421 : Block(dataBlock(Tlv::NameComponent, value.buf(), value.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700422{
423}
424
425inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700426Component::Component(const uint8_t* value, size_t valueLen)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700427 : Block(dataBlock(Tlv::NameComponent, value, valueLen))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700428{
429}
430
431template<class InputIterator>
432inline
433Component::Component(InputIterator begin, InputIterator end)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700434 : Block(dataBlock(Tlv::NameComponent, begin, end))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700435{
436}
437
438inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700439Component::Component(const char* str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700440 : Block(dataBlock(Tlv::NameComponent, str, ::strlen(str)))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700441{
442}
443
444inline
445Component::Component(const std::string& str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700446 : Block(dataBlock(Tlv::NameComponent, str.c_str(), str.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700447{
448}
449
450
451inline Component
452Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
453{
454 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
455 trim(trimmedString);
456 std::string value = unescape(trimmedString);
457
458 if (value.find_first_not_of(".") == std::string::npos) {
459 // Special case for component of only periods.
460 if (value.size() <= 2)
461 // Zero, one or two periods is illegal. Ignore this component.
462 return Component();
463 else
464 // Remove 3 periods.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700465 return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700466 }
467 else
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700468 return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700469}
470
471
472inline void
Alexander Afanasyev9c578182014-05-14 17:28:28 -0700473Component::toUri(std::ostream& result) const
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700474{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700475 const uint8_t* valuePtr = value();
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700476 size_t valueSize = value_size();
477
478 bool gotNonDot = false;
479 for (unsigned i = 0; i < valueSize; ++i) {
480 if (valuePtr[i] != 0x2e) {
481 gotNonDot = true;
482 break;
483 }
484 }
485 if (!gotNonDot) {
486 // Special case for component of zero or more periods. Add 3 periods.
487 result << "...";
488 for (size_t i = 0; i < valueSize; ++i)
489 result << '.';
490 }
491 else {
492 // In case we need to escape, set to upper case hex and save the previous flags.
493 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
494
495 for (size_t i = 0; i < valueSize; ++i) {
496 uint8_t x = valuePtr[i];
497 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
498 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
499 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
500 x == 0x2e || x == 0x5f)
501 result << x;
502 else {
503 result << '%';
504 if (x < 16)
505 result << '0';
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700506 result << static_cast<unsigned int>(x);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700507 }
508 }
509
510 // Restore.
511 result.flags(saveFlags);
512 }
513}
514
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700515
516inline Component
517Component::fromNumber(uint64_t number)
518{
519 /// \todo Change to Tlv::NumberComponent
520 return nonNegativeIntegerBlock(Tlv::NameComponent, number);
521}
522
523
524inline uint64_t
525Component::toNumber() const
526{
527 /// \todo Check if Component is of Tlv::NumberComponent type
528 return readNonNegativeInteger(static_cast<const Block&>(*this));
529}
530
531
532inline uint64_t
533Component::toVersion() const
534{
535 return toNumber();
536}
537
538inline uint64_t
539Component::toSegment() const
540{
541 return toNumber();
542}
543
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700544inline int
545Component::compare(const Component& other) const
546{
547 // Imitate ndn_Exclude_compareComponents.
548 if (value_size() < other.value_size())
549 return -1;
550 if (value_size() > other.value_size())
551 return 1;
552
553 if (value_size() == 0)
554 return 0;
555
556 // The components are equal length. Just do a byte compare.
557 return std::memcmp(value(), other.value(), value_size());
558}
559
560
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800561template<bool T>
562inline size_t
563Component::wireEncode(EncodingImpl<T>& block) const
564{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700565 size_t totalLength = 0;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800566 if (value_size() > 0)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700567 totalLength += block.prependByteArray(value(), value_size());
568 totalLength += block.prependVarNumber(value_size());
569 totalLength += block.prependVarNumber(Tlv::NameComponent);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700570 return totalLength;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800571}
572
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700573inline const Block&
574Component::wireEncode() const
575{
576 if (this->hasWire())
577 return *this;
578
579 EncodingEstimator estimator;
580 size_t estimatedSize = wireEncode(estimator);
581
582 EncodingBuffer buffer(estimatedSize, 0);
583 wireEncode(buffer);
584
585 const_cast<Component&>(*this) = buffer.block();
586 return *this;
587}
588
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700589inline void
590Component::wireDecode(const Block& wire)
591{
592 if (wire.type() != Tlv::NameComponent)
593 throw Error("wireDecode name component from non name component TLV wire block");
594
595 *this = wire;
596}
597
598
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800599} // namespace name
600} // namespace ndn
601
602#endif // NDN_NAME_COMPONENT_HPP