]>
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
22 #include <string_view>
25 #include <boost/container/small_vector.hpp>
26 #include <boost/optional/optional_io.hpp>
27 #include <boost/tuple/tuple.hpp>
29 #include "include/unordered_map.h"
30 #include "include/unordered_set.h"
31 #include "common/ceph_time.h"
33 #include "include/int_types.h"
35 #include "common/convenience.h"
37 #include "byteorder.h"
40 // pull in the new-style encoding so that we get the denc_traits<> definition.
50 * Notes on feature encoding:
52 * - The default encode() methods have a features argument with a default parameter
53 * (which goes to zero).
54 * - Normal classes will use WRITE_CLASS_ENCODER, with that features=0 default.
55 * - Classes that _require_ features will use WRITE_CLASS_ENCODER_FEATURES, which
56 * does not define the default. Any caller must explicitly pass it in.
57 * - STL container macros have two encode variants: one with a features arg, and one
61 * - A feature encode() method will fail to compile if a value is not
63 * - The feature varianet of the STL templates will be used when the feature arg is
64 * provided. It will be passed through to any template arg types, but it will be
65 * ignored when not needed.
68 // --------------------------------------
72 inline void encode_raw(const T
& t
, bufferlist
& bl
)
74 bl
.append((char*)&t
, sizeof(t
));
77 inline void decode_raw(T
& t
, bufferlist::const_iterator
&p
)
79 p
.copy(sizeof(t
), (char*)&t
);
82 #define WRITE_RAW_ENCODER(type) \
83 inline void encode(const type &v, ::ceph::bufferlist& bl, uint64_t features=0) { ::ceph::encode_raw(v, bl); } \
84 inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { ::ceph::decode_raw(v, p); }
86 WRITE_RAW_ENCODER(__u8
)
87 #ifndef _CHAR_IS_SIGNED
88 WRITE_RAW_ENCODER(__s8
)
90 WRITE_RAW_ENCODER(char)
91 WRITE_RAW_ENCODER(ceph_le64
)
92 WRITE_RAW_ENCODER(ceph_le32
)
93 WRITE_RAW_ENCODER(ceph_le16
)
95 inline void encode(const bool &v
, bufferlist
& bl
) {
99 inline void decode(bool &v
, bufferlist::const_iterator
& p
) {
106 // -----------------------------------
109 #define WRITE_INTTYPE_ENCODER(type, etype) \
110 inline void encode(type v, ::ceph::bufferlist& bl, uint64_t features=0) { \
113 ::ceph::encode_raw(e, bl); \
115 inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { \
117 ::ceph::decode_raw(e, p); \
121 WRITE_INTTYPE_ENCODER(uint64_t, le64
)
122 WRITE_INTTYPE_ENCODER(int64_t, le64
)
123 WRITE_INTTYPE_ENCODER(uint32_t, le32
)
124 WRITE_INTTYPE_ENCODER(int32_t, le32
)
125 WRITE_INTTYPE_ENCODER(uint16_t, le16
)
126 WRITE_INTTYPE_ENCODER(int16_t, le16
)
128 // -----------------------------------
131 // NOTE: The following code assumes all supported platforms use IEEE binary32
132 // as float and IEEE binary64 as double floating-point format. The assumption
133 // is verified by the assertions below.
135 // Under this assumption, we can use raw encoding of floating-point types
136 // on little-endian machines, but we still need to perform a byte swap
137 // on big-endian machines to ensure cross-architecture compatibility.
138 // To achive that, we reinterpret the values as integers first, which are
139 // byte-swapped via the ceph_le types as above. The extra conversions
140 // are optimized away on little-endian machines by the compiler.
141 #define WRITE_FLTTYPE_ENCODER(type, itype, etype) \
142 static_assert(sizeof(type) == sizeof(itype)); \
143 static_assert(std::numeric_limits<type>::is_iec559, \
144 "floating-point type not using IEEE754 format"); \
145 inline void encode(type v, ::ceph::bufferlist& bl, uint64_t features=0) { \
147 e = *reinterpret_cast<itype *>(&v); \
148 ::ceph::encode_raw(e, bl); \
150 inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { \
152 ::ceph::decode_raw(e, p); \
153 *reinterpret_cast<itype *>(&v) = e; \
156 WRITE_FLTTYPE_ENCODER(float, uint32_t, le32
)
157 WRITE_FLTTYPE_ENCODER(double, uint64_t, le64
)
159 // see denc.h for ENCODE_DUMP_PATH discussion and definition.
160 #ifdef ENCODE_DUMP_PATH
161 # define ENCODE_DUMP_PRE() \
162 unsigned pre_off = bl.length()
163 # define ENCODE_DUMP_POST(cl) \
168 for (unsigned t = i; t; bits++) \
173 snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \
174 int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC|O_BINARY, 0644); \
176 ::ceph::bufferlist sub; \
177 sub.substr_of(bl, pre_off, bl.length() - pre_off); \
183 # define ENCODE_DUMP_PRE()
184 # define ENCODE_DUMP_POST(cl)
188 #define WRITE_CLASS_ENCODER(cl) \
189 inline void encode(const cl& c, ::ceph::buffer::list &bl, uint64_t features=0) { \
190 ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \
191 inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); }
193 #define WRITE_CLASS_MEMBER_ENCODER(cl) \
194 inline void encode(const cl &c, ::ceph::bufferlist &bl) const { \
195 ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \
196 inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); }
198 #define WRITE_CLASS_ENCODER_FEATURES(cl) \
199 inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features) { \
200 ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \
201 inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); }
203 #define WRITE_CLASS_ENCODER_OPTIONAL_FEATURES(cl) \
204 inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features = 0) { \
205 ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \
206 inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); }
210 inline void encode(std::string_view s
, bufferlist
& bl
, uint64_t features
=0)
212 __u32 len
= s
.length();
215 bl
.append(s
.data(), len
);
217 inline void encode(const std::string
& s
, bufferlist
& bl
, uint64_t features
=0)
219 return encode(std::string_view(s
), bl
, features
);
221 inline void decode(std::string
& s
, bufferlist::const_iterator
& p
)
229 inline void encode_nohead(std::string_view s
, bufferlist
& bl
)
231 bl
.append(s
.data(), s
.length());
233 inline void encode_nohead(const std::string
& s
, bufferlist
& bl
)
235 encode_nohead(std::string_view(s
), bl
);
237 inline void decode_nohead(int len
, std::string
& s
, bufferlist::const_iterator
& p
)
243 // const char* (encode only, string compatible)
244 inline void encode(const char *s
, bufferlist
& bl
)
246 encode(std::string_view(s
, strlen(s
)), bl
);
249 // opaque byte vectors
250 inline void encode(std::vector
<uint8_t>& v
, bufferlist
& bl
)
252 uint32_t len
= v
.size();
255 bl
.append((char *)v
.data(), len
);
258 inline void decode(std::vector
<uint8_t>& v
, bufferlist::const_iterator
& p
)
264 p
.copy(len
, (char *)v
.data());
267 // -----------------------------
270 // bufferptr (encapsulated)
271 inline void encode(const buffer::ptr
& bp
, bufferlist
& bl
)
273 __u32 len
= bp
.length();
278 inline void decode(buffer::ptr
& bp
, bufferlist::const_iterator
& p
)
287 if (s
.get_num_buffers() == 1)
290 bp
= buffer::copy(s
.c_str(), s
.length());
294 // bufferlist (encapsulated)
295 inline void encode(const bufferlist
& s
, bufferlist
& bl
)
297 __u32 len
= s
.length();
301 inline void encode_destructively(bufferlist
& s
, bufferlist
& bl
)
303 __u32 len
= s
.length();
307 inline void decode(bufferlist
& s
, bufferlist::const_iterator
& p
)
315 inline void encode_nohead(const bufferlist
& s
, bufferlist
& bl
)
319 inline void decode_nohead(int len
, bufferlist
& s
, bufferlist::const_iterator
& p
)
325 // Time, since the templates are defined in std::chrono
327 template<typename Clock
, typename Duration
,
328 typename
std::enable_if_t
<converts_to_timespec_v
<Clock
>>* = nullptr>
329 void encode(const std::chrono::time_point
<Clock
, Duration
>& t
,
330 ceph::bufferlist
&bl
) {
331 auto ts
= Clock::to_timespec(t
);
332 // A 32 bit count of seconds causes me vast unhappiness.
333 uint32_t s
= ts
.tv_sec
;
334 uint32_t ns
= ts
.tv_nsec
;
339 template<typename Clock
, typename Duration
,
340 typename
std::enable_if_t
<converts_to_timespec_v
<Clock
>>* = nullptr>
341 void decode(std::chrono::time_point
<Clock
, Duration
>& t
,
342 bufferlist::const_iterator
& p
) {
347 struct timespec ts
= {
348 static_cast<time_t>(s
),
349 static_cast<long int>(ns
)};
351 t
= Clock::from_timespec(ts
);
354 template<typename Rep
, typename Period
,
355 typename
std::enable_if_t
<std::is_integral_v
<Rep
>>* = nullptr>
356 void encode(const std::chrono::duration
<Rep
, Period
>& d
,
357 ceph::bufferlist
&bl
) {
358 using namespace std::chrono
;
359 int32_t s
= duration_cast
<seconds
>(d
).count();
360 int32_t ns
= (duration_cast
<nanoseconds
>(d
) % seconds(1)).count();
365 template<typename Rep
, typename Period
,
366 typename
std::enable_if_t
<std::is_integral_v
<Rep
>>* = nullptr>
367 void decode(std::chrono::duration
<Rep
, Period
>& d
,
368 bufferlist::const_iterator
& p
) {
373 d
= std::chrono::seconds(s
) + std::chrono::nanoseconds(ns
);
376 // -----------------------------
377 // STL container types
380 inline void encode(const boost::optional
<T
> &p
, bufferlist
&bl
);
382 inline void decode(boost::optional
<T
> &p
, bufferlist::const_iterator
&bp
);
384 inline void encode(const std::optional
<T
> &p
, bufferlist
&bl
);
386 inline void decode(std::optional
<T
> &p
, bufferlist::const_iterator
&bp
);
387 template<class A
, class B
, class C
>
388 inline void encode(const boost::tuple
<A
, B
, C
> &t
, bufferlist
& bl
);
389 template<class A
, class B
, class C
>
390 inline void decode(boost::tuple
<A
, B
, C
> &t
, bufferlist::const_iterator
&bp
);
391 template<class A
, class B
,
392 typename a_traits
=denc_traits
<A
>, typename b_traits
=denc_traits
<B
>>
393 inline std::enable_if_t
<!a_traits::supported
|| !b_traits::supported
>
394 encode(const std::pair
<A
,B
> &p
, bufferlist
&bl
, uint64_t features
);
395 template<class A
, class B
,
396 typename a_traits
=denc_traits
<A
>, typename b_traits
=denc_traits
<B
>>
397 inline std::enable_if_t
<!a_traits::supported
||
398 !b_traits::supported
>
399 encode(const std::pair
<A
,B
> &p
, bufferlist
&bl
);
400 template<class A
, class B
,
401 typename a_traits
=denc_traits
<A
>, typename b_traits
=denc_traits
<B
>>
402 inline std::enable_if_t
<!a_traits::supported
||
403 !b_traits::supported
>
404 decode(std::pair
<A
,B
> &pa
, bufferlist::const_iterator
&p
);
405 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
406 inline std::enable_if_t
<!traits::supported
>
407 encode(const std::list
<T
, Alloc
>& ls
, bufferlist
& bl
);
408 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
409 inline std::enable_if_t
<!traits::supported
>
410 encode(const std::list
<T
,Alloc
>& ls
, bufferlist
& bl
, uint64_t features
);
411 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
412 inline std::enable_if_t
<!traits::supported
>
413 decode(std::list
<T
,Alloc
>& ls
, bufferlist::const_iterator
& p
);
414 template<class T
, class Alloc
>
415 inline void encode(const std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
417 template<class T
, class Alloc
>
418 inline void encode(const std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
419 bufferlist
& bl
, uint64_t features
);
420 template<class T
, class Alloc
>
421 inline void decode(std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
422 bufferlist::const_iterator
& p
);
423 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
424 inline std::enable_if_t
<!traits::supported
>
425 encode(const std::set
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
);
426 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
427 inline std::enable_if_t
<!traits::supported
>
428 decode(std::set
<T
,Comp
,Alloc
>& s
, bufferlist::const_iterator
& p
);
429 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
430 inline std::enable_if_t
<!traits::supported
>
431 encode_nohead(const std::set
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
);
432 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
433 inline std::enable_if_t
<!traits::supported
>
434 decode_nohead(int len
, std::set
<T
,Comp
,Alloc
>& s
, bufferlist::iterator
& p
);
435 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
436 inline std::enable_if_t
<!traits::supported
>
437 encode(const boost::container::flat_set
<T
, Comp
, Alloc
>& s
, bufferlist
& bl
);
438 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
439 inline std::enable_if_t
<!traits::supported
>
440 decode(boost::container::flat_set
<T
, Comp
, Alloc
>& s
, bufferlist::const_iterator
& p
);
441 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
442 inline std::enable_if_t
<!traits::supported
>
443 encode_nohead(const boost::container::flat_set
<T
, Comp
, Alloc
>& s
,
445 template<class T
, class Comp
, class Alloc
, typename traits
=denc_traits
<T
>>
446 inline std::enable_if_t
<!traits::supported
>
447 decode_nohead(int len
, boost::container::flat_set
<T
, Comp
, Alloc
>& s
,
448 bufferlist::iterator
& p
);
449 template<class T
, class Comp
, class Alloc
>
450 inline void encode(const std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
);
451 template<class T
, class Comp
, class Alloc
>
452 inline void decode(std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist::const_iterator
& p
);
453 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
454 inline std::enable_if_t
<!traits::supported
>
455 encode(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
, uint64_t features
);
456 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
457 inline std::enable_if_t
<!traits::supported
>
458 encode(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
);
459 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
460 inline std::enable_if_t
<!traits::supported
>
461 decode(std::vector
<T
,Alloc
>& v
, bufferlist::const_iterator
& p
);
462 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
463 inline std::enable_if_t
<!traits::supported
>
464 encode_nohead(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
);
465 template<class T
, class Alloc
, typename traits
=denc_traits
<T
>>
466 inline std::enable_if_t
<!traits::supported
>
467 decode_nohead(int len
, std::vector
<T
,Alloc
>& v
, bufferlist::const_iterator
& p
);
468 template<class T
,class Alloc
>
469 inline void encode(const std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
472 template<class T
, class Alloc
>
473 inline void encode(const std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
475 template<class T
, class Alloc
>
476 inline void decode(std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
477 bufferlist::const_iterator
& p
);
479 template<class T
, std::size_t N
, class Alloc
, typename traits
=denc_traits
<T
>>
480 inline std::enable_if_t
<!traits::supported
>
481 encode(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
, uint64_t features
);
482 template<class T
, std::size_t N
, class Alloc
, typename traits
=denc_traits
<T
>>
483 inline std::enable_if_t
<!traits::supported
>
484 encode(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
);
485 template<class T
, std::size_t N
, class Alloc
, typename traits
=denc_traits
<T
>>
486 inline std::enable_if_t
<!traits::supported
>
487 decode(boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist::const_iterator
& p
);
488 template<class T
, std::size_t N
, class Alloc
, typename traits
=denc_traits
<T
>>
489 inline std::enable_if_t
<!traits::supported
>
490 encode_nohead(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
);
491 template<class T
, std::size_t N
, class Alloc
, typename traits
=denc_traits
<T
>>
492 inline std::enable_if_t
<!traits::supported
>
493 decode_nohead(int len
, boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist::const_iterator
& p
);
495 template<class T
, class U
, class Comp
, class Alloc
,
496 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
497 inline std::enable_if_t
<!t_traits::supported
||
498 !u_traits::supported
>
499 encode(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
);
500 template<class T
, class U
, class Comp
, class Alloc
,
501 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
502 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
503 encode(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
, uint64_t features
);
504 template<class T
, class U
, class Comp
, class Alloc
,
505 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
506 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
507 decode(std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
);
508 template<class T
, class U
, class Comp
, class Alloc
>
509 inline void decode_noclear(std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
);
510 template<class T
, class U
, class Comp
, class Alloc
,
511 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
512 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
513 encode_nohead(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
);
514 template<class T
, class U
, class Comp
, class Alloc
,
515 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
516 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
517 encode_nohead(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
, uint64_t features
);
518 template<class T
, class U
, class Comp
, class Alloc
,
519 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
520 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
521 decode_nohead(int n
, std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
);
522 template<class T
, class U
, class Comp
, class Alloc
,
523 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
524 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
525 encode(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
);
526 template<class T
, class U
, class Comp
, class Alloc
,
527 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
528 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
529 encode(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
,
531 template<class T
, class U
, class Comp
, class Alloc
,
532 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
533 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
534 decode(boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
);
535 template<class T
, class U
, class Comp
, class Alloc
>
536 inline void decode_noclear(boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
537 bufferlist::const_iterator
& p
);
538 template<class T
, class U
, class Comp
, class Alloc
,
539 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
540 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
541 encode_nohead(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
543 template<class T
, class U
, class Comp
, class Alloc
,
544 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
545 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
546 encode_nohead(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
547 bufferlist
& bl
, uint64_t features
);
548 template<class T
, class U
, class Comp
, class Alloc
,
549 typename t_traits
=denc_traits
<T
>, typename u_traits
=denc_traits
<U
>>
550 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
551 decode_nohead(int n
, boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
552 bufferlist::const_iterator
& p
);
553 template<class T
, class U
, class Comp
, class Alloc
>
554 inline void encode(const std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
);
555 template<class T
, class U
, class Comp
, class Alloc
>
556 inline void decode(std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
);
557 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
558 inline void encode(const unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
,
560 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
561 inline void encode(const unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
);
562 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
563 inline void decode(unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist::const_iterator
& p
);
564 template<class T
, class Hash
, class Pred
, class Alloc
>
565 inline void encode(const ceph::unordered_set
<T
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
);
566 template<class T
, class Hash
, class Pred
, class Alloc
>
567 inline void decode(ceph::unordered_set
<T
,Hash
,Pred
,Alloc
>& m
, bufferlist::const_iterator
& p
);
568 template<class T
, class Alloc
>
569 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
, uint64_t features
);
570 template<class T
, class Alloc
>
571 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
);
572 template<class T
, class Alloc
>
573 inline void decode(std::deque
<T
,Alloc
>& ls
, bufferlist::const_iterator
& p
);
574 template<class T
, size_t N
, typename traits
= denc_traits
<T
>>
575 inline std::enable_if_t
<!traits::supported
>
576 encode(const std::array
<T
, N
>& v
, bufferlist
& bl
, uint64_t features
);
577 template<class T
, size_t N
, typename traits
= denc_traits
<T
>>
578 inline std::enable_if_t
<!traits::supported
>
579 encode(const std::array
<T
, N
>& v
, bufferlist
& bl
);
580 template<class T
, size_t N
, typename traits
= denc_traits
<T
>>
581 inline std::enable_if_t
<!traits::supported
>
582 decode(std::array
<T
, N
>& v
, bufferlist::const_iterator
& p
);
586 inline void decode(T
&o
, const bufferlist
& bl
)
590 ceph_assert(p
.end());
595 inline void encode(const boost::optional
<T
> &p
, bufferlist
&bl
)
597 __u8 present
= static_cast<bool>(p
);
603 #pragma GCC diagnostic ignored "-Wpragmas"
604 #pragma GCC diagnostic push
605 #pragma GCC diagnostic ignored "-Wuninitialized"
607 inline void decode(boost::optional
<T
> &p
, bufferlist::const_iterator
&bp
)
618 #pragma GCC diagnostic pop
619 #pragma GCC diagnostic warning "-Wpragmas"
623 inline void encode(const std::optional
<T
> &p
, bufferlist
&bl
)
625 __u8 present
= static_cast<bool>(p
);
631 #pragma GCC diagnostic ignored "-Wpragmas"
632 #pragma GCC diagnostic push
633 #pragma GCC diagnostic ignored "-Wuninitialized"
635 inline void decode(std::optional
<T
> &p
, bufferlist::const_iterator
&bp
)
648 template<typename
... Ts
>
649 inline void encode(const std::tuple
<Ts
...> &t
, bufferlist
& bl
)
651 ceph::for_each(t
, [&bl
](const auto& e
) {
655 template<typename
... Ts
>
656 inline void decode(std::tuple
<Ts
...> &t
, bufferlist::const_iterator
&bp
)
658 ceph::for_each(t
, [&bp
](auto& e
) {
663 //triple boost::tuple
664 template<class A
, class B
, class C
>
665 inline void encode(const boost::tuple
<A
, B
, C
> &t
, bufferlist
& bl
)
667 encode(boost::get
<0>(t
), bl
);
668 encode(boost::get
<1>(t
), bl
);
669 encode(boost::get
<2>(t
), bl
);
671 template<class A
, class B
, class C
>
672 inline void decode(boost::tuple
<A
, B
, C
> &t
, bufferlist::const_iterator
&bp
)
674 decode(boost::get
<0>(t
), bp
);
675 decode(boost::get
<1>(t
), bp
);
676 decode(boost::get
<2>(t
), bp
);
680 template<class A
, class B
,
681 typename a_traits
, typename b_traits
>
682 inline std::enable_if_t
<!a_traits::supported
|| !b_traits::supported
>
683 encode(const std::pair
<A
,B
> &p
, bufferlist
&bl
, uint64_t features
)
685 encode(p
.first
, bl
, features
);
686 encode(p
.second
, bl
, features
);
688 template<class A
, class B
,
689 typename a_traits
, typename b_traits
>
690 inline std::enable_if_t
<!a_traits::supported
||
691 !b_traits::supported
>
692 encode(const std::pair
<A
,B
> &p
, bufferlist
&bl
)
695 encode(p
.second
, bl
);
697 template<class A
, class B
, typename a_traits
, typename b_traits
>
698 inline std::enable_if_t
<!a_traits::supported
||
699 !b_traits::supported
>
700 decode(std::pair
<A
,B
> &pa
, bufferlist::const_iterator
&p
)
703 decode(pa
.second
, p
);
707 template<class T
, class Alloc
, typename traits
>
708 inline std::enable_if_t
<!traits::supported
>
709 encode(const std::list
<T
, Alloc
>& ls
, bufferlist
& bl
)
711 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
713 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
716 template<class T
, class Alloc
, typename traits
>
717 inline std::enable_if_t
<!traits::supported
>
718 encode(const std::list
<T
,Alloc
>& ls
, bufferlist
& bl
, uint64_t features
)
720 using counter_encode_t
= ceph_le32
;
722 auto filler
= bl
.append_hole(sizeof(counter_encode_t
));
723 for (const auto& item
: ls
) {
724 // we count on our own because of buggy std::list::size() implementation
725 // which doesn't follow the O(1) complexity constraint C++11 has brought.
727 encode(item
, bl
, features
);
731 filler
.copy_in(sizeof(en
), reinterpret_cast<char*>(&en
));
734 template<class T
, class Alloc
, typename traits
>
735 inline std::enable_if_t
<!traits::supported
>
736 decode(std::list
<T
,Alloc
>& ls
, bufferlist::const_iterator
& p
)
743 decode(ls
.back(), p
);
747 // std::list<std::shared_ptr<T>>
748 template<class T
, class Alloc
>
749 inline void encode(const std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
752 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
754 for (const auto& ref
: ls
) {
758 template<class T
, class Alloc
>
759 inline void encode(const std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
760 bufferlist
& bl
, uint64_t features
)
762 __u32 n
= (__u32
)(ls
.size()); // c++11 std::list::size() is O(1)
764 for (const auto& ref
: ls
) {
765 encode(*ref
, bl
, features
);
768 template<class T
, class Alloc
>
769 inline void decode(std::list
<std::shared_ptr
<T
>, Alloc
>& ls
,
770 bufferlist::const_iterator
& p
)
776 auto ref
= std::make_shared
<T
>();
778 ls
.emplace_back(std::move(ref
));
783 template<class T
, class Comp
, class Alloc
, typename traits
>
784 inline std::enable_if_t
<!traits::supported
>
785 encode(const std::set
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
)
787 __u32 n
= (__u32
)(s
.size());
789 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
792 template<class T
, class Comp
, class Alloc
, typename traits
>
793 inline std::enable_if_t
<!traits::supported
>
794 decode(std::set
<T
,Comp
,Alloc
>& s
, bufferlist::const_iterator
& p
)
806 template<class T
, class Comp
, class Alloc
, typename traits
>
807 inline typename
std::enable_if
<!traits::supported
>::type
808 encode_nohead(const std::set
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
)
810 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
813 template<class T
, class Comp
, class Alloc
, typename traits
>
814 inline std::enable_if_t
<!traits::supported
>
815 decode_nohead(int len
, std::set
<T
,Comp
,Alloc
>& s
, bufferlist::const_iterator
& p
)
817 for (int i
=0; i
<len
; i
++) {
824 // boost::container::flat_set<T>
825 template<class T
, class Comp
, class Alloc
, typename traits
>
826 inline std::enable_if_t
<!traits::supported
>
827 encode(const boost::container::flat_set
<T
, Comp
, Alloc
>& s
, bufferlist
& bl
)
829 __u32 n
= (__u32
)(s
.size());
831 for (const auto& e
: s
)
834 template<class T
, class Comp
, class Alloc
, typename traits
>
835 inline std::enable_if_t
<!traits::supported
>
836 decode(boost::container::flat_set
<T
, Comp
, Alloc
>& s
, bufferlist::const_iterator
& p
)
849 template<class T
, class Comp
, class Alloc
, typename traits
>
850 inline std::enable_if_t
<!traits::supported
>
851 encode_nohead(const boost::container::flat_set
<T
, Comp
, Alloc
>& s
,
854 for (const auto& e
: s
)
857 template<class T
, class Comp
, class Alloc
, typename traits
>
858 inline std::enable_if_t
<!traits::supported
>
859 decode_nohead(int len
, boost::container::flat_set
<T
, Comp
, Alloc
>& s
,
860 bufferlist::iterator
& p
)
863 for (int i
=0; i
<len
; i
++) {
871 template<class T
, class Comp
, class Alloc
>
872 inline void encode(const std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist
& bl
)
874 __u32 n
= (__u32
)(s
.size());
876 for (auto p
= s
.begin(); p
!= s
.end(); ++p
)
879 template<class T
, class Comp
, class Alloc
>
880 inline void decode(std::multiset
<T
,Comp
,Alloc
>& s
, bufferlist::const_iterator
& p
)
892 template<class T
, class Alloc
, typename traits
>
893 inline std::enable_if_t
<!traits::supported
>
894 encode(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
, uint64_t features
)
896 __u32 n
= (__u32
)(v
.size());
898 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
899 encode(*p
, bl
, features
);
901 template<class T
, class Alloc
, typename traits
>
902 inline std::enable_if_t
<!traits::supported
>
903 encode(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
)
905 __u32 n
= (__u32
)(v
.size());
907 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
910 template<class T
, class Alloc
, typename traits
>
911 inline std::enable_if_t
<!traits::supported
>
912 decode(std::vector
<T
,Alloc
>& v
, bufferlist::const_iterator
& p
)
917 for (__u32 i
=0; i
<n
; i
++)
921 template<class T
, class Alloc
, typename traits
>
922 inline std::enable_if_t
<!traits::supported
>
923 encode_nohead(const std::vector
<T
,Alloc
>& v
, bufferlist
& bl
)
925 for (auto p
= v
.begin(); p
!= v
.end(); ++p
)
928 template<class T
, class Alloc
, typename traits
>
929 inline std::enable_if_t
<!traits::supported
>
930 decode_nohead(int len
, std::vector
<T
,Alloc
>& v
, bufferlist::const_iterator
& p
)
933 for (__u32 i
=0; i
<v
.size(); i
++)
938 template<class T
, std::size_t N
, class Alloc
, typename traits
>
939 inline std::enable_if_t
<!traits::supported
>
940 encode(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
, uint64_t features
)
942 __u32 n
= (__u32
)(v
.size());
944 for (const auto& i
: v
)
945 encode(i
, bl
, features
);
947 template<class T
, std::size_t N
, class Alloc
, typename traits
>
948 inline std::enable_if_t
<!traits::supported
>
949 encode(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
)
951 __u32 n
= (__u32
)(v
.size());
953 for (const auto& i
: v
)
956 template<class T
, std::size_t N
, class Alloc
, typename traits
>
957 inline std::enable_if_t
<!traits::supported
>
958 decode(boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist::const_iterator
& p
)
967 template<class T
, std::size_t N
, class Alloc
, typename traits
>
968 inline std::enable_if_t
<!traits::supported
>
969 encode_nohead(const boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist
& bl
)
971 for (const auto& i
: v
)
974 template<class T
, std::size_t N
, class Alloc
, typename traits
>
975 inline std::enable_if_t
<!traits::supported
>
976 decode_nohead(int len
, boost::container::small_vector
<T
,N
,Alloc
>& v
, bufferlist::const_iterator
& p
)
984 // vector (shared_ptr)
985 template<class T
,class Alloc
>
986 inline void encode(const std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
990 __u32 n
= (__u32
)(v
.size());
992 for (const auto& ref
: v
) {
994 encode(*ref
, bl
, features
);
996 encode(T(), bl
, features
);
999 template<class T
, class Alloc
>
1000 inline void encode(const std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
1003 __u32 n
= (__u32
)(v
.size());
1005 for (const auto& ref
: v
) {
1012 template<class T
, class Alloc
>
1013 inline void decode(std::vector
<std::shared_ptr
<T
>,Alloc
>& v
,
1014 bufferlist::const_iterator
& p
)
1021 auto ref
= std::make_shared
<T
>();
1023 v
.emplace_back(std::move(ref
));
1028 template<class T
, class U
, class Comp
, class Alloc
,
1029 typename t_traits
, typename u_traits
>
1030 inline std::enable_if_t
<!t_traits::supported
||
1031 !u_traits::supported
>
1032 encode(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
)
1034 __u32 n
= (__u32
)(m
.size());
1036 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1037 encode(p
->first
, bl
);
1038 encode(p
->second
, bl
);
1041 template<class T
, class U
, class Comp
, class Alloc
,
1042 typename t_traits
, typename u_traits
>
1043 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1044 encode(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
, uint64_t features
)
1046 __u32 n
= (__u32
)(m
.size());
1048 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1049 encode(p
->first
, bl
, features
);
1050 encode(p
->second
, bl
, features
);
1053 template<class T
, class U
, class Comp
, class Alloc
,
1054 typename t_traits
, typename u_traits
>
1055 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1056 decode(std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1067 template<class T
, class U
, class Comp
, class Alloc
>
1068 inline void decode_noclear(std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1078 template<class T
, class U
, class Comp
, class Alloc
,
1079 typename t_traits
, typename u_traits
>
1080 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1081 encode_nohead(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
)
1083 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1084 encode(p
->first
, bl
);
1085 encode(p
->second
, bl
);
1088 template<class T
, class U
, class Comp
, class Alloc
,
1089 typename t_traits
, typename u_traits
>
1090 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1091 encode_nohead(const std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
, uint64_t features
)
1093 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1094 encode(p
->first
, bl
, features
);
1095 encode(p
->second
, bl
, features
);
1098 template<class T
, class U
, class Comp
, class Alloc
,
1099 typename t_traits
, typename u_traits
>
1100 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1101 decode_nohead(int n
, std::map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1111 // boost::container::flat-map
1112 template<class T
, class U
, class Comp
, class Alloc
,
1113 typename t_traits
, typename u_traits
>
1114 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1115 encode(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
)
1117 __u32 n
= (__u32
)(m
.size());
1119 for (typename
boost::container::flat_map
<T
,U
,Comp
>::const_iterator p
1120 = m
.begin(); p
!= m
.end(); ++p
) {
1121 encode(p
->first
, bl
);
1122 encode(p
->second
, bl
);
1125 template<class T
, class U
, class Comp
, class Alloc
,
1126 typename t_traits
, typename u_traits
>
1127 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1128 encode(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
,
1131 __u32 n
= (__u32
)(m
.size());
1133 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1134 encode(p
->first
, bl
, features
);
1135 encode(p
->second
, bl
, features
);
1138 template<class T
, class U
, class Comp
, class Alloc
,
1139 typename t_traits
, typename u_traits
>
1140 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1141 decode(boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1153 template<class T
, class U
, class Comp
, class Alloc
>
1154 inline void decode_noclear(boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
1155 bufferlist::const_iterator
& p
)
1159 m
.reserve(m
.size() + n
);
1166 template<class T
, class U
, class Comp
, class Alloc
,
1167 typename t_traits
, typename u_traits
>
1168 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1169 encode_nohead(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
1172 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1173 encode(p
->first
, bl
);
1174 encode(p
->second
, bl
);
1177 template<class T
, class U
, class Comp
, class Alloc
,
1178 typename t_traits
, typename u_traits
>
1179 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1180 encode_nohead(const boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
1181 bufferlist
& bl
, uint64_t features
)
1183 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1184 encode(p
->first
, bl
, features
);
1185 encode(p
->second
, bl
, features
);
1188 template<class T
, class U
, class Comp
, class Alloc
,
1189 typename t_traits
, typename u_traits
>
1190 inline std::enable_if_t
<!t_traits::supported
|| !u_traits::supported
>
1191 decode_nohead(int n
, boost::container::flat_map
<T
,U
,Comp
,Alloc
>& m
,
1192 bufferlist::const_iterator
& p
)
1203 template<class T
, class U
, class Comp
, class Alloc
>
1204 inline void encode(const std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist
& bl
)
1206 __u32 n
= (__u32
)(m
.size());
1208 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1209 encode(p
->first
, bl
);
1210 encode(p
->second
, bl
);
1213 template<class T
, class U
, class Comp
, class Alloc
>
1214 inline void decode(std::multimap
<T
,U
,Comp
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1220 typename
std::pair
<T
,U
> tu
= std::pair
<T
,U
>();
1221 decode(tu
.first
, p
);
1222 typename
std::multimap
<T
,U
,Comp
,Alloc
>::iterator it
= m
.insert(tu
);
1223 decode(it
->second
, p
);
1227 // ceph::unordered_map
1228 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
1229 inline void encode(const unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
,
1232 __u32 n
= (__u32
)(m
.size());
1234 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1235 encode(p
->first
, bl
, features
);
1236 encode(p
->second
, bl
, features
);
1239 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
1240 inline void encode(const unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
)
1242 __u32 n
= (__u32
)(m
.size());
1244 for (auto p
= m
.begin(); p
!= m
.end(); ++p
) {
1245 encode(p
->first
, bl
);
1246 encode(p
->second
, bl
);
1249 template<class T
, class U
, class Hash
, class Pred
, class Alloc
>
1250 inline void decode(unordered_map
<T
,U
,Hash
,Pred
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1262 // ceph::unordered_set
1263 template<class T
, class Hash
, class Pred
, class Alloc
>
1264 inline void encode(const ceph::unordered_set
<T
,Hash
,Pred
,Alloc
>& m
, bufferlist
& bl
)
1266 __u32 n
= (__u32
)(m
.size());
1268 for (auto p
= m
.begin(); p
!= m
.end(); ++p
)
1271 template<class T
, class Hash
, class Pred
, class Alloc
>
1272 inline void decode(ceph::unordered_set
<T
,Hash
,Pred
,Alloc
>& m
, bufferlist::const_iterator
& p
)
1285 template<class T
, class Alloc
>
1286 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
, uint64_t features
)
1288 __u32 n
= ls
.size();
1290 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
1291 encode(*p
, bl
, features
);
1293 template<class T
, class Alloc
>
1294 inline void encode(const std::deque
<T
,Alloc
>& ls
, bufferlist
& bl
)
1296 __u32 n
= ls
.size();
1298 for (auto p
= ls
.begin(); p
!= ls
.end(); ++p
)
1301 template<class T
, class Alloc
>
1302 inline void decode(std::deque
<T
,Alloc
>& ls
, bufferlist::const_iterator
& p
)
1309 decode(ls
.back(), p
);
1314 template<class T
, size_t N
, typename traits
>
1315 inline std::enable_if_t
<!traits::supported
>
1316 encode(const std::array
<T
, N
>& v
, bufferlist
& bl
, uint64_t features
)
1318 for (const auto& e
: v
)
1319 encode(e
, bl
, features
);
1321 template<class T
, size_t N
, typename traits
>
1322 inline std::enable_if_t
<!traits::supported
>
1323 encode(const std::array
<T
, N
>& v
, bufferlist
& bl
)
1325 for (const auto& e
: v
)
1328 template<class T
, size_t N
, typename traits
>
1329 inline std::enable_if_t
<!traits::supported
>
1330 decode(std::array
<T
, N
>& v
, bufferlist::const_iterator
& p
)
1342 * start encoding block
1344 * @param v current (code) version of the encoding
1345 * @param compat oldest code version that can decode it
1346 * @param bl bufferlist to encode to
1349 #define ENCODE_START(v, compat, bl) \
1350 __u8 struct_v = v; \
1351 __u8 struct_compat = compat; \
1352 ceph_le32 struct_len; \
1353 auto filler = (bl).append_hole(sizeof(struct_v) + \
1354 sizeof(struct_compat) + sizeof(struct_len)); \
1355 const auto starting_bl_len = (bl).length(); \
1356 using ::ceph::encode; \
1360 * finish encoding block
1362 * @param bl bufferlist we were encoding to
1363 * @param new_struct_compat struct-compat value to use
1365 #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \
1367 if (new_struct_compat) { \
1368 struct_compat = new_struct_compat; \
1370 struct_len = (bl).length() - starting_bl_len; \
1371 filler.copy_in(sizeof(struct_v), (char *)&struct_v); \
1372 filler.copy_in(sizeof(struct_compat), \
1373 (char *)&struct_compat); \
1374 filler.copy_in(sizeof(struct_len), (char *)&struct_len);
1376 #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0)
1378 #define DECODE_ERR_OLDVERSION(func, v, compatv) \
1379 (std::string(func) + " no longer understand old encoding version " #v " < " + std::to_string(compatv))
1381 #define DECODE_ERR_PAST(func) \
1382 (std::string(func) + " decode past end of struct encoding")
1385 * check for very old encoding
1387 * If the encoded data is older than oldestv, raise an exception.
1389 * @param oldestv oldest version of the code we can successfully decode.
1391 #define DECODE_OLDEST(oldestv) \
1392 if (struct_v < oldestv) \
1393 throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv));
1396 * start a decoding block
1398 * @param v current version of the encoding that the code supports/encodes
1399 * @param bl bufferlist::iterator for the encoded data
1401 #define DECODE_START(v, bl) \
1402 __u8 struct_v, struct_compat; \
1403 using ::ceph::decode; \
1404 decode(struct_v, bl); \
1405 decode(struct_compat, bl); \
1406 if (v < struct_compat) \
1407 throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1409 decode(struct_len, bl); \
1410 if (struct_len > bl.get_remaining()) \
1411 throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1412 unsigned struct_end = bl.get_off() + struct_len; \
1415 /* BEWARE: any change to this macro MUST be also reflected in the duplicative
1416 * DECODE_START_LEGACY_COMPAT_LEN! */
1417 #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \
1418 using ::ceph::decode; \
1420 decode(struct_v, bl); \
1421 if (struct_v >= compatv) { \
1422 __u8 struct_compat; \
1423 decode(struct_compat, bl); \
1424 if (v < struct_compat) \
1425 throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \
1426 } else if (skip_v) { \
1427 if (bl.get_remaining() < skip_v) \
1428 throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1431 unsigned struct_end = 0; \
1432 if (struct_v >= lenv) { \
1434 decode(struct_len, bl); \
1435 if (struct_len > bl.get_remaining()) \
1436 throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1437 struct_end = bl.get_off() + struct_len; \
1442 * start a decoding block with legacy support for older encoding schemes
1444 * The old encoding schemes has a __u8 struct_v only, or lacked either
1445 * the compat version or length. Skip those fields conditionally.
1447 * Most of the time, v, compatv, and lenv will all match the version
1448 * where the structure was switched over to the new macros.
1450 * @param v current version of the encoding that the code supports/encodes
1451 * @param compatv oldest version that includes a __u8 compat version field
1452 * @param lenv oldest version that includes a __u32 length wrapper
1453 * @param bl bufferlist::iterator containing the encoded data
1456 /* BEWARE: this is duplication of __DECODE_START_LEGACY_COMPAT_LEN which
1457 * MUST be changed altogether. For the rationale behind code duplication,
1458 * please `git blame` and refer to the commit message. */
1459 #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \
1460 using ::ceph::decode; \
1462 decode(struct_v, bl); \
1463 if (struct_v >= compatv) { \
1464 __u8 struct_compat; \
1465 decode(struct_compat, bl); \
1466 if (v < struct_compat) \
1467 throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION( \
1468 __PRETTY_FUNCTION__, v, struct_compat)); \
1470 unsigned struct_end = 0; \
1471 if (struct_v >= lenv) { \
1473 decode(struct_len, bl); \
1474 if (struct_len > bl.get_remaining()) \
1475 throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1476 struct_end = bl.get_off() + struct_len; \
1481 * start a decoding block with legacy support for older encoding schemes
1483 * This version of the macro assumes the legacy encoding had a 32 bit
1486 * The old encoding schemes has a __u8 struct_v only, or lacked either
1487 * the compat version or length. Skip those fields conditionally.
1489 * Most of the time, v, compatv, and lenv will all match the version
1490 * where the structure was switched over to the new macros.
1492 * @param v current version of the encoding that the code supports/encodes
1493 * @param compatv oldest version that includes a __u8 compat version field
1494 * @param lenv oldest version that includes a __u32 length wrapper
1495 * @param bl bufferlist::iterator containing the encoded data
1497 #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \
1498 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3u, bl)
1500 #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \
1501 __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1u, bl)
1504 * finish decode block
1506 * @param bl bufferlist::iterator we were decoding from
1508 #define DECODE_FINISH(bl) \
1511 if (bl.get_off() > struct_end) \
1512 throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \
1513 if (bl.get_off() < struct_end) \
1514 bl += struct_end - bl.get_off(); \
1520 * Encoders/decoders to read from current offset in a file handle and
1521 * encode/decode the data according to argument types.
1523 inline ssize_t
decode_file(int fd
, std::string
&str
)
1527 bl
.read_fd(fd
, sizeof(len
));
1529 bl
.read_fd(fd
, len
);
1534 inline ssize_t
decode_file(int fd
, bufferptr
&bp
)
1538 bl
.read_fd(fd
, sizeof(len
));
1540 bl
.read_fd(fd
, len
);
1541 auto bli
= std::cbegin(bl
);