blob: b7b93331db67265fe4198fd4f43d86e29467da23 [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"));
Junxiao Shie2099612019-02-15 14:46:27 +000062 }
63}
64
65Convention
66getConventionDecoding()
67{
68 return g_conventionDecoding;
69}
70
71void
72setConventionDecoding(Convention convention)
73{
74 g_conventionDecoding = convention;
75}
76
77static bool
78canDecodeMarkerConvention()
79{
Davide Pesavento869b11e2019-08-18 17:44:27 -040080 return (to_underlying(g_conventionDecoding) & to_underlying(Convention::MARKER)) != 0;
Junxiao Shie2099612019-02-15 14:46:27 +000081}
82
83static bool
84canDecodeTypedConvention()
85{
Davide Pesavento869b11e2019-08-18 17:44:27 -040086 return (to_underlying(g_conventionDecoding) & to_underlying(Convention::TYPED)) != 0;
Junxiao Shie2099612019-02-15 14:46:27 +000087}
88
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000089void
90Component::ensureValid() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -070091{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000092 if (type() < tlv::NameComponentMin || type() > tlv::NameComponentMax) {
Davide Pesavento923ba442019-02-12 22:00:38 -050093 NDN_THROW(Error("TLV-TYPE " + to_string(type()) + " is not a valid NameComponent"));
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000094 }
Junxiao Shid2e60632018-08-10 10:48:44 -060095 detail::getComponentTypeTable().get(type()).check(*this);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +000096}
97
98Component::Component(uint32_t type)
99 : Block(type)
100{
101 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700102}
103
104Component::Component(const Block& wire)
105 : Block(wire)
106{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000107 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700108}
109
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000110Component::Component(uint32_t type, ConstBufferPtr buffer)
111 : Block(type, std::move(buffer))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700112{
Junxiao Shid2e60632018-08-10 10:48:44 -0600113 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700114}
115
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000116Component::Component(uint32_t type, const uint8_t* value, size_t valueLen)
117 : Block(makeBinaryBlock(type, value, valueLen))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700118{
Junxiao Shid2e60632018-08-10 10:48:44 -0600119 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700120}
121
122Component::Component(const char* str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000123 : Block(makeBinaryBlock(tlv::GenericNameComponent, str, std::char_traits<char>::length(str)))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700124{
125}
126
127Component::Component(const std::string& str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000128 : Block(makeStringBlock(tlv::GenericNameComponent, str))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700129{
130}
131
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000132static Component
Junxiao Shid2e60632018-08-10 10:48:44 -0600133parseUriEscapedValue(uint32_t type, const char* input, size_t len)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000134{
Junxiao Shid2e60632018-08-10 10:48:44 -0600135 std::ostringstream oss;
136 unescape(oss, input, len);
137 std::string value = oss.str();
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000138 if (value.find_first_not_of('.') == std::string::npos) { // all periods
139 if (value.size() < 3) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500140 NDN_THROW(Component::Error("Illegal URI (name component cannot be . or ..)"));
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700141 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000142 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size() - 3);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700143 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000144 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700145}
146
Junxiao Shid2e60632018-08-10 10:48:44 -0600147Component
148Component::fromEscapedString(const std::string& input)
149{
150 size_t equalPos = input.find('=');
151 if (equalPos == std::string::npos) {
152 return parseUriEscapedValue(tlv::GenericNameComponent, input.data(), input.size());
153 }
154
Davide Pesavento6b330402019-04-24 00:14:01 -0400155 auto typePrefix = input.substr(0, equalPos);
156 auto type = std::strtoul(typePrefix.data(), nullptr, 10);
Junxiao Shid2e60632018-08-10 10:48:44 -0600157 if (type >= tlv::NameComponentMin && type <= tlv::NameComponentMax &&
Davide Pesavento6b330402019-04-24 00:14:01 -0400158 to_string(type) == typePrefix) {
Junxiao Shid2e60632018-08-10 10:48:44 -0600159 size_t valuePos = equalPos + 1;
Davide Pesavento6b330402019-04-24 00:14:01 -0400160 return parseUriEscapedValue(static_cast<uint32_t>(type),
161 input.data() + valuePos, input.size() - valuePos);
Junxiao Shid2e60632018-08-10 10:48:44 -0600162 }
163
Junxiao Shid2e60632018-08-10 10:48:44 -0600164 auto ct = detail::getComponentTypeTable().findByUriPrefix(typePrefix);
165 if (ct == nullptr) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500166 NDN_THROW(Error("Incorrect TLV-TYPE '" + typePrefix + "' in NameComponent URI"));
Junxiao Shid2e60632018-08-10 10:48:44 -0600167 }
168 return ct->parseAltUriValue(input.substr(equalPos + 1));
169}
170
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700171void
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000172Component::toUri(std::ostream& os) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700173{
Junxiao Shid2e60632018-08-10 10:48:44 -0600174 detail::getComponentTypeTable().get(type()).writeUri(os, *this);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700175}
176
177std::string
178Component::toUri() const
179{
180 std::ostringstream os;
181 toUri(os);
182 return os.str();
183}
184
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700185////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700186
187bool
188Component::isNumber() const
189{
190 return (value_size() == 1 || value_size() == 2 ||
191 value_size() == 4 || value_size() == 8);
192}
193
194bool
195Component::isNumberWithMarker(uint8_t marker) const
196{
197 return (!empty() && value()[0] == marker &&
198 (value_size() == 2 || value_size() == 3 ||
199 value_size() == 5 || value_size() == 9));
200}
201
202bool
203Component::isVersion() const
204{
Junxiao Shie2099612019-02-15 14:46:27 +0000205 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(VERSION_MARKER)) ||
206 (canDecodeTypedConvention() && type() == tlv::VersionNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700207}
208
209bool
210Component::isSegment() const
211{
Junxiao Shie2099612019-02-15 14:46:27 +0000212 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_MARKER)) ||
213 (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700214}
215
216bool
Junxiao Shie2099612019-02-15 14:46:27 +0000217Component::isByteOffset() const
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700218{
Junxiao Shie2099612019-02-15 14:46:27 +0000219 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_OFFSET_MARKER)) ||
220 (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700221}
222
223bool
224Component::isTimestamp() const
225{
Junxiao Shie2099612019-02-15 14:46:27 +0000226 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(TIMESTAMP_MARKER)) ||
227 (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700228}
229
230bool
231Component::isSequenceNumber() const
232{
Junxiao Shie2099612019-02-15 14:46:27 +0000233 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEQUENCE_NUMBER_MARKER)) ||
234 (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700235}
236
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700237////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700238
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700239uint64_t
240Component::toNumber() const
241{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700242 if (!isNumber())
Davide Pesavento923ba442019-02-12 22:00:38 -0500243 NDN_THROW(Error("Name component does not have nonNegativeInteger value"));
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700244
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700245 return readNonNegativeInteger(*this);
246}
247
248uint64_t
249Component::toNumberWithMarker(uint8_t marker) const
250{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700251 if (!isNumberWithMarker(marker))
Davide Pesavento923ba442019-02-12 22:00:38 -0500252 NDN_THROW(Error("Name component does not have the requested marker "
253 "or the value is not a nonNegativeInteger"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700254
255 Buffer::const_iterator valueBegin = value_begin() + 1;
256 return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
257}
258
259uint64_t
260Component::toVersion() const
261{
Junxiao Shie2099612019-02-15 14:46:27 +0000262 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
263 return toNumberWithMarker(VERSION_MARKER);
264 }
265 if (canDecodeTypedConvention() && type() == tlv::VersionNameComponent) {
266 return toNumber();
267 }
268 NDN_THROW(Error("Not a Version component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700269}
270
271uint64_t
272Component::toSegment() const
273{
Junxiao Shie2099612019-02-15 14:46:27 +0000274 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
275 return toNumberWithMarker(SEGMENT_MARKER);
276 }
277 if (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent) {
278 return toNumber();
279 }
280 NDN_THROW(Error("Not a Segment component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700281}
282
283uint64_t
Junxiao Shie2099612019-02-15 14:46:27 +0000284Component::toByteOffset() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700285{
Junxiao Shie2099612019-02-15 14:46:27 +0000286 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
287 return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
288 }
289 if (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent) {
290 return toNumber();
291 }
292 NDN_THROW(Error("Not a ByteOffset component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700293}
294
295time::system_clock::TimePoint
296Component::toTimestamp() const
297{
Junxiao Shie2099612019-02-15 14:46:27 +0000298 uint64_t value = 0;
299 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
300 value = toNumberWithMarker(TIMESTAMP_MARKER);
301 }
302 else if (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent) {
303 value = toNumber();
304 }
305 else {
306 NDN_THROW(Error("Not a Timestamp component"));
307 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700308 return time::getUnixEpoch() + time::microseconds(value);
309}
310
311uint64_t
312Component::toSequenceNumber() const
313{
Junxiao Shie2099612019-02-15 14:46:27 +0000314 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
315 return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
316 }
317 if (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent) {
318 return toNumber();
319 }
320 NDN_THROW(Error("Not a SequenceNumber component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700321}
322
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700323////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700324
325Component
Junxiao Shie2099612019-02-15 14:46:27 +0000326Component::fromNumber(uint64_t number, uint32_t type)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700327{
Junxiao Shie2099612019-02-15 14:46:27 +0000328 return makeNonNegativeIntegerBlock(type, number);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700329}
330
331Component
332Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
333{
334 EncodingEstimator estimator;
335
336 size_t valueLength = estimator.prependNonNegativeInteger(number);
337 valueLength += estimator.prependByteArray(&marker, 1);
338 size_t totalLength = valueLength;
339 totalLength += estimator.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000340 totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700341
342 EncodingBuffer encoder(totalLength, 0);
343 encoder.prependNonNegativeInteger(number);
344 encoder.prependByteArray(&marker, 1);
345 encoder.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000346 encoder.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700347
348 return encoder.block();
349}
350
351Component
352Component::fromVersion(uint64_t version)
353{
Junxiao Shie2099612019-02-15 14:46:27 +0000354 return g_conventionEncoding == Convention::MARKER ?
355 fromNumberWithMarker(VERSION_MARKER, version) :
356 fromNumber(version, tlv::VersionNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700357}
358
359Component
360Component::fromSegment(uint64_t segmentNo)
361{
Junxiao Shie2099612019-02-15 14:46:27 +0000362 return g_conventionEncoding == Convention::MARKER ?
363 fromNumberWithMarker(SEGMENT_MARKER, segmentNo) :
364 fromNumber(segmentNo, tlv::SegmentNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700365}
366
367Component
Junxiao Shie2099612019-02-15 14:46:27 +0000368Component::fromByteOffset(uint64_t offset)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700369{
Junxiao Shie2099612019-02-15 14:46:27 +0000370 return g_conventionEncoding == Convention::MARKER ?
371 fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset) :
372 fromNumber(offset, tlv::ByteOffsetNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700373}
374
375Component
376Component::fromTimestamp(const time::system_clock::TimePoint& timePoint)
377{
Junxiao Shie2099612019-02-15 14:46:27 +0000378 uint64_t value = time::duration_cast<time::microseconds>(timePoint - time::getUnixEpoch()).count();
379 return g_conventionEncoding == Convention::MARKER ?
380 fromNumberWithMarker(TIMESTAMP_MARKER, value) :
381 fromNumber(value, tlv::TimestampNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700382}
383
384Component
385Component::fromSequenceNumber(uint64_t seqNo)
386{
Junxiao Shie2099612019-02-15 14:46:27 +0000387 return g_conventionEncoding == Convention::MARKER ?
388 fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo) :
389 fromNumber(seqNo, tlv::SequenceNumNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700390}
391
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700392////////////////////////////////////////////////////////////////////////////////
393
394bool
395Component::isGeneric() const
396{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000397 return type() == tlv::GenericNameComponent;
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700398}
399
400bool
401Component::isImplicitSha256Digest() const
402{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600403 return detail::getComponentType1().match(*this);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700404}
405
406Component
Davide Pesavento3b101d02018-07-21 22:44:09 -0400407Component::fromImplicitSha256Digest(ConstBufferPtr digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700408{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600409 return detail::getComponentType1().create(digest);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700410}
411
412Component
413Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
414{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600415 return detail::getComponentType1().create(digest, digestSize);
416}
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700417
Junxiao Shi4053bd52018-08-16 13:39:25 -0600418bool
419Component::isParametersSha256Digest() const
420{
421 return detail::getComponentType2().match(*this);
422}
423
424Component
425Component::fromParametersSha256Digest(ConstBufferPtr digest)
426{
427 return detail::getComponentType2().create(digest);
428}
429
430Component
431Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
432{
433 return detail::getComponentType2().create(digest, digestSize);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700434}
435
436////////////////////////////////////////////////////////////////////////////////
437
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000438bool
439Component::equals(const Component& other) const
440{
441 return type() == other.type() &&
442 value_size() == other.value_size() &&
Davide Pesaventoe245b052017-10-31 13:00:44 -0400443 (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000444 std::equal(value_begin(), value_end(), other.value_begin()));
445}
446
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700447int
448Component::compare(const Component& other) const
449{
Junxiao Shi010f0862016-10-11 21:08:32 +0000450 if (this->hasWire() && other.hasWire()) {
451 // In the common case where both components have wire encoding,
452 // it's more efficient to simply compare the wire encoding.
453 // This works because lexical order of TLV encoding happens to be
454 // the same as canonical order of the value.
455 return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
456 }
457
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000458 int cmpType = type() - other.type();
459 if (cmpType != 0)
460 return cmpType;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700461
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000462 int cmpSize = value_size() - other.value_size();
463 if (cmpSize != 0)
464 return cmpSize;
465
Davide Pesaventoe245b052017-10-31 13:00:44 -0400466 if (empty())
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700467 return 0;
468
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700469 return std::memcmp(value(), other.value(), value_size());
470}
471
472Component
473Component::getSuccessor() const
474{
Junxiao Shid2e60632018-08-10 10:48:44 -0600475 bool isOverflow = false;
476 Component successor;
477 std::tie(isOverflow, successor) =
478 detail::getComponentTypeTable().get(type()).getSuccessor(*this);
479 if (!isOverflow) {
480 return successor;
Junxiao Shicf0aff82018-07-23 06:42:13 -0600481 }
482
Junxiao Shid2e60632018-08-10 10:48:44 -0600483 uint32_t type = this->type() + 1;
484 const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
485 return Component(type, value.data(), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700486}
487
Alexander Afanasyev74633892015-02-08 18:08:46 -0800488template<encoding::Tag TAG>
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700489size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700490Component::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700491{
492 size_t totalLength = 0;
493 if (value_size() > 0)
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700494 totalLength += encoder.prependByteArray(value(), value_size());
495 totalLength += encoder.prependVarNumber(value_size());
496 totalLength += encoder.prependVarNumber(type());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700497 return totalLength;
498}
499
Davide Pesavento88a0d812017-08-19 21:31:42 -0400500NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700501
502const Block&
503Component::wireEncode() const
504{
505 if (this->hasWire())
506 return *this;
507
508 EncodingEstimator estimator;
509 size_t estimatedSize = wireEncode(estimator);
510
511 EncodingBuffer buffer(estimatedSize, 0);
512 wireEncode(buffer);
513
514 const_cast<Component&>(*this) = buffer.block();
515 return *this;
516}
517
518void
519Component::wireDecode(const Block& wire)
520{
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700521 *this = wire;
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800522 // validity check is done within Component(const Block& wire)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700523}
524
525} // namespace name
526} // namespace ndn