delegation-list.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2019 Regents of the University of California.
4  *
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 
24 
25 namespace ndn {
26 
27 BOOST_CONCEPT_ASSERT((boost::EqualityComparable<DelegationList>));
28 BOOST_CONCEPT_ASSERT((WireEncodableWithEncodingBuffer<DelegationList>));
29 BOOST_CONCEPT_ASSERT((WireDecodable<DelegationList>));
30 
32  : m_isSorted(true)
33 {
34 }
35 
36 DelegationList::DelegationList(std::initializer_list<Delegation> dels)
37  : m_isSorted(true)
38 {
39  for (const Delegation& del : dels) {
40  this->insert(del, INS_REPLACE);
41  }
42 }
43 
44 DelegationList::DelegationList(const Block& block, bool wantSort)
45 {
46  this->wireDecode(block, wantSort);
47 }
48 
49 bool
50 DelegationList::isValidTlvType(uint32_t type)
51 {
52  switch (type) {
53  case tlv::Content:
55  return true;
56  default:
57  return false;
58  }
59 }
60 
61 template<encoding::Tag TAG>
62 size_t
63 DelegationList::wireEncode(EncodingImpl<TAG>& encoder, uint32_t type) const
64 {
65  if (!isValidTlvType(type)) {
66  NDN_THROW(std::invalid_argument("Unexpected TLV-TYPE " + to_string(type) +
67  " while encoding DelegationList"));
68  }
69 
70  if (this->size() == 0) {
71  NDN_THROW(Error("Empty DelegationList"));
72  }
73 
74  // LinkContent ::= (type) TLV-LENGTH
75  // Delegation+
76 
77  // Delegation ::= LINK-DELEGATION-TYPE TLV-LENGTH
78  // Preference
79  // Name
80 
81  // Preference ::= LINK-PREFERENCE-TYPE TLV-LENGTH
82  // nonNegativeInteger
83 
84  size_t totalLen = 0;
85  for (auto i = m_dels.rbegin(); i != m_dels.rend(); ++i) {
86  size_t delLen = 0;
87  delLen += i->name.wireEncode(encoder);
88  delLen += prependNonNegativeIntegerBlock(encoder, tlv::LinkPreference, i->preference);
89  delLen += encoder.prependVarNumber(delLen);
90  delLen += encoder.prependVarNumber(tlv::LinkDelegation);
91  totalLen += delLen;
92  }
93  totalLen += encoder.prependVarNumber(totalLen);
94  totalLen += encoder.prependVarNumber(type);
95  return totalLen;
96 }
97 
98 template size_t
99 DelegationList::wireEncode<encoding::EncoderTag>(EncodingBuffer&, uint32_t) const;
100 
101 template size_t
102 DelegationList::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, uint32_t) const;
103 
104 void
105 DelegationList::wireDecode(const Block& block, bool wantSort)
106 {
107  if (!isValidTlvType(block.type())) {
108  NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(block.type()) + " while decoding DelegationList"));
109  }
110 
111  m_isSorted = wantSort;
112  m_dels.clear();
113 
114  block.parse();
115  for (const auto& del : block.elements()) {
116  if (del.type() != tlv::LinkDelegation) {
117  NDN_THROW(Error("Unexpected TLV-TYPE " + to_string(del.type()) + " while decoding Delegation"));
118  }
119  del.parse();
120 
121  auto val = del.elements_begin();
122  if (val == del.elements_end() || val->type() != tlv::LinkPreference) {
123  NDN_THROW(Error("Missing Preference field in Delegation"));
124  }
125  uint64_t preference = 0;
126  try {
127  preference = readNonNegativeInteger(*val);
128  }
129  catch (const tlv::Error&) {
130  NDN_THROW_NESTED(Error("Invalid Preference field in Delegation"));
131  }
132 
133  ++val;
134  if (val == del.elements_end() || val->type() != tlv::Name) {
135  NDN_THROW(Error("Missing Name field in Delegation"));
136  }
137  Name name;
138  try {
139  name.wireDecode(*val);
140  }
141  catch (const tlv::Error&) {
142  NDN_THROW_NESTED(Error("Invalid Name field in Delegation"));
143  }
144 
145  this->insertImpl(preference, name);
146  }
147 
148  if (this->size() == 0) {
149  NDN_THROW(Error("Empty DelegationList"));
150  }
151 }
152 
153 void
155 {
156  if (m_isSorted) {
157  return;
158  }
159 
160  std::vector<Delegation> dels;
161  dels.swap(m_dels);
162 
163  m_isSorted = true;
164  for (const Delegation& del : dels) {
165  this->insertImpl(del.preference, del.name);
166  }
167 }
168 
169 bool
170 DelegationList::insert(uint64_t preference, const Name& name,
171  InsertConflictResolution onConflict)
172 {
173  switch (onConflict) {
174  case INS_REPLACE:
175  this->eraseImpl(nullopt, name);
176  this->insertImpl(preference, name);
177  return true;
178  case INS_APPEND:
179  this->insertImpl(preference, name);
180  return true;
181  case INS_SKIP:
182  if (!std::any_of(m_dels.begin(), m_dels.end(),
183  [name] (const Delegation& del) { return del.name == name; })) {
184  this->insertImpl(preference, name);
185  return true;
186  }
187  return false;
188  }
189 
190  NDN_THROW(std::invalid_argument("Unknown InsertConflictResolution"));
191 }
192 
193 void
194 DelegationList::insertImpl(uint64_t preference, const Name& name)
195 {
196  if (!m_isSorted) {
197  m_dels.push_back({preference, name});
198  return;
199  }
200 
201  Delegation del{preference, name};
202  auto pos = std::upper_bound(m_dels.begin(), m_dels.end(), del);
203  m_dels.insert(pos, del);
204 }
205 
206 size_t
207 DelegationList::eraseImpl(optional<uint64_t> preference, const Name& name)
208 {
209  size_t nErased = 0;
210  for (auto i = m_dels.begin(); i != m_dels.end();) {
211  if ((!preference || i->preference == *preference) &&
212  i->name == name) {
213  ++nErased;
214  i = m_dels.erase(i);
215  }
216  else {
217  ++i;
218  }
219  }
220  return nErased;
221 }
222 
223 std::ostream&
224 operator<<(std::ostream& os, const DelegationList& dl)
225 {
226  os << '[';
227  std::copy(dl.begin(), dl.end(), make_ostream_joiner(os, ','));
228  return os << ']';
229 }
230 
231 } // namespace ndn
#define NDN_THROW_NESTED(e)
Definition: exception.hpp:71
Definition: data.cpp:26
existing delegation(s) with the same name are replaced with the new delegation
size_t prependNonNegativeIntegerBlock(EncodingImpl< TAG > &encoder, uint32_t type, uint64_t value)
Prepend a TLV element containing a non-negative integer.
std::string to_string(const T &val)
Definition: backports.hpp:102
new delegation is not inserted if an existing delegation has the same name
DelegationList()
construct an empty DelegationList
std::ostream & operator<<(std::ostream &os, const Data &data)
Definition: data.cpp:322
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:325
Represents a TLV element of NDN packet format.
Definition: block.hpp:42
uint64_t readNonNegativeInteger(const Block &block)
Read a non-negative integer from a TLV element.
const element_container & elements() const
Get container of sub-elements.
Definition: block.hpp:391
#define NDN_THROW(e)
Definition: exception.hpp:61
void wireDecode(const Block &block, bool wantSort=true)
decode a DelegationList
const_iterator end() const noexcept
Backport of ostream_joiner from the Library Fundamentals v2 TS.
ostream_joiner< std::decay_t< DelimT >, CharT, Traits > make_ostream_joiner(std::basic_ostream< CharT, Traits > &os, DelimT &&delimiter)
size_t wireEncode(EncodingImpl< TAG > &encoder, uint32_t type=tlv::ForwardingHint) const
encode into wire format
size_t size() const noexcept
Represents an absolute name.
Definition: name.hpp:43
bool insert(uint64_t preference, const Name &name, InsertConflictResolution onConflict=INS_REPLACE)
insert Delegation
InsertConflictResolution
what to do when inserting a duplicate name
Represents a Delegation.
Definition: delegation.hpp:32
void sort()
sort the delegation list
represents a list of Delegations
void wireDecode(const Block &wire)
Decode name from wire encoding.
Definition: name.cpp:150
multiple delegations with the same name are kept in the DelegationList
EncodingImpl< EncoderTag > EncodingBuffer
const nullopt_t nullopt((nullopt_t::init()))
uint32_t type() const
Return the TLV-TYPE of the Block.
Definition: block.hpp:274
represents an error in TLV encoding or decoding
Definition: tlv.hpp:52
EncodingImpl< EstimatorTag > EncodingEstimator
const_iterator begin() const noexcept