blob: b83dd4025db5988a581a6cf0e97a6c1f8db2ddbf [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"
22#include "encoding/encoding-buffer.hpp"
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070023#include "util/string-helper.hpp"
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080024
25namespace ndn {
26namespace name {
27
28/**
Alexander Afanasyev3aeeaeb2014-04-22 23:34:23 -070029 * @brief Component holds a read-only name component value.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080030 */
31class Component : public Block
32{
33public:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070034 /**
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070035 * @brief Error that can be thrown from name::Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070036 */
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070037 class Error : public Block::Error
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070038 {
39 public:
40 explicit
41 Error(const std::string& what)
Alexander Afanasyev2a7f7202014-04-23 14:25:29 -070042 : Block::Error(what)
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043 {
44 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070045 };
46
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080047 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070048 * Create a new name::Component with an empty value
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080049 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070050 Component();
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080051
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080052 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070053 * @brief Create name::Component from a wire block
54 *
55 * @param wire Tlv::NameComponent Block from which to create name::Component
56 * @throws Error if wire.type() is not Tlv::NameComponent
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080057 *
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070058 * Any block can be implicitly converted to name::Component
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -080059 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070060 Component(const Block& wire);
61
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080062 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070063 * @brief Create a new name::Component from the buffer pointer (buffer pointer will be copied)
64 *
65 * @param buffer A pointer to an immutable buffer
66 *
67 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
68 * Note that this method **will not** allocate new memory for and copy the payload until
69 * toWire() method is called.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080070 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070071 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070072 Component(const ConstBufferPtr& buffer);
73
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080074 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -070075 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
76 * @param buffer A reference to the buffer
77 *
78 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
79 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080080 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070081 explicit
Alexander Afanasyev770827c2014-05-13 17:42:55 -070082 Component(const Buffer& buffer);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080083
84 /**
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 pointer to the first byte of the buffer
87 * @param bufferSize Size of the buffer
88 *
89 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
90 * Note that this method **will** allocate new memory for and copy the payload.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080091 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -070092 Component(const uint8_t* buffer, size_t bufferSize);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -080093
Alexander Afanasyev770827c2014-05-13 17:42:55 -070094 /**
95 * @brief Create a new name::Component from the buffer (data from buffer will be copied)
96 * @param begin Iterator pointing to the beginning of the buffer
97 * @param end Iterator pointing to the ending 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.
101 */
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800102 template<class InputIterator>
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700103 Component(InputIterator begin, InputIterator end);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800104
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700105 /**
106 * @brief Create a new name::Component from the C string (data from string will be copied)
107 *
108 * @param str Zero-ended string. Note that this string will be interpreted as is (i.e.,
109 * it will not be interpreted as URI)
110 *
111 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
112 * Note that this method **will** allocate new memory for and copy the payload.
113 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800114 explicit
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700115 Component(const char* str);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800116
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700117 /**
118 * @brief Create a new name::Component from the STL string (data from string will be copied)
119 *
120 * @param str Const reference to STL string. Note that this string will be interpreted
121 * as is (i.e., it will not be interpreted as URI)
122 *
123 * This constructor will create a new Tlv::NameComponent Block with `buffer` as a payload.
124 * Note that this method **will** allocate new memory for and copy the payload.
125 */
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800126 explicit
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700127 Component(const std::string& str);
128
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800129 /**
130 * @brief Fast encoding or block size estimation
131 */
132 template<bool T>
133 size_t
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700134 wireEncode(EncodingImpl<T>& block) const;
135
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800136 /**
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137 * @brief Encode to a wire format
138 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700139 const Block&
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700140 wireEncode() const;
141
142 /**
143 * @brief Decode from the wire format
144 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700145 void
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146 wireDecode(const Block& wire);
147
148 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700149 * @brief Create name::Component by decoding the escapedString between beginOffset and
150 * endOffset according to the NDN URI Scheme.
151 *
152 * If the escaped string is "", "." or ".." then return an empty name::Component. Note
153 * that an empty name::Component should not be added to Name and if attempted, an
154 * exception will be thrown.
155 *
156 * @param escapedString String containing NDN URI-encoded name
157 * component. [escapedString+beginOffset, beginOffset+endOffset)
158 * must be a valid memory buffer.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800159 * @param beginOffset The offset in escapedString of the beginning of the portion to decode.
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700160 * @param endOffset The offset in escapedString of the end of the portion to decode.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800161 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700162 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700163 fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800164
165 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700166 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
167 *
168 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800169 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700170 static Component
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700171 fromEscapedString(const char* escapedString)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800172 {
173 return fromEscapedString(escapedString, 0, ::strlen(escapedString));
174 }
175
176 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700177 * @brief Create name::Component by decoding the escapedString according to the NDN URI Scheme
178 *
179 * This overload is a convenience wrapper for fromEscapedString(char*,size_t,size)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800180 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700181 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800182 fromEscapedString(const std::string& escapedString)
183 {
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700184 return fromEscapedString(escapedString.c_str(), 0, escapedString.size());
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800185 }
186
187 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700188 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
189 *
190 * @deprecated Use toUri(std::ostream&) instead
191 *
192 * This also adds "..." to a value with zero or more "."
193 *
194 * @param os The output stream to where write the URI escaped version *this
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800195 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700196 void
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700197 toEscapedString(std::ostream& os) const;
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700198
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800199 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700200 * @brief Convert *this by escaping characters according to the NDN URI Scheme
201 *
202 * @deprecated Use toUri() instead
203 *
204 * This also adds "..." to a value with zero or more "."
205 *
206 * @return The escaped string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800207 */
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700208 std::string
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800209 toEscapedString() const
210 {
211 std::ostringstream result;
212 toEscapedString(result);
213 return result.str();
214 }
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800215
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700216 /**
217 * @brief Write *this to the output stream, escaping characters according to the NDN URI Scheme
218 *
219 * This also adds "..." to a value with zero or more "."
220 *
221 * @param os The output stream to where write the URI escaped version *this
222 */
223 void
224 toUri(std::ostream& os) const
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800225 {
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700226 return toEscapedString(os);
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800227 }
228
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700229 /**
230 * @brief Convert *this by escaping characters according to the NDN URI Scheme
231 *
232 * This also adds "..." to a value with zero or more "."
233 *
234 * @return The escaped string
235 */
236 std::string
Alexander Afanasyev52eb20d2014-02-06 18:25:54 -0800237 toUri() const
238 {
239 return toEscapedString();
240 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700241
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800242 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700243 * @brief Interpret this name component as nonNegativeInteger
244 *
245 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
246 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800247 * @return The integer number.
248 */
249 uint64_t
250 toNumber() const;
251
252 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700253 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800254 */
255 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700256 toVersion() const;
257
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800258 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700259 * @brief An alias for toNumber()
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800260 */
261 uint64_t
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700262 toSegment() const;
263
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800264 /**
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700265 * @brief Create a component encoded as nonNegativeInteger
266 *
267 * @see http://named-data.net/doc/ndn-tlv/tlv.html#non-negative-integer-encoding
268 *
269 * @param number The non-negative number
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800270 * @return The component value.
271 */
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700272 static Component
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800273 fromNumber(uint64_t number);
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800274
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700275 bool
276 empty() const
277 {
278 return !hasValue();
279 }
280
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800281 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700282 * @brief Check if this is the same component as other
283 *
284 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800285 * @return true if the components are equal, otherwise false.
286 */
287 bool
288 equals(const Component& other) const
289 {
290 if (value_size() != other.value_size())
291 return false;
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800292 if (value_size() == 0 /* == other.value_size()*/)
293 return true;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800294
Alexander Afanasyev60c86812014-02-20 15:19:33 -0800295 // somehow, behavior is wrong on OSX 10.9 when component is empty
296 // (probably some bug in STL...)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800297 return std::equal(value_begin(), value_end(), other.value_begin());
298 }
299
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800300 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700301 * @brief Compare this to the other Component using NDN canonical ordering
302 *
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800303 * @param other The other Component to compare with.
304 * @return 0 If they compare equal, -1 if *this comes before other in the canonical ordering, or
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700305 * 1 if *this comes after other in the canonical ordering.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800306 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700307 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800308 */
309 int
310 compare(const Component& other) const;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800311
312 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700313 * @brief Check if this is the same component as other
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800314 *
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700315 * @param other The other Component to compare with.
316 * @return true if the components are equal, otherwise false.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800317 */
318 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700319 operator==(const Component& other) const
320 {
321 return equals(other);
322 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700323
324 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700325 * @brief Check if this is not the same component as other
326 * @param other The other Component to compare with
327 * @return true if the components are not equal, otherwise false
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700328 */
329 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700330 operator!=(const Component& other) const
331 {
332 return !equals(other);
333 }
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700334
335 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700336 * @brief Check if the *this is less than or equal to the other in NDN canonical ordering
337 * @param other The other Component to compare with
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700338 *
339 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
340 */
341 bool
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700342 operator<=(const Component& other) const
343 {
344 return compare(other) <= 0;
345 }
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800346
347 /**
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700348 * @brief Check if the *this is less than the other in NDN canonical ordering
349 * @param other The other Component to compare with
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800350 *
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700351 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800352 */
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
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700359 /**
360 * @brief Check if the *this is greater or equal than the other in NDN canonical ordering
361 * @param other The other Component to compare with
362 *
363 * @see http://named-data.net/doc/ndn-tlv/name.html#canonical-order
364 */
365 bool
366 operator>=(const Component& other) const
367 {
368 return compare(other) >= 0;
369 }
370
371 /**
372 * @brief Check if the *this is greater 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 // !!! NOTE TO IMPLEMENTOR !!!
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700384 //
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700385 // This class MUST NOT contain any data fields.
386 // Block can be reinterpret_cast'ed as Component type.
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800387};
388
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700389inline std::ostream&
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700390operator<<(std::ostream& os, const Component& component)
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800391{
392 component.toEscapedString(os);
393 return os;
394}
395
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700396inline
397Component::Component()
398 : Block(Tlv::NameComponent)
399{
400}
401
402inline
403Component::Component(const Block& wire)
404 : Block(wire)
405{
406 if (type() != Tlv::NameComponent)
407 throw Error("Constructing name component from non name component TLV wire block");
408}
409
410inline
411Component::Component(const ConstBufferPtr& buffer)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700412 : Block(Tlv::NameComponent, buffer)
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700413{
414}
415
416inline
417Component::Component(const Buffer& value)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700418 : Block(dataBlock(Tlv::NameComponent, value.buf(), value.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700419{
420}
421
422inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700423Component::Component(const uint8_t* value, size_t valueLen)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700424 : Block(dataBlock(Tlv::NameComponent, value, valueLen))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700425{
426}
427
428template<class InputIterator>
429inline
430Component::Component(InputIterator begin, InputIterator end)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700431 : Block(dataBlock(Tlv::NameComponent, begin, end))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700432{
433}
434
435inline
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700436Component::Component(const char* str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700437 : Block(dataBlock(Tlv::NameComponent, str, ::strlen(str)))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700438{
439}
440
441inline
442Component::Component(const std::string& str)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700443 : Block(dataBlock(Tlv::NameComponent, str.c_str(), str.size()))
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700444{
445}
446
447
448inline Component
449Component::fromEscapedString(const char* escapedString, size_t beginOffset, size_t endOffset)
450{
451 std::string trimmedString(escapedString + beginOffset, escapedString + endOffset);
452 trim(trimmedString);
453 std::string value = unescape(trimmedString);
454
455 if (value.find_first_not_of(".") == std::string::npos) {
456 // Special case for component of only periods.
457 if (value.size() <= 2)
458 // Zero, one or two periods is illegal. Ignore this component.
459 return Component();
460 else
461 // Remove 3 periods.
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700462 return Component(reinterpret_cast<const uint8_t*>(&value[3]), value.size() - 3);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700463 }
464 else
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700465 return Component(reinterpret_cast<const uint8_t*>(&value[0]), value.size());
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700466}
467
468
469inline void
470Component::toEscapedString(std::ostream& result) const
471{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700472 const uint8_t* valuePtr = value();
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700473 size_t valueSize = value_size();
474
475 bool gotNonDot = false;
476 for (unsigned i = 0; i < valueSize; ++i) {
477 if (valuePtr[i] != 0x2e) {
478 gotNonDot = true;
479 break;
480 }
481 }
482 if (!gotNonDot) {
483 // Special case for component of zero or more periods. Add 3 periods.
484 result << "...";
485 for (size_t i = 0; i < valueSize; ++i)
486 result << '.';
487 }
488 else {
489 // In case we need to escape, set to upper case hex and save the previous flags.
490 std::ios::fmtflags saveFlags = result.flags(std::ios::hex | std::ios::uppercase);
491
492 for (size_t i = 0; i < valueSize; ++i) {
493 uint8_t x = valuePtr[i];
494 // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
495 if ((x >= 0x30 && x <= 0x39) || (x >= 0x41 && x <= 0x5a) ||
496 (x >= 0x61 && x <= 0x7a) || x == 0x2b || x == 0x2d ||
497 x == 0x2e || x == 0x5f)
498 result << x;
499 else {
500 result << '%';
501 if (x < 16)
502 result << '0';
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700503 result << static_cast<unsigned int>(x);
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700504 }
505 }
506
507 // Restore.
508 result.flags(saveFlags);
509 }
510}
511
Alexander Afanasyev4b98e8c2014-03-22 19:10:19 -0700512
513inline Component
514Component::fromNumber(uint64_t number)
515{
516 /// \todo Change to Tlv::NumberComponent
517 return nonNegativeIntegerBlock(Tlv::NameComponent, number);
518}
519
520
521inline uint64_t
522Component::toNumber() const
523{
524 /// \todo Check if Component is of Tlv::NumberComponent type
525 return readNonNegativeInteger(static_cast<const Block&>(*this));
526}
527
528
529inline uint64_t
530Component::toVersion() const
531{
532 return toNumber();
533}
534
535inline uint64_t
536Component::toSegment() const
537{
538 return toNumber();
539}
540
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700541inline int
542Component::compare(const Component& other) const
543{
544 // Imitate ndn_Exclude_compareComponents.
545 if (value_size() < other.value_size())
546 return -1;
547 if (value_size() > other.value_size())
548 return 1;
549
550 if (value_size() == 0)
551 return 0;
552
553 // The components are equal length. Just do a byte compare.
554 return std::memcmp(value(), other.value(), value_size());
555}
556
557
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800558template<bool T>
559inline size_t
560Component::wireEncode(EncodingImpl<T>& block) const
561{
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700562 size_t totalLength = 0;
Alexander Afanasyev380420b2014-02-09 20:52:29 -0800563 if (value_size() > 0)
Alexander Afanasyev770827c2014-05-13 17:42:55 -0700564 totalLength += block.prependByteArray(value(), value_size());
565 totalLength += block.prependVarNumber(value_size());
566 totalLength += block.prependVarNumber(Tlv::NameComponent);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700567 return totalLength;
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800568}
569
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700570inline const Block&
571Component::wireEncode() const
572{
573 if (this->hasWire())
574 return *this;
575
576 EncodingEstimator estimator;
577 size_t estimatedSize = wireEncode(estimator);
578
579 EncodingBuffer buffer(estimatedSize, 0);
580 wireEncode(buffer);
581
582 const_cast<Component&>(*this) = buffer.block();
583 return *this;
584}
585
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700586inline void
587Component::wireDecode(const Block& wire)
588{
589 if (wire.type() != Tlv::NameComponent)
590 throw Error("wireDecode name component from non name component TLV wire block");
591
592 *this = wire;
593}
594
595
Alexander Afanasyev95e8c2f2014-02-06 17:29:30 -0800596} // namespace name
597} // namespace ndn
598
599#endif // NDN_NAME_COMPONENT_HPP