blob: f41fda0d9e026c9982d6812e0e27a59b5c71d978 [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 Pesavento009062d2019-11-20 00:16:33 -0500166 NDN_THROW(Error("Unknown 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{
Davide Pesavento009062d2019-11-20 00:16:33 -0500190 return value_size() == 1 || value_size() == 2 ||
191 value_size() == 4 || value_size() == 8;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700192}
193
194bool
195Component::isNumberWithMarker(uint8_t marker) const
196{
Davide Pesavento009062d2019-11-20 00:16:33 -0500197 return (value_size() == 2 || value_size() == 3 ||
198 value_size() == 5 || value_size() == 9) && value()[0] == marker;
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700199}
200
201bool
202Component::isVersion() const
203{
Junxiao Shie2099612019-02-15 14:46:27 +0000204 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(VERSION_MARKER)) ||
205 (canDecodeTypedConvention() && type() == tlv::VersionNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700206}
207
208bool
209Component::isSegment() const
210{
Junxiao Shie2099612019-02-15 14:46:27 +0000211 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_MARKER)) ||
212 (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700213}
214
215bool
Junxiao Shie2099612019-02-15 14:46:27 +0000216Component::isByteOffset() const
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700217{
Junxiao Shie2099612019-02-15 14:46:27 +0000218 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEGMENT_OFFSET_MARKER)) ||
219 (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700220}
221
222bool
223Component::isTimestamp() const
224{
Junxiao Shie2099612019-02-15 14:46:27 +0000225 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(TIMESTAMP_MARKER)) ||
226 (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700227}
228
229bool
230Component::isSequenceNumber() const
231{
Junxiao Shie2099612019-02-15 14:46:27 +0000232 return (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent && isNumberWithMarker(SEQUENCE_NUMBER_MARKER)) ||
233 (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent && isNumber());
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700234}
235
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700236////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700237
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700238uint64_t
239Component::toNumber() const
240{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700241 if (!isNumber())
Davide Pesavento923ba442019-02-12 22:00:38 -0500242 NDN_THROW(Error("Name component does not have nonNegativeInteger value"));
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700243
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700244 return readNonNegativeInteger(*this);
245}
246
247uint64_t
248Component::toNumberWithMarker(uint8_t marker) const
249{
Alexander Afanasyev0f232c52014-10-23 13:07:31 -0700250 if (!isNumberWithMarker(marker))
Davide Pesavento923ba442019-02-12 22:00:38 -0500251 NDN_THROW(Error("Name component does not have the requested marker "
252 "or the value is not a nonNegativeInteger"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700253
254 Buffer::const_iterator valueBegin = value_begin() + 1;
255 return tlv::readNonNegativeInteger(value_size() - 1, valueBegin, value_end());
256}
257
258uint64_t
259Component::toVersion() const
260{
Junxiao Shie2099612019-02-15 14:46:27 +0000261 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
262 return toNumberWithMarker(VERSION_MARKER);
263 }
264 if (canDecodeTypedConvention() && type() == tlv::VersionNameComponent) {
265 return toNumber();
266 }
267 NDN_THROW(Error("Not a Version component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700268}
269
270uint64_t
271Component::toSegment() const
272{
Junxiao Shie2099612019-02-15 14:46:27 +0000273 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
274 return toNumberWithMarker(SEGMENT_MARKER);
275 }
276 if (canDecodeTypedConvention() && type() == tlv::SegmentNameComponent) {
277 return toNumber();
278 }
279 NDN_THROW(Error("Not a Segment component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700280}
281
282uint64_t
Junxiao Shie2099612019-02-15 14:46:27 +0000283Component::toByteOffset() const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700284{
Junxiao Shie2099612019-02-15 14:46:27 +0000285 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
286 return toNumberWithMarker(SEGMENT_OFFSET_MARKER);
287 }
288 if (canDecodeTypedConvention() && type() == tlv::ByteOffsetNameComponent) {
289 return toNumber();
290 }
291 NDN_THROW(Error("Not a ByteOffset component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700292}
293
294time::system_clock::TimePoint
295Component::toTimestamp() const
296{
Junxiao Shie2099612019-02-15 14:46:27 +0000297 uint64_t value = 0;
298 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
299 value = toNumberWithMarker(TIMESTAMP_MARKER);
300 }
301 else if (canDecodeTypedConvention() && type() == tlv::TimestampNameComponent) {
302 value = toNumber();
303 }
304 else {
305 NDN_THROW(Error("Not a Timestamp component"));
306 }
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700307 return time::getUnixEpoch() + time::microseconds(value);
308}
309
310uint64_t
311Component::toSequenceNumber() const
312{
Junxiao Shie2099612019-02-15 14:46:27 +0000313 if (canDecodeMarkerConvention() && type() == tlv::GenericNameComponent) {
314 return toNumberWithMarker(SEQUENCE_NUMBER_MARKER);
315 }
316 if (canDecodeTypedConvention() && type() == tlv::SequenceNumNameComponent) {
317 return toNumber();
318 }
319 NDN_THROW(Error("Not a SequenceNumber component"));
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700320}
321
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700322////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700323
324Component
Junxiao Shie2099612019-02-15 14:46:27 +0000325Component::fromNumber(uint64_t number, uint32_t type)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700326{
Junxiao Shie2099612019-02-15 14:46:27 +0000327 return makeNonNegativeIntegerBlock(type, number);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700328}
329
330Component
331Component::fromNumberWithMarker(uint8_t marker, uint64_t number)
332{
333 EncodingEstimator estimator;
334
335 size_t valueLength = estimator.prependNonNegativeInteger(number);
336 valueLength += estimator.prependByteArray(&marker, 1);
337 size_t totalLength = valueLength;
338 totalLength += estimator.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000339 totalLength += estimator.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700340
341 EncodingBuffer encoder(totalLength, 0);
342 encoder.prependNonNegativeInteger(number);
343 encoder.prependByteArray(&marker, 1);
344 encoder.prependVarNumber(valueLength);
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000345 encoder.prependVarNumber(tlv::GenericNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700346
347 return encoder.block();
348}
349
350Component
351Component::fromVersion(uint64_t version)
352{
Junxiao Shie2099612019-02-15 14:46:27 +0000353 return g_conventionEncoding == Convention::MARKER ?
354 fromNumberWithMarker(VERSION_MARKER, version) :
355 fromNumber(version, tlv::VersionNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700356}
357
358Component
359Component::fromSegment(uint64_t segmentNo)
360{
Junxiao Shie2099612019-02-15 14:46:27 +0000361 return g_conventionEncoding == Convention::MARKER ?
362 fromNumberWithMarker(SEGMENT_MARKER, segmentNo) :
363 fromNumber(segmentNo, tlv::SegmentNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700364}
365
366Component
Junxiao Shie2099612019-02-15 14:46:27 +0000367Component::fromByteOffset(uint64_t offset)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700368{
Junxiao Shie2099612019-02-15 14:46:27 +0000369 return g_conventionEncoding == Convention::MARKER ?
370 fromNumberWithMarker(SEGMENT_OFFSET_MARKER, offset) :
371 fromNumber(offset, tlv::ByteOffsetNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700372}
373
374Component
375Component::fromTimestamp(const time::system_clock::TimePoint& timePoint)
376{
Junxiao Shie2099612019-02-15 14:46:27 +0000377 uint64_t value = time::duration_cast<time::microseconds>(timePoint - time::getUnixEpoch()).count();
378 return g_conventionEncoding == Convention::MARKER ?
379 fromNumberWithMarker(TIMESTAMP_MARKER, value) :
380 fromNumber(value, tlv::TimestampNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700381}
382
383Component
384Component::fromSequenceNumber(uint64_t seqNo)
385{
Junxiao Shie2099612019-02-15 14:46:27 +0000386 return g_conventionEncoding == Convention::MARKER ?
387 fromNumberWithMarker(SEQUENCE_NUMBER_MARKER, seqNo) :
388 fromNumber(seqNo, tlv::SequenceNumNameComponent);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700389}
390
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700391////////////////////////////////////////////////////////////////////////////////
392
393bool
394Component::isGeneric() const
395{
Junxiao Shicf4ac5b2018-03-28 22:46:06 +0000396 return type() == tlv::GenericNameComponent;
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700397}
398
399bool
400Component::isImplicitSha256Digest() const
401{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600402 return detail::getComponentType1().match(*this);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700403}
404
405Component
Davide Pesavento3b101d02018-07-21 22:44:09 -0400406Component::fromImplicitSha256Digest(ConstBufferPtr digest)
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700407{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600408 return detail::getComponentType1().create(digest);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700409}
410
411Component
412Component::fromImplicitSha256Digest(const uint8_t* digest, size_t digestSize)
413{
Junxiao Shi4053bd52018-08-16 13:39:25 -0600414 return detail::getComponentType1().create(digest, digestSize);
415}
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700416
Junxiao Shi4053bd52018-08-16 13:39:25 -0600417bool
418Component::isParametersSha256Digest() const
419{
420 return detail::getComponentType2().match(*this);
421}
422
423Component
424Component::fromParametersSha256Digest(ConstBufferPtr digest)
425{
426 return detail::getComponentType2().create(digest);
427}
428
429Component
430Component::fromParametersSha256Digest(const uint8_t* digest, size_t digestSize)
431{
432 return detail::getComponentType2().create(digest, digestSize);
Alexander Afanasyev6486d522014-10-23 14:14:11 -0700433}
434
435////////////////////////////////////////////////////////////////////////////////
436
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000437bool
438Component::equals(const Component& other) const
439{
440 return type() == other.type() &&
441 value_size() == other.value_size() &&
Davide Pesaventoe245b052017-10-31 13:00:44 -0400442 (empty() || // needed with Apple clang < 9.0.0 due to libc++ bug
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000443 std::equal(value_begin(), value_end(), other.value_begin()));
444}
445
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700446int
447Component::compare(const Component& other) const
448{
Junxiao Shi010f0862016-10-11 21:08:32 +0000449 if (this->hasWire() && other.hasWire()) {
450 // In the common case where both components have wire encoding,
451 // it's more efficient to simply compare the wire encoding.
452 // This works because lexical order of TLV encoding happens to be
453 // the same as canonical order of the value.
454 return std::memcmp(wire(), other.wire(), std::min(size(), other.size()));
455 }
456
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000457 int cmpType = type() - other.type();
458 if (cmpType != 0)
459 return cmpType;
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700460
Junxiao Shidf4b24e2016-07-14 21:41:43 +0000461 int cmpSize = value_size() - other.value_size();
462 if (cmpSize != 0)
463 return cmpSize;
464
Davide Pesaventoe245b052017-10-31 13:00:44 -0400465 if (empty())
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700466 return 0;
467
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700468 return std::memcmp(value(), other.value(), value_size());
469}
470
471Component
472Component::getSuccessor() const
473{
Junxiao Shid2e60632018-08-10 10:48:44 -0600474 bool isOverflow = false;
475 Component successor;
476 std::tie(isOverflow, successor) =
477 detail::getComponentTypeTable().get(type()).getSuccessor(*this);
478 if (!isOverflow) {
479 return successor;
Junxiao Shicf0aff82018-07-23 06:42:13 -0600480 }
481
Junxiao Shid2e60632018-08-10 10:48:44 -0600482 uint32_t type = this->type() + 1;
483 const std::vector<uint8_t>& value = detail::getComponentTypeTable().get(type).getMinValue();
484 return Component(type, value.data(), value.size());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700485}
486
Alexander Afanasyev74633892015-02-08 18:08:46 -0800487template<encoding::Tag TAG>
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700488size_t
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700489Component::wireEncode(EncodingImpl<TAG>& encoder) const
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700490{
491 size_t totalLength = 0;
492 if (value_size() > 0)
Alexander Afanasyevd5c48e02015-06-24 11:58:14 -0700493 totalLength += encoder.prependByteArray(value(), value_size());
494 totalLength += encoder.prependVarNumber(value_size());
495 totalLength += encoder.prependVarNumber(type());
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700496 return totalLength;
497}
498
Davide Pesavento88a0d812017-08-19 21:31:42 -0400499NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(Component);
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700500
501const Block&
502Component::wireEncode() const
503{
504 if (this->hasWire())
505 return *this;
506
507 EncodingEstimator estimator;
508 size_t estimatedSize = wireEncode(estimator);
509
510 EncodingBuffer buffer(estimatedSize, 0);
511 wireEncode(buffer);
512
513 const_cast<Component&>(*this) = buffer.block();
514 return *this;
515}
516
517void
518Component::wireDecode(const Block& wire)
519{
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700520 *this = wire;
Qiuhan Ding2c3cbe42014-11-25 18:10:23 -0800521 // validity check is done within Component(const Block& wire)
Alexander Afanasyev15f67312014-07-22 15:11:09 -0700522}
523
524} // namespace name
525} // namespace ndn