blob: 4338cc42ee8d2b4c80ff6b90122df4e8bb89b60a [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 Shia39c0b52019-12-31 15:13:15 -070089static bool
90chooseAltUri(UriFormat format)
91{
92 if (format == UriFormat::DEFAULT) {
93 static const char* env = std::getenv("NDN_NAME_ALT_URI");
94 static bool defaultSetting = env == nullptr || env[0] != '0';
95 return defaultSetting;
96 }
97 return format == UriFormat::ALTERNATE;
98}
99
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000100void
101Component::ensureValid() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700102{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000103 if (type() < tlv::NameComponentMin || type() > tlv::NameComponentMax) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500104 NDN_THROW(Error("TLV-TYPE " + to_string(type()) + " is not a valid NameComponent"));
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000105 }
Junxiao Shid2e60632018-08-10 10:48:44 -0600106 detail::getComponentTypeTable().get(type()).check(*this);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000107}
108
109Component::Component(uint32_t type)
110 : Block(type)
111{
112 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700113}
114
115Component::Component(const Block& wire)
116 : Block(wire)
117{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000118 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700119}
120
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000121Component::Component(uint32_t type, ConstBufferPtr buffer)
122 : Block(type, std::move(buffer))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700123{
Junxiao Shid2e60632018-08-10 10:48:44 -0600124 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700125}
126
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000127Component::Component(uint32_t type, const uint8_t* value, size_t valueLen)
128 : Block(makeBinaryBlock(type, value, valueLen))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700129{
Junxiao Shid2e60632018-08-10 10:48:44 -0600130 ensureValid();
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700131}
132
133Component::Component(const char* str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000134 : Block(makeBinaryBlock(tlv::GenericNameComponent, str, std::char_traits<char>::length(str)))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700135{
136}
137
138Component::Component(const std::string& str)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000139 : Block(makeStringBlock(tlv::GenericNameComponent, str))
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700140{
141}
142
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000143static Component
Junxiao Shid2e60632018-08-10 10:48:44 -0600144parseUriEscapedValue(uint32_t type, const char* input, size_t len)
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000145{
Junxiao Shid2e60632018-08-10 10:48:44 -0600146 std::ostringstream oss;
147 unescape(oss, input, len);
148 std::string value = oss.str();
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000149 if (value.find_first_not_of('.') == std::string::npos) { // all periods
150 if (value.size() < 3) {
Davide Pesavento923ba442019-02-12 22:00:38 -0500151 NDN_THROW(Component::Error("Illegal URI (name component cannot be . or ..)"));
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700152 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000153 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size() - 3);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700154 }
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000155 return Component(type, reinterpret_cast<const uint8_t*>(value.data()), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700156}
157
Junxiao Shid2e60632018-08-10 10:48:44 -0600158Component
159Component::fromEscapedString(const std::string& input)
160{
161 size_t equalPos = input.find('=');
162 if (equalPos == std::string::npos) {
163 return parseUriEscapedValue(tlv::GenericNameComponent, input.data(), input.size());
164 }
165
Davide Pesavento6b330402019-04-24 00:14:01 -0400166 auto typePrefix = input.substr(0, equalPos);
167 auto type = std::strtoul(typePrefix.data(), nullptr, 10);
Junxiao Shid2e60632018-08-10 10:48:44 -0600168 if (type >= tlv::NameComponentMin && type <= tlv::NameComponentMax &&
Davide Pesavento6b330402019-04-24 00:14:01 -0400169 to_string(type) == typePrefix) {
Junxiao Shid2e60632018-08-10 10:48:44 -0600170 size_t valuePos = equalPos + 1;
Davide Pesavento6b330402019-04-24 00:14:01 -0400171 return parseUriEscapedValue(static_cast<uint32_t>(type),
172 input.data() + valuePos, input.size() - valuePos);
Junxiao Shid2e60632018-08-10 10:48:44 -0600173 }
174
Junxiao Shid2e60632018-08-10 10:48:44 -0600175 auto ct = detail::getComponentTypeTable().findByUriPrefix(typePrefix);
176 if (ct == nullptr) {
Davide Pesavento009062d2019-11-20 00:16:33 -0500177 NDN_THROW(Error("Unknown TLV-TYPE '" + typePrefix + "' in NameComponent URI"));
Junxiao Shid2e60632018-08-10 10:48:44 -0600178 }
179 return ct->parseAltUriValue(input.substr(equalPos + 1));
180}
181
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700182void
Junxiao Shia39c0b52019-12-31 15:13:15 -0700183Component::toUri(std::ostream& os, UriFormat format) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700184{
Junxiao Shia39c0b52019-12-31 15:13:15 -0700185 if (chooseAltUri(format)) {
186 detail::getComponentTypeTable().get(type()).writeUri(os, *this);
187 }
188 else {
189 detail::ComponentType().writeUri(os, *this);
190 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700191}
192
193std::string
Junxiao Shia39c0b52019-12-31 15:13:15 -0700194Component::toUri(UriFormat format) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700195{
196 std::ostringstream os;
Junxiao Shia39c0b52019-12-31 15:13:15 -0700197 toUri(os, format);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700198 return os.str();
199}
200
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700201////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700202
203bool
204Component::isNumber() const
205{
Davide Pesavento009062d2019-11-20 00:16:33 -0500206 return value_size() == 1 || value_size() == 2 ||
207 value_size() == 4 || value_size() == 8;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700208}
209
210bool
211Component::isNumberWithMarker(uint8_t marker) const
212{
Davide Pesavento009062d2019-11-20 00:16:33 -0500213 return (value_size() == 2 || value_size() == 3 ||
214 value_size() == 5 || value_size() == 9) && value()[0] == marker;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700215}
216
217bool
218Component::isVersion() const
219{
Junxiao Shie2099612019-02-15 14:46:27 +0000220 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(VERSION_MARKER)) ||
221 (canDecodeTypedConvention() && type() == tlv::VersionNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700222}
223
224bool
225Component::isSegment() const
226{
Junxiao Shie2099612019-02-15 14:46:27 +0000227 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_MARKER)) ||
228 (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700229}
230
231bool
Junxiao Shie2099612019-02-15 14:46:27 +0000232Component::isByteOffset() const
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700233{
Junxiao Shie2099612019-02-15 14:46:27 +0000234 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_OFFSET_MARKER)) ||
235 (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700236}
237
238bool
239Component::isTimestamp() const
240{
Junxiao Shie2099612019-02-15 14:46:27 +0000241 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(TIMESTAMP_MARKER)) ||
242 (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700243}
244
245bool
246Component::isSequenceNumber() const
247{
Junxiao Shie2099612019-02-15 14:46:27 +0000248 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEQUENCE_NUMBER_MARKER)) ||
249 (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700250}
251
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700252////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700253
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700254uint64_t
255Component::toNumber() const
256{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700257 if (!isNumber())
Davide Pesavento923ba442019-02-12 22:00:38 -0500258 NDN_THROW(Error("Name component does not have nonNegativeInteger value"));
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700259
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700260 return readNonNegativeInteger(*this);
261}
262
263uint64_t
264Component::toNumberWithMarker(uint8_t marker) const
265{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700266 if (!isNumberWithMarker(marker))
Davide Pesavento923ba442019-02-12 22:00:38 -0500267 NDN_THROW(Error("Name component does not have the requested marker "
268 "or the value is not a nonNegativeInteger"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700269
270 Buffer::const_iterator valueBegin = value_begin() + 1;
271 return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
272}
273
274uint64_t
275Component::toVersion() const
276{
Junxiao Shie2099612019-02-15 14:46:27 +0000277 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
278 return toNumberWithMarker(VERSION_MARKER);
279 }
280 if (canDecodeTypedConvention() && type() == tlv::VersionNameComponent) {
281 return toNumber();
282 }
283 NDN_THROW(Error("Not a Version component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700284}
285
286uint64_t
287Component::toSegment() const
288{
Junxiao Shie2099612019-02-15 14:46:27 +0000289 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
290 return toNumberWithMarker(SEGMENT_MARKER);
291 }
292 if (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent) {
293 return toNumber();
294 }
295 NDN_THROW(Error("Not a Segment component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700296}
297
298uint64_t
Junxiao Shie2099612019-02-15 14:46:27 +0000299Component::toByteOffset() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700300{
Junxiao Shie2099612019-02-15 14:46:27 +0000301 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
302 return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
303 }
304 if (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent) {
305 return toNumber();
306 }
307 NDN_THROW(Error("Not a ByteOffset component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700308}
309
310time::system_clock::TimePoint
311Component::toTimestamp() const
312{
Junxiao Shie2099612019-02-15 14:46:27 +0000313 uint64_t value = 0;
314 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
315 value = toNumberWithMarker(TIMESTAMP_MARKER);
316 }
317 else if (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent) {
318 value = toNumber();
319 }
320 else {
321 NDN_THROW(Error("Not a Timestamp component"));
322 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700323 return time::getUnixEpoch() + time::microseconds(value);
324}
325
326uint64_t
327Component::toSequenceNumber() const
328{
Junxiao Shie2099612019-02-15 14:46:27 +0000329 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
330 return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
331 }
332 if (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent) {
333 return toNumber();
334 }
335 NDN_THROW(Error("Not a SequenceNumber component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700336}
337
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700338////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700339
340Component
Junxiao Shie2099612019-02-15 14:46:27 +0000341Component::fromNumber(uint64_t number, uint32_t type)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700342{
Junxiao Shie2099612019-02-15 14:46:27 +0000343 return makeNonNegativeIntegerBlock(type, number);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700344}
345
346Component
347Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
348{
349 EncodingEstimator estimator;
350
351 size_t valueLength = estimator.prependNonNegativeInteger(number);
352 valueLength += estimator.prependByteArray(&marker, 1);
353 size_t totalLength = valueLength;
354 totalLength += estimator.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000355 totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700356
357 EncodingBuffer encoder(totalLength, 0);
358 encoder.prependNonNegativeInteger(number);
359 encoder.prependByteArray(&marker, 1);
360 encoder.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000361 encoder.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700362
363 return encoder.block();
364}
365
366Component
367Component::fromVersion(uint64_t version)
368{
Junxiao Shie2099612019-02-15 14:46:27 +0000369 return g_conventionEncoding == Convention::MARKER ?
370 fromNumberWithMarker(VERSION_MARKER, version) :
371 fromNumber(version, tlv::VersionNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700372}
373
374Component
375Component::fromSegment(uint64_t segmentNo)
376{
Junxiao Shie2099612019-02-15 14:46:27 +0000377 return g_conventionEncoding == Convention::MARKER ?
378 fromNumberWithMarker(SEGMENT_MARKER, segmentNo) :
379 fromNumber(segmentNo, tlv::SegmentNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700380}
381
382Component
Junxiao Shie2099612019-02-15 14:46:27 +0000383Component::fromByteOffset(uint64_t offset)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700384{
Junxiao Shie2099612019-02-15 14:46:27 +0000385 return g_conventionEncoding == Convention::MARKER ?
386 fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset) :
387 fromNumber(offset, tlv::ByteOffsetNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700388}
389
390Component
391Component::fromTimestamp(const time::system_clock::TimePoint& timePoint)
392{
Junxiao Shie2099612019-02-15 14:46:27 +0000393 uint64_t value = time::duration_cast<time::microseconds>(timePoint - time::getUnixEpoch()).count();
394 return g_conventionEncoding == Convention::MARKER ?
395 fromNumberWithMarker(TIMESTAMP_MARKER, value) :
396 fromNumber(value, tlv::TimestampNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700397}
398
399Component
400Component::fromSequenceNumber(uint64_t seqNo)
401{
Junxiao Shie2099612019-02-15 14:46:27 +0000402 return g_conventionEncoding == Convention::MARKER ?
403 fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo) :
404 fromNumber(seqNo, tlv::SequenceNumNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700405}
406
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700407////////////////////////////////////////////////////////////////////////////////
408
409bool
410Component::isGeneric() const
411{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000412 return type() == tlv::GenericNameComponent;
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700413}
414
415bool
416Component::isImplicitSha256Digest() const
417{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600418 return detail::getComponentType1().match(*this);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700419}
420
421Component
Davide Pesavento3b101d02018-07-21 22:44:09 -0400422Component::fromImplicitSha256Digest(ConstBufferPtr digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700423{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600424 return detail::getComponentType1().create(digest);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700425}
426
427Component
428Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
429{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600430 return detail::getComponentType1().create(digest, digestSize);
431}
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700432
Junxiao Shi4053bd52018-08-16 13:39:25 -0600433bool
434Component::isParametersSha256Digest() const
435{
436 return detail::getComponentType2().match(*this);
437}
438
439Component
440Component::fromParametersSha256Digest(ConstBufferPtr digest)
441{
442 return detail::getComponentType2().create(digest);
443}
444
445Component
446Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
447{
448 return detail::getComponentType2().create(digest, digestSize);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700449}
450
451////////////////////////////////////////////////////////////////////////////////
452
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000453bool
454Component::equals(const Component& other) const
455{
456 return type() == other.type() &&
457 value_size() == other.value_size() &&
Davide Pesaventoe245b052017-10-31 13:00:44 -0400458 (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000459 std::equal(value_begin(), value_end(), other.value_begin()));
460}
461
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700462int
463Component::compare(const Component& other) const
464{
Junxiao Shi010f0862016-10-11 21:08:32 +0000465 if (this->hasWire() && other.hasWire()) {
466 // In the common case where both components have wire encoding,
467 // it's more efficient to simply compare the wire encoding.
468 // This works because lexical order of TLV encoding happens to be
469 // the same as canonical order of the value.
470 return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
471 }
472
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000473 int cmpType = type() - other.type();
474 if (cmpType != 0)
475 return cmpType;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700476
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000477 int cmpSize = value_size() - other.value_size();
478 if (cmpSize != 0)
479 return cmpSize;
480
Davide Pesaventoe245b052017-10-31 13:00:44 -0400481 if (empty())
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700482 return 0;
483
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700484 return std::memcmp(value(), other.value(), value_size());
485}
486
487Component
488Component::getSuccessor() const
489{
Junxiao Shid2e60632018-08-10 10:48:44 -0600490 bool isOverflow = false;
491 Component successor;
492 std::tie(isOverflow, successor) =
493 detail::getComponentTypeTable().get(type()).getSuccessor(*this);
494 if (!isOverflow) {
495 return successor;
Junxiao Shicf0aff82018-07-23 06:42:13 -0600496 }
497
Junxiao Shid2e60632018-08-10 10:48:44 -0600498 uint32_t type = this->type() + 1;
499 const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
500 return Component(type, value.data(), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700501}
502
Alexander Afanasyev74633892015-02-08 18:08:46 -0800503template<encoding::Tag TAG>
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700504size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700505Component::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700506{
507 size_t totalLength = 0;
508 if (value_size() > 0)
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700509 totalLength += encoder.prependByteArray(value(), value_size());
510 totalLength += encoder.prependVarNumber(value_size());
511 totalLength += encoder.prependVarNumber(type());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700512 return totalLength;
513}
514
Davide Pesavento88a0d812017-08-19 21:31:42 -0400515NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700516
517const Block&
518Component::wireEncode() const
519{
520 if (this->hasWire())
521 return *this;
522
523 EncodingEstimator estimator;
524 size_t estimatedSize = wireEncode(estimator);
525
526 EncodingBuffer buffer(estimatedSize, 0);
527 wireEncode(buffer);
528
529 const_cast<Component&>(*this) = buffer.block();
530 return *this;
531}
532
533void
534Component::wireDecode(const Block& wire)
535{
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700536 *this = wire;
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800537 // validity check is done within Component(const Block& wire)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700538}
539
540} // namespace name
541} // namespace ndn