]>
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 | ||
200 | // array | |
201 | template<class A> | |
202 | inline void encode_array_nohead(const A a[], int n, bufferlist &bl) | |
203 | { | |
204 | for (int i=0; i<n; i++) | |
205 | encode(a[i], bl); | |
206 | } | |
207 | template<class A> | |
208 | inline void decode_array_nohead(A a[], int n, bufferlist::iterator &p) | |
209 | { | |
210 | for (int i=0; i<n; i++) | |
211 | decode(a[i], p); | |
212 | } | |
213 | ||
214 | ||
215 | ||
216 | // ----------------------------- | |
217 | // buffers | |
218 | ||
219 | // bufferptr (encapsulated) | |
220 | inline void encode(const buffer::ptr& bp, bufferlist& bl) | |
221 | { | |
222 | __u32 len = bp.length(); | |
223 | encode(len, bl); | |
224 | if (len) | |
225 | bl.append(bp); | |
226 | } | |
227 | inline void decode(buffer::ptr& bp, bufferlist::iterator& p) | |
228 | { | |
229 | __u32 len; | |
230 | decode(len, p); | |
231 | ||
232 | bufferlist s; | |
233 | p.copy(len, s); | |
234 | ||
235 | if (len) { | |
236 | if (s.get_num_buffers() == 1) | |
237 | bp = s.front(); | |
238 | else | |
239 | bp = buffer::copy(s.c_str(), s.length()); | |
240 | } | |
241 | } | |
242 | ||
243 | // bufferlist (encapsulated) | |
244 | inline void encode(const bufferlist& s, bufferlist& bl) | |
245 | { | |
246 | __u32 len = s.length(); | |
247 | encode(len, bl); | |
248 | bl.append(s); | |
249 | } | |
250 | inline void encode_destructively(bufferlist& s, bufferlist& bl) | |
251 | { | |
252 | __u32 len = s.length(); | |
253 | encode(len, bl); | |
254 | bl.claim_append(s); | |
255 | } | |
256 | inline void decode(bufferlist& s, bufferlist::iterator& p) | |
257 | { | |
258 | __u32 len; | |
259 | decode(len, p); | |
260 | s.clear(); | |
261 | p.copy(len, s); | |
262 | } | |
263 | ||
264 | inline void encode_nohead(const bufferlist& s, bufferlist& bl) | |
265 | { | |
266 | bl.append(s); | |
267 | } | |
268 | inline void decode_nohead(int len, bufferlist& s, bufferlist::iterator& p) | |
269 | { | |
270 | s.clear(); | |
271 | p.copy(len, s); | |
272 | } | |
273 | ||
274 | ||
275 | // full bl decoder | |
276 | template<class T> | |
277 | inline void decode(T &o, bufferlist& bl) | |
278 | { | |
279 | bufferlist::iterator p = bl.begin(); | |
280 | decode(o, p); | |
281 | assert(p.end()); | |
282 | } | |
283 | ||
284 | ||
285 | // ----------------------------- | |
286 | // STL container types | |
287 | ||
288 | #include <set> | |
289 | #include <map> | |
290 | #include <deque> | |
291 | #include <vector> | |
292 | #include <string> | |
293 | #include <boost/optional/optional_io.hpp> | |
294 | #include <boost/tuple/tuple.hpp> | |
295 | ||
296 | #ifndef _BACKWARD_BACKWARD_WARNING_H | |
297 | #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_* | |
298 | #endif | |
299 | #include "include/unordered_map.h" | |
300 | #include "include/unordered_set.h" | |
301 | ||
302 | ||
303 | // boost optional | |
304 | template<typename T> | |
305 | inline void encode(const boost::optional<T> &p, bufferlist &bl) | |
306 | { | |
307 | __u8 present = static_cast<bool>(p); | |
308 | ::encode(present, bl); | |
309 | if (p) | |
310 | encode(p.get(), bl); | |
311 | } | |
312 | ||
313 | #pragma GCC diagnostic ignored "-Wpragmas" | |
314 | #pragma GCC diagnostic push | |
315 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
316 | #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" | |
317 | template<typename T> | |
318 | inline void decode(boost::optional<T> &p, bufferlist::iterator &bp) | |
319 | { | |
320 | __u8 present; | |
321 | ::decode(present, bp); | |
322 | if (present) { | |
323 | T t; | |
324 | p = t; | |
325 | decode(p.get(), bp); | |
326 | } | |
327 | } | |
328 | #pragma GCC diagnostic pop | |
329 | #pragma GCC diagnostic warning "-Wpragmas" | |
330 | ||
331 | //triple tuple | |
332 | template<class A, class B, class C> | |
333 | inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl) | |
334 | { | |
335 | encode(boost::get<0>(t), bl); | |
336 | encode(boost::get<1>(t), bl); | |
337 | encode(boost::get<2>(t), bl); | |
338 | } | |
339 | template<class A, class B, class C> | |
340 | inline void decode(boost::tuple<A, B, C> &t, bufferlist::iterator &bp) | |
341 | { | |
342 | decode(boost::get<0>(t), bp); | |
343 | decode(boost::get<1>(t), bp); | |
344 | decode(boost::get<2>(t), bp); | |
345 | } | |
346 | ||
347 | // std::pair<A,B> | |
348 | template<class A, class B, | |
349 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
350 | inline typename std::enable_if<!a_traits::supported || | |
351 | !b_traits::supported>::type | |
352 | encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features) | |
353 | { | |
354 | encode(p.first, bl, features); | |
355 | encode(p.second, bl, features); | |
356 | } | |
357 | template<class A, class B, | |
358 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
359 | inline typename std::enable_if<!a_traits::supported || | |
360 | !b_traits::supported>::type | |
361 | encode(const std::pair<A,B> &p, bufferlist &bl) | |
362 | { | |
363 | encode(p.first, bl); | |
364 | encode(p.second, bl); | |
365 | } | |
366 | template<class A, class B, | |
367 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
368 | inline typename std::enable_if<!a_traits::supported || | |
369 | !b_traits::supported>::type | |
370 | decode(std::pair<A,B> &pa, bufferlist::iterator &p) | |
371 | { | |
372 | decode(pa.first, p); | |
373 | decode(pa.second, p); | |
374 | } | |
375 | ||
376 | // std::list<T> | |
377 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
378 | inline typename std::enable_if<!traits::supported>::type | |
379 | encode(const std::list<T, Alloc>& ls, bufferlist& bl) | |
380 | { | |
381 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
382 | encode(n, bl); | |
383 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
384 | encode(*p, bl); | |
385 | } | |
386 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
387 | inline typename std::enable_if<!traits::supported>::type | |
388 | encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
389 | { | |
390 | // should i pre- or post- count? | |
391 | if (!ls.empty()) { | |
392 | unsigned pos = bl.length(); | |
393 | unsigned n = 0; | |
394 | encode(n, bl); | |
395 | for (auto p = ls.begin(); p != ls.end(); ++p) { | |
396 | n++; | |
397 | encode(*p, bl, features); | |
398 | } | |
399 | ceph_le32 en; | |
400 | en = n; | |
401 | bl.copy_in(pos, sizeof(en), (char*)&en); | |
402 | } else { | |
403 | __u32 n = (__u32)(ls.size()); // FIXME: this is slow on a list. | |
404 | encode(n, bl); | |
405 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
406 | encode(*p, bl, features); | |
407 | } | |
408 | } | |
409 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
410 | inline typename std::enable_if<!traits::supported>::type | |
411 | decode(std::list<T,Alloc>& ls, bufferlist::iterator& p) | |
412 | { | |
413 | __u32 n; | |
414 | decode(n, p); | |
415 | ls.clear(); | |
416 | while (n--) { | |
417 | T v; | |
418 | decode(v, p); | |
419 | ls.push_back(v); | |
420 | } | |
421 | } | |
422 | ||
423 | // std::list<ceph::shared_ptr<T>> | |
424 | template<class T, class Alloc> | |
425 | inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
426 | bufferlist& bl) | |
427 | { | |
428 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
429 | encode(n, bl); | |
430 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
431 | encode(**p, bl); | |
432 | } | |
433 | template<class T, class Alloc> | |
434 | inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
435 | bufferlist& bl, uint64_t features) | |
436 | { | |
437 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
438 | encode(n, bl); | |
439 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
440 | encode(**p, bl, features); | |
441 | } | |
442 | template<class T, class Alloc> | |
443 | inline void decode(std::list<ceph::shared_ptr<T>, Alloc>& ls, | |
444 | bufferlist::iterator& p) | |
445 | { | |
446 | __u32 n; | |
447 | decode(n, p); | |
448 | ls.clear(); | |
449 | while (n--) { | |
450 | ceph::shared_ptr<T> v(std::make_shared<T>()); | |
451 | decode(*v, p); | |
452 | ls.push_back(v); | |
453 | } | |
454 | } | |
455 | ||
456 | // std::set<T> | |
457 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
458 | inline typename std::enable_if<!traits::supported>::type | |
459 | encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
460 | { | |
461 | __u32 n = (__u32)(s.size()); | |
462 | encode(n, bl); | |
463 | for (auto p = s.begin(); p != s.end(); ++p) | |
464 | encode(*p, bl); | |
465 | } | |
466 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
467 | inline typename std::enable_if<!traits::supported>::type | |
468 | decode(std::set<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
469 | { | |
470 | __u32 n; | |
471 | decode(n, p); | |
472 | s.clear(); | |
473 | while (n--) { | |
474 | T v; | |
475 | decode(v, p); | |
476 | s.insert(v); | |
477 | } | |
478 | } | |
479 | ||
480 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
481 | inline typename std::enable_if<!traits::supported>::type | |
482 | encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
483 | { | |
484 | for (auto p = s.begin(); p != s.end(); ++p) | |
485 | encode(*p, bl); | |
486 | } | |
487 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
488 | inline typename std::enable_if<!traits::supported>::type | |
489 | decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
490 | { | |
491 | for (int i=0; i<len; i++) { | |
492 | T v; | |
493 | decode(v, p); | |
494 | s.insert(v); | |
495 | } | |
496 | } | |
497 | ||
498 | // boost::container::flat_set<T> | |
499 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
500 | inline typename std::enable_if<!traits::supported>::type | |
501 | encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl) | |
502 | { | |
503 | __u32 n = (__u32)(s.size()); | |
504 | encode(n, bl); | |
505 | for (const auto& e : s) | |
506 | encode(e, bl); | |
507 | } | |
508 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
509 | inline typename std::enable_if<!traits::supported>::type | |
510 | decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::iterator& p) | |
511 | { | |
512 | __u32 n; | |
513 | decode(n, p); | |
514 | s.clear(); | |
31f18b77 | 515 | s.reserve(n); |
7c673cae FG |
516 | while (n--) { |
517 | T v; | |
518 | decode(v, p); | |
519 | s.insert(v); | |
520 | } | |
521 | } | |
522 | ||
523 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
524 | inline typename std::enable_if<!traits::supported>::type | |
525 | encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s, | |
526 | bufferlist& bl) | |
527 | { | |
528 | for (const auto& e : s) | |
529 | encode(e, bl); | |
530 | } | |
531 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
532 | inline typename std::enable_if<!traits::supported>::type | |
533 | decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s, | |
534 | bufferlist::iterator& p) | |
535 | { | |
31f18b77 | 536 | s.reserve(len); |
7c673cae FG |
537 | for (int i=0; i<len; i++) { |
538 | T v; | |
539 | decode(v, p); | |
540 | s.insert(v); | |
541 | } | |
542 | } | |
543 | ||
544 | // multiset | |
545 | template<class T, class Comp, class Alloc> | |
546 | inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl) | |
547 | { | |
548 | __u32 n = (__u32)(s.size()); | |
549 | encode(n, bl); | |
550 | for (auto p = s.begin(); p != s.end(); ++p) | |
551 | encode(*p, bl); | |
552 | } | |
553 | template<class T, class Comp, class Alloc> | |
554 | inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::iterator& p) | |
555 | { | |
556 | __u32 n; | |
557 | decode(n, p); | |
558 | s.clear(); | |
559 | while (n--) { | |
560 | T v; | |
561 | decode(v, p); | |
562 | s.insert(v); | |
563 | } | |
564 | } | |
565 | ||
566 | // vector (pointers) | |
567 | /*template<class T> | |
568 | inline void encode(const std::vector<T*>& v, bufferlist& bl) | |
569 | { | |
570 | __u32 n = v.size(); | |
571 | encode(n, bl); | |
572 | for (typename std::vector<T*>::const_iterator p = v.begin(); p != v.end(); ++p) | |
573 | encode(**p, bl); | |
574 | } | |
575 | template<class T> | |
576 | inline void decode(std::vector<T*>& v, bufferlist::iterator& p) | |
577 | { | |
578 | __u32 n; | |
579 | decode(n, p); | |
580 | v.resize(n); | |
581 | for (__u32 i=0; i<n; i++) | |
582 | v[i] = new T(p); | |
583 | } | |
584 | */ | |
585 | // std::vector<T> | |
586 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
587 | inline typename std::enable_if<!traits::supported>::type | |
588 | encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features) | |
589 | { | |
590 | __u32 n = (__u32)(v.size()); | |
591 | encode(n, bl); | |
592 | for (auto p = v.begin(); p != v.end(); ++p) | |
593 | encode(*p, bl, features); | |
594 | } | |
595 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
596 | inline typename std::enable_if<!traits::supported>::type | |
597 | encode(const std::vector<T,Alloc>& v, bufferlist& bl) | |
598 | { | |
599 | __u32 n = (__u32)(v.size()); | |
600 | encode(n, bl); | |
601 | for (auto p = v.begin(); p != v.end(); ++p) | |
602 | encode(*p, bl); | |
603 | } | |
604 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
605 | inline typename std::enable_if<!traits::supported>::type | |
606 | decode(std::vector<T,Alloc>& v, bufferlist::iterator& p) | |
607 | { | |
608 | __u32 n; | |
609 | decode(n, p); | |
610 | v.resize(n); | |
611 | for (__u32 i=0; i<n; i++) | |
612 | decode(v[i], p); | |
613 | } | |
614 | ||
615 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
616 | inline typename std::enable_if<!traits::supported>::type | |
617 | encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl) | |
618 | { | |
619 | for (auto p = v.begin(); p != v.end(); ++p) | |
620 | encode(*p, bl); | |
621 | } | |
622 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
623 | inline typename std::enable_if<!traits::supported>::type | |
624 | decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::iterator& p) | |
625 | { | |
626 | v.resize(len); | |
627 | for (__u32 i=0; i<v.size(); i++) | |
628 | decode(v[i], p); | |
629 | } | |
630 | ||
631 | // vector (shared_ptr) | |
632 | template<class T,class Alloc> | |
633 | inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
634 | bufferlist& bl, | |
635 | uint64_t features) | |
636 | { | |
637 | __u32 n = (__u32)(v.size()); | |
638 | encode(n, bl); | |
639 | for (auto p = v.begin(); p != v.end(); ++p) | |
640 | if (*p) | |
641 | encode(**p, bl, features); | |
642 | else | |
643 | encode(T(), bl, features); | |
644 | } | |
645 | template<class T, class Alloc> | |
646 | inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
647 | bufferlist& bl) | |
648 | { | |
649 | __u32 n = (__u32)(v.size()); | |
650 | encode(n, bl); | |
651 | for (auto p = v.begin(); p != v.end(); ++p) | |
652 | if (*p) | |
653 | encode(**p, bl); | |
654 | else | |
655 | encode(T(), bl); | |
656 | } | |
657 | template<class T, class Alloc> | |
658 | inline void decode(std::vector<ceph::shared_ptr<T>,Alloc>& v, | |
659 | bufferlist::iterator& p) | |
660 | { | |
661 | __u32 n; | |
662 | decode(n, p); | |
663 | v.resize(n); | |
664 | for (__u32 i=0; i<n; i++) { | |
665 | v[i] = std::make_shared<T>(); | |
666 | decode(*v[i], p); | |
667 | } | |
668 | } | |
669 | ||
670 | // map (pointers) | |
671 | /* | |
672 | template<class T, class U> | |
673 | inline void encode(const std::map<T,U*>& m, bufferlist& bl) | |
674 | { | |
675 | __u32 n = m.size(); | |
676 | encode(n, bl); | |
677 | for (typename std::map<T,U*>::const_iterator p = m.begin(); p != m.end(); ++p) { | |
678 | encode(p->first, bl); | |
679 | encode(*p->second, bl); | |
680 | } | |
681 | } | |
682 | template<class T, class U> | |
683 | inline void decode(std::map<T,U*>& m, bufferlist::iterator& p) | |
684 | { | |
685 | __u32 n; | |
686 | decode(n, p); | |
687 | m.clear(); | |
688 | while (n--) { | |
689 | T k; | |
690 | decode(k, p); | |
691 | m[k] = new U(p); | |
692 | } | |
693 | }*/ | |
694 | ||
695 | // map | |
696 | template<class T, class U, class Comp, class Alloc, | |
697 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
698 | inline typename std::enable_if<!t_traits::supported || | |
699 | !u_traits::supported>::type | |
700 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
701 | { | |
702 | __u32 n = (__u32)(m.size()); | |
703 | encode(n, bl); | |
704 | for (auto p = m.begin(); p != m.end(); ++p) { | |
705 | encode(p->first, bl); | |
706 | encode(p->second, bl); | |
707 | } | |
708 | } | |
709 | template<class T, class U, class Comp, class Alloc, | |
710 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
711 | inline typename std::enable_if<!t_traits::supported || | |
712 | !u_traits::supported>::type | |
713 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) | |
714 | { | |
715 | __u32 n = (__u32)(m.size()); | |
716 | encode(n, bl); | |
717 | for (auto p = m.begin(); p != m.end(); ++p) { | |
718 | encode(p->first, bl, features); | |
719 | encode(p->second, bl, features); | |
720 | } | |
721 | } | |
722 | template<class T, class U, class Comp, class Alloc, | |
723 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
724 | inline typename std::enable_if<!t_traits::supported || | |
725 | !u_traits::supported>::type | |
726 | decode(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
727 | { | |
728 | __u32 n; | |
729 | decode(n, p); | |
730 | m.clear(); | |
731 | while (n--) { | |
732 | T k; | |
733 | decode(k, p); | |
734 | decode(m[k], p); | |
735 | } | |
736 | } | |
737 | template<class T, class U, class Comp, class Alloc> | |
738 | inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
739 | { | |
740 | __u32 n; | |
741 | decode(n, p); | |
742 | while (n--) { | |
743 | T k; | |
744 | decode(k, p); | |
745 | decode(m[k], p); | |
746 | } | |
747 | } | |
748 | template<class T, class U, class Comp, class Alloc, | |
749 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
750 | inline typename std::enable_if<!t_traits::supported || | |
751 | !u_traits::supported>::type | |
752 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
753 | { | |
754 | for (auto p = m.begin(); p != m.end(); ++p) { | |
755 | encode(p->first, bl); | |
756 | encode(p->second, bl); | |
757 | } | |
758 | } | |
759 | template<class T, class U, class Comp, class Alloc, | |
760 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
761 | inline typename std::enable_if<!t_traits::supported || | |
762 | !u_traits::supported>::type | |
763 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) | |
764 | { | |
765 | for (auto p = m.begin(); p != m.end(); ++p) { | |
766 | encode(p->first, bl, features); | |
767 | encode(p->second, bl, features); | |
768 | } | |
769 | } | |
770 | template<class T, class U, class Comp, class Alloc, | |
771 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
772 | inline typename std::enable_if<!t_traits::supported || | |
773 | !u_traits::supported>::type | |
774 | decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
775 | { | |
776 | m.clear(); | |
777 | while (n--) { | |
778 | T k; | |
779 | decode(k, p); | |
780 | decode(m[k], p); | |
781 | } | |
782 | } | |
783 | ||
784 | // boost::container::flat-map | |
785 | template<class T, class U, class Comp, class Alloc, | |
786 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
787 | inline typename std::enable_if<!t_traits::supported || | |
788 | !u_traits::supported>::type | |
789 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl) | |
790 | { | |
791 | __u32 n = (__u32)(m.size()); | |
792 | encode(n, bl); | |
793 | for (typename boost::container::flat_map<T,U,Comp>::const_iterator p | |
794 | = m.begin(); p != m.end(); ++p) { | |
795 | encode(p->first, bl); | |
796 | encode(p->second, bl); | |
797 | } | |
798 | } | |
799 | template<class T, class U, class Comp, class Alloc, | |
800 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
801 | inline typename std::enable_if<!t_traits::supported || | |
802 | !u_traits::supported>::type | |
803 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl, | |
804 | uint64_t features) | |
805 | { | |
806 | __u32 n = (__u32)(m.size()); | |
807 | encode(n, bl); | |
808 | for (auto p = m.begin(); p != m.end(); ++p) { | |
809 | encode(p->first, bl, features); | |
810 | encode(p->second, bl, features); | |
811 | } | |
812 | } | |
813 | template<class T, class U, class Comp, class Alloc, | |
814 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
815 | inline typename std::enable_if<!t_traits::supported || | |
816 | !u_traits::supported>::type | |
817 | decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
818 | { | |
819 | __u32 n; | |
820 | decode(n, p); | |
821 | m.clear(); | |
31f18b77 | 822 | m.reserve(n); |
7c673cae FG |
823 | while (n--) { |
824 | T k; | |
825 | decode(k, p); | |
826 | decode(m[k], p); | |
827 | } | |
828 | } | |
829 | template<class T, class U, class Comp, class Alloc> | |
830 | inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m, | |
831 | bufferlist::iterator& p) | |
832 | { | |
833 | __u32 n; | |
834 | decode(n, p); | |
31f18b77 | 835 | m.reserve(m.size() + n); |
7c673cae FG |
836 | while (n--) { |
837 | T k; | |
838 | decode(k, p); | |
839 | decode(m[k], p); | |
840 | } | |
841 | } | |
842 | template<class T, class U, class Comp, class Alloc, | |
843 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
844 | inline typename std::enable_if<!t_traits::supported || | |
845 | !u_traits::supported>::type | |
846 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
847 | bufferlist& bl) | |
848 | { | |
849 | for (auto p = m.begin(); p != m.end(); ++p) { | |
850 | encode(p->first, bl); | |
851 | encode(p->second, bl); | |
852 | } | |
853 | } | |
854 | template<class T, class U, class Comp, class Alloc, | |
855 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
856 | inline typename std::enable_if<!t_traits::supported || | |
857 | !u_traits::supported>::type | |
858 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
859 | bufferlist& bl, uint64_t features) | |
860 | { | |
861 | for (auto p = m.begin(); p != m.end(); ++p) { | |
862 | encode(p->first, bl, features); | |
863 | encode(p->second, bl, features); | |
864 | } | |
865 | } | |
866 | template<class T, class U, class Comp, class Alloc, | |
867 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
868 | inline typename std::enable_if<!t_traits::supported || | |
869 | !u_traits::supported>::type | |
870 | decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m, | |
871 | bufferlist::iterator& p) | |
872 | { | |
873 | m.clear(); | |
874 | while (n--) { | |
875 | T k; | |
876 | decode(k, p); | |
877 | decode(m[k], p); | |
878 | } | |
879 | } | |
880 | ||
881 | // multimap | |
882 | template<class T, class U, class Comp, class Alloc> | |
883 | inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl) | |
884 | { | |
885 | __u32 n = (__u32)(m.size()); | |
886 | encode(n, bl); | |
887 | for (auto p = m.begin(); p != m.end(); ++p) { | |
888 | encode(p->first, bl); | |
889 | encode(p->second, bl); | |
890 | } | |
891 | } | |
892 | template<class T, class U, class Comp, class Alloc> | |
893 | inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::iterator& p) | |
894 | { | |
895 | __u32 n; | |
896 | decode(n, p); | |
897 | m.clear(); | |
898 | while (n--) { | |
899 | typename std::pair<T,U> tu = std::pair<T,U>(); | |
900 | decode(tu.first, p); | |
901 | typename std::multimap<T,U,Comp,Alloc>::iterator it = m.insert(tu); | |
902 | decode(it->second, p); | |
903 | } | |
904 | } | |
905 | ||
906 | // ceph::unordered_map | |
907 | template<class T, class U, class Hash, class Pred, class Alloc> | |
908 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl, | |
909 | uint64_t features) | |
910 | { | |
911 | __u32 n = (__u32)(m.size()); | |
912 | encode(n, bl); | |
913 | for (auto p = m.begin(); p != m.end(); ++p) { | |
914 | encode(p->first, bl, features); | |
915 | encode(p->second, bl, features); | |
916 | } | |
917 | } | |
918 | template<class T, class U, class Hash, class Pred, class Alloc> | |
919 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl) | |
920 | { | |
921 | __u32 n = (__u32)(m.size()); | |
922 | encode(n, bl); | |
923 | for (auto p = m.begin(); p != m.end(); ++p) { | |
924 | encode(p->first, bl); | |
925 | encode(p->second, bl); | |
926 | } | |
927 | } | |
928 | template<class T, class U, class Hash, class Pred, class Alloc> | |
929 | inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::iterator& p) | |
930 | { | |
931 | __u32 n; | |
932 | decode(n, p); | |
933 | m.clear(); | |
934 | while (n--) { | |
935 | T k; | |
936 | decode(k, p); | |
937 | decode(m[k], p); | |
938 | } | |
939 | } | |
940 | ||
941 | // ceph::unordered_set | |
942 | template<class T, class Hash, class Pred, class Alloc> | |
943 | inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl) | |
944 | { | |
945 | __u32 n = (__u32)(m.size()); | |
946 | encode(n, bl); | |
947 | for (auto p = m.begin(); p != m.end(); ++p) | |
948 | encode(*p, bl); | |
949 | } | |
950 | template<class T, class Hash, class Pred, class Alloc> | |
951 | inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::iterator& p) | |
952 | { | |
953 | __u32 n; | |
954 | decode(n, p); | |
955 | m.clear(); | |
956 | while (n--) { | |
957 | T k; | |
958 | decode(k, p); | |
959 | m.insert(k); | |
960 | } | |
961 | } | |
962 | ||
963 | // deque | |
964 | template<class T, class Alloc> | |
965 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
966 | { | |
967 | __u32 n = ls.size(); | |
968 | encode(n, bl); | |
969 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
970 | encode(*p, bl, features); | |
971 | } | |
972 | template<class T, class Alloc> | |
973 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl) | |
974 | { | |
975 | __u32 n = ls.size(); | |
976 | encode(n, bl); | |
977 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
978 | encode(*p, bl); | |
979 | } | |
980 | template<class T, class Alloc> | |
981 | inline void decode(std::deque<T,Alloc>& ls, bufferlist::iterator& p) | |
982 | { | |
983 | __u32 n; | |
984 | decode(n, p); | |
985 | ls.clear(); | |
986 | while (n--) { | |
987 | T v; | |
988 | decode(v, p); | |
989 | ls.push_back(v); | |
990 | } | |
991 | } | |
992 | ||
993 | // std::array<T, N> | |
994 | template<class T, size_t N, typename traits = denc_traits<T>> | |
995 | inline typename std::enable_if<!traits::supported>::type | |
996 | encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features) | |
997 | { | |
998 | for (const auto& e : v) | |
999 | encode(e, bl, features); | |
1000 | } | |
1001 | template<class T, size_t N, typename traits = denc_traits<T>> | |
1002 | inline typename std::enable_if<!traits::supported>::type | |
1003 | encode(const std::array<T, N>& v, bufferlist& bl) | |
1004 | { | |
1005 | for (const auto& e : v) | |
1006 | encode(e, bl); | |
1007 | } | |
1008 | template<class T, size_t N, typename traits = denc_traits<T>> | |
1009 | inline typename std::enable_if<!traits::supported>::type | |
1010 | decode(std::array<T, N>& v, bufferlist::iterator& p) | |
1011 | { | |
1012 | for (auto& e : v) | |
1013 | decode(e, p); | |
1014 | } | |
1015 | ||
1016 | ||
1017 | /* | |
1018 | * guards | |
1019 | */ | |
1020 | ||
1021 | /** | |
1022 | * start encoding block | |
1023 | * | |
1024 | * @param v current (code) version of the encoding | |
1025 | * @param compat oldest code version that can decode it | |
1026 | * @param bl bufferlist to encode to | |
1027 | */ | |
1028 | #define ENCODE_START(v, compat, bl) \ | |
1029 | __u8 struct_v = v, struct_compat = compat; \ | |
1030 | ::encode(struct_v, (bl)); \ | |
1031 | ::encode(struct_compat, (bl)); \ | |
1032 | buffer::list::iterator struct_compat_it = (bl).end(); \ | |
1033 | struct_compat_it.advance(-1); \ | |
1034 | ceph_le32 struct_len; \ | |
1035 | struct_len = 0; \ | |
1036 | ::encode(struct_len, (bl)); \ | |
1037 | buffer::list::iterator struct_len_it = (bl).end(); \ | |
1038 | struct_len_it.advance(-4); \ | |
1039 | do { | |
1040 | ||
1041 | /** | |
1042 | * finish encoding block | |
1043 | * | |
1044 | * @param bl bufferlist we were encoding to | |
1045 | * @param new_struct_compat struct-compat value to use | |
1046 | */ | |
1047 | #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \ | |
1048 | } while (false); \ | |
1049 | struct_len = (bl).length() - struct_len_it.get_off() - sizeof(struct_len); \ | |
1050 | struct_len_it.copy_in(4, (char *)&struct_len); \ | |
1051 | if (new_struct_compat) { \ | |
1052 | struct_compat = new_struct_compat; \ | |
1053 | struct_compat_it.copy_in(1, (char *)&struct_compat); \ | |
1054 | } | |
1055 | ||
1056 | #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0) | |
1057 | ||
1058 | #define DECODE_ERR_OLDVERSION(func, v, compatv) \ | |
1059 | (std::string(func) + " no longer understand old encoding version " #v " < " #compatv) | |
1060 | ||
1061 | #define DECODE_ERR_PAST(func) \ | |
1062 | (std::string(func) + " decode past end of struct encoding") | |
1063 | ||
1064 | /** | |
1065 | * check for very old encoding | |
1066 | * | |
1067 | * If the encoded data is older than oldestv, raise an exception. | |
1068 | * | |
1069 | * @param oldestv oldest version of the code we can successfully decode. | |
1070 | */ | |
1071 | #define DECODE_OLDEST(oldestv) \ | |
1072 | if (struct_v < oldestv) \ | |
1073 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv)); | |
1074 | ||
1075 | /** | |
1076 | * start a decoding block | |
1077 | * | |
1078 | * @param v current version of the encoding that the code supports/encodes | |
1079 | * @param bl bufferlist::iterator for the encoded data | |
1080 | */ | |
1081 | #define DECODE_START(v, bl) \ | |
1082 | __u8 struct_v, struct_compat; \ | |
1083 | ::decode(struct_v, bl); \ | |
1084 | ::decode(struct_compat, bl); \ | |
1085 | if (v < struct_compat) \ | |
1086 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ | |
1087 | __u32 struct_len; \ | |
1088 | ::decode(struct_len, bl); \ | |
1089 | if (struct_len > bl.get_remaining()) \ | |
1090 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1091 | unsigned struct_end = bl.get_off() + struct_len; \ | |
1092 | do { | |
1093 | ||
1094 | #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \ | |
1095 | __u8 struct_v; \ | |
1096 | ::decode(struct_v, bl); \ | |
1097 | if (struct_v >= compatv) { \ | |
1098 | __u8 struct_compat; \ | |
1099 | ::decode(struct_compat, bl); \ | |
1100 | if (v < struct_compat) \ | |
1101 | throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ | |
1102 | } else if (skip_v) { \ | |
1103 | if ((int)bl.get_remaining() < skip_v) \ | |
1104 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1105 | bl.advance(skip_v); \ | |
1106 | } \ | |
1107 | unsigned struct_end = 0; \ | |
1108 | if (struct_v >= lenv) { \ | |
1109 | __u32 struct_len; \ | |
1110 | ::decode(struct_len, bl); \ | |
1111 | if (struct_len > bl.get_remaining()) \ | |
1112 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1113 | struct_end = bl.get_off() + struct_len; \ | |
1114 | } \ | |
1115 | do { | |
1116 | ||
1117 | /** | |
1118 | * start a decoding block with legacy support for older encoding schemes | |
1119 | * | |
1120 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1121 | * the compat version or length. Skip those fields conditionally. | |
1122 | * | |
1123 | * Most of the time, v, compatv, and lenv will all match the version | |
1124 | * where the structure was switched over to the new macros. | |
1125 | * | |
1126 | * @param v current version of the encoding that the code supports/encodes | |
1127 | * @param compatv oldest version that includes a __u8 compat version field | |
1128 | * @param lenv oldest version that includes a __u32 length wrapper | |
1129 | * @param bl bufferlist::iterator containing the encoded data | |
1130 | */ | |
1131 | #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \ | |
1132 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 0, bl) | |
1133 | ||
1134 | /** | |
1135 | * start a decoding block with legacy support for older encoding schemes | |
1136 | * | |
1137 | * This version of the macro assumes the legacy encoding had a 32 bit | |
1138 | * version | |
1139 | * | |
1140 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1141 | * the compat version or length. Skip those fields conditionally. | |
1142 | * | |
1143 | * Most of the time, v, compatv, and lenv will all match the version | |
1144 | * where the structure was switched over to the new macros. | |
1145 | * | |
1146 | * @param v current version of the encoding that the code supports/encodes | |
1147 | * @param compatv oldest version that includes a __u8 compat version field | |
1148 | * @param lenv oldest version that includes a __u32 length wrapper | |
1149 | * @param bl bufferlist::iterator containing the encoded data | |
1150 | */ | |
1151 | #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \ | |
1152 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3, bl) | |
1153 | ||
1154 | #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \ | |
1155 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1, bl) | |
1156 | ||
1157 | /** | |
1158 | * finish decode block | |
1159 | * | |
1160 | * @param bl bufferlist::iterator we were decoding from | |
1161 | */ | |
1162 | #define DECODE_FINISH(bl) \ | |
1163 | } while (false); \ | |
1164 | if (struct_end) { \ | |
1165 | if (bl.get_off() > struct_end) \ | |
1166 | throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ | |
1167 | if (bl.get_off() < struct_end) \ | |
1168 | bl.advance(struct_end - bl.get_off()); \ | |
1169 | } | |
1170 | ||
1171 | /* | |
1172 | * Encoders/decoders to read from current offset in a file handle and | |
1173 | * encode/decode the data according to argument types. | |
1174 | */ | |
1175 | inline ssize_t decode_file(int fd, std::string &str) | |
1176 | { | |
1177 | bufferlist bl; | |
1178 | __u32 len = 0; | |
1179 | bl.read_fd(fd, sizeof(len)); | |
1180 | decode(len, bl); | |
1181 | bl.read_fd(fd, len); | |
1182 | decode(str, bl); | |
1183 | return bl.length(); | |
1184 | } | |
1185 | ||
1186 | inline ssize_t decode_file(int fd, bufferptr &bp) | |
1187 | { | |
1188 | bufferlist bl; | |
1189 | __u32 len = 0; | |
1190 | bl.read_fd(fd, sizeof(len)); | |
1191 | decode(len, bl); | |
1192 | bl.read_fd(fd, len); | |
1193 | bufferlist::iterator bli = bl.begin(); | |
1194 | ||
1195 | decode(bp, bli); | |
1196 | return bl.length(); | |
1197 | } | |
1198 | ||
1199 | #endif |