blob: 23f00609a743129a8e027564e4bfc842b84acf99 [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/*
Eric Newberryc25e4632021-02-11 10:48:11 -08003 * Copyright (c) 2013-2021 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
Davide Pesaventobc17d952020-02-15 20:10:52 -050033#include <boost/logic/tribool.hpp>
34
Alexander Afanasyev15f67312014-07-22 15:11:09 -070035namespace ndn {
36namespace name {
37
Junxiao Shic2b8d242014-11-04 08:35:29 -070038BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Component>));
39BOOST_CONCEPT_ASSERT((WireEncodable<Component>));
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -070040BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<Component>));
Junxiao Shic2b8d242014-11-04 08:35:29 -070041BOOST_CONCEPT_ASSERT((WireDecodable<Component>));
42static_assert(std::is_base_of<tlv::Error, Component::Error>::value,
43 "name::Component::Error must inherit from tlv::Error");
44
Eric Newberryc25e4632021-02-11 10:48:11 -080045static Convention g_conventionEncoding = Convention::TYPED;
Junxiao Shie2099612019-02-15 14:46:27 +000046static Convention g_conventionDecoding = Convention::EITHER;
47
48Convention
49getConventionEncoding()
50{
51 return g_conventionEncoding;
52}
53
54void
55setConventionEncoding(Convention convention)
56{
57 switch (convention) {
58 case Convention::MARKER:
59 case Convention::TYPED:
60 g_conventionEncoding = convention;
61 break;
62 default:
63 NDN_THROW(std::invalid_argument("Unknown naming convention"));
Junxiao Shie2099612019-02-15 14:46:27 +000064 }
65}
66
67Convention
68getConventionDecoding()
69{
70 return g_conventionDecoding;
71}
72
73void
74setConventionDecoding(Convention convention)
75{
76 g_conventionDecoding = convention;
77}
78
79static bool
80canDecodeMarkerConvention()
81{
Davide Pesavento869b11e2019-08-18 17:44:27 -040082 return (to_underlying(g_conventionDecoding) & to_underlying(Convention::MARKER)) != 0;
Junxiao Shie2099612019-02-15 14:46:27 +000083}
84
85static bool
86canDecodeTypedConvention()
87{
Davide Pesavento869b11e2019-08-18 17:44:27 -040088 return (to_underlying(g_conventionDecoding) & to_underlying(Convention::TYPED)) != 0;
Junxiao Shie2099612019-02-15 14:46:27 +000089}
90
Junxiao Shia39c0b52019-12-31 15:13:15 -070091static bool
Davide Pesaventobc17d952020-02-15 20:10:52 -050092wantAltUri(UriFormat format)
Junxiao Shia39c0b52019-12-31 15:13:15 -070093{
Davide Pesaventobc17d952020-02-15 20:10:52 -050094 static const auto wantAltEnv = []() -> boost::tribool {
95 const char* env = std::getenv("NDN_NAME_ALT_URI");
96 if (env == nullptr)
97 return boost::indeterminate;
98 else if (env[0] == '0')
99 return false;
100 else if (env[0] == '1')
101 return true;
102 else
103 return boost::indeterminate;
104 }();
105
106 if (format == UriFormat::ENV_OR_CANONICAL) {
107 static const bool wantAlt = boost::indeterminate(wantAltEnv) ? false : bool(wantAltEnv);
108 return wantAlt;
Junxiao Shia39c0b52019-12-31 15:13:15 -0700109 }
Davide Pesaventobc17d952020-02-15 20:10:52 -0500110 else if (format == UriFormat::ENV_OR_ALTERNATE) {
111 static const bool wantAlt = boost::indeterminate(wantAltEnv) ? true : bool(wantAltEnv);
112 return wantAlt;
113 }
114 else {
115 return format == UriFormat::ALTERNATE;
116 }
Junxiao Shia39c0b52019-12-31 15:13:15 -0700117}
118
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000119void
120Component::ensureValid() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700121{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000122 if (type() < tlv::NameComponentMin || type() > tlv::NameComponentMax) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500123 NDN_THROW(Error("TLV-TYPE " + to_string(type()) + " is not a valid NameComponent"));
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000124 }
Junxiao Shid2e60632018-08-10 10:48:44 -0600125 detail::getComponentTypeTable().get(type()).check(*this);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000126}
127
128Component::Component(uint32_t type)
129 : Block(type)
130{
131 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700132}
133
134Component::Component(const Block& wire)
135 : Block(wire)
136{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000137 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700138}
139
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000140Component::Component(uint32_t type, ConstBufferPtr buffer)
141 : Block(type, std::move(buffer))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700142{
Junxiao Shid2e60632018-08-10 10:48:44 -0600143 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700144}
145
Davide Pesavento765abc92021-12-27 00:44:04 -0500146Component::Component(uint32_t type, span<const uint8_t> value)
147 : Block(makeBinaryBlock(type, value))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700148{
Junxiao Shid2e60632018-08-10 10:48:44 -0600149 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700150}
151
152Component::Component(const char* str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000153 : Block(makeBinaryBlock(tlv::GenericNameComponent, str, std::char_traits<char>::length(str)))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700154{
155}
156
157Component::Component(const std::string& str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000158 : Block(makeStringBlock(tlv::GenericNameComponent, str))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700159{
160}
161
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000162static Component
Junxiao Shid2e60632018-08-10 10:48:44 -0600163parseUriEscapedValue(uint32_t type, const char* input, size_t len)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000164{
Junxiao Shid2e60632018-08-10 10:48:44 -0600165 std::ostringstream oss;
166 unescape(oss, input, len);
167 std::string value = oss.str();
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000168 if (value.find_first_not_of('.') == std::string::npos) { // all periods
169 if (value.size() < 3) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500170 NDN_THROW(Component::Error("Illegal URI (name component cannot be . or ..)"));
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700171 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000172 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size() - 3);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700173 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000174 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700175}
176
Junxiao Shid2e60632018-08-10 10:48:44 -0600177Component
178Component::fromEscapedString(const std::string& input)
179{
180 size_t equalPos = input.find('=');
181 if (equalPos == std::string::npos) {
182 return parseUriEscapedValue(tlv::GenericNameComponent, input.data(), input.size());
183 }
184
Davide Pesavento6b330402019-04-24 00:14:01 -0400185 auto typePrefix = input.substr(0, equalPos);
186 auto type = std::strtoul(typePrefix.data(), nullptr, 10);
Junxiao Shid2e60632018-08-10 10:48:44 -0600187 if (type >= tlv::NameComponentMin && type <= tlv::NameComponentMax &&
Davide Pesavento6b330402019-04-24 00:14:01 -0400188 to_string(type) == typePrefix) {
Junxiao Shid2e60632018-08-10 10:48:44 -0600189 size_t valuePos = equalPos + 1;
Davide Pesavento6b330402019-04-24 00:14:01 -0400190 return parseUriEscapedValue(static_cast<uint32_t>(type),
191 input.data() + valuePos, input.size() - valuePos);
Junxiao Shid2e60632018-08-10 10:48:44 -0600192 }
193
Junxiao Shid2e60632018-08-10 10:48:44 -0600194 auto ct = detail::getComponentTypeTable().findByUriPrefix(typePrefix);
195 if (ct == nullptr) {
Davide Pesavento009062d2019-11-20 00:16:33 -0500196 NDN_THROW(Error("Unknown TLV-TYPE '" + typePrefix + "' in NameComponent URI"));
Junxiao Shid2e60632018-08-10 10:48:44 -0600197 }
198 return ct->parseAltUriValue(input.substr(equalPos + 1));
199}
200
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700201void
Junxiao Shia39c0b52019-12-31 15:13:15 -0700202Component::toUri(std::ostream& os, UriFormat format) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700203{
Davide Pesaventobc17d952020-02-15 20:10:52 -0500204 if (wantAltUri(format)) {
Junxiao Shia39c0b52019-12-31 15:13:15 -0700205 detail::getComponentTypeTable().get(type()).writeUri(os, *this);
206 }
207 else {
208 detail::ComponentType().writeUri(os, *this);
209 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700210}
211
212std::string
Junxiao Shia39c0b52019-12-31 15:13:15 -0700213Component::toUri(UriFormat format) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700214{
215 std::ostringstream os;
Junxiao Shia39c0b52019-12-31 15:13:15 -0700216 toUri(os, format);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700217 return os.str();
218}
219
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700220////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700221
222bool
223Component::isNumber() const
224{
Davide Pesavento009062d2019-11-20 00:16:33 -0500225 return value_size() == 1 || value_size() == 2 ||
226 value_size() == 4 || value_size() == 8;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700227}
228
229bool
230Component::isNumberWithMarker(uint8_t marker) const
231{
Davide Pesavento009062d2019-11-20 00:16:33 -0500232 return (value_size() == 2 || value_size() == 3 ||
233 value_size() == 5 || value_size() == 9) && value()[0] == marker;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700234}
235
236bool
237Component::isVersion() const
238{
Junxiao Shie2099612019-02-15 14:46:27 +0000239 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(VERSION_MARKER)) ||
240 (canDecodeTypedConvention() && type() == tlv::VersionNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700241}
242
243bool
244Component::isSegment() const
245{
Junxiao Shie2099612019-02-15 14:46:27 +0000246 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_MARKER)) ||
247 (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700248}
249
250bool
Junxiao Shie2099612019-02-15 14:46:27 +0000251Component::isByteOffset() const
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700252{
Junxiao Shie2099612019-02-15 14:46:27 +0000253 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_OFFSET_MARKER)) ||
254 (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700255}
256
257bool
258Component::isTimestamp() const
259{
Junxiao Shie2099612019-02-15 14:46:27 +0000260 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(TIMESTAMP_MARKER)) ||
261 (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700262}
263
264bool
265Component::isSequenceNumber() const
266{
Junxiao Shie2099612019-02-15 14:46:27 +0000267 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEQUENCE_NUMBER_MARKER)) ||
268 (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700269}
270
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700271////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700272
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700273uint64_t
274Component::toNumber() const
275{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700276 if (!isNumber())
Davide Pesavento47a94d12021-10-31 16:41:05 -0400277 NDN_THROW(Error("Name component does not have NonNegativeInteger value"));
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700278
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700279 return readNonNegativeInteger(*this);
280}
281
282uint64_t
283Component::toNumberWithMarker(uint8_t marker) const
284{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700285 if (!isNumberWithMarker(marker))
Davide Pesavento923ba442019-02-12 22:00:38 -0500286 NDN_THROW(Error("Name component does not have the requested marker "
Davide Pesavento47a94d12021-10-31 16:41:05 -0400287 "or the value is not a NonNegativeInteger"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700288
Davide Pesavento47a94d12021-10-31 16:41:05 -0400289 auto valueBegin = value_begin() + 1;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700290 return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
291}
292
293uint64_t
294Component::toVersion() const
295{
Junxiao Shie2099612019-02-15 14:46:27 +0000296 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
297 return toNumberWithMarker(VERSION_MARKER);
298 }
299 if (canDecodeTypedConvention() && type() == tlv::VersionNameComponent) {
300 return toNumber();
301 }
302 NDN_THROW(Error("Not a Version component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700303}
304
305uint64_t
306Component::toSegment() const
307{
Junxiao Shie2099612019-02-15 14:46:27 +0000308 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
309 return toNumberWithMarker(SEGMENT_MARKER);
310 }
311 if (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent) {
312 return toNumber();
313 }
314 NDN_THROW(Error("Not a Segment component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700315}
316
317uint64_t
Junxiao Shie2099612019-02-15 14:46:27 +0000318Component::toByteOffset() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700319{
Junxiao Shie2099612019-02-15 14:46:27 +0000320 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
321 return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
322 }
323 if (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent) {
324 return toNumber();
325 }
326 NDN_THROW(Error("Not a ByteOffset component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700327}
328
Davide Pesavento47a94d12021-10-31 16:41:05 -0400329time::system_clock::time_point
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700330Component::toTimestamp() const
331{
Junxiao Shie2099612019-02-15 14:46:27 +0000332 uint64_t value = 0;
333 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
334 value = toNumberWithMarker(TIMESTAMP_MARKER);
335 }
336 else if (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent) {
337 value = toNumber();
338 }
339 else {
340 NDN_THROW(Error("Not a Timestamp component"));
341 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700342 return time::getUnixEpoch() + time::microseconds(value);
343}
344
345uint64_t
346Component::toSequenceNumber() const
347{
Junxiao Shie2099612019-02-15 14:46:27 +0000348 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
349 return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
350 }
351 if (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent) {
352 return toNumber();
353 }
354 NDN_THROW(Error("Not a SequenceNumber component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700355}
356
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700357////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700358
359Component
Junxiao Shie2099612019-02-15 14:46:27 +0000360Component::fromNumber(uint64_t number, uint32_t type)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700361{
Junxiao Shie2099612019-02-15 14:46:27 +0000362 return makeNonNegativeIntegerBlock(type, number);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700363}
364
365Component
366Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
367{
368 EncodingEstimator estimator;
369
370 size_t valueLength = estimator.prependNonNegativeInteger(number);
371 valueLength += estimator.prependByteArray(&marker, 1);
372 size_t totalLength = valueLength;
373 totalLength += estimator.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000374 totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700375
376 EncodingBuffer encoder(totalLength, 0);
377 encoder.prependNonNegativeInteger(number);
378 encoder.prependByteArray(&marker, 1);
379 encoder.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000380 encoder.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700381
382 return encoder.block();
383}
384
385Component
386Component::fromVersion(uint64_t version)
387{
Junxiao Shie2099612019-02-15 14:46:27 +0000388 return g_conventionEncoding == Convention::MARKER ?
389 fromNumberWithMarker(VERSION_MARKER, version) :
390 fromNumber(version, tlv::VersionNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700391}
392
393Component
394Component::fromSegment(uint64_t segmentNo)
395{
Junxiao Shie2099612019-02-15 14:46:27 +0000396 return g_conventionEncoding == Convention::MARKER ?
397 fromNumberWithMarker(SEGMENT_MARKER, segmentNo) :
398 fromNumber(segmentNo, tlv::SegmentNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700399}
400
401Component
Junxiao Shie2099612019-02-15 14:46:27 +0000402Component::fromByteOffset(uint64_t offset)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700403{
Junxiao Shie2099612019-02-15 14:46:27 +0000404 return g_conventionEncoding == Convention::MARKER ?
405 fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset) :
406 fromNumber(offset, tlv::ByteOffsetNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700407}
408
409Component
Davide Pesavento47a94d12021-10-31 16:41:05 -0400410Component::fromTimestamp(const time::system_clock::time_point& timePoint)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700411{
Junxiao Shie2099612019-02-15 14:46:27 +0000412 uint64_t value = time::duration_cast<time::microseconds>(timePoint - time::getUnixEpoch()).count();
413 return g_conventionEncoding == Convention::MARKER ?
414 fromNumberWithMarker(TIMESTAMP_MARKER, value) :
415 fromNumber(value, tlv::TimestampNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700416}
417
418Component
419Component::fromSequenceNumber(uint64_t seqNo)
420{
Junxiao Shie2099612019-02-15 14:46:27 +0000421 return g_conventionEncoding == Convention::MARKER ?
422 fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo) :
423 fromNumber(seqNo, tlv::SequenceNumNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700424}
425
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700426////////////////////////////////////////////////////////////////////////////////
427
428bool
429Component::isGeneric() const
430{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000431 return type() == tlv::GenericNameComponent;
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700432}
433
434bool
435Component::isImplicitSha256Digest() const
436{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600437 return detail::getComponentType1().match(*this);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700438}
439
440Component
Davide Pesavento3b101d02018-07-21 22:44:09 -0400441Component::fromImplicitSha256Digest(ConstBufferPtr digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700442{
Davide Pesavento765abc92021-12-27 00:44:04 -0500443 return detail::getComponentType1().create(std::move(digest));
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700444}
445
446Component
Davide Pesavento765abc92021-12-27 00:44:04 -0500447Component::fromImplicitSha256Digest(span<const uint8_t> digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700448{
Davide Pesavento765abc92021-12-27 00:44:04 -0500449 return detail::getComponentType1().create(digest);
Junxiao Shi4053bd52018-08-16 13:39:25 -0600450}
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700451
Junxiao Shi4053bd52018-08-16 13:39:25 -0600452bool
453Component::isParametersSha256Digest() const
454{
455 return detail::getComponentType2().match(*this);
456}
457
458Component
459Component::fromParametersSha256Digest(ConstBufferPtr digest)
460{
Davide Pesavento765abc92021-12-27 00:44:04 -0500461 return detail::getComponentType2().create(std::move(digest));
Junxiao Shi4053bd52018-08-16 13:39:25 -0600462}
463
464Component
Davide Pesavento765abc92021-12-27 00:44:04 -0500465Component::fromParametersSha256Digest(span<const uint8_t> digest)
Junxiao Shi4053bd52018-08-16 13:39:25 -0600466{
Davide Pesavento765abc92021-12-27 00:44:04 -0500467 return detail::getComponentType2().create(digest);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700468}
469
470////////////////////////////////////////////////////////////////////////////////
471
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000472bool
473Component::equals(const Component& other) const
474{
475 return type() == other.type() &&
476 value_size() == other.value_size() &&
Davide Pesavento71c622b2020-04-24 01:39:01 -0400477 std::equal(value_begin(), value_end(), other.value_begin());
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000478}
479
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700480int
481Component::compare(const Component& other) const
482{
Junxiao Shi010f0862016-10-11 21:08:32 +0000483 if (this->hasWire() && other.hasWire()) {
484 // In the common case where both components have wire encoding,
485 // it's more efficient to simply compare the wire encoding.
486 // This works because lexical order of TLV encoding happens to be
487 // the same as canonical order of the value.
488 return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
489 }
490
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000491 int cmpType = type() - other.type();
492 if (cmpType != 0)
493 return cmpType;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700494
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000495 int cmpSize = value_size() - other.value_size();
496 if (cmpSize != 0)
497 return cmpSize;
498
Davide Pesaventoe245b052017-10-31 13:00:44 -0400499 if (empty())
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700500 return 0;
501
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700502 return std::memcmp(value(), other.value(), value_size());
503}
504
505Component
506Component::getSuccessor() const
507{
Junxiao Shid2e60632018-08-10 10:48:44 -0600508 bool isOverflow = false;
509 Component successor;
Davide Pesavento765abc92021-12-27 00:44:04 -0500510 std::tie(isOverflow, successor) = detail::getComponentTypeTable().get(type()).getSuccessor(*this);
Junxiao Shid2e60632018-08-10 10:48:44 -0600511 if (!isOverflow) {
512 return successor;
Junxiao Shicf0aff82018-07-23 06:42:13 -0600513 }
514
Junxiao Shid2e60632018-08-10 10:48:44 -0600515 uint32_t type = this->type() + 1;
Davide Pesavento765abc92021-12-27 00:44:04 -0500516 auto value = detail::getComponentTypeTable().get(type).getMinValue();
Junxiao Shid2e60632018-08-10 10:48:44 -0600517 return Component(type, value.data(), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700518}
519
Alexander Afanasyev74633892015-02-08 18:08:46 -0800520template<encoding::Tag TAG>
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700521size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700522Component::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700523{
524 size_t totalLength = 0;
525 if (value_size() > 0)
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700526 totalLength += encoder.prependByteArray(value(), value_size());
527 totalLength += encoder.prependVarNumber(value_size());
528 totalLength += encoder.prependVarNumber(type());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700529 return totalLength;
530}
531
Davide Pesavento88a0d812017-08-19 21:31:42 -0400532NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700533
534const Block&
535Component::wireEncode() const
536{
537 if (this->hasWire())
538 return *this;
539
540 EncodingEstimator estimator;
541 size_t estimatedSize = wireEncode(estimator);
542
543 EncodingBuffer buffer(estimatedSize, 0);
544 wireEncode(buffer);
545
546 const_cast<Component&>(*this) = buffer.block();
547 return *this;
548}
549
550void
551Component::wireDecode(const Block& wire)
552{
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700553 *this = wire;
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800554 // validity check is done within Component(const Block& wire)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700555}
556
557} // namespace name
558} // namespace ndn