]>
git.proxmox.com Git - ceph.git/blob - 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
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
14 #ifndef CEPH_ENCODING_H
15 #define CEPH_ENCODING_H
17 #include "include/int_types.h"
19 #include "include/memory.h"
21 #include "byteorder.h"
24 // pull in the new-style encoding so that we get the denc_traits<> definition.
32 * Notes on feature encoding:
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
43 * - A feature encode() method will fail to compile if a value is not
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.
50 // --------------------------------------
54 inline void encode_raw(const T
& t
, bufferlist
& bl
)
56 bl
.append((char*)&t
, sizeof(t
));
59 inline void decode_raw(T
& t
, bufferlist::iterator
&p
)
61 p
.copy(sizeof(t
), (char*)&t
);
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); }
68 WRITE_RAW_ENCODER(__u8
)
69 #ifndef _CHAR_IS_SIGNED
70 WRITE_RAW_ENCODER(__s8
)
72 WRITE_RAW_ENCODER(char)
73 WRITE_RAW_ENCODER(ceph_le64
)
74 WRITE_RAW_ENCODER(ceph_le32
)
75 WRITE_RAW_ENCODER(ceph_le16
)
77 // FIXME: we need to choose some portable floating point encoding here
78 WRITE_RAW_ENCODER(float)
79 WRITE_RAW_ENCODER(double)
81 inline void encode(const bool &v
, bufferlist
& bl
) {
85 inline void decode(bool &v
, bufferlist::iterator
& p
) {
92 // -----------------------------------
95 #define WRITE_INTTYPE_ENCODER(type, etype) \
96 inline void encode(type v, bufferlist& bl, uint64_t features=0) { \
101 inline void decode(type &v, bufferlist::iterator& p) { \
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
)
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) \
123 for (unsigned t = i; t; bits++) \
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); \
132 sub.substr_of(bl, pre_off, bl.length() - pre_off); \
138 # define ENCODE_DUMP_PRE()
139 # define ENCODE_DUMP_POST(cl)
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); }
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); }
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); }
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); }
165 inline void encode(const std::string
& s
, bufferlist
& bl
, uint64_t features
=0)
167 __u32 len
= s
.length();
170 bl
.append(s
.data(), len
);
172 inline void decode(std::string
& s
, bufferlist::iterator
& p
)
180 inline void encode_nohead(const std::string
& s
, bufferlist
& bl
)
182 bl
.append(s
.data(), s
.length());
184 inline void decode_nohead(int len
, std::string
& s
, bufferlist::iterator
& p
)
190 // const char* (encode only, string compatible)
191 inline void encode(const char *s
, bufferlist
& bl
)
193 __u32 len
= strlen(s
);
202 inline void encode_array_nohead(const A a
[], int n
, bufferlist
&bl
)
204 for (int i
=0; i
<n
; i
++)
208 inline void decode_array_nohead(A a
[], int n
, bufferlist::iterator
&p
)
210 for (int i
=0; i
<n
; i
++)
216 // -----------------------------
219 // bufferptr (encapsulated)
220 inline void encode(const buffer::ptr
& bp
, bufferlist
& bl
)
222 __u32 len
= bp
.length();
227 inline void decode(buffer::ptr
& bp
, bufferlist::iterator
& p
)
236 if (s
.get_num_buffers() == 1)
239 bp
= buffer::copy(s
.c_str(), s
.length());
243 // bufferlist (encapsulated)
244 inline void encode(const bufferlist
& s
, bufferlist
& bl
)
246 __u32 len
= s
.length();
250 inline void encode_destructively(bufferlist
& s
, bufferlist
& bl
)
252 __u32 len
= s
.length();
256 inline void decode(bufferlist
& s
, bufferlist::iterator
& p
)
264 inline void encode_nohead(const bufferlist
& s
, bufferlist
& bl
)
268 inline void decode_nohead(int len
, bufferlist
& s
, bufferlist::iterator
& p
)
277 inline void decode(T
&o
, bufferlist
& bl
)
279 bufferlist::iterator p
= bl
.begin();
285 // -----------------------------
286 // STL container types
293 #include <boost/optional/optional_io.hpp>
294 #include <boost/tuple/tuple.hpp>
296 #ifndef _BACKWARD_BACKWARD_WARNING_H
297 #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_*
299 #include "include/unordered_map.h"
300 #include "include/unordered_set.h"
305 inline void encode(const boost::optional
<T
> &p
, bufferlist
&bl
)
307 __u8 present
= static_cast<bool>(p
);
308 ::encode(present
, bl
);
313 #pragma GCC diagnostic ignored "-Wpragmas"
314 #pragma GCC diagnostic push
315 #pragma GCC diagnostic ignored "-Wuninitialized"
316 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
318 inline void decode(boost::optional
<T
> &p
, bufferlist::iterator
&bp
)
321 ::decode(present
, bp
);
328 #pragma GCC diagnostic pop
329 #pragma GCC diagnostic warning "-Wpragmas"
332 template<class A
, class B
, class C
>
333 inline void encode(const boost::tuple
<A
, B
, C
> &t
, bufferlist
& bl
)
335 encode(boost::get
<0>(t
), bl
);
336 encode(boost::get
<1>(t
), bl
);
337 encode(boost::get
<2>(t
), bl
);
339 template<class A
, class B
, class C
>
340 inline void decode(boost::tuple
<A
, B
, C
> &t
, bufferlist::iterator
&bp
)
342 decode(boost::get
<0>(t
), bp
);
343 decode(boost::get
<1>(t
), bp
);
344 decode(boost::get
<2>(t
), bp
);
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
)
354 encode(p
.first
, bl
, features
);
355 encode(p
.second
, bl
, features
);
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
)
364 encode(p
.second
, bl
);
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
)
373 decode(pa
.second
, p
);
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
)
381 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
383 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
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
)
390 // should i pre- or post- count?
392 unsigned pos
= bl
.length();
395 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
) {
397 encode(*p
, bl
, features
);
401 bl
.copy_in(pos
, sizeof(en
), (char*)&en
);
403 __u32 n
= (__u32
)(ls
.size()); // FIXME: this is slow on a list.
405 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
406 encode(*p
, bl
, features
);
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
)
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
,
428 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
430 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
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
)
437 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
439 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
440 encode(**p
, bl
, features
);
442 template<class T
, class Alloc
>
443 inline void decode(std::list
<ceph::shared_ptr
<T
>, Alloc
>& ls
,
444 bufferlist::iterator
& p
)
450 ceph::shared_ptr
<T
> v(std::make_shared
<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
)
461 __u32 n
= (__u32
)(s
.size());
463 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
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
)
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
)
484 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
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
)
491 for (int i
=0; i
<len
; i
++) {
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
)
503 __u32 n
= (__u32
)(s
.size());
505 for (const auto& e
: s
)
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
)
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
,
528 for (const auto& e
: s
)
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
)
537 for (int i
=0; i
<len
; i
++) {
545 template<class T
, class Comp
, class Alloc
>
546 inline void encode(const std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
)
548 __u32 n
= (__u32
)(s
.size());
550 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
553 template<class T
, class Comp
, class Alloc
>
554 inline void decode(std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist::iterator
& p
)
568 inline void encode(const std::vector<T*>& v, bufferlist& bl)
572 for (typename std::vector<T*>::const_iterator p = v.begin(); p != v.end(); ++p)
576 inline void decode(std::vector<T*>& v, bufferlist::iterator& p)
581 for (__u32 i=0; i<n; i++)
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
)
590 __u32 n
= (__u32
)(v
.size());
592 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
593 encode(*p
, bl
, features
);
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
)
599 __u32 n
= (__u32
)(v
.size());
601 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
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
)
611 for (__u32 i
=0; i
<n
; i
++)
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
)
619 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
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
)
627 for (__u32 i
=0; i
<v
.size(); i
++)
631 // vector (shared_ptr)
632 template<class T
,class Alloc
>
633 inline void encode(const std::vector
<ceph::shared_ptr
<T
>,Alloc
>& v
,
637 __u32 n
= (__u32
)(v
.size());
639 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
641 encode(**p
, bl
, features
);
643 encode(T(), bl
, features
);
645 template<class T
, class Alloc
>
646 inline void encode(const std::vector
<ceph::shared_ptr
<T
>,Alloc
>& v
,
649 __u32 n
= (__u32
)(v
.size());
651 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
657 template<class T
, class Alloc
>
658 inline void decode(std::vector
<ceph::shared_ptr
<T
>,Alloc
>& v
,
659 bufferlist::iterator
& p
)
664 for (__u32 i
=0; i
<n
; i
++) {
665 v
[i
] = std::make_shared
<T
>();
672 template<class T, class U>
673 inline void encode(const std::map<T,U*>& m, bufferlist& 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);
682 template<class T, class U>
683 inline void decode(std::map<T,U*>& m, bufferlist::iterator& p)
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
)
702 __u32 n
= (__u32
)(m
.size());
704 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
705 encode(p
->first
, bl
);
706 encode(p
->second
, bl
);
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
)
715 __u32 n
= (__u32
)(m
.size());
717 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
718 encode(p
->first
, bl
, features
);
719 encode(p
->second
, bl
, features
);
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
)
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
)
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
)
754 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
755 encode(p
->first
, bl
);
756 encode(p
->second
, bl
);
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
)
765 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
766 encode(p
->first
, bl
, features
);
767 encode(p
->second
, bl
, features
);
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
)
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
)
791 __u32 n
= (__u32
)(m
.size());
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
);
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
,
806 __u32 n
= (__u32
)(m
.size());
808 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
809 encode(p
->first
, bl
, features
);
810 encode(p
->second
, bl
, features
);
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
)
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
)
835 m
.reserve(m
.size() + n
);
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
,
849 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
850 encode(p
->first
, bl
);
851 encode(p
->second
, bl
);
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
)
861 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
862 encode(p
->first
, bl
, features
);
863 encode(p
->second
, bl
, features
);
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
)
882 template<class T
, class U
, class Comp
, class Alloc
>
883 inline void encode(const std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
)
885 __u32 n
= (__u32
)(m
.size());
887 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
888 encode(p
->first
, bl
);
889 encode(p
->second
, bl
);
892 template<class T
, class U
, class Comp
, class Alloc
>
893 inline void decode(std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist::iterator
& p
)
899 typename
std::pair
<T
,U
> tu
= std::pair
<T
,U
>();
901 typename
std::multimap
<T
,U
,Comp
,Alloc
>::iterator it
= m
.insert(tu
);
902 decode(it
->second
, p
);
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
,
911 __u32 n
= (__u32
)(m
.size());
913 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
914 encode(p
->first
, bl
, features
);
915 encode(p
->second
, bl
, features
);
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
)
921 __u32 n
= (__u32
)(m
.size());
923 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
924 encode(p
->first
, bl
);
925 encode(p
->second
, bl
);
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
)
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
)
945 __u32 n
= (__u32
)(m
.size());
947 for (auto p
= m
.begin(); p
!= m
.end(); ++p
)
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
)
964 template<class T
, class Alloc
>
965 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
, uint64_t features
)
969 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
970 encode(*p
, bl
, features
);
972 template<class T
, class Alloc
>
973 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
)
977 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
980 template<class T
, class Alloc
>
981 inline void decode(std::deque
<T
,Alloc
>& ls
, bufferlist::iterator
& p
)
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
)
998 for (const auto& e
: v
)
999 encode(e
, bl
, features
);
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
)
1005 for (const auto& e
: v
)
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
)
1022 * start encoding block
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
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; \
1036 ::encode(struct_len, (bl)); \
1037 buffer::list::iterator struct_len_it = (bl).end(); \
1038 struct_len_it.advance(-4); \
1042 * finish encoding block
1044 * @param bl bufferlist we were encoding to
1045 * @param new_struct_compat struct-compat value to use
1047 #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \
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); \
1056 #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0)
1058 #define DECODE_ERR_OLDVERSION(func, v, compatv) \
1059 (std::string(func) + " no longer understand old encoding version " #v " < " #compatv)
1061 #define DECODE_ERR_PAST(func) \
1062 (std::string(func) + " decode past end of struct encoding")
1065 * check for very old encoding
1067 * If the encoded data is older than oldestv, raise an exception.
1069 * @param oldestv oldest version of the code we can successfully decode.
1071 #define DECODE_OLDEST(oldestv) \
1072 if (struct_v < oldestv) \
1073 throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv));
1076 * start a decoding block
1078 * @param v current version of the encoding that the code supports/encodes
1079 * @param bl bufferlist::iterator for the encoded data
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)); \
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; \
1094 #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \
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); \
1107 unsigned struct_end = 0; \
1108 if (struct_v >= lenv) { \
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; \
1118 * start a decoding block with legacy support for older encoding schemes
1120 * The old encoding schemes has a __u8 struct_v only, or lacked either
1121 * the compat version or length. Skip those fields conditionally.
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.
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
1131 #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \
1132 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 0, bl)
1135 * start a decoding block with legacy support for older encoding schemes
1137 * This version of the macro assumes the legacy encoding had a 32 bit
1140 * The old encoding schemes has a __u8 struct_v only, or lacked either
1141 * the compat version or length. Skip those fields conditionally.
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.
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
1151 #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \
1152 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3, bl)
1154 #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \
1155 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1, bl)
1158 * finish decode block
1160 * @param bl bufferlist::iterator we were decoding from
1162 #define DECODE_FINISH(bl) \
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()); \
1172 * Encoders/decoders to read from current offset in a file handle and
1173 * encode/decode the data according to argument types.
1175 inline ssize_t
decode_file(int fd
, std::string
&str
)
1179 bl
.read_fd(fd
, sizeof(len
));
1181 bl
.read_fd(fd
, len
);
1186 inline ssize_t
decode_file(int fd
, bufferptr
&bp
)
1190 bl
.read_fd(fd
, sizeof(len
));
1192 bl
.read_fd(fd
, len
);
1193 bufferlist::iterator bli
= bl
.begin();