]> git.proxmox.com Git - ceph.git/blob - ceph/src/include/encoding.h
update sources to v12.1.0
[ceph.git] / ceph / src / include / encoding.h
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();
515 s.reserve(n);
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 {
536 s.reserve(len);
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();
822 m.reserve(n);
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);
835 m.reserve(m.size() + n);
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