blob: 8a8c4bb71499d06eb9ee697886f1f67d2ec7c8d6 [file] [log] [blame]
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Shuo Chenba793e92014-03-17 17:17:16 -07002/**
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07003 * Copyright (c) 2014, Regents of the University of California.
4 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Shuo Chenba793e92014-03-17 17:17:16 -070018 */
19
Alexander Afanasyev39d98072014-05-04 12:46:29 -070020#ifndef REPO_REPO_COMMAND_PARAMETER_HPP
21#define REPO_REPO_COMMAND_PARAMETER_HPP
Shuo Chenba793e92014-03-17 17:17:16 -070022
Alexander Afanasyeve291caf2014-04-25 11:17:36 -070023#include <ndn-cxx/encoding/encoding-buffer.hpp>
24#include <ndn-cxx/name.hpp>
25#include <ndn-cxx/selectors.hpp>
Shuo Chenba793e92014-03-17 17:17:16 -070026#include "repo-tlv.hpp"
27
28namespace repo {
29
30using ndn::Name;
31using ndn::Block;
32using ndn::EncodingImpl;
33using ndn::Selectors;
34using ndn::EncodingEstimator;
35using ndn::EncodingBuffer;
36
37/**
38* @brief Class defining abstraction of parameter of command for NDN Repo Protocol
39* @sa link http://redmine.named-data.net/projects/repo-ng/wiki/Repo_Protocol_Specification#RepoCommandParameter
40**/
41
42class RepoCommandParameter
43{
44public:
45 class Error : public ndn::Tlv::Error
46 {
47 public:
48 explicit
49 Error(const std::string& what)
50 : ndn::Tlv::Error(what)
51 {
52 }
53 };
54
55 RepoCommandParameter()
56 : m_hasName(false)
57 , m_hasStartBlockId(false)
58 , m_hasEndBlockId(false)
59 , m_hasProcessId(false)
60 {
61 }
62
63 explicit
64 RepoCommandParameter(const Block& block)
65 {
66 wireDecode(block);
67 }
68
69 const Name&
70 getName() const
71 {
72 return m_name;
73 }
74
75 RepoCommandParameter&
76 setName(const Name& name)
77 {
78 m_name = name;
79 m_hasName = true;
80 m_wire.reset();
81 return *this;
82 }
83
84 bool
85 hasName() const
86 {
87 return m_hasName;
88 }
89
90 const Selectors&
91 getSelectors() const
92 {
93 return m_selectors;
94 }
95
96 RepoCommandParameter&
97 setSelectors(const Selectors& selectors)
98 {
99 m_selectors = selectors;
100 m_wire.reset();
101 return *this;
102 }
103
104 bool
105 hasSelectors() const
106 {
107 return !m_selectors.empty();
108 }
109
110 uint64_t
111 getStartBlockId() const
112 {
113 assert(hasStartBlockId());
114 return m_startBlockId;
115 }
116
117 RepoCommandParameter&
118 setStartBlockId(uint64_t startBlockId)
119 {
120 m_startBlockId = startBlockId;
121 m_hasStartBlockId = true;
122 m_wire.reset();
123 return *this;
124 }
125
126 bool
127 hasStartBlockId() const
128 {
129 return m_hasStartBlockId;
130 }
131
132 uint64_t
133 getEndBlockId() const
134 {
135 assert(hasEndBlockId());
136 return m_endBlockId;
137 }
138
139 RepoCommandParameter&
140 setEndBlockId(uint64_t endBlockId)
141 {
142 m_endBlockId = endBlockId;
143 m_hasEndBlockId = true;
144 m_wire.reset();
145 return *this;
146 }
147
148 bool
149 hasEndBlockId() const
150 {
151 return m_hasEndBlockId;
152 }
153
154 uint64_t
155 getProcessId() const
156 {
157 assert(hasProcessId());
158 return m_processId;
159 }
160
161 bool
162 hasProcessId() const
163 {
164 return m_hasProcessId;
165 }
166
167 RepoCommandParameter&
168 setProcessId(uint64_t processId)
169 {
170 m_processId = processId;
171 m_hasProcessId = true;
172 m_wire.reset();
173 return *this;
174 }
175
176 template<bool T>
177 size_t
178 wireEncode(EncodingImpl<T>& block) const;
179
180 const Block&
181 wireEncode() const;
182
183 void
184 wireDecode(const Block& wire);
185
186private:
187
188 Name m_name;
189 Selectors m_selectors;
190 uint64_t m_startBlockId;
191 uint64_t m_endBlockId;
192 uint64_t m_processId;
193
194 bool m_hasName;
195 bool m_hasStartBlockId;
196 bool m_hasEndBlockId;
197 bool m_hasProcessId;
198
199 mutable Block m_wire;
200};
201
202template<bool T>
203inline size_t
204RepoCommandParameter::wireEncode(EncodingImpl<T>& encoder) const
205{
206 size_t totalLength = 0;
207 size_t variableLength = 0;
208
209 if (m_hasProcessId) {
210 variableLength = encoder.prependNonNegativeInteger(m_processId);
211 totalLength += variableLength;
212 totalLength += encoder.prependVarNumber(variableLength);
213 totalLength += encoder.prependVarNumber(tlv::ProcessId);
214 }
215
216 if (m_hasEndBlockId) {
217 variableLength = encoder.prependNonNegativeInteger(m_endBlockId);
218 totalLength += variableLength;
219 totalLength += encoder.prependVarNumber(variableLength);
220 totalLength += encoder.prependVarNumber(tlv::EndBlockId);
221 }
222
223 if (m_hasStartBlockId) {
224 variableLength = encoder.prependNonNegativeInteger(m_startBlockId);
225 totalLength += variableLength;
226 totalLength += encoder.prependVarNumber(variableLength);
227 totalLength += encoder.prependVarNumber(tlv::StartBlockId);
228 }
229
230 if (!getSelectors().empty()) {
231 totalLength += getSelectors().wireEncode(encoder);
232 }
233
234 if (m_hasName) {
235 totalLength += getName().wireEncode(encoder);
236 }
237
238 totalLength += encoder.prependVarNumber(totalLength);
239 totalLength += encoder.prependVarNumber(tlv::RepoCommandParameter);
240 return totalLength;
241}
242
243inline const Block&
244RepoCommandParameter::wireEncode() const
245{
246 if (m_wire.hasWire())
247 return m_wire;
248
249 EncodingEstimator estimator;
250 size_t estimatedSize = wireEncode(estimator);
251
252 EncodingBuffer buffer(estimatedSize, 0);
253 wireEncode(buffer);
254
255 m_wire = buffer.block();
256 return m_wire;
257}
258
259inline void
260RepoCommandParameter::wireDecode(const Block& wire)
261{
262 m_hasName = false;
263 m_hasStartBlockId = false;
264 m_hasEndBlockId = false;
265 m_hasProcessId = false;
266
267 m_wire = wire;
268
269 m_wire.parse();
270
271 if (m_wire.type() != tlv::RepoCommandParameter)
272 throw Error("Requested decoding of RepoCommandParameter, but Block is of different type");
273
274 // Name
275 Block::element_const_iterator val = m_wire.find(tlv::Name);
276 if (val != m_wire.elements_end())
277 {
278 m_hasName = true;
279 m_name.wireDecode(m_wire.get(tlv::Name));
280 }
281
282 // Selectors
283 val = m_wire.find(tlv::Selectors);
284 if (val != m_wire.elements_end())
285 {
286 m_selectors.wireDecode(*val);
287 }
288 else
289 m_selectors = Selectors();
290
291 // StartBlockId
292 val = m_wire.find(tlv::StartBlockId);
293 if (val != m_wire.elements_end())
294 {
295 m_hasStartBlockId = true;
296 m_startBlockId = readNonNegativeInteger(*val);
297 }
298
299 // EndBlockId
300 val = m_wire.find(tlv::EndBlockId);
301 if (val != m_wire.elements_end())
302 {
303 m_hasEndBlockId = true;
304 m_endBlockId = readNonNegativeInteger(*val);
305 }
306
307 // ProcessId
308 val = m_wire.find(tlv::ProcessId);
309 if (val != m_wire.elements_end())
310 {
311 m_hasProcessId = true;
312 m_processId = readNonNegativeInteger(*val);
313 }
314
315}
316
317inline std::ostream&
318operator<<(std::ostream& os, const RepoCommandParameter& repoCommandParameter)
319{
320 os << "RepoCommandParameter(";
321
322 // Name
323 if (repoCommandParameter.hasName()) {
324 os << " Name: " << repoCommandParameter.getName();
325 }
326 if (repoCommandParameter.hasStartBlockId()) {
327 // StartBlockId
328 os << " StartBlockId: " << repoCommandParameter.getStartBlockId();
329 }
330 // EndBlockId
331 if (repoCommandParameter.hasEndBlockId()) {
332 os << " EndBlockId: " << repoCommandParameter.getEndBlockId();
333 }
334 //ProcessId
335 if (repoCommandParameter.hasProcessId()) {
336 os << " ProcessId: " << repoCommandParameter.getProcessId();
337 }
338 os << " )";
339 return os;
340}
341
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700342} // namespace repo
Shuo Chenba793e92014-03-17 17:17:16 -0700343
Alexander Afanasyev39d98072014-05-04 12:46:29 -0700344#endif // REPO_REPO_COMMAND_PARAMETER_HPP