blob: 4503c17cd3dcbad407b98d39d6fb85a369dd3699 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
* Copyright (c) 2013-2014, Regents of the University of California.
* All rights reserved.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
* This file licensed under New BSD License. See COPYING for detailed information about
* ndn-cxx library copyright, permissions, and redistribution restrictions.
*/
#ifndef NDN_SELECTORS_HPP
#define NDN_SELECTORS_HPP
#include "common.hpp"
#include "key-locator.hpp"
#include "exclude.hpp"
#include "encoding/encoding-buffer.hpp"
namespace ndn {
/**
* @brief Abstraction implementing Interest selectors
*/
class Selectors
{
public:
Selectors()
: m_minSuffixComponents(-1)
, m_maxSuffixComponents(-1)
, m_childSelector(-1)
, m_mustBeFresh(false)
{
}
/** @deprecated Selectors().setX(...).setY(...)
*/
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)
{
}
/**
* @brief Create from wire encoding
*/
Selectors(const Block& wire)
{
wireDecode(wire);
}
bool
empty() const;
/**
* @brief Fast encoding or block size estimation
*/
template<bool T>
size_t
wireEncode(EncodingImpl<T>& block) const;
/**
* @brief Encode to a wire format
*/
const Block&
wireEncode() const;
/**
* @brief Decode the input from wire format
*/
void
wireDecode(const Block& wire);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int
getMinSuffixComponents() const
{
return m_minSuffixComponents;
}
Selectors&
setMinSuffixComponents(int minSuffixComponents)
{
m_minSuffixComponents = minSuffixComponents;
m_wire.reset();
return *this;
}
//
int
getMaxSuffixComponents() const
{
return m_maxSuffixComponents;
}
Selectors&
setMaxSuffixComponents(int maxSuffixComponents)
{
m_maxSuffixComponents = maxSuffixComponents;
m_wire.reset();
return *this;
}
//
const KeyLocator&
getPublisherPublicKeyLocator() const
{
return m_publisherPublicKeyLocator;
}
Selectors&
setPublisherPublicKeyLocator(const KeyLocator& keyLocator)
{
m_publisherPublicKeyLocator = keyLocator;
m_wire.reset();
return *this;
}
//
const Exclude&
getExclude() const
{
return m_exclude;
}
Selectors&
setExclude(const Exclude& exclude)
{
m_exclude = exclude;
m_wire.reset();
return *this;
}
//
int
getChildSelector() const
{
return m_childSelector;
}
Selectors&
setChildSelector(int childSelector)
{
m_childSelector = childSelector;
m_wire.reset();
return *this;
}
//
int
getMustBeFresh() const
{
return m_mustBeFresh;
}
Selectors&
setMustBeFresh(bool mustBeFresh)
{
m_mustBeFresh = mustBeFresh;
m_wire.reset();
return *this;
}
public: // EqualityComparable concept
bool
operator==(const Selectors& other) const
{
return wireEncode() == other.wireEncode();
}
bool
operator!=(const Selectors& other) const
{
return !(*this == other);
}
private:
int m_minSuffixComponents;
int m_maxSuffixComponents;
KeyLocator m_publisherPublicKeyLocator;
Exclude m_exclude;
int m_childSelector;
bool m_mustBeFresh;
mutable Block m_wire;
};
inline 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>
inline 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;
}
inline 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;
}
inline 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 aka AnswerOriginKind
val = m_wire.find(Tlv::MustBeFresh);
if (val != m_wire.elements_end())
{
m_mustBeFresh = true;
}
}
} // namespace ndn
#endif // NDN_SELECTORS_HPP