blob: 656a485ab361875ab7869353546869c833559669 [file] [log] [blame]
Junxiao Shi688a6412017-06-22 10:12:07 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shibb8d4a32017-07-13 02:40:09 +00002/*
Junxiao Shi68b53852018-07-25 13:56:38 -06003 * Copyright (c) 2013-2018 Regents of the University of California.
Junxiao Shi688a6412017-06-22 10:12:07 +00004 *
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
22#ifndef NDN_DELEGATION_LIST_HPP
23#define NDN_DELEGATION_LIST_HPP
24
25#include "delegation.hpp"
Junxiao Shid21abd32017-06-30 02:56:40 +000026#include <initializer_list>
Junxiao Shi688a6412017-06-22 10:12:07 +000027
28namespace ndn {
29
30/** \brief represents a list of Delegations
31 * \sa https://named-data.net/doc/ndn-tlv/link.html
32 *
33 * Delegations are stored in an std::vector, under the assumption that there is usually only a
34 * small number of Delegations, so that copying is acceptable when they are modified.
35 */
36class DelegationList
37{
38public:
39 class Error : public tlv::Error
40 {
41 public:
Junxiao Shi68b53852018-07-25 13:56:38 -060042 using tlv::Error::Error;
Junxiao Shi688a6412017-06-22 10:12:07 +000043
44 Error(const std::string& what, const std::exception& innerException);
45 };
46
47 /** \brief construct an empty DelegationList
48 */
49 DelegationList();
50
Junxiao Shid21abd32017-06-30 02:56:40 +000051 /** \brief construct a sorted DelegationList with specified delegations
52 *
53 * This is equivalent to inserting each delegation into an empty DelegationList with INS_REPLACE
54 * conflict resolution.
55 */
56 DelegationList(std::initializer_list<Delegation> dels);
57
Junxiao Shi688a6412017-06-22 10:12:07 +000058 /** \brief decode a DelegationList
59 * \sa wireDecode
60 */
61 explicit
62 DelegationList(const Block& block, bool wantSort = true);
63
64 /** \brief encode into wire format
65 * \param encoder either an EncodingBuffer or an EncodingEstimator
Junxiao Shi7d3c14b2017-08-05 16:34:39 +000066 * \param type TLV-TYPE number, either Content (for \p Link) or ForwardingHint
Junxiao Shi688a6412017-06-22 10:12:07 +000067 * \throw std::invalid_argument \p type is invalid
68 * \throw Error there is no Delegation
69 */
70 template<encoding::Tag TAG>
71 size_t
72 wireEncode(EncodingImpl<TAG>& encoder, uint32_t type = tlv::ForwardingHint) const;
73
74 /** \brief decode a DelegationList
75 * \param block either a Content block (from \p Link) or a ForwardingHint block
76 * \param wantSort if true, delegations are sorted
77 * \throw Error the block cannot be parsed as a list of Delegations
78 */
79 void
80 wireDecode(const Block& block, bool wantSort = true);
81
82 bool
Junxiao Shibb8d4a32017-07-13 02:40:09 +000083 isSorted() const noexcept
Junxiao Shi688a6412017-06-22 10:12:07 +000084 {
85 return m_isSorted;
86 }
87
88 using const_iterator = std::vector<Delegation>::const_iterator;
89
90 const_iterator
Junxiao Shibb8d4a32017-07-13 02:40:09 +000091 begin() const noexcept
Junxiao Shi688a6412017-06-22 10:12:07 +000092 {
93 return m_dels.begin();
94 }
95
96 const_iterator
Junxiao Shibb8d4a32017-07-13 02:40:09 +000097 end() const noexcept
Junxiao Shi688a6412017-06-22 10:12:07 +000098 {
99 return m_dels.end();
100 }
101
Junxiao Shibb8d4a32017-07-13 02:40:09 +0000102 bool
103 empty() const noexcept
104 {
105 return m_dels.empty();
106 }
107
Junxiao Shi688a6412017-06-22 10:12:07 +0000108 size_t
Junxiao Shibb8d4a32017-07-13 02:40:09 +0000109 size() const noexcept
Junxiao Shi688a6412017-06-22 10:12:07 +0000110 {
111 return m_dels.size();
112 }
113
114 /** \brief get the i-th delegation
115 * \pre i < size()
116 */
117 const Delegation&
118 operator[](size_t i) const
119 {
120 BOOST_ASSERT(i < size());
121 return m_dels[i];
122 }
123
124 /** \brief get the i-th delegation
125 * \throw std::out_of_range i >= size()
126 */
127 const Delegation&
128 at(size_t i) const
129 {
130 return m_dels.at(i);
131 }
132
133public: // modifiers
134 /** \brief sort the delegation list
135 * \post isSorted() == true
136 * \post Delegations are sorted in increasing preference order.
137 *
138 * A DelegationList can be constructed as sorted or unsorted. In most cases, it is recommended
139 * to use a sorted DelegationList. An unsorted DelegationList is useful for extracting the i-th
140 * delegation from a received ForwardingHint or Link object.
141 *
142 * This method turns an unsorted DelegationList into a sorted DelegationList.
143 * If access to unsorted DelegationList is not needed, it is more efficient to sort the
144 * DelegationList in wireDecode.
145 */
146 void
147 sort();
148
149 /** \brief what to do when inserting a duplicate name
150 */
151 enum InsertConflictResolution {
152 /** \brief existing delegation(s) with the same name are replaced with the new delegation
153 */
154 INS_REPLACE,
155
156 /** \brief multiple delegations with the same name are kept in the DelegationList
157 * \note This is NOT RECOMMENDED by Link specification.
158 */
159 INS_APPEND,
160
161 /** \brief new delegation is not inserted if an existing delegation has the same name
162 */
163 INS_SKIP
164 };
165
166 /** \brief insert Delegation
167 * \return whether inserted
168 */
169 bool
170 insert(uint64_t preference, const Name& name,
171 InsertConflictResolution onConflict = INS_REPLACE);
172
173 /** \brief insert Delegation
174 * \return whether inserted
175 */
176 bool
177 insert(const Delegation& del, InsertConflictResolution onConflict = INS_REPLACE)
178 {
179 return this->insert(del.preference, del.name, onConflict);
180 }
181
182 /** \brief delete Delegation(s) with specified preference and name
183 * \return count of erased Delegation(s)
184 */
185 size_t
186 erase(uint64_t preference, const Name& name)
187 {
188 return this->eraseImpl(preference, name);
189 }
190
191 /** \brief delete Delegation(s) with matching preference and name
192 * \return count of erased Delegation(s)
193 */
194 size_t
195 erase(const Delegation& del)
196 {
197 return this->eraseImpl(del.preference, del.name);
198 }
199
200 /** \brief erase Delegation(s) with specified name
201 * \return count of erased Delegation(s)
202 */
203 size_t
204 erase(const Name& name)
205 {
206 return this->eraseImpl(nullopt, name);
207 }
208
209private:
210 static bool
211 isValidTlvType(uint32_t type);
212
213 void
214 insertImpl(uint64_t preference, const Name& name);
215
216 size_t
217 eraseImpl(optional<uint64_t> preference, const Name& name);
218
219private:
220 bool m_isSorted;
221
222 /** \brief delegation container; its contents are sorted when \p m_isSorted is true
223 * \note This container is a member field rather than a base class, in order to ensure contents
224 * are sorted when \p m_isSorted is true.
225 * \note A vector is chosen instead of a std::set, so that the container can be unsorted when
226 * \p m_isSorted is false. This container is expected to have less than seven items, and
227 * therefore the overhead of moving items during insertion and deletion is small.
228 */
229 std::vector<Delegation> m_dels;
230
231 friend bool operator==(const DelegationList&, const DelegationList&);
232};
233
Davide Pesavento88a0d812017-08-19 21:31:42 -0400234#ifndef DOXYGEN
235extern template size_t
236DelegationList::wireEncode<encoding::EncoderTag>(EncodingBuffer&, uint32_t) const;
237
238extern template size_t
239DelegationList::wireEncode<encoding::EstimatorTag>(EncodingEstimator&, uint32_t) const;
240#endif
241
Junxiao Shi688a6412017-06-22 10:12:07 +0000242/** \brief compare whether two DelegationLists are equal
243 * \note Order matters! If two DelegationLists contain the same Delegations but at least one is
244 * unsorted, they may compare unequal if the Delegations appear in different order.
245 */
246bool
247operator==(const DelegationList& lhs, const DelegationList& rhs);
248
249inline bool
250operator!=(const DelegationList& lhs, const DelegationList& rhs)
251{
252 return !(lhs == rhs);
253}
254
255std::ostream&
256operator<<(std::ostream& os, const DelegationList& dl);
257
258} // namespace ndn
259
260#endif // NDN_DELEGATION_LIST_HPP