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