blob: d58e4d64cb59f90c2f36ca98f6444e0c0b85cd4e [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 Afanasyev1dd95c52014-03-22 19:11:36 -0700197 void
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700198 toEscapedString(std::ostream& os) const;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700199
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800200 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700201 * @brief Convert *this by escaping characters according to the NDN URI Scheme
202 *
203 * @deprecated Use toUri() instead
204 *
205 * This also adds "..." to a value with zero or more "."
206 *
207 * @return The escaped string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800208 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700209 std::string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800210 toEscapedString() const
211 {
212 std::ostringstream result;
213 toEscapedString(result);
214 return result.str();
215 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800216
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700217 /**
218 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
219 *
220 * This also adds "..." to a value with zero or more "."
221 *
222 * @param os The output stream to where write the URI escaped version *this
223 */
224 void
225 toUri(std::ostream& os) const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800226 {
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700227 return toEscapedString(os);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800228 }
229
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 {
240 return toEscapedString();
241 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700242
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800243 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700244 * @brief Interpret this name component as nonNegativeInteger
245 *
246 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
247 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800248 * @return The integer number.
249 */
250 uint64_t
251 toNumber() const;
252
253 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700254 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800255 */
256 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700257 toVersion() const;
258
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800259 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700260 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800261 */
262 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700263 toSegment() const;
264
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800265 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700266 * @brief Create a component encoded as nonNegativeInteger
267 *
268 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
269 *
270 * @param number The non-negative number
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800271 * @return The component value.
272 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700273 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800274 fromNumber(uint64_t number);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800275
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700276 bool
277 empty() const
278 {
279 return !hasValue();
280 }
281
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800282 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700283 * @brief Check if this is the same component as other
284 *
285 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800286 * @return true if the components are equal, otherwise false.
287 */
288 bool
289 equals(const Component& other) const
290 {
291 if (value_size() != other.value_size())
292 return false;
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800293 if (value_size() == 0 /* == other.value_size()*/)
294 return true;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800295
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800296 // somehow, behavior is wrong on OSX 10.9 when component is empty
297 // (probably some bug in STL...)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800298 return std::equal(value_begin(), value_end(), other.value_begin());
299 }
300
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800301 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700302 * @brief Compare this to the other Component using NDN canonical ordering
303 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800304 * @param other The other Component to compare with.
305 * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700306 * 1 if *this comes after other in the canonical ordering.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800307 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700308 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800309 */
310 int
311 compare(const Component& other) const;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800312
313 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700314 * @brief Check if this is the same component as other
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800315 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700316 * @param other The other Component to compare with.
317 * @return true if the components are equal, otherwise false.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800318 */
319 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700320 operator==(const Component& other) const
321 {
322 return equals(other);
323 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700324
325 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700326 * @brief Check if this is not the same component as other
327 * @param other The other Component to compare with
328 * @return true if the components are not equal, otherwise false
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700329 */
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 the *this is less than or equal to the other in NDN canonical ordering
338 * @param other The other Component to compare with
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700339 *
340 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
341 */
342 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700343 operator<=(const Component& other) const
344 {
345 return compare(other) <= 0;
346 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800347
348 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700349 * @brief Check if the *this is less than the other in NDN canonical ordering
350 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800351 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700352 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800353 */
354 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700355 operator<(const Component& other) const
356 {
357 return compare(other) < 0;
358 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800359
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700360 /**
361 * @brief Check if the *this is greater or equal than the other in NDN canonical ordering
362 * @param other The other Component to compare with
363 *
364 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
365 */
366 bool
367 operator>=(const Component& other) const
368 {
369 return compare(other) >= 0;
370 }
371
372 /**
373 * @brief Check if the *this is greater than the other in NDN canonical ordering
374 * @param other The other Component to compare with
375 *
376 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
377 */
378 bool
379 operator>(const Component& other) const
380 {
381 return compare(other) > 0;
382 }
383
384 // !!! NOTE TO IMPLEMENTOR !!!
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700385 //
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700386 // This class MUST NOT contain any data fields.
387 // Block can be reinterpret_cast'ed as Component type.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800388};
389
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700390inline std::ostream&
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700391operator<<(std::ostream& os, const Component& component)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800392{
393 component.toEscapedString(os);
394 return os;
395}
396
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700397inline
398Component::Component()
399 : Block(Tlv::NameComponent)
400{
401}
402
403inline
404Component::Component(const Block& wire)
405 : Block(wire)
406{
407 if (type() != Tlv::NameComponent)
408 throw Error("Constructing name component from non name component TLV wire block");
409}
410
411inline
412Component::Component(const ConstBufferPtr& buffer)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700413 : Block(Tlv::NameComponent, buffer)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700414{
415}
416
417inline
418Component::Component(const Buffer& value)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700419 : Block(dataBlock(Tlv::NameComponent, value.buf(), value.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700420{
421}
422
423inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700424Component::Component(const uint8_t* value, size_t valueLen)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700425 : Block(dataBlock(Tlv::NameComponent, value, valueLen))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700426{
427}
428
429template<class InputIterator>
430inline
431Component::Component(InputIterator begin, InputIterator end)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700432 : Block(dataBlock(Tlv::NameComponent, begin, end))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700433{
434}
435
436inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700437Component::Component(const char* str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700438 : Block(dataBlock(Tlv::NameComponent, str, ::strlen(str)))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700439{
440}
441
442inline
443Component::Component(const std::string& str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700444 : Block(dataBlock(Tlv::NameComponent, str.c_str(), str.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700445{
446}
447
448
449inline Component
450Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
451{
452 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
453 trim(trimmedString);
454 std::string value = unescape(trimmedString);
455
456 if (value.find_first_not_of(".") == std::string::npos) {
457 // Special case for component of only periods.
458 if (value.size() <= 2)
459 // Zero, one or two periods is illegal. Ignore this component.
460 return Component();
461 else
462 // Remove 3 periods.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700463 return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700464 }
465 else
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700466 return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700467}
468
469
470inline void
471Component::toEscapedString(std::ostream& result) const
472{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700473 const uint8_t* valuePtr = value();
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700474 size_t valueSize = value_size();
475
476 bool gotNonDot = false;
477 for (unsigned i = 0; i < valueSize; ++i) {
478 if (valuePtr[i] != 0x2e) {
479 gotNonDot = true;
480 break;
481 }
482 }
483 if (!gotNonDot) {
484 // Special case for component of zero or more periods. Add 3 periods.
485 result << "...";
486 for (size_t i = 0; i < valueSize; ++i)
487 result << '.';
488 }
489 else {
490 // In case we need to escape, set to upper case hex and save the previous flags.
491 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
492
493 for (size_t i = 0; i < valueSize; ++i) {
494 uint8_t x = valuePtr[i];
495 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
496 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
497 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
498 x == 0x2e || x == 0x5f)
499 result << x;
500 else {
501 result << '%';
502 if (x < 16)
503 result << '0';
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700504 result << static_cast<unsigned int>(x);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700505 }
506 }
507
508 // Restore.
509 result.flags(saveFlags);
510 }
511}
512
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700513
514inline Component
515Component::fromNumber(uint64_t number)
516{
517 /// \todo Change to Tlv::NumberComponent
518 return nonNegativeIntegerBlock(Tlv::NameComponent, number);
519}
520
521
522inline uint64_t
523Component::toNumber() const
524{
525 /// \todo Check if Component is of Tlv::NumberComponent type
526 return readNonNegativeInteger(static_cast<const Block&>(*this));
527}
528
529
530inline uint64_t
531Component::toVersion() const
532{
533 return toNumber();
534}
535
536inline uint64_t
537Component::toSegment() const
538{
539 return toNumber();
540}
541
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700542inline int
543Component::compare(const Component& other) const
544{
545 // Imitate ndn_Exclude_compareComponents.
546 if (value_size() < other.value_size())
547 return -1;
548 if (value_size() > other.value_size())
549 return 1;
550
551 if (value_size() == 0)
552 return 0;
553
554 // The components are equal length. Just do a byte compare.
555 return std::memcmp(value(), other.value(), value_size());
556}
557
558
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800559template<bool T>
560inline size_t
561Component::wireEncode(EncodingImpl<T>& block) const
562{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700563 size_t totalLength = 0;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800564 if (value_size() > 0)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700565 totalLength += block.prependByteArray(value(), value_size());
566 totalLength += block.prependVarNumber(value_size());
567 totalLength += block.prependVarNumber(Tlv::NameComponent);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700568 return totalLength;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800569}
570
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700571inline const Block&
572Component::wireEncode() const
573{
574 if (this->hasWire())
575 return *this;
576
577 EncodingEstimator estimator;
578 size_t estimatedSize = wireEncode(estimator);
579
580 EncodingBuffer buffer(estimatedSize, 0);
581 wireEncode(buffer);
582
583 const_cast<Component&>(*this) = buffer.block();
584 return *this;
585}
586
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700587inline void
588Component::wireDecode(const Block& wire)
589{
590 if (wire.type() != Tlv::NameComponent)
591 throw Error("wireDecode name component from non name component TLV wire block");
592
593 *this = wire;
594}
595
596
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800597} // namespace name
598} // namespace ndn
599
600#endif // NDN_NAME_COMPONENT_HPP