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);
200 // -----------------------------
203 // bufferptr (encapsulated)
204 inline void encode(const buffer::ptr& bp, bufferlist& bl)
206 __u32 len = bp.length();
211 inline void decode(buffer::ptr& bp, bufferlist::iterator& p)
220 if (s.get_num_buffers() == 1)
223 bp = buffer::copy(s.c_str(), s.length());
227 // bufferlist (encapsulated)
228 inline void encode(const bufferlist& s, bufferlist& bl)
230 __u32 len = s.length();
234 inline void encode_destructively(bufferlist& s, bufferlist& bl)
236 __u32 len = s.length();
240 inline void decode(bufferlist& s, bufferlist::iterator& p)
248 inline void encode_nohead(const bufferlist& s, bufferlist& bl)
252 inline void decode_nohead(int len, bufferlist& s, bufferlist::iterator& p)
261 inline void decode(T &o, bufferlist& bl)
263 bufferlist::iterator p = bl.begin();
269 // -----------------------------
270 // STL container types
277 #include <boost/optional/optional_io.hpp>
278 #include <boost/tuple/tuple.hpp>
280 #ifndef _BACKWARD_BACKWARD_WARNING_H
281 #define _BACKWARD_BACKWARD_WARNING_H // make gcc 4.3 shut up about hash_*
283 #include "include/unordered_map.h"
284 #include "include/unordered_set.h"
289 inline void encode(const boost::optional<T> &p, bufferlist &bl)
291 __u8 present = static_cast<bool>(p);
292 ::encode(present, bl);
297 #pragma GCC diagnostic ignored "-Wpragmas"
298 #pragma GCC diagnostic push
299 #pragma GCC diagnostic ignored "-Wuninitialized"
301 inline void decode(boost::optional<T> &p, bufferlist::iterator &bp)
304 ::decode(present, bp);
312 #pragma GCC diagnostic pop
313 #pragma GCC diagnostic warning "-Wpragmas"
316 template<class A, class B, class C>
317 inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl)
319 encode(boost::get<0>(t), bl);
320 encode(boost::get<1>(t), bl);
321 encode(boost::get<2>(t), bl);
323 template<class A, class B, class C>
324 inline void decode(boost::tuple<A, B, C> &t, bufferlist::iterator &bp)
326 decode(boost::get<0>(t), bp);
327 decode(boost::get<1>(t), bp);
328 decode(boost::get<2>(t), bp);
332 template<class A, class B,
333 typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
334 inline typename std::enable_if<!a_traits::supported ||
335 !b_traits::supported>::type
336 encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features)
338 encode(p.first, bl, features);
339 encode(p.second, bl, features);
341 template<class A, class B,
342 typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
343 inline typename std::enable_if<!a_traits::supported ||
344 !b_traits::supported>::type
345 encode(const std::pair<A,B> &p, bufferlist &bl)
348 encode(p.second, bl);
350 template<class A, class B,
351 typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>>
352 inline typename std::enable_if<!a_traits::supported ||
353 !b_traits::supported>::type
354 decode(std::pair<A,B> &pa, bufferlist::iterator &p)
357 decode(pa.second, p);
361 template<class T, class Alloc, typename traits=denc_traits<T>>
362 inline typename std::enable_if<!traits::supported>::type
363 encode(const std::list<T, Alloc>& ls, bufferlist& bl)
365 __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1)
367 for (auto p = ls.begin(); p != ls.end(); ++p)
370 template<class T, class Alloc, typename traits=denc_traits<T>>
371 inline typename std::enable_if<!traits::supported>::type
372 encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features)
374 // should i pre- or post- count?
376 unsigned pos = bl.length();
379 for (auto p = ls.begin(); p != ls.end(); ++p) {
381 encode(*p, bl, features);
385 bl.copy_in(pos, sizeof(en), (char*)&en);
387 __u32 n = (__u32)(ls.size()); // FIXME: this is slow on a list.
389 for (auto p = ls.begin(); p != ls.end(); ++p)
390 encode(*p, bl, features);
393 template<class T, class Alloc, typename traits=denc_traits<T>>
394 inline typename std::enable_if<!traits::supported>::type
395 decode(std::list<T,Alloc>& ls, bufferlist::iterator& p)
407 // std::list<ceph::shared_ptr<T>>
408 template<class T, class Alloc>
409 inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls,
412 __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1)
414 for (auto p = ls.begin(); p != ls.end(); ++p)
417 template<class T, class Alloc>
418 inline void encode(const std::list<ceph::shared_ptr<T>, Alloc>& ls,
419 bufferlist& bl, uint64_t features)
421 __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1)
423 for (auto p = ls.begin(); p != ls.end(); ++p)
424 encode(**p, bl, features);
426 template<class T, class Alloc>
427 inline void decode(std::list<ceph::shared_ptr<T>, Alloc>& ls,
428 bufferlist::iterator& p)
434 ceph::shared_ptr<T> v(std::make_shared<T>());
441 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
442 inline typename std::enable_if<!traits::supported>::type
443 encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl)
445 __u32 n = (__u32)(s.size());
447 for (auto p = s.begin(); p != s.end(); ++p)
450 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
451 inline typename std::enable_if<!traits::supported>::type
452 decode(std::set<T,Comp,Alloc>& s, bufferlist::iterator& p)
464 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
465 inline typename std::enable_if<!traits::supported>::type
466 encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl)
468 for (auto p = s.begin(); p != s.end(); ++p)
471 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
472 inline typename std::enable_if<!traits::supported>::type
473 decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::iterator& p)
475 for (int i=0; i<len; i++) {
482 // boost::container::flat_set<T>
483 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
484 inline typename std::enable_if<!traits::supported>::type
485 encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl)
487 __u32 n = (__u32)(s.size());
489 for (const auto& e : s)
492 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
493 inline typename std::enable_if<!traits::supported>::type
494 decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::iterator& p)
507 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
508 inline typename std::enable_if<!traits::supported>::type
509 encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s,
512 for (const auto& e : s)
515 template<class T, class Comp, class Alloc, typename traits=denc_traits<T>>
516 inline typename std::enable_if<!traits::supported>::type
517 decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s,
518 bufferlist::iterator& p)
521 for (int i=0; i<len; i++) {
529 template<class T, class Comp, class Alloc>
530 inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl)
532 __u32 n = (__u32)(s.size());
534 for (auto p = s.begin(); p != s.end(); ++p)
537 template<class T, class Comp, class Alloc>
538 inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::iterator& p)
552 inline void encode(const std::vector<T*>& v, bufferlist& bl)
556 for (typename std::vector<T*>::const_iterator p = v.begin(); p != v.end(); ++p)
560 inline void decode(std::vector<T*>& v, bufferlist::iterator& p)
565 for (__u32 i=0; i<n; i++)
570 template<class T, class Alloc, typename traits=denc_traits<T>>
571 inline typename std::enable_if<!traits::supported>::type
572 encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features)
574 __u32 n = (__u32)(v.size());
576 for (auto p = v.begin(); p != v.end(); ++p)
577 encode(*p, bl, features);
579 template<class T, class Alloc, typename traits=denc_traits<T>>
580 inline typename std::enable_if<!traits::supported>::type
581 encode(const std::vector<T,Alloc>& v, bufferlist& bl)
583 __u32 n = (__u32)(v.size());
585 for (auto p = v.begin(); p != v.end(); ++p)
588 template<class T, class Alloc, typename traits=denc_traits<T>>
589 inline typename std::enable_if<!traits::supported>::type
590 decode(std::vector<T,Alloc>& v, bufferlist::iterator& p)
595 for (__u32 i=0; i<n; i++)
599 template<class T, class Alloc, typename traits=denc_traits<T>>
600 inline typename std::enable_if<!traits::supported>::type
601 encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl)
603 for (auto p = v.begin(); p != v.end(); ++p)
606 template<class T, class Alloc, typename traits=denc_traits<T>>
607 inline typename std::enable_if<!traits::supported>::type
608 decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::iterator& p)
611 for (__u32 i=0; i<v.size(); i++)
615 // vector (shared_ptr)
616 template<class T,class Alloc>
617 inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v,
621 __u32 n = (__u32)(v.size());
623 for (auto p = v.begin(); p != v.end(); ++p)
625 encode(**p, bl, features);
627 encode(T(), bl, features);
629 template<class T, class Alloc>
630 inline void encode(const std::vector<ceph::shared_ptr<T>,Alloc>& v,
633 __u32 n = (__u32)(v.size());
635 for (auto p = v.begin(); p != v.end(); ++p)
641 template<class T, class Alloc>
642 inline void decode(std::vector<ceph::shared_ptr<T>,Alloc>& v,
643 bufferlist::iterator& p)
648 for (__u32 i=0; i<n; i++) {
649 v[i] = std::make_shared<T>();
656 template<class T, class U>
657 inline void encode(const std::map<T,U*>& m, bufferlist& bl)
661 for (typename std::map<T,U*>::const_iterator p = m.begin(); p != m.end(); ++p) {
662 encode(p->first, bl);
663 encode(*p->second, bl);
666 template<class T, class U>
667 inline void decode(std::map<T,U*>& m, bufferlist::iterator& p)
680 template<class T, class U, class Comp, class Alloc,
681 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
682 inline typename std::enable_if<!t_traits::supported ||
683 !u_traits::supported>::type
684 encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl)
686 __u32 n = (__u32)(m.size());
688 for (auto p = m.begin(); p != m.end(); ++p) {
689 encode(p->first, bl);
690 encode(p->second, bl);
693 template<class T, class U, class Comp, class Alloc,
694 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
695 inline typename std::enable_if<!t_traits::supported ||
696 !u_traits::supported>::type
697 encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features)
699 __u32 n = (__u32)(m.size());
701 for (auto p = m.begin(); p != m.end(); ++p) {
702 encode(p->first, bl, features);
703 encode(p->second, bl, features);
706 template<class T, class U, class Comp, class Alloc,
707 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
708 inline typename std::enable_if<!t_traits::supported ||
709 !u_traits::supported>::type
710 decode(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
721 template<class T, class U, class Comp, class Alloc>
722 inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
732 template<class T, class U, class Comp, class Alloc,
733 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
734 inline typename std::enable_if<!t_traits::supported ||
735 !u_traits::supported>::type
736 encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl)
738 for (auto p = m.begin(); p != m.end(); ++p) {
739 encode(p->first, bl);
740 encode(p->second, bl);
743 template<class T, class U, class Comp, class Alloc,
744 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
745 inline typename std::enable_if<!t_traits::supported ||
746 !u_traits::supported>::type
747 encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features)
749 for (auto p = m.begin(); p != m.end(); ++p) {
750 encode(p->first, bl, features);
751 encode(p->second, bl, features);
754 template<class T, class U, class Comp, class Alloc,
755 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
756 inline typename std::enable_if<!t_traits::supported ||
757 !u_traits::supported>::type
758 decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
768 // boost::container::flat-map
769 template<class T, class U, class Comp, class Alloc,
770 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
771 inline typename std::enable_if<!t_traits::supported ||
772 !u_traits::supported>::type
773 encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl)
775 __u32 n = (__u32)(m.size());
777 for (typename boost::container::flat_map<T,U,Comp>::const_iterator p
778 = m.begin(); p != m.end(); ++p) {
779 encode(p->first, bl);
780 encode(p->second, bl);
783 template<class T, class U, class Comp, class Alloc,
784 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
785 inline typename std::enable_if<!t_traits::supported ||
786 !u_traits::supported>::type
787 encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl,
790 __u32 n = (__u32)(m.size());
792 for (auto p = m.begin(); p != m.end(); ++p) {
793 encode(p->first, bl, features);
794 encode(p->second, bl, features);
797 template<class T, class U, class Comp, class Alloc,
798 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
799 inline typename std::enable_if<!t_traits::supported ||
800 !u_traits::supported>::type
801 decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
813 template<class T, class U, class Comp, class Alloc>
814 inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m,
815 bufferlist::iterator& p)
819 m.reserve(m.size() + n);
826 template<class T, class U, class Comp, class Alloc,
827 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
828 inline typename std::enable_if<!t_traits::supported ||
829 !u_traits::supported>::type
830 encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m,
833 for (auto p = m.begin(); p != m.end(); ++p) {
834 encode(p->first, bl);
835 encode(p->second, bl);
838 template<class T, class U, class Comp, class Alloc,
839 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
840 inline typename std::enable_if<!t_traits::supported ||
841 !u_traits::supported>::type
842 encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m,
843 bufferlist& bl, uint64_t features)
845 for (auto p = m.begin(); p != m.end(); ++p) {
846 encode(p->first, bl, features);
847 encode(p->second, bl, features);
850 template<class T, class U, class Comp, class Alloc,
851 typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>>
852 inline typename std::enable_if<!t_traits::supported ||
853 !u_traits::supported>::type
854 decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m,
855 bufferlist::iterator& p)
866 template<class T, class U, class Comp, class Alloc>
867 inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl)
869 __u32 n = (__u32)(m.size());
871 for (auto p = m.begin(); p != m.end(); ++p) {
872 encode(p->first, bl);
873 encode(p->second, bl);
876 template<class T, class U, class Comp, class Alloc>
877 inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::iterator& p)
883 typename std::pair<T,U> tu = std::pair<T,U>();
885 typename std::multimap<T,U,Comp,Alloc>::iterator it = m.insert(tu);
886 decode(it->second, p);
890 // ceph::unordered_map
891 template<class T, class U, class Hash, class Pred, class Alloc>
892 inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl,
895 __u32 n = (__u32)(m.size());
897 for (auto p = m.begin(); p != m.end(); ++p) {
898 encode(p->first, bl, features);
899 encode(p->second, bl, features);
902 template<class T, class U, class Hash, class Pred, class Alloc>
903 inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl)
905 __u32 n = (__u32)(m.size());
907 for (auto p = m.begin(); p != m.end(); ++p) {
908 encode(p->first, bl);
909 encode(p->second, bl);
912 template<class T, class U, class Hash, class Pred, class Alloc>
913 inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::iterator& p)
925 // ceph::unordered_set
926 template<class T, class Hash, class Pred, class Alloc>
927 inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl)
929 __u32 n = (__u32)(m.size());
931 for (auto p = m.begin(); p != m.end(); ++p)
934 template<class T, class Hash, class Pred, class Alloc>
935 inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::iterator& p)
948 template<class T, class Alloc>
949 inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features)
953 for (auto p = ls.begin(); p != ls.end(); ++p)
954 encode(*p, bl, features);
956 template<class T, class Alloc>
957 inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl)
961 for (auto p = ls.begin(); p != ls.end(); ++p)
964 template<class T, class Alloc>
965 inline void decode(std::deque<T,Alloc>& ls, bufferlist::iterator& p)
978 template<class T, size_t N, typename traits = denc_traits<T>>
979 inline typename std::enable_if<!traits::supported>::type
980 encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features)
982 for (const auto& e : v)
983 encode(e, bl, features);
985 template<class T, size_t N, typename traits = denc_traits<T>>
986 inline typename std::enable_if<!traits::supported>::type
987 encode(const std::array<T, N>& v, bufferlist& bl)
989 for (const auto& e : v)
992 template<class T, size_t N, typename traits = denc_traits<T>>
993 inline typename std::enable_if<!traits::supported>::type
994 decode(std::array<T, N>& v, bufferlist::iterator& p)
1006 * start encoding block
1008 * @param v current (code) version of the encoding
1009 * @param compat oldest code version that can decode it
1010 * @param bl bufferlist to encode to
1012 #define ENCODE_START(v, compat, bl) \
1013 __u8 struct_v = v, struct_compat = compat; \
1014 ::encode(struct_v, (bl)); \
1015 ::encode(struct_compat, (bl)); \
1016 buffer::list::iterator struct_compat_it = (bl).end(); \
1017 struct_compat_it.advance(-1); \
1018 ceph_le32 struct_len; \
1020 ::encode(struct_len, (bl)); \
1021 buffer::list::iterator struct_len_it = (bl).end(); \
1022 struct_len_it.advance(-4); \
1026 * finish encoding block
1028 * @param bl bufferlist we were encoding to
1029 * @param new_struct_compat struct-compat value to use
1031 #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \
1033 struct_len = (bl).length() - struct_len_it.get_off() - sizeof(struct_len); \
1034 struct_len_it.copy_in(4, (char *)&struct_len); \
1035 if (new_struct_compat) { \
1036 struct_compat = new_struct_compat; \
1037 struct_compat_it.copy_in(1, (char *)&struct_compat); \
1040 #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0)
1042 #define DECODE_ERR_OLDVERSION(func, v, compatv) \
1043 (std::string(func) + " no longer understand old encoding version " #v " < " #compatv)
1045 #define DECODE_ERR_PAST(func) \
1046 (std::string(func) + " decode past end of struct encoding")
1049 * check for very old encoding
1051 * If the encoded data is older than oldestv, raise an exception.
1053 * @param oldestv oldest version of the code we can successfully decode.
1055 #define DECODE_OLDEST(oldestv) \
1056 if (struct_v < oldestv) \
1057 throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv));
1060 * start a decoding block
1062 * @param v current version of the encoding that the code supports/encodes
1063 * @param bl bufferlist::iterator for the encoded data
1065 #define DECODE_START(v, bl) \
1066 __u8 struct_v, struct_compat; \
1067 ::decode(struct_v, bl); \
1068 ::decode(struct_compat, bl); \
1069 if (v < struct_compat) \
1070 throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1072 ::decode(struct_len, bl); \
1073 if (struct_len > bl.get_remaining()) \
1074 throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1075 unsigned struct_end = bl.get_off() + struct_len; \
1078 #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \
1080 ::decode(struct_v, bl); \
1081 if (struct_v >= compatv) { \
1082 __u8 struct_compat; \
1083 ::decode(struct_compat, bl); \
1084 if (v < struct_compat) \
1085 throw buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1086 } else if (skip_v) { \
1087 if ((int)bl.get_remaining() < skip_v) \
1088 throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1089 bl.advance(skip_v); \
1091 unsigned struct_end = 0; \
1092 if (struct_v >= lenv) { \
1094 ::decode(struct_len, bl); \
1095 if (struct_len > bl.get_remaining()) \
1096 throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1097 struct_end = bl.get_off() + struct_len; \
1102 * start a decoding block with legacy support for older encoding schemes
1104 * The old encoding schemes has a __u8 struct_v only, or lacked either
1105 * the compat version or length. Skip those fields conditionally.
1107 * Most of the time, v, compatv, and lenv will all match the version
1108 * where the structure was switched over to the new macros.
1110 * @param v current version of the encoding that the code supports/encodes
1111 * @param compatv oldest version that includes a __u8 compat version field
1112 * @param lenv oldest version that includes a __u32 length wrapper
1113 * @param bl bufferlist::iterator containing the encoded data
1115 #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \
1116 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 0, bl)
1119 * start a decoding block with legacy support for older encoding schemes
1121 * This version of the macro assumes the legacy encoding had a 32 bit
1124 * The old encoding schemes has a __u8 struct_v only, or lacked either
1125 * the compat version or length. Skip those fields conditionally.
1127 * Most of the time, v, compatv, and lenv will all match the version
1128 * where the structure was switched over to the new macros.
1130 * @param v current version of the encoding that the code supports/encodes
1131 * @param compatv oldest version that includes a __u8 compat version field
1132 * @param lenv oldest version that includes a __u32 length wrapper
1133 * @param bl bufferlist::iterator containing the encoded data
1135 #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \
1136 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3, bl)
1138 #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \
1139 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1, bl)
1142 * finish decode block
1144 * @param bl bufferlist::iterator we were decoding from
1146 #define DECODE_FINISH(bl) \
1149 if (bl.get_off() > struct_end) \
1150 throw buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1151 if (bl.get_off() < struct_end) \
1152 bl.advance(struct_end - bl.get_off()); \
1156 * Encoders/decoders to read from current offset in a file handle and
1157 * encode/decode the data according to argument types.
1159 inline ssize_t decode_file(int fd, std::string &str)
1163 bl.read_fd(fd, sizeof(len));
1165 bl.read_fd(fd, len);
1170 inline ssize_t decode_file(int fd, bufferptr &bp)
1174 bl.read_fd(fd, sizeof(len));
1176 bl.read_fd(fd, len);
1177 bufferlist::iterator bli = bl.begin();