]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | #ifndef CEPH_ENCODING_H | |
15 | #define CEPH_ENCODING_H | |
16 | ||
17 | #include "include/int_types.h" | |
18 | ||
19 | #include "include/memory.h" | |
20 | ||
21 | #include "byteorder.h" | |
22 | #include "buffer.h" | |
23 | ||
24 | // pull in the new-style encoding so that we get the denc_traits<> definition. | |
25 | #include "denc.h" | |
26 | ||
27 | #include "assert.h" | |
28 | ||
29 | using namespace ceph; | |
30 | ||
31 | /* | |
32 | * Notes on feature encoding: | |
33 | * | |
34 | * - The default encode() methods have a features argument with a default parameter | |
35 | * (which goes to zero). | |
36 | * - Normal classes will use WRITE_CLASS_ENCODER, with that features=0 default. | |
37 | * - Classes that _require_ features will use WRITE_CLASS_ENCODER_FEATURES, which | |
38 | * does not define the default. Any caller must explicitly pass it in. | |
39 | * - STL container macros have two encode variants: one with a features arg, and one | |
40 | * without. | |
41 | * | |
42 | * The result: | |
43 | * - A feature encode() method will fail to compile if a value is not | |
44 | * passed in. | |
45 | * - The feature varianet of the STL templates will be used when the feature arg is | |
46 | * provided. It will be passed through to any template arg types, but it will be | |
47 | * ignored when not needed. | |
48 | */ | |
49 | ||
50 | // -------------------------------------- | |
51 | // base types | |
52 | ||
53 | template<class T> | |
54 | inline void encode_raw(const T& t, bufferlist& bl) | |
55 | { | |
56 | bl.append((char*)&t, sizeof(t)); | |
57 | } | |
58 | template<class T> | |
59 | inline void decode_raw(T& t, bufferlist::iterator &p) | |
60 | { | |
61 | p.copy(sizeof(t), (char*)&t); | |
62 | } | |
63 | ||
64 | #define WRITE_RAW_ENCODER(type) \ | |
65 | inline void encode(const type &v, bufferlist& bl, uint64_t features=0) { encode_raw(v, bl); } \ | |
66 | inline void decode(type &v, bufferlist::iterator& p) { __ASSERT_FUNCTION decode_raw(v, p); } | |
67 | ||
68 | WRITE_RAW_ENCODER(__u8) | |
69 | #ifndef _CHAR_IS_SIGNED | |
70 | WRITE_RAW_ENCODER(__s8) | |
71 | #endif | |
72 | WRITE_RAW_ENCODER(char) | |
73 | WRITE_RAW_ENCODER(ceph_le64) | |
74 | WRITE_RAW_ENCODER(ceph_le32) | |
75 | WRITE_RAW_ENCODER(ceph_le16) | |
76 | ||
77 | // FIXME: we need to choose some portable floating point encoding here | |
78 | WRITE_RAW_ENCODER(float) | |
79 | WRITE_RAW_ENCODER(double) | |
80 | ||
81 | inline void encode(const bool &v, bufferlist& bl) { | |
82 | __u8 vv = v; | |
83 | encode_raw(vv, bl); | |
84 | } | |
85 | inline void decode(bool &v, bufferlist::iterator& p) { | |
86 | __u8 vv; | |
87 | decode_raw(vv, p); | |
88 | v = vv; | |
89 | } | |
90 | ||
91 | ||
92 | // ----------------------------------- | |
93 | // int types | |
94 | ||
95 | #define WRITE_INTTYPE_ENCODER(type, etype) \ | |
96 | inline void encode(type v, bufferlist& bl, uint64_t features=0) { \ | |
97 | ceph_##etype e; \ | |
98 | e = v; \ | |
99 | encode_raw(e, bl); \ | |
100 | } \ | |
101 | inline void decode(type &v, bufferlist::iterator& p) { \ | |
102 | ceph_##etype e; \ | |
103 | decode_raw(e, p); \ | |
104 | v = e; \ | |
105 | } | |
106 | ||
107 | WRITE_INTTYPE_ENCODER(uint64_t, le64) | |
108 | WRITE_INTTYPE_ENCODER(int64_t, le64) | |
109 | WRITE_INTTYPE_ENCODER(uint32_t, le32) | |
110 | WRITE_INTTYPE_ENCODER(int32_t, le32) | |
111 | WRITE_INTTYPE_ENCODER(uint16_t, le16) | |
112 | WRITE_INTTYPE_ENCODER(int16_t, le16) | |
113 | ||
114 | // see denc.h for ENCODE_DUMP_PATH discussion and definition. | |
115 | #ifdef ENCODE_DUMP_PATH | |
116 | # define ENCODE_DUMP_PRE() \ | |
117 | unsigned pre_off = bl.length() | |
118 | # define ENCODE_DUMP_POST(cl) \ | |
119 | do { \ | |
120 | static int i = 0; \ | |
121 | i++; \ | |
122 | int bits = 0; \ | |
123 | for (unsigned t = i; t; bits++) \ | |
124 | t &= t - 1; \ | |
125 | if (bits > 2) \ | |
126 | break; \ | |
127 | char fn[PATH_MAX]; \ | |
128 | snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \ | |
129 | int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644); \ | |
130 | if (fd >= 0) { \ | |
131 | bufferlist sub; \ | |
132 | sub.substr_of(bl, pre_off, bl.length() - pre_off); \ | |
133 | sub.write_fd(fd); \ | |
134 | ::close(fd); \ | |
135 | } \ | |
136 | } while (0) | |
137 | #else | |
138 | # define ENCODE_DUMP_PRE() | |
139 | # define ENCODE_DUMP_POST(cl) | |
140 | #endif | |
141 | ||
142 | ||
143 | #define WRITE_CLASS_ENCODER(cl) \ | |
144 | inline void encode(const cl &c, bufferlist &bl, uint64_t features=0) { \ | |
145 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ | |
146 | inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); } | |
147 | ||
148 | #define WRITE_CLASS_MEMBER_ENCODER(cl) \ | |
149 | inline void encode(const cl &c, bufferlist &bl) const { \ | |
150 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ | |
151 | inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); } | |
152 | ||
153 | #define WRITE_CLASS_ENCODER_FEATURES(cl) \ | |
154 | inline void encode(const cl &c, bufferlist &bl, uint64_t features) { \ | |
155 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ | |
156 | inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); } | |
157 | ||
158 | #define WRITE_CLASS_ENCODER_OPTIONAL_FEATURES(cl) \ | |
159 | inline void encode(const cl &c, bufferlist &bl, uint64_t features = 0) { \ | |
160 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ | |
161 | inline void decode(cl &c, bufferlist::iterator &p) { c.decode(p); } | |
162 | ||
163 | ||
164 | // string | |
165 | inline void encode(const std::string& s, bufferlist& bl, uint64_t features=0) | |
166 | { | |
167 | __u32 len = s.length(); | |
168 | encode(len, bl); | |
169 | if (len) | |
170 | bl.append(s.data(), len); | |
171 | } | |
172 | inline void decode(std::string& s, bufferlist::iterator& p) | |
173 | { | |
174 | __u32 len; | |
175 | decode(len, p); | |
176 | s.clear(); | |
177 | p.copy(len, s); | |
178 | } | |
179 | ||
180 | inline void encode_nohead(const std::string& s, bufferlist& bl) | |
181 | { | |
182 | bl.append(s.data(), s.length()); | |
183 | } | |
184 | inline void decode_nohead(int len, std::string& s, bufferlist::iterator& p) | |
185 | { | |
186 | s.clear(); | |
187 | p.copy(len, s); | |
188 | } | |
189 | ||
190 | // const char* (encode only, string compatible) | |
191 | inline void encode(const char *s, bufferlist& bl) | |
192 | { | |
193 | __u32 len = strlen(s); | |
194 | encode(len, bl); | |
195 | if (len) | |
196 | bl.append(s, len); | |
197 | } | |
198 | ||
199 | ||
7c673cae FG |
200 | // ----------------------------- |
201 | // buffers | |
202 | ||
203 | // bufferptr (encapsulated) | |
204 | inline void encode(const buffer::ptr& bp, bufferlist& bl) | |
205 | { | |
206 | __u32 len = bp.length(); | |
207 | encode(len, bl); | |
208 | if (len) | |
209 | bl.append(bp); | |
210 | } | |
211 | inline void decode(buffer::ptr& bp, bufferlist::iterator& p) | |
212 | { | |
213 | __u32 len; | |
214 | decode(len, p); | |
215 | ||
216 | bufferlist s; | |
217 | p.copy(len, s); | |
218 | ||
219 | if (len) { | |
220 | if (s.get_num_buffers() == 1) | |
221 | bp = s.front(); | |
222 | else | |
223 | bp = buffer::copy(s.c_str(), s.length()); | |
224 | } | |
225 | } | |
226 | ||
227 | // bufferlist (encapsulated) | |
228 | inline void encode(const bufferlist& s, bufferlist& bl) | |
229 | { | |
230 | __u32 len = s.length(); | |
231 | encode(len, bl); | |
232 | bl.append(s); | |
233 | } | |
234 | inline void encode_destructively(bufferlist& s, bufferlist& bl) | |
235 | { | |
236 | __u32 len = s.length(); | |
237 | encode(len, bl); | |
238 | bl.claim_append(s); | |
239 | } | |
240 | inline void decode(bufferlist& s, bufferlist::iterator& p) | |
241 | { | |
242 | __u32 len; | |
243 | decode(len, p); | |
244 | s.clear(); | |
245 | p.copy(len, s); | |
246 | } | |
247 | ||
248 | inline void encode_nohead(const bufferlist& s, bufferlist& bl) | |
249 | { | |
250 | bl.append(s); | |
251 | } | |
252 | inline void decode_nohead(int len, bufferlist& s, bufferlist::iterator& p) | |
253 | { | |
254 | s.clear(); | |
255 | p.copy(len, s); | |
256 | } | |
257 | ||
258 | ||
259 | // full bl decoder | |
260 | template<class T> | |
261 | inline void decode(T &o, bufferlist& bl) | |
262 | { | |
263 | bufferlist::iterator p = bl.begin(); | |
264 | decode(o, p); | |
265 | assert(p.end()); | |
266 | } | |
267 | ||
268 | ||
269 | // ----------------------------- | |
270 | // STL container types | |
271 | ||
272 | #include <set> | |
273 | #include <map> | |
274 | #include <deque> | |
275 | #include <vector> | |
276 | #include <string> | |
277 | #include <boost/optional/optional_io.hpp> | |
278 | #include <boost/tuple/tuple.hpp> | |
279 | ||
280 | #ifndef _BACKWARD_BACKWARD_WARNING_H | |
281 | #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_* | |
282 | #endif | |
283 | #include "include/unordered_map.h" | |
284 | #include "include/unordered_set.h" | |
285 | ||
286 | ||
287 | // boost optional | |
288 | template<typename T> | |
289 | inline void encode(const boost::optional<T> &p, bufferlist &bl) | |
290 | { | |
291 | __u8 present = static_cast<bool>(p); | |
292 | ::encode(present, bl); | |
293 | if (p) | |
294 | encode(p.get(), bl); | |
295 | } | |
296 | ||
297 | #pragma GCC diagnostic ignored "-Wpragmas" | |
298 | #pragma GCC diagnostic push | |
299 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
300 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" | |
301 | template<typename T> | |
302 | inline void decode(boost::optional<T> &p, bufferlist::iterator &bp) | |
303 | { | |
304 | __u8 present; | |
305 | ::decode(present, bp); | |
306 | if (present) { | |
307 | T t; | |
308 | p = t; | |
309 | decode(p.get(), bp); | |
310 | } | |
311 | } | |
312 | #pragma GCC diagnostic pop | |
313 | #pragma GCC diagnostic warning "-Wpragmas" | |
314 | ||
315 | //triple tuple | |
316 | template<class A, class B, class C> | |
317 | inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl) | |
318 | { | |
319 | encode(boost::get<0>(t), bl); | |
320 | encode(boost::get<1>(t), bl); | |
321 | encode(boost::get<2>(t), bl); | |
322 | } | |
323 | template<class A, class B, class C> | |
324 | inline void decode(boost::tuple<A, B, C> &t, bufferlist::iterator &bp) | |
325 | { | |
326 | decode(boost::get<0>(t), bp); | |
327 | decode(boost::get<1>(t), bp); | |
328 | decode(boost::get<2>(t), bp); | |
329 | } | |
330 | ||
331 | // std::pair<A,B> | |
332 | template<class A, class B, | |
333 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
334 | inline typename std::enable_if<!a_traits::supported || | |
335 | !b_traits::supported>::type | |
336 | encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features) | |
337 | { | |
338 | encode(p.first, bl, features); | |
339 | encode(p.second, bl, features); | |
340 | } | |
341 | template<class A, class B, | |
342 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
343 | inline typename std::enable_if<!a_traits::supported || | |
344 | !b_traits::supported>::type | |
345 | encode(const std::pair<A,B> &p, bufferlist &bl) | |
346 | { | |
347 | encode(p.first, bl); | |
348 | encode(p.second, bl); | |
349 | } | |
350 | template<class A, class B, | |
351 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
352 | inline typename std::enable_if<!a_traits::supported || | |
353 | !b_traits::supported>::type | |
354 | decode(std::pair<A,B> &pa, bufferlist::iterator &p) | |
355 | { | |
356 | decode(pa.first, p); | |
357 | decode(pa.second, p); | |
358 | } | |
359 | ||
360 | // std::list<T> | |
361 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
362 | inline typename std::enable_if<!traits::supported>::type | |
363 | encode(const std::list<T, Alloc>& ls, bufferlist& bl) | |
364 | { | |
365 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
366 | encode(n, bl); | |
367 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
368 | encode(*p, bl); | |
369 | } | |
370 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
371 | inline typename std::enable_if<!traits::supported>::type | |
372 | encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
373 | { | |
374 | // should i pre- or post- count? | |
375 | if (!ls.empty()) { | |
376 | unsigned pos = bl.length(); | |
377 | unsigned n = 0; | |
378 | encode(n, bl); | |
379 | for (auto p = ls.begin(); p != ls.end(); ++p) { | |
380 | n++; | |
381 | encode(*p, bl, features); | |
382 | } | |
383 | ceph_le32 en; | |
384 | en = n; | |
385 | bl.copy_in(pos, sizeof(en), (char*)&en); | |
386 | } else { | |
387 | __u32 n = (__u32)(ls.size()); // FIXME: this is slow on a list. | |
388 | encode(n, bl); | |
389 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
390 | encode(*p, bl, features); | |
391 | } | |
392 | } | |
393 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
394 | inline typename std::enable_if<!traits::supported>::type | |
395 | decode(std::list<T,Alloc>& ls, bufferlist::iterator& p) | |
396 | { | |
397 | __u32 n; | |
398 | decode(n, p); | |
399 | ls.clear(); | |
400 | while (n--) { | |
401 | T v; | |
402 | decode(v, p); | |
403 | ls.push_back(v); | |
404 | } | |
405 | } | |
406 | ||
407 | // std::list<ceph::shared_ptr<T>> | |
408 | template<class T, class Alloc> | |
409 | inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
410 | bufferlist& bl) | |
411 | { | |
412 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
413 | encode(n, bl); | |
414 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
415 | encode(**p, bl); | |
416 | } | |
417 | template<class T, class Alloc> | |
418 | inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
419 | bufferlist& bl, uint64_t features) | |
420 | { | |
421 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
422 | encode(n, bl); | |
423 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
424 | encode(**p, bl, features); | |
425 | } | |
426 | template<class T, class Alloc> | |
427 | inline void decode(std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
428 | bufferlist::iterator& p) | |
429 | { | |
430 | __u32 n; | |
431 | decode(n, p); | |
432 | ls.clear(); | |
433 | while (n--) { | |
434 | ceph::shared_ptr<T> v(std::make_shared<T>()); | |
435 | decode(*v, p); | |
436 | ls.push_back(v); | |
437 | } | |
438 | } | |
439 | ||
440 | // std::set<T> | |
441 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
442 | inline typename std::enable_if<!traits::supported>::type | |
443 | encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
444 | { | |
445 | __u32 n = (__u32)(s.size()); | |
446 | encode(n, bl); | |
447 | for (auto p = s.begin(); p != s.end(); ++p) | |
448 | encode(*p, bl); | |
449 | } | |
450 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
451 | inline typename std::enable_if<!traits::supported>::type | |
452 | decode(std::set<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
453 | { | |
454 | __u32 n; | |
455 | decode(n, p); | |
456 | s.clear(); | |
457 | while (n--) { | |
458 | T v; | |
459 | decode(v, p); | |
460 | s.insert(v); | |
461 | } | |
462 | } | |
463 | ||
464 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
465 | inline typename std::enable_if<!traits::supported>::type | |
466 | encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
467 | { | |
468 | for (auto p = s.begin(); p != s.end(); ++p) | |
469 | encode(*p, bl); | |
470 | } | |
471 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
472 | inline typename std::enable_if<!traits::supported>::type | |
473 | decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
474 | { | |
475 | for (int i=0; i<len; i++) { | |
476 | T v; | |
477 | decode(v, p); | |
478 | s.insert(v); | |
479 | } | |
480 | } | |
481 | ||
482 | // boost::container::flat_set<T> | |
483 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
484 | inline typename std::enable_if<!traits::supported>::type | |
485 | encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl) | |
486 | { | |
487 | __u32 n = (__u32)(s.size()); | |
488 | encode(n, bl); | |
489 | for (const auto& e : s) | |
490 | encode(e, bl); | |
491 | } | |
492 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
493 | inline typename std::enable_if<!traits::supported>::type | |
494 | decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::iterator& p) | |
495 | { | |
496 | __u32 n; | |
497 | decode(n, p); | |
498 | s.clear(); | |
31f18b77 | 499 | s.reserve(n); |
7c673cae FG |
500 | while (n--) { |
501 | T v; | |
502 | decode(v, p); | |
503 | s.insert(v); | |
504 | } | |
505 | } | |
506 | ||
507 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
508 | inline typename std::enable_if<!traits::supported>::type | |
509 | encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s, | |
510 | bufferlist& bl) | |
511 | { | |
512 | for (const auto& e : s) | |
513 | encode(e, bl); | |
514 | } | |
515 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
516 | inline typename std::enable_if<!traits::supported>::type | |
517 | decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s, | |
518 | bufferlist::iterator& p) | |
519 | { | |
31f18b77 | 520 | s.reserve(len); |
7c673cae FG |
521 | for (int i=0; i<len; i++) { |
522 | T v; | |
523 | decode(v, p); | |
524 | s.insert(v); | |
525 | } | |
526 | } | |
527 | ||
528 | // multiset | |
529 | template<class T, class Comp, class Alloc> | |
530 | inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl) | |
531 | { | |
532 | __u32 n = (__u32)(s.size()); | |
533 | encode(n, bl); | |
534 | for (auto p = s.begin(); p != s.end(); ++p) | |
535 | encode(*p, bl); | |
536 | } | |
537 | template<class T, class Comp, class Alloc> | |
538 | inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
539 | { | |
540 | __u32 n; | |
541 | decode(n, p); | |
542 | s.clear(); | |
543 | while (n--) { | |
544 | T v; | |
545 | decode(v, p); | |
546 | s.insert(v); | |
547 | } | |
548 | } | |
549 | ||
550 | // vector (pointers) | |
551 | /*template<class T> | |
552 | inline void encode(const std::vector<T*>& v, bufferlist& bl) | |
553 | { | |
554 | __u32 n = v.size(); | |
555 | encode(n, bl); | |
556 | for (typename std::vector<T*>::const_iterator p = v.begin(); p != v.end(); ++p) | |
557 | encode(**p, bl); | |
558 | } | |
559 | template<class T> | |
560 | inline void decode(std::vector<T*>& v, bufferlist::iterator& p) | |
561 | { | |
562 | __u32 n; | |
563 | decode(n, p); | |
564 | v.resize(n); | |
565 | for (__u32 i=0; i<n; i++) | |
566 | v[i] = new T(p); | |
567 | } | |
568 | */ | |
569 | // std::vector<T> | |
570 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
571 | inline typename std::enable_if<!traits::supported>::type | |
572 | encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features) | |
573 | { | |
574 | __u32 n = (__u32)(v.size()); | |
575 | encode(n, bl); | |
576 | for (auto p = v.begin(); p != v.end(); ++p) | |
577 | encode(*p, bl, features); | |
578 | } | |
579 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
580 | inline typename std::enable_if<!traits::supported>::type | |
581 | encode(const std::vector<T,Alloc>& v, bufferlist& bl) | |
582 | { | |
583 | __u32 n = (__u32)(v.size()); | |
584 | encode(n, bl); | |
585 | for (auto p = v.begin(); p != v.end(); ++p) | |
586 | encode(*p, bl); | |
587 | } | |
588 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
589 | inline typename std::enable_if<!traits::supported>::type | |
590 | decode(std::vector<T,Alloc>& v, bufferlist::iterator& p) | |
591 | { | |
592 | __u32 n; | |
593 | decode(n, p); | |
594 | v.resize(n); | |
595 | for (__u32 i=0; i<n; i++) | |
596 | decode(v[i], p); | |
597 | } | |
598 | ||
599 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
600 | inline typename std::enable_if<!traits::supported>::type | |
601 | encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl) | |
602 | { | |
603 | for (auto p = v.begin(); p != v.end(); ++p) | |
604 | encode(*p, bl); | |
605 | } | |
606 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
607 | inline typename std::enable_if<!traits::supported>::type | |
608 | decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::iterator& p) | |
609 | { | |
610 | v.resize(len); | |
611 | for (__u32 i=0; i<v.size(); i++) | |
612 | decode(v[i], p); | |
613 | } | |
614 | ||
615 | // vector (shared_ptr) | |
616 | template<class T,class Alloc> | |
617 | inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
618 | bufferlist& bl, | |
619 | uint64_t features) | |
620 | { | |
621 | __u32 n = (__u32)(v.size()); | |
622 | encode(n, bl); | |
623 | for (auto p = v.begin(); p != v.end(); ++p) | |
624 | if (*p) | |
625 | encode(**p, bl, features); | |
626 | else | |
627 | encode(T(), bl, features); | |
628 | } | |
629 | template<class T, class Alloc> | |
630 | inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
631 | bufferlist& bl) | |
632 | { | |
633 | __u32 n = (__u32)(v.size()); | |
634 | encode(n, bl); | |
635 | for (auto p = v.begin(); p != v.end(); ++p) | |
636 | if (*p) | |
637 | encode(**p, bl); | |
638 | else | |
639 | encode(T(), bl); | |
640 | } | |
641 | template<class T, class Alloc> | |
642 | inline void decode(std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
643 | bufferlist::iterator& p) | |
644 | { | |
645 | __u32 n; | |
646 | decode(n, p); | |
647 | v.resize(n); | |
648 | for (__u32 i=0; i<n; i++) { | |
649 | v[i] = std::make_shared<T>(); | |
650 | decode(*v[i], p); | |
651 | } | |
652 | } | |
653 | ||
654 | // map (pointers) | |
655 | /* | |
656 | template<class T, class U> | |
657 | inline void encode(const std::map<T,U*>& m, bufferlist& bl) | |
658 | { | |
659 | __u32 n = m.size(); | |
660 | encode(n, bl); | |
661 | for (typename std::map<T,U*>::const_iterator p = m.begin(); p != m.end(); ++p) { | |
662 | encode(p->first, bl); | |
663 | encode(*p->second, bl); | |
664 | } | |
665 | } | |
666 | template<class T, class U> | |
667 | inline void decode(std::map<T,U*>& m, bufferlist::iterator& p) | |
668 | { | |
669 | __u32 n; | |
670 | decode(n, p); | |
671 | m.clear(); | |
672 | while (n--) { | |
673 | T k; | |
674 | decode(k, p); | |
675 | m[k] = new U(p); | |
676 | } | |
677 | }*/ | |
678 | ||
679 | // map | |
680 | template<class T, class U, class Comp, class Alloc, | |
681 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
682 | inline typename std::enable_if<!t_traits::supported || | |
683 | !u_traits::supported>::type | |
684 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
685 | { | |
686 | __u32 n = (__u32)(m.size()); | |
687 | encode(n, bl); | |
688 | for (auto p = m.begin(); p != m.end(); ++p) { | |
689 | encode(p->first, bl); | |
690 | encode(p->second, bl); | |
691 | } | |
692 | } | |
693 | template<class T, class U, class Comp, class Alloc, | |
694 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
695 | inline typename std::enable_if<!t_traits::supported || | |
696 | !u_traits::supported>::type | |
697 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) | |
698 | { | |
699 | __u32 n = (__u32)(m.size()); | |
700 | encode(n, bl); | |
701 | for (auto p = m.begin(); p != m.end(); ++p) { | |
702 | encode(p->first, bl, features); | |
703 | encode(p->second, bl, features); | |
704 | } | |
705 | } | |
706 | template<class T, class U, class Comp, class Alloc, | |
707 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
708 | inline typename std::enable_if<!t_traits::supported || | |
709 | !u_traits::supported>::type | |
710 | decode(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
711 | { | |
712 | __u32 n; | |
713 | decode(n, p); | |
714 | m.clear(); | |
715 | while (n--) { | |
716 | T k; | |
717 | decode(k, p); | |
718 | decode(m[k], p); | |
719 | } | |
720 | } | |
721 | template<class T, class U, class Comp, class Alloc> | |
722 | inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
723 | { | |
724 | __u32 n; | |
725 | decode(n, p); | |
726 | while (n--) { | |
727 | T k; | |
728 | decode(k, p); | |
729 | decode(m[k], p); | |
730 | } | |
731 | } | |
732 | template<class T, class U, class Comp, class Alloc, | |
733 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
734 | inline typename std::enable_if<!t_traits::supported || | |
735 | !u_traits::supported>::type | |
736 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
737 | { | |
738 | for (auto p = m.begin(); p != m.end(); ++p) { | |
739 | encode(p->first, bl); | |
740 | encode(p->second, bl); | |
741 | } | |
742 | } | |
743 | template<class T, class U, class Comp, class Alloc, | |
744 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
745 | inline typename std::enable_if<!t_traits::supported || | |
746 | !u_traits::supported>::type | |
747 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) | |
748 | { | |
749 | for (auto p = m.begin(); p != m.end(); ++p) { | |
750 | encode(p->first, bl, features); | |
751 | encode(p->second, bl, features); | |
752 | } | |
753 | } | |
754 | template<class T, class U, class Comp, class Alloc, | |
755 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
756 | inline typename std::enable_if<!t_traits::supported || | |
757 | !u_traits::supported>::type | |
758 | decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
759 | { | |
760 | m.clear(); | |
761 | while (n--) { | |
762 | T k; | |
763 | decode(k, p); | |
764 | decode(m[k], p); | |
765 | } | |
766 | } | |
767 | ||
768 | // boost::container::flat-map | |
769 | template<class T, class U, class Comp, class Alloc, | |
770 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
771 | inline typename std::enable_if<!t_traits::supported || | |
772 | !u_traits::supported>::type | |
773 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
774 | { | |
775 | __u32 n = (__u32)(m.size()); | |
776 | encode(n, bl); | |
777 | for (typename boost::container::flat_map<T,U,Comp>::const_iterator p | |
778 | = m.begin(); p != m.end(); ++p) { | |
779 | encode(p->first, bl); | |
780 | encode(p->second, bl); | |
781 | } | |
782 | } | |
783 | template<class T, class U, class Comp, class Alloc, | |
784 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
785 | inline typename std::enable_if<!t_traits::supported || | |
786 | !u_traits::supported>::type | |
787 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl, | |
788 | uint64_t features) | |
789 | { | |
790 | __u32 n = (__u32)(m.size()); | |
791 | encode(n, bl); | |
792 | for (auto p = m.begin(); p != m.end(); ++p) { | |
793 | encode(p->first, bl, features); | |
794 | encode(p->second, bl, features); | |
795 | } | |
796 | } | |
797 | template<class T, class U, class Comp, class Alloc, | |
798 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
799 | inline typename std::enable_if<!t_traits::supported || | |
800 | !u_traits::supported>::type | |
801 | decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
802 | { | |
803 | __u32 n; | |
804 | decode(n, p); | |
805 | m.clear(); | |
31f18b77 | 806 | m.reserve(n); |
7c673cae FG |
807 | while (n--) { |
808 | T k; | |
809 | decode(k, p); | |
810 | decode(m[k], p); | |
811 | } | |
812 | } | |
813 | template<class T, class U, class Comp, class Alloc> | |
814 | inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m, | |
815 | bufferlist::iterator& p) | |
816 | { | |
817 | __u32 n; | |
818 | decode(n, p); | |
31f18b77 | 819 | m.reserve(m.size() + n); |
7c673cae FG |
820 | while (n--) { |
821 | T k; | |
822 | decode(k, p); | |
823 | decode(m[k], p); | |
824 | } | |
825 | } | |
826 | template<class T, class U, class Comp, class Alloc, | |
827 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
828 | inline typename std::enable_if<!t_traits::supported || | |
829 | !u_traits::supported>::type | |
830 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
831 | bufferlist& bl) | |
832 | { | |
833 | for (auto p = m.begin(); p != m.end(); ++p) { | |
834 | encode(p->first, bl); | |
835 | encode(p->second, bl); | |
836 | } | |
837 | } | |
838 | template<class T, class U, class Comp, class Alloc, | |
839 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
840 | inline typename std::enable_if<!t_traits::supported || | |
841 | !u_traits::supported>::type | |
842 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
843 | bufferlist& bl, uint64_t features) | |
844 | { | |
845 | for (auto p = m.begin(); p != m.end(); ++p) { | |
846 | encode(p->first, bl, features); | |
847 | encode(p->second, bl, features); | |
848 | } | |
849 | } | |
850 | template<class T, class U, class Comp, class Alloc, | |
851 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
852 | inline typename std::enable_if<!t_traits::supported || | |
853 | !u_traits::supported>::type | |
854 | decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m, | |
855 | bufferlist::iterator& p) | |
856 | { | |
857 | m.clear(); | |
858 | while (n--) { | |
859 | T k; | |
860 | decode(k, p); | |
861 | decode(m[k], p); | |
862 | } | |
863 | } | |
864 | ||
865 | // multimap | |
866 | template<class T, class U, class Comp, class Alloc> | |
867 | inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl) | |
868 | { | |
869 | __u32 n = (__u32)(m.size()); | |
870 | encode(n, bl); | |
871 | for (auto p = m.begin(); p != m.end(); ++p) { | |
872 | encode(p->first, bl); | |
873 | encode(p->second, bl); | |
874 | } | |
875 | } | |
876 | template<class T, class U, class Comp, class Alloc> | |
877 | inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
878 | { | |
879 | __u32 n; | |
880 | decode(n, p); | |
881 | m.clear(); | |
882 | while (n--) { | |
883 | typename std::pair<T,U> tu = std::pair<T,U>(); | |
884 | decode(tu.first, p); | |
885 | typename std::multimap<T,U,Comp,Alloc>::iterator it = m.insert(tu); | |
886 | decode(it->second, p); | |
887 | } | |
888 | } | |
889 | ||
890 | // ceph::unordered_map | |
891 | template<class T, class U, class Hash, class Pred, class Alloc> | |
892 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl, | |
893 | uint64_t features) | |
894 | { | |
895 | __u32 n = (__u32)(m.size()); | |
896 | encode(n, bl); | |
897 | for (auto p = m.begin(); p != m.end(); ++p) { | |
898 | encode(p->first, bl, features); | |
899 | encode(p->second, bl, features); | |
900 | } | |
901 | } | |
902 | template<class T, class U, class Hash, class Pred, class Alloc> | |
903 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl) | |
904 | { | |
905 | __u32 n = (__u32)(m.size()); | |
906 | encode(n, bl); | |
907 | for (auto p = m.begin(); p != m.end(); ++p) { | |
908 | encode(p->first, bl); | |
909 | encode(p->second, bl); | |
910 | } | |
911 | } | |
912 | template<class T, class U, class Hash, class Pred, class Alloc> | |
913 | inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::iterator& p) | |
914 | { | |
915 | __u32 n; | |
916 | decode(n, p); | |
917 | m.clear(); | |
918 | while (n--) { | |
919 | T k; | |
920 | decode(k, p); | |
921 | decode(m[k], p); | |
922 | } | |
923 | } | |
924 | ||
925 | // ceph::unordered_set | |
926 | template<class T, class Hash, class Pred, class Alloc> | |
927 | inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl) | |
928 | { | |
929 | __u32 n = (__u32)(m.size()); | |
930 | encode(n, bl); | |
931 | for (auto p = m.begin(); p != m.end(); ++p) | |
932 | encode(*p, bl); | |
933 | } | |
934 | template<class T, class Hash, class Pred, class Alloc> | |
935 | inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::iterator& p) | |
936 | { | |
937 | __u32 n; | |
938 | decode(n, p); | |
939 | m.clear(); | |
940 | while (n--) { | |
941 | T k; | |
942 | decode(k, p); | |
943 | m.insert(k); | |
944 | } | |
945 | } | |
946 | ||
947 | // deque | |
948 | template<class T, class Alloc> | |
949 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
950 | { | |
951 | __u32 n = ls.size(); | |
952 | encode(n, bl); | |
953 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
954 | encode(*p, bl, features); | |
955 | } | |
956 | template<class T, class Alloc> | |
957 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl) | |
958 | { | |
959 | __u32 n = ls.size(); | |
960 | encode(n, bl); | |
961 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
962 | encode(*p, bl); | |
963 | } | |
964 | template<class T, class Alloc> | |
965 | inline void decode(std::deque<T,Alloc>& ls, bufferlist::iterator& p) | |
966 | { | |
967 | __u32 n; | |
968 | decode(n, p); | |
969 | ls.clear(); | |
970 | while (n--) { | |
971 | T v; | |
972 | decode(v, p); | |
973 | ls.push_back(v); | |
974 | } | |
975 | } | |
976 | ||
977 | // std::array<T, N> | |
978 | template<class T, size_t N, typename traits = denc_traits<T>> | |
979 | inline typename std::enable_if<!traits::supported>::type | |
980 | encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features) | |
981 | { | |
982 | for (const auto& e : v) | |
983 | encode(e, bl, features); | |
984 | } | |
985 | template<class T, size_t N, typename traits = denc_traits<T>> | |
986 | inline typename std::enable_if<!traits::supported>::type | |
987 | encode(const std::array<T, N>& v, bufferlist& bl) | |
988 | { | |
989 | for (const auto& e : v) | |
990 | encode(e, bl); | |
991 | } | |
992 | template<class T, size_t N, typename traits = denc_traits<T>> | |
993 | inline typename std::enable_if<!traits::supported>::type | |
994 | decode(std::array<T, N>& v, bufferlist::iterator& p) | |
995 | { | |
996 | for (auto& e : v) | |
997 | decode(e, p); | |
998 | } | |
999 | ||
1000 | ||
1001 | /* | |
1002 | * guards | |
1003 | */ | |
1004 | ||
1005 | /** | |
1006 | * start encoding block | |
1007 | * | |
1008 | * @param v current (code) version of the encoding | |
1009 | * @param compat oldest code version that can decode it | |
1010 | * @param bl bufferlist to encode to | |
1011 | */ | |
1012 | #define ENCODE_START(v, compat, bl) \ | |
1013 | __u8 struct_v = v, struct_compat = compat; \ | |
1014 | ::encode(struct_v, (bl)); \ | |
1015 | ::encode(struct_compat, (bl)); \ | |
1016 | buffer::list::iterator struct_compat_it = (bl).end(); \ | |
1017 | struct_compat_it.advance(-1); \ | |
1018 | ceph_le32 struct_len; \ | |
1019 | struct_len = 0; \ | |
1020 | ::encode(struct_len, (bl)); \ | |
1021 | buffer::list::iterator struct_len_it = (bl).end(); \ | |
1022 | struct_len_it.advance(-4); \ | |
1023 | do { | |
1024 | ||
1025 | /** | |
1026 | * finish encoding block | |
1027 | * | |
1028 | * @param bl bufferlist we were encoding to | |
1029 | * @param new_struct_compat struct-compat value to use | |
1030 | */ | |
1031 | #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \ | |
1032 | } while (false); \ | |
1033 | struct_len = (bl).length() - struct_len_it.get_off() - sizeof(struct_len); \ | |
1034 | struct_len_it.copy_in(4, (char *)&struct_len); \ | |
1035 | if (new_struct_compat) { \ | |
1036 | struct_compat = new_struct_compat; \ | |
1037 | struct_compat_it.copy_in(1, (char *)&struct_compat); \ | |
1038 | } | |
1039 | ||
1040 | #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0) | |
1041 | ||
1042 | #define DECODE_ERR_OLDVERSION(func, v, compatv) \ | |
1043 | (std::string(func) + " no longer understand old encoding version " #v " < " #compatv) | |
1044 | ||
1045 | #define DECODE_ERR_PAST(func) \ | |
1046 | (std::string(func) + " decode past end of struct encoding") | |
1047 | ||
1048 | /** | |
1049 | * check for very old encoding | |
1050 | * | |
1051 | * If the encoded data is older than oldestv, raise an exception. | |
1052 | * | |
1053 | * @param oldestv oldest version of the code we can successfully decode. | |
1054 | */ | |
1055 | #define DECODE_OLDEST(oldestv) \ | |
1056 | if (struct_v < oldestv) \ | |
1057 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv)); | |
1058 | ||
1059 | /** | |
1060 | * start a decoding block | |
1061 | * | |
1062 | * @param v current version of the encoding that the code supports/encodes | |
1063 | * @param bl bufferlist::iterator for the encoded data | |
1064 | */ | |
1065 | #define DECODE_START(v, bl) \ | |
1066 | __u8 struct_v, struct_compat; \ | |
1067 | ::decode(struct_v, bl); \ | |
1068 | ::decode(struct_compat, bl); \ | |
1069 | if (v < struct_compat) \ | |
1070 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ | |
1071 | __u32 struct_len; \ | |
1072 | ::decode(struct_len, bl); \ | |
1073 | if (struct_len > bl.get_remaining()) \ | |
1074 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1075 | unsigned struct_end = bl.get_off() + struct_len; \ | |
1076 | do { | |
1077 | ||
1078 | #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \ | |
1079 | __u8 struct_v; \ | |
1080 | ::decode(struct_v, bl); \ | |
1081 | if (struct_v >= compatv) { \ | |
1082 | __u8 struct_compat; \ | |
1083 | ::decode(struct_compat, bl); \ | |
1084 | if (v < struct_compat) \ | |
1085 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ | |
1086 | } else if (skip_v) { \ | |
1087 | if ((int)bl.get_remaining() < skip_v) \ | |
1088 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1089 | bl.advance(skip_v); \ | |
1090 | } \ | |
1091 | unsigned struct_end = 0; \ | |
1092 | if (struct_v >= lenv) { \ | |
1093 | __u32 struct_len; \ | |
1094 | ::decode(struct_len, bl); \ | |
1095 | if (struct_len > bl.get_remaining()) \ | |
1096 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1097 | struct_end = bl.get_off() + struct_len; \ | |
1098 | } \ | |
1099 | do { | |
1100 | ||
1101 | /** | |
1102 | * start a decoding block with legacy support for older encoding schemes | |
1103 | * | |
1104 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1105 | * the compat version or length. Skip those fields conditionally. | |
1106 | * | |
1107 | * Most of the time, v, compatv, and lenv will all match the version | |
1108 | * where the structure was switched over to the new macros. | |
1109 | * | |
1110 | * @param v current version of the encoding that the code supports/encodes | |
1111 | * @param compatv oldest version that includes a __u8 compat version field | |
1112 | * @param lenv oldest version that includes a __u32 length wrapper | |
1113 | * @param bl bufferlist::iterator containing the encoded data | |
1114 | */ | |
1115 | #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \ | |
1116 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 0, bl) | |
1117 | ||
1118 | /** | |
1119 | * start a decoding block with legacy support for older encoding schemes | |
1120 | * | |
1121 | * This version of the macro assumes the legacy encoding had a 32 bit | |
1122 | * version | |
1123 | * | |
1124 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1125 | * the compat version or length. Skip those fields conditionally. | |
1126 | * | |
1127 | * Most of the time, v, compatv, and lenv will all match the version | |
1128 | * where the structure was switched over to the new macros. | |
1129 | * | |
1130 | * @param v current version of the encoding that the code supports/encodes | |
1131 | * @param compatv oldest version that includes a __u8 compat version field | |
1132 | * @param lenv oldest version that includes a __u32 length wrapper | |
1133 | * @param bl bufferlist::iterator containing the encoded data | |
1134 | */ | |
1135 | #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \ | |
1136 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3, bl) | |
1137 | ||
1138 | #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \ | |
1139 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1, bl) | |
1140 | ||
1141 | /** | |
1142 | * finish decode block | |
1143 | * | |
1144 | * @param bl bufferlist::iterator we were decoding from | |
1145 | */ | |
1146 | #define DECODE_FINISH(bl) \ | |
1147 | } while (false); \ | |
1148 | if (struct_end) { \ | |
1149 | if (bl.get_off() > struct_end) \ | |
1150 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1151 | if (bl.get_off() < struct_end) \ | |
1152 | bl.advance(struct_end - bl.get_off()); \ | |
1153 | } | |
1154 | ||
1155 | /* | |
1156 | * Encoders/decoders to read from current offset in a file handle and | |
1157 | * encode/decode the data according to argument types. | |
1158 | */ | |
1159 | inline ssize_t decode_file(int fd, std::string &str) | |
1160 | { | |
1161 | bufferlist bl; | |
1162 | __u32 len = 0; | |
1163 | bl.read_fd(fd, sizeof(len)); | |
1164 | decode(len, bl); | |
1165 | bl.read_fd(fd, len); | |
1166 | decode(str, bl); | |
1167 | return bl.length(); | |
1168 | } | |
1169 | ||
1170 | inline ssize_t decode_file(int fd, bufferptr &bp) | |
1171 | { | |
1172 | bufferlist bl; | |
1173 | __u32 len = 0; | |
1174 | bl.read_fd(fd, sizeof(len)); | |
1175 | decode(len, bl); | |
1176 | bl.read_fd(fd, len); | |
1177 | bufferlist::iterator bli = bl.begin(); | |
1178 | ||
1179 | decode(bp, bli); | |
1180 | return bl.length(); | |
1181 | } | |
1182 | ||
1183 | #endif |