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