blob: 9ef5d97ebfa3670b23e8e934037b109b70527e3a [file] [log] [blame]
Junxiao Shi688a6412017-06-22 10:12:07 +00001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 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
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:
42 explicit
43 Error(const std::string& what);
44
45 Error(const std::string& what, const std::exception& innerException);
46 };
47
48 /** \brief construct an empty DelegationList
49 */
50 DelegationList();
51
Junxiao Shid21abd32017-06-30 02:56:40 +000052 /** \brief construct a sorted DelegationList with specified delegations
53 *
54 * This is equivalent to inserting each delegation into an empty DelegationList with INS_REPLACE
55 * conflict resolution.
56 */
57 DelegationList(std::initializer_list<Delegation> dels);
58
Junxiao Shi688a6412017-06-22 10:12:07 +000059 /** \brief decode a DelegationList
60 * \sa wireDecode
61 */
62 explicit
63 DelegationList(const Block& block, bool wantSort = true);
64
65 /** \brief encode into wire format
66 * \param encoder either an EncodingBuffer or an EncodingEstimator
67 * \param type TLV-TYPE code, either Content (for \p Link) or ForwardingHint
68 * \throw std::invalid_argument \p type is invalid
69 * \throw Error there is no Delegation
70 */
71 template<encoding::Tag TAG>
72 size_t
73 wireEncode(EncodingImpl<TAG>& encoder, uint32_t type = tlv::ForwardingHint) const;
74
75 /** \brief decode a DelegationList
76 * \param block either a Content block (from \p Link) or a ForwardingHint block
77 * \param wantSort if true, delegations are sorted
78 * \throw Error the block cannot be parsed as a list of Delegations
79 */
80 void
81 wireDecode(const Block& block, bool wantSort = true);
82
83 bool
84 isSorted() const
85 {
86 return m_isSorted;
87 }
88
89 using const_iterator = std::vector<Delegation>::const_iterator;
90
91 const_iterator
92 begin() const
93 {
94 return m_dels.begin();
95 }
96
97 const_iterator
98 end() const
99 {
100 return m_dels.end();
101 }
102
103 size_t
104 size() const
105 {
106 return m_dels.size();
107 }
108
109 /** \brief get the i-th delegation
110 * \pre i < size()
111 */
112 const Delegation&
113 operator[](size_t i) const
114 {
115 BOOST_ASSERT(i < size());
116 return m_dels[i];
117 }
118
119 /** \brief get the i-th delegation
120 * \throw std::out_of_range i >= size()
121 */
122 const Delegation&
123 at(size_t i) const
124 {
125 return m_dels.at(i);
126 }
127
128public: // modifiers
129 /** \brief sort the delegation list
130 * \post isSorted() == true
131 * \post Delegations are sorted in increasing preference order.
132 *
133 * A DelegationList can be constructed as sorted or unsorted. In most cases, it is recommended
134 * to use a sorted DelegationList. An unsorted DelegationList is useful for extracting the i-th
135 * delegation from a received ForwardingHint or Link object.
136 *
137 * This method turns an unsorted DelegationList into a sorted DelegationList.
138 * If access to unsorted DelegationList is not needed, it is more efficient to sort the
139 * DelegationList in wireDecode.
140 */
141 void
142 sort();
143
144 /** \brief what to do when inserting a duplicate name
145 */
146 enum InsertConflictResolution {
147 /** \brief existing delegation(s) with the same name are replaced with the new delegation
148 */
149 INS_REPLACE,
150
151 /** \brief multiple delegations with the same name are kept in the DelegationList
152 * \note This is NOT RECOMMENDED by Link specification.
153 */
154 INS_APPEND,
155
156 /** \brief new delegation is not inserted if an existing delegation has the same name
157 */
158 INS_SKIP
159 };
160
161 /** \brief insert Delegation
162 * \return whether inserted
163 */
164 bool
165 insert(uint64_t preference, const Name& name,
166 InsertConflictResolution onConflict = INS_REPLACE);
167
168 /** \brief insert Delegation
169 * \return whether inserted
170 */
171 bool
172 insert(const Delegation& del, InsertConflictResolution onConflict = INS_REPLACE)
173 {
174 return this->insert(del.preference, del.name, onConflict);
175 }
176
177 /** \brief delete Delegation(s) with specified preference and name
178 * \return count of erased Delegation(s)
179 */
180 size_t
181 erase(uint64_t preference, const Name& name)
182 {
183 return this->eraseImpl(preference, name);
184 }
185
186 /** \brief delete Delegation(s) with matching preference and name
187 * \return count of erased Delegation(s)
188 */
189 size_t
190 erase(const Delegation& del)
191 {
192 return this->eraseImpl(del.preference, del.name);
193 }
194
195 /** \brief erase Delegation(s) with specified name
196 * \return count of erased Delegation(s)
197 */
198 size_t
199 erase(const Name& name)
200 {
201 return this->eraseImpl(nullopt, name);
202 }
203
204private:
205 static bool
206 isValidTlvType(uint32_t type);
207
208 void
209 insertImpl(uint64_t preference, const Name& name);
210
211 size_t
212 eraseImpl(optional<uint64_t> preference, const Name& name);
213
214private:
215 bool m_isSorted;
216
217 /** \brief delegation container; its contents are sorted when \p m_isSorted is true
218 * \note This container is a member field rather than a base class, in order to ensure contents
219 * are sorted when \p m_isSorted is true.
220 * \note A vector is chosen instead of a std::set, so that the container can be unsorted when
221 * \p m_isSorted is false. This container is expected to have less than seven items, and
222 * therefore the overhead of moving items during insertion and deletion is small.
223 */
224 std::vector<Delegation> m_dels;
225
226 friend bool operator==(const DelegationList&, const DelegationList&);
227};
228
229/** \brief compare whether two DelegationLists are equal
230 * \note Order matters! If two DelegationLists contain the same Delegations but at least one is
231 * unsorted, they may compare unequal if the Delegations appear in different order.
232 */
233bool
234operator==(const DelegationList& lhs, const DelegationList& rhs);
235
236inline bool
237operator!=(const DelegationList& lhs, const DelegationList& rhs)
238{
239 return !(lhs == rhs);
240}
241
242std::ostream&
243operator<<(std::ostream& os, const DelegationList& dl);
244
245} // namespace ndn
246
247#endif // NDN_DELEGATION_LIST_HPP