base: ensure Element::Error inherits from tlv::Error
Adding static asserts to ensure (Name|name::Component|Interest|
Selectors|Exclude|KeyLocator|Data|MetaInfo|Signature|SignatureInfo)
::Error are subclasses of tlv::Error.
This commit also adds WireEncodable and WireDecodable concept checks
to Name,name::Component,Interest,Selectors,Exclude,KeyLocator,Data,
MetaInfo,SignatureInfo types.
This commit also moves definition of Selectors method into .cpp.
refs #1983
Change-Id: I15220b93437d4a624ae09df66defc91ceac2386c
diff --git a/src/selectors.cpp b/src/selectors.cpp
new file mode 100644
index 0000000..bfb4df4
--- /dev/null
+++ b/src/selectors.cpp
@@ -0,0 +1,248 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "selectors.hpp"
+#include "encoding/encoding-buffer.hpp"
+#include "encoding/block-helpers.hpp"
+#include "util/concepts.hpp"
+
+namespace ndn {
+
+BOOST_CONCEPT_ASSERT((boost::EqualityComparable<Selectors>));
+BOOST_CONCEPT_ASSERT((WireEncodable<Selectors>));
+BOOST_CONCEPT_ASSERT((WireDecodable<Selectors>));
+static_assert(std::is_base_of<tlv::Error, Selectors::Error>::value,
+ "Selectors::Error must inherit from tlv::Error");
+
+Selectors::Selectors()
+ : m_minSuffixComponents(-1)
+ , m_maxSuffixComponents(-1)
+ , m_childSelector(-1)
+ , m_mustBeFresh(false)
+{
+}
+
+Selectors::Selectors(int minSuffixComponents, int maxSuffixComponents,
+ const Exclude& exclude,
+ int childSelector,
+ bool mustBeFresh)
+ : m_minSuffixComponents(minSuffixComponents)
+ , m_maxSuffixComponents(maxSuffixComponents)
+ , m_exclude(exclude)
+ , m_childSelector(childSelector)
+ , m_mustBeFresh(mustBeFresh)
+{
+}
+
+Selectors::Selectors(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+bool
+Selectors::empty() const
+{
+ return m_minSuffixComponents < 0 &&
+ m_maxSuffixComponents < 0 &&
+ m_publisherPublicKeyLocator.empty() &&
+ m_exclude.empty() &&
+ m_childSelector < 0 &&
+ !m_mustBeFresh;
+}
+
+template<bool T>
+size_t
+Selectors::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ // Selectors ::= SELECTORS-TYPE TLV-LENGTH
+ // MinSuffixComponents?
+ // MaxSuffixComponents?
+ // PublisherPublicKeyLocator?
+ // Exclude?
+ // ChildSelector?
+ // MustBeFresh?
+
+ // (reverse encoding)
+
+ // MustBeFresh
+ if (getMustBeFresh()) {
+ totalLength += prependBooleanBlock(block, tlv::MustBeFresh);
+ }
+
+ // ChildSelector
+ if (getChildSelector() >= 0) {
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::ChildSelector, getChildSelector());
+ }
+
+ // Exclude
+ if (!getExclude().empty()) {
+ totalLength += getExclude().wireEncode(block);
+ }
+
+ // PublisherPublicKeyLocator
+ if (!getPublisherPublicKeyLocator().empty()) {
+ totalLength += getPublisherPublicKeyLocator().wireEncode(block);
+ }
+
+ // MaxSuffixComponents
+ if (getMaxSuffixComponents() >= 0) {
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::MaxSuffixComponents,
+ getMaxSuffixComponents());
+ }
+
+ // MinSuffixComponents
+ if (getMinSuffixComponents() >= 0) {
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::MinSuffixComponents,
+ getMinSuffixComponents());
+ }
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::Selectors);
+ return totalLength;
+}
+
+template size_t
+Selectors::wireEncode<true>(EncodingImpl<true>& estimator) const;
+
+template size_t
+Selectors::wireEncode<false>(EncodingImpl<false>& encoder) const;
+
+const Block&
+Selectors::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+Selectors::wireDecode(const Block& wire)
+{
+ if (wire.type() != tlv::Selectors)
+ throw tlv::Error("Unexpected TLV type when decoding Selectors");
+
+ *this = Selectors();
+
+ m_wire = wire;
+ m_wire.parse();
+
+ // MinSuffixComponents
+ Block::element_const_iterator val = m_wire.find(tlv::MinSuffixComponents);
+ if (val != m_wire.elements_end()) {
+ m_minSuffixComponents = readNonNegativeInteger(*val);
+ }
+
+ // MaxSuffixComponents
+ val = m_wire.find(tlv::MaxSuffixComponents);
+ if (val != m_wire.elements_end()) {
+ m_maxSuffixComponents = readNonNegativeInteger(*val);
+ }
+
+ // PublisherPublicKeyLocator
+ val = m_wire.find(tlv::KeyLocator);
+ if (val != m_wire.elements_end()) {
+ m_publisherPublicKeyLocator.wireDecode(*val);
+ }
+
+ // Exclude
+ val = m_wire.find(tlv::Exclude);
+ if (val != m_wire.elements_end()) {
+ m_exclude.wireDecode(*val);
+ }
+
+ // ChildSelector
+ val = m_wire.find(tlv::ChildSelector);
+ if (val != m_wire.elements_end()) {
+ m_childSelector = readNonNegativeInteger(*val);
+ }
+
+ // MustBeFresh
+ val = m_wire.find(tlv::MustBeFresh);
+ if (val != m_wire.elements_end()) {
+ m_mustBeFresh = true;
+ }
+}
+
+Selectors&
+Selectors::setMinSuffixComponents(int minSuffixComponents)
+{
+ m_minSuffixComponents = minSuffixComponents;
+ m_wire.reset();
+ return *this;
+}
+
+Selectors&
+Selectors::setMaxSuffixComponents(int maxSuffixComponents)
+{
+ m_maxSuffixComponents = maxSuffixComponents;
+ m_wire.reset();
+ return *this;
+}
+
+Selectors&
+Selectors::setPublisherPublicKeyLocator(const KeyLocator& keyLocator)
+{
+ m_publisherPublicKeyLocator = keyLocator;
+ m_wire.reset();
+ return *this;
+}
+
+Selectors&
+Selectors::setExclude(const Exclude& exclude)
+{
+ m_exclude = exclude;
+ m_wire.reset();
+ return *this;
+}
+
+Selectors&
+Selectors::setChildSelector(int childSelector)
+{
+ m_childSelector = childSelector;
+ m_wire.reset();
+ return *this;
+}
+
+Selectors&
+Selectors::setMustBeFresh(bool mustBeFresh)
+{
+ m_mustBeFresh = mustBeFresh;
+ m_wire.reset();
+ return *this;
+}
+
+bool
+Selectors::operator==(const Selectors& other) const
+{
+ return wireEncode() == other.wireEncode();
+}
+
+} // namespace ndn