blob: 5e2a9b3172ad44f6b5667237ce40a19751eb4a26 [file] [log] [blame]
Alexander Afanasyev15f67312014-07-22 15:11:09 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento10b24be2017-07-12 23:23:46 -04002/*
Davide Pesavento923ba442019-02-12 22:00:38 -05003 * Copyright (c) 2013-2019 Regents of the University of California.
Alexander Afanasyev15f67312014-07-22 15:11:09 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * 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.
20 *
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/>
24 */
25
Davide Pesavento7e780642018-11-24 15:51:34 -050026#include "ndn-cxx/name-component.hpp"
Junxiao Shi24c5a002018-12-12 04:47:15 +000027#include "ndn-cxx/impl/name-component-types.hpp"
Alexander Afanasyev15f67312014-07-22 15:11:09 -070028
Junxiao Shid2e60632018-08-10 10:48:44 -060029#include <cstdlib>
Davide Pesaventoe245b052017-10-31 13:00:44 -040030#include <cstring>
Davide Pesaventoa84f4642017-08-23 16:14:51 -040031#include <sstream>
Alexander Afanasyev6486d522014-10-23 14:14:11 -070032
Alexander Afanasyev15f67312014-07-22 15:11:09 -070033namespace ndn {
34namespace name {
35
Junxiao Shic2b8d242014-11-04 08:35:29 -070036BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Component>));
37BOOST_CONCEPT_ASSERT((WireEncodable<Component>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070038BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Component>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070039BOOST_CONCEPT_ASSERT((WireDecodable<Component>));
40static_assert(std::is_base_of<tlv::Error, Component::Error>::value,
41 "name::Component::Error must inherit from tlv::Error");
42
Junxiao Shie2099612019-02-15 14:46:27 +000043static Convention g_conventionEncoding = Convention::MARKER;
44static Convention g_conventionDecoding = Convention::EITHER;
45
46Convention
47getConventionEncoding()
48{
49 return g_conventionEncoding;
50}
51
52void
53setConventionEncoding(Convention convention)
54{
55 switch (convention) {
56 case Convention::MARKER:
57 case Convention::TYPED:
58 g_conventionEncoding = convention;
59 break;
60 default:
61 NDN_THROW(std::invalid_argument("Unknown naming convention"));
62 break;
63 }
64}
65
66Convention
67getConventionDecoding()
68{
69 return g_conventionDecoding;
70}
71
72void
73setConventionDecoding(Convention convention)
74{
75 g_conventionDecoding = convention;
76}
77
78static bool
79canDecodeMarkerConvention()
80{
81 return (static_cast<int>(g_conventionDecoding) & static_cast<int>(Convention::MARKER)) != 0;
82}
83
84static bool
85canDecodeTypedConvention()
86{
87 return (static_cast<int>(g_conventionDecoding) & static_cast<int>(Convention::TYPED)) != 0;
88}
89
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000090void
91Component::ensureValid() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -070092{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000093 if (type() < tlv::NameComponentMin || type() > tlv::NameComponentMax) {
Davide Pesavento923ba442019-02-12 22:00:38 -050094 NDN_THROW(Error("TLV-TYPE " + to_string(type()) + " is not a valid NameComponent"));
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000095 }
Junxiao Shid2e60632018-08-10 10:48:44 -060096 detail::getComponentTypeTable().get(type()).check(*this);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000097}
98
99Component::Component(uint32_t type)
100 : Block(type)
101{
102 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700103}
104
105Component::Component(const Block& wire)
106 : Block(wire)
107{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000108 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700109}
110
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000111Component::Component(uint32_t type, ConstBufferPtr buffer)
112 : Block(type, std::move(buffer))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700113{
Junxiao Shid2e60632018-08-10 10:48:44 -0600114 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700115}
116
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000117Component::Component(uint32_t type, const uint8_t* value, size_t valueLen)
118 : Block(makeBinaryBlock(type, value, valueLen))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700119{
Junxiao Shid2e60632018-08-10 10:48:44 -0600120 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700121}
122
123Component::Component(const char* str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000124 : Block(makeBinaryBlock(tlv::GenericNameComponent, str, std::char_traits<char>::length(str)))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700125{
126}
127
128Component::Component(const std::string& str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000129 : Block(makeStringBlock(tlv::GenericNameComponent, str))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700130{
131}
132
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000133static Component
Junxiao Shid2e60632018-08-10 10:48:44 -0600134parseUriEscapedValue(uint32_t type, const char* input, size_t len)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000135{
Junxiao Shid2e60632018-08-10 10:48:44 -0600136 std::ostringstream oss;
137 unescape(oss, input, len);
138 std::string value = oss.str();
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000139 if (value.find_first_not_of('.') == std::string::npos) { // all periods
140 if (value.size() < 3) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500141 NDN_THROW(Component::Error("Illegal URI (name component cannot be . or ..)"));
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700142 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000143 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size() - 3);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700144 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000145 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700146}
147
Junxiao Shid2e60632018-08-10 10:48:44 -0600148Component
149Component::fromEscapedString(const std::string& input)
150{
151 size_t equalPos = input.find('=');
152 if (equalPos == std::string::npos) {
153 return parseUriEscapedValue(tlv::GenericNameComponent, input.data(), input.size());
154 }
155
156 long type = std::strtol(input.data(), nullptr, 10);
157 if (type >= tlv::NameComponentMin && type <= tlv::NameComponentMax &&
158 to_string(type).size() == equalPos) {
159 size_t valuePos = equalPos + 1;
160 return parseUriEscapedValue(static_cast<uint32_t>(type), input.data() + valuePos,
161 input.size() - valuePos);
162 }
163
164 auto typePrefix = input.substr(0, equalPos);
165 auto ct = detail::getComponentTypeTable().findByUriPrefix(typePrefix);
166 if (ct == nullptr) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500167 NDN_THROW(Error("Incorrect TLV-TYPE '" + typePrefix + "' in NameComponent URI"));
Junxiao Shid2e60632018-08-10 10:48:44 -0600168 }
169 return ct->parseAltUriValue(input.substr(equalPos + 1));
170}
171
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700172void
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000173Component::toUri(std::ostream& os) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700174{
Junxiao Shid2e60632018-08-10 10:48:44 -0600175 detail::getComponentTypeTable().get(type()).writeUri(os, *this);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700176}
177
178std::string
179Component::toUri() const
180{
181 std::ostringstream os;
182 toUri(os);
183 return os.str();
184}
185
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700186////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700187
188bool
189Component::isNumber() const
190{
191 return (value_size() == 1 || value_size() == 2 ||
192 value_size() == 4 || value_size() == 8);
193}
194
195bool
196Component::isNumberWithMarker(uint8_t marker) const
197{
198 return (!empty() && value()[0] == marker &&
199 (value_size() == 2 || value_size() == 3 ||
200 value_size() == 5 || value_size() == 9));
201}
202
203bool
204Component::isVersion() const
205{
Junxiao Shie2099612019-02-15 14:46:27 +0000206 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(VERSION_MARKER)) ||
207 (canDecodeTypedConvention() && type() == tlv::VersionNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700208}
209
210bool
211Component::isSegment() const
212{
Junxiao Shie2099612019-02-15 14:46:27 +0000213 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_MARKER)) ||
214 (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700215}
216
217bool
Junxiao Shie2099612019-02-15 14:46:27 +0000218Component::isByteOffset() const
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700219{
Junxiao Shie2099612019-02-15 14:46:27 +0000220 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_OFFSET_MARKER)) ||
221 (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700222}
223
224bool
225Component::isTimestamp() const
226{
Junxiao Shie2099612019-02-15 14:46:27 +0000227 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(TIMESTAMP_MARKER)) ||
228 (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700229}
230
231bool
232Component::isSequenceNumber() const
233{
Junxiao Shie2099612019-02-15 14:46:27 +0000234 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEQUENCE_NUMBER_MARKER)) ||
235 (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700236}
237
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700238////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700239
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700240uint64_t
241Component::toNumber() const
242{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700243 if (!isNumber())
Davide Pesavento923ba442019-02-12 22:00:38 -0500244 NDN_THROW(Error("Name component does not have nonNegativeInteger value"));
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700245
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700246 return readNonNegativeInteger(*this);
247}
248
249uint64_t
250Component::toNumberWithMarker(uint8_t marker) const
251{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700252 if (!isNumberWithMarker(marker))
Davide Pesavento923ba442019-02-12 22:00:38 -0500253 NDN_THROW(Error("Name component does not have the requested marker "
254 "or the value is not a nonNegativeInteger"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700255
256 Buffer::const_iterator valueBegin = value_begin() + 1;
257 return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
258}
259
260uint64_t
261Component::toVersion() const
262{
Junxiao Shie2099612019-02-15 14:46:27 +0000263 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
264 return toNumberWithMarker(VERSION_MARKER);
265 }
266 if (canDecodeTypedConvention() && type() == tlv::VersionNameComponent) {
267 return toNumber();
268 }
269 NDN_THROW(Error("Not a Version component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700270}
271
272uint64_t
273Component::toSegment() const
274{
Junxiao Shie2099612019-02-15 14:46:27 +0000275 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
276 return toNumberWithMarker(SEGMENT_MARKER);
277 }
278 if (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent) {
279 return toNumber();
280 }
281 NDN_THROW(Error("Not a Segment component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700282}
283
284uint64_t
Junxiao Shie2099612019-02-15 14:46:27 +0000285Component::toByteOffset() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700286{
Junxiao Shie2099612019-02-15 14:46:27 +0000287 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
288 return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
289 }
290 if (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent) {
291 return toNumber();
292 }
293 NDN_THROW(Error("Not a ByteOffset component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700294}
295
296time::system_clock::TimePoint
297Component::toTimestamp() const
298{
Junxiao Shie2099612019-02-15 14:46:27 +0000299 uint64_t value = 0;
300 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
301 value = toNumberWithMarker(TIMESTAMP_MARKER);
302 }
303 else if (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent) {
304 value = toNumber();
305 }
306 else {
307 NDN_THROW(Error("Not a Timestamp component"));
308 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700309 return time::getUnixEpoch() + time::microseconds(value);
310}
311
312uint64_t
313Component::toSequenceNumber() const
314{
Junxiao Shie2099612019-02-15 14:46:27 +0000315 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
316 return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
317 }
318 if (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent) {
319 return toNumber();
320 }
321 NDN_THROW(Error("Not a SequenceNumber component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700322}
323
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700324////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700325
326Component
Junxiao Shie2099612019-02-15 14:46:27 +0000327Component::fromNumber(uint64_t number, uint32_t type)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700328{
Junxiao Shie2099612019-02-15 14:46:27 +0000329 return makeNonNegativeIntegerBlock(type, number);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700330}
331
332Component
333Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
334{
335 EncodingEstimator estimator;
336
337 size_t valueLength = estimator.prependNonNegativeInteger(number);
338 valueLength += estimator.prependByteArray(&marker, 1);
339 size_t totalLength = valueLength;
340 totalLength += estimator.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000341 totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700342
343 EncodingBuffer encoder(totalLength, 0);
344 encoder.prependNonNegativeInteger(number);
345 encoder.prependByteArray(&marker, 1);
346 encoder.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000347 encoder.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700348
349 return encoder.block();
350}
351
352Component
353Component::fromVersion(uint64_t version)
354{
Junxiao Shie2099612019-02-15 14:46:27 +0000355 return g_conventionEncoding == Convention::MARKER ?
356 fromNumberWithMarker(VERSION_MARKER, version) :
357 fromNumber(version, tlv::VersionNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700358}
359
360Component
361Component::fromSegment(uint64_t segmentNo)
362{
Junxiao Shie2099612019-02-15 14:46:27 +0000363 return g_conventionEncoding == Convention::MARKER ?
364 fromNumberWithMarker(SEGMENT_MARKER, segmentNo) :
365 fromNumber(segmentNo, tlv::SegmentNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700366}
367
368Component
Junxiao Shie2099612019-02-15 14:46:27 +0000369Component::fromByteOffset(uint64_t offset)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700370{
Junxiao Shie2099612019-02-15 14:46:27 +0000371 return g_conventionEncoding == Convention::MARKER ?
372 fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset) :
373 fromNumber(offset, tlv::ByteOffsetNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700374}
375
376Component
377Component::fromTimestamp(const time::system_clock::TimePoint& timePoint)
378{
Junxiao Shie2099612019-02-15 14:46:27 +0000379 uint64_t value = time::duration_cast<time::microseconds>(timePoint - time::getUnixEpoch()).count();
380 return g_conventionEncoding == Convention::MARKER ?
381 fromNumberWithMarker(TIMESTAMP_MARKER, value) :
382 fromNumber(value, tlv::TimestampNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700383}
384
385Component
386Component::fromSequenceNumber(uint64_t seqNo)
387{
Junxiao Shie2099612019-02-15 14:46:27 +0000388 return g_conventionEncoding == Convention::MARKER ?
389 fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo) :
390 fromNumber(seqNo, tlv::SequenceNumNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700391}
392
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700393////////////////////////////////////////////////////////////////////////////////
394
395bool
396Component::isGeneric() const
397{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000398 return type() == tlv::GenericNameComponent;
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700399}
400
401bool
402Component::isImplicitSha256Digest() const
403{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600404 return detail::getComponentType1().match(*this);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700405}
406
407Component
Davide Pesavento3b101d02018-07-21 22:44:09 -0400408Component::fromImplicitSha256Digest(ConstBufferPtr digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700409{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600410 return detail::getComponentType1().create(digest);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700411}
412
413Component
414Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
415{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600416 return detail::getComponentType1().create(digest, digestSize);
417}
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700418
Junxiao Shi4053bd52018-08-16 13:39:25 -0600419bool
420Component::isParametersSha256Digest() const
421{
422 return detail::getComponentType2().match(*this);
423}
424
425Component
426Component::fromParametersSha256Digest(ConstBufferPtr digest)
427{
428 return detail::getComponentType2().create(digest);
429}
430
431Component
432Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
433{
434 return detail::getComponentType2().create(digest, digestSize);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700435}
436
437////////////////////////////////////////////////////////////////////////////////
438
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000439bool
440Component::equals(const Component& other) const
441{
442 return type() == other.type() &&
443 value_size() == other.value_size() &&
Davide Pesaventoe245b052017-10-31 13:00:44 -0400444 (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000445 std::equal(value_begin(), value_end(), other.value_begin()));
446}
447
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700448int
449Component::compare(const Component& other) const
450{
Junxiao Shi010f0862016-10-11 21:08:32 +0000451 if (this->hasWire() && other.hasWire()) {
452 // In the common case where both components have wire encoding,
453 // it's more efficient to simply compare the wire encoding.
454 // This works because lexical order of TLV encoding happens to be
455 // the same as canonical order of the value.
456 return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
457 }
458
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000459 int cmpType = type() - other.type();
460 if (cmpType != 0)
461 return cmpType;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700462
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000463 int cmpSize = value_size() - other.value_size();
464 if (cmpSize != 0)
465 return cmpSize;
466
Davide Pesaventoe245b052017-10-31 13:00:44 -0400467 if (empty())
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700468 return 0;
469
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700470 return std::memcmp(value(), other.value(), value_size());
471}
472
473Component
474Component::getSuccessor() const
475{
Junxiao Shid2e60632018-08-10 10:48:44 -0600476 bool isOverflow = false;
477 Component successor;
478 std::tie(isOverflow, successor) =
479 detail::getComponentTypeTable().get(type()).getSuccessor(*this);
480 if (!isOverflow) {
481 return successor;
Junxiao Shicf0aff82018-07-23 06:42:13 -0600482 }
483
Junxiao Shid2e60632018-08-10 10:48:44 -0600484 uint32_t type = this->type() + 1;
485 const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
486 return Component(type, value.data(), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700487}
488
Alexander Afanasyev74633892015-02-08 18:08:46 -0800489template<encoding::Tag TAG>
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700490size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700491Component::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700492{
493 size_t totalLength = 0;
494 if (value_size() > 0)
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700495 totalLength += encoder.prependByteArray(value(), value_size());
496 totalLength += encoder.prependVarNumber(value_size());
497 totalLength += encoder.prependVarNumber(type());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700498 return totalLength;
499}
500
Davide Pesavento88a0d812017-08-19 21:31:42 -0400501NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700502
503const Block&
504Component::wireEncode() const
505{
506 if (this->hasWire())
507 return *this;
508
509 EncodingEstimator estimator;
510 size_t estimatedSize = wireEncode(estimator);
511
512 EncodingBuffer buffer(estimatedSize, 0);
513 wireEncode(buffer);
514
515 const_cast<Component&>(*this) = buffer.block();
516 return *this;
517}
518
519void
520Component::wireDecode(const Block& wire)
521{
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700522 *this = wire;
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800523 // validity check is done within Component(const Block& wire)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700524}
525
526} // namespace name
527} // namespace ndn