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