]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | #ifndef CEPH_ENCODING_H | |
15 | #define CEPH_ENCODING_H | |
16 | ||
94b18763 FG |
17 | #include <set> |
18 | #include <map> | |
19 | #include <deque> | |
20 | #include <vector> | |
21 | #include <string> | |
11fdf7f2 | 22 | #include <string_view> |
94b18763 | 23 | #include <tuple> |
9f95a23c | 24 | #include <optional> |
11fdf7f2 | 25 | #include <boost/container/small_vector.hpp> |
94b18763 FG |
26 | #include <boost/optional/optional_io.hpp> |
27 | #include <boost/tuple/tuple.hpp> | |
28 | ||
29 | #include "include/unordered_map.h" | |
30 | #include "include/unordered_set.h" | |
11fdf7f2 | 31 | #include "common/ceph_time.h" |
94b18763 | 32 | |
7c673cae FG |
33 | #include "include/int_types.h" |
34 | ||
11fdf7f2 | 35 | #include "common/convenience.h" |
7c673cae FG |
36 | |
37 | #include "byteorder.h" | |
38 | #include "buffer.h" | |
39 | ||
40 | // pull in the new-style encoding so that we get the denc_traits<> definition. | |
41 | #include "denc.h" | |
42 | ||
43 | #include "assert.h" | |
44 | ||
45 | using namespace ceph; | |
46 | ||
11fdf7f2 TL |
47 | namespace ceph { |
48 | ||
7c673cae FG |
49 | /* |
50 | * Notes on feature encoding: | |
51 | * | |
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 | |
58 | * without. | |
59 | * | |
60 | * The result: | |
61 | * - A feature encode() method will fail to compile if a value is not | |
62 | * passed in. | |
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. | |
66 | */ | |
67 | ||
68 | // -------------------------------------- | |
69 | // base types | |
70 | ||
71 | template<class T> | |
72 | inline void encode_raw(const T& t, bufferlist& bl) | |
73 | { | |
74 | bl.append((char*)&t, sizeof(t)); | |
75 | } | |
76 | template<class T> | |
11fdf7f2 | 77 | inline void decode_raw(T& t, bufferlist::const_iterator &p) |
7c673cae FG |
78 | { |
79 | p.copy(sizeof(t), (char*)&t); | |
80 | } | |
81 | ||
82 | #define WRITE_RAW_ENCODER(type) \ | |
11fdf7f2 TL |
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); } | |
7c673cae FG |
85 | |
86 | WRITE_RAW_ENCODER(__u8) | |
87 | #ifndef _CHAR_IS_SIGNED | |
88 | WRITE_RAW_ENCODER(__s8) | |
89 | #endif | |
90 | WRITE_RAW_ENCODER(char) | |
91 | WRITE_RAW_ENCODER(ceph_le64) | |
92 | WRITE_RAW_ENCODER(ceph_le32) | |
93 | WRITE_RAW_ENCODER(ceph_le16) | |
94 | ||
7c673cae FG |
95 | inline void encode(const bool &v, bufferlist& bl) { |
96 | __u8 vv = v; | |
97 | encode_raw(vv, bl); | |
98 | } | |
11fdf7f2 | 99 | inline void decode(bool &v, bufferlist::const_iterator& p) { |
7c673cae FG |
100 | __u8 vv; |
101 | decode_raw(vv, p); | |
102 | v = vv; | |
103 | } | |
104 | ||
105 | ||
106 | // ----------------------------------- | |
107 | // int types | |
108 | ||
109 | #define WRITE_INTTYPE_ENCODER(type, etype) \ | |
11fdf7f2 | 110 | inline void encode(type v, ::ceph::bufferlist& bl, uint64_t features=0) { \ |
7c673cae FG |
111 | ceph_##etype e; \ |
112 | e = v; \ | |
11fdf7f2 | 113 | ::ceph::encode_raw(e, bl); \ |
7c673cae | 114 | } \ |
11fdf7f2 | 115 | inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { \ |
7c673cae | 116 | ceph_##etype e; \ |
11fdf7f2 | 117 | ::ceph::decode_raw(e, p); \ |
7c673cae FG |
118 | v = e; \ |
119 | } | |
120 | ||
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) | |
127 | ||
f91f0fd5 TL |
128 | // ----------------------------------- |
129 | // float types | |
130 | // | |
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. | |
134 | // | |
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) { \ | |
146 | ceph_##etype e; \ | |
147 | e = *reinterpret_cast<itype *>(&v); \ | |
148 | ::ceph::encode_raw(e, bl); \ | |
149 | } \ | |
150 | inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { \ | |
151 | ceph_##etype e; \ | |
152 | ::ceph::decode_raw(e, p); \ | |
153 | *reinterpret_cast<itype *>(&v) = e; \ | |
154 | } | |
155 | ||
156 | WRITE_FLTTYPE_ENCODER(float, uint32_t, le32) | |
157 | WRITE_FLTTYPE_ENCODER(double, uint64_t, le64) | |
158 | ||
7c673cae FG |
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) \ | |
164 | do { \ | |
165 | static int i = 0; \ | |
166 | i++; \ | |
167 | int bits = 0; \ | |
168 | for (unsigned t = i; t; bits++) \ | |
169 | t &= t - 1; \ | |
170 | if (bits > 2) \ | |
171 | break; \ | |
172 | char fn[PATH_MAX]; \ | |
173 | snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \ | |
f67539c2 | 174 | int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC|O_BINARY, 0644); \ |
7c673cae | 175 | if (fd >= 0) { \ |
11fdf7f2 | 176 | ::ceph::bufferlist sub; \ |
7c673cae FG |
177 | sub.substr_of(bl, pre_off, bl.length() - pre_off); \ |
178 | sub.write_fd(fd); \ | |
179 | ::close(fd); \ | |
180 | } \ | |
181 | } while (0) | |
182 | #else | |
183 | # define ENCODE_DUMP_PRE() | |
184 | # define ENCODE_DUMP_POST(cl) | |
185 | #endif | |
186 | ||
187 | ||
188 | #define WRITE_CLASS_ENCODER(cl) \ | |
9f95a23c | 189 | inline void encode(const cl& c, ::ceph::buffer::list &bl, uint64_t features=0) { \ |
7c673cae | 190 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 191 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
192 | |
193 | #define WRITE_CLASS_MEMBER_ENCODER(cl) \ | |
11fdf7f2 | 194 | inline void encode(const cl &c, ::ceph::bufferlist &bl) const { \ |
7c673cae | 195 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 196 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
197 | |
198 | #define WRITE_CLASS_ENCODER_FEATURES(cl) \ | |
11fdf7f2 | 199 | inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features) { \ |
7c673cae | 200 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 201 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
202 | |
203 | #define WRITE_CLASS_ENCODER_OPTIONAL_FEATURES(cl) \ | |
11fdf7f2 | 204 | inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features = 0) { \ |
7c673cae | 205 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 206 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
207 | |
208 | ||
209 | // string | |
11fdf7f2 | 210 | inline void encode(std::string_view s, bufferlist& bl, uint64_t features=0) |
7c673cae FG |
211 | { |
212 | __u32 len = s.length(); | |
213 | encode(len, bl); | |
214 | if (len) | |
215 | bl.append(s.data(), len); | |
216 | } | |
94b18763 FG |
217 | inline void encode(const std::string& s, bufferlist& bl, uint64_t features=0) |
218 | { | |
11fdf7f2 | 219 | return encode(std::string_view(s), bl, features); |
94b18763 | 220 | } |
11fdf7f2 | 221 | inline void decode(std::string& s, bufferlist::const_iterator& p) |
7c673cae FG |
222 | { |
223 | __u32 len; | |
224 | decode(len, p); | |
225 | s.clear(); | |
226 | p.copy(len, s); | |
227 | } | |
228 | ||
11fdf7f2 | 229 | inline void encode_nohead(std::string_view s, bufferlist& bl) |
7c673cae FG |
230 | { |
231 | bl.append(s.data(), s.length()); | |
232 | } | |
94b18763 FG |
233 | inline void encode_nohead(const std::string& s, bufferlist& bl) |
234 | { | |
11fdf7f2 | 235 | encode_nohead(std::string_view(s), bl); |
94b18763 | 236 | } |
11fdf7f2 | 237 | inline void decode_nohead(int len, std::string& s, bufferlist::const_iterator& p) |
7c673cae FG |
238 | { |
239 | s.clear(); | |
240 | p.copy(len, s); | |
241 | } | |
242 | ||
243 | // const char* (encode only, string compatible) | |
244 | inline void encode(const char *s, bufferlist& bl) | |
245 | { | |
11fdf7f2 | 246 | encode(std::string_view(s, strlen(s)), bl); |
7c673cae FG |
247 | } |
248 | ||
1e59de90 TL |
249 | // opaque byte vectors |
250 | inline void encode(std::vector<uint8_t>& v, bufferlist& bl) | |
251 | { | |
252 | uint32_t len = v.size(); | |
253 | encode(len, bl); | |
254 | if (len) | |
255 | bl.append((char *)v.data(), len); | |
256 | } | |
257 | ||
258 | inline void decode(std::vector<uint8_t>& v, bufferlist::const_iterator& p) | |
259 | { | |
260 | uint32_t len; | |
261 | ||
262 | decode(len, p); | |
263 | v.resize(len); | |
264 | p.copy(len, (char *)v.data()); | |
265 | } | |
7c673cae | 266 | |
7c673cae FG |
267 | // ----------------------------- |
268 | // buffers | |
269 | ||
270 | // bufferptr (encapsulated) | |
271 | inline void encode(const buffer::ptr& bp, bufferlist& bl) | |
272 | { | |
273 | __u32 len = bp.length(); | |
274 | encode(len, bl); | |
275 | if (len) | |
276 | bl.append(bp); | |
277 | } | |
11fdf7f2 | 278 | inline void decode(buffer::ptr& bp, bufferlist::const_iterator& p) |
7c673cae FG |
279 | { |
280 | __u32 len; | |
281 | decode(len, p); | |
282 | ||
283 | bufferlist s; | |
284 | p.copy(len, s); | |
285 | ||
286 | if (len) { | |
287 | if (s.get_num_buffers() == 1) | |
288 | bp = s.front(); | |
289 | else | |
290 | bp = buffer::copy(s.c_str(), s.length()); | |
291 | } | |
292 | } | |
293 | ||
294 | // bufferlist (encapsulated) | |
295 | inline void encode(const bufferlist& s, bufferlist& bl) | |
296 | { | |
297 | __u32 len = s.length(); | |
298 | encode(len, bl); | |
299 | bl.append(s); | |
300 | } | |
301 | inline void encode_destructively(bufferlist& s, bufferlist& bl) | |
302 | { | |
303 | __u32 len = s.length(); | |
304 | encode(len, bl); | |
305 | bl.claim_append(s); | |
306 | } | |
11fdf7f2 | 307 | inline void decode(bufferlist& s, bufferlist::const_iterator& p) |
7c673cae FG |
308 | { |
309 | __u32 len; | |
310 | decode(len, p); | |
311 | s.clear(); | |
312 | p.copy(len, s); | |
313 | } | |
314 | ||
315 | inline void encode_nohead(const bufferlist& s, bufferlist& bl) | |
316 | { | |
317 | bl.append(s); | |
318 | } | |
11fdf7f2 | 319 | inline void decode_nohead(int len, bufferlist& s, bufferlist::const_iterator& p) |
7c673cae FG |
320 | { |
321 | s.clear(); | |
322 | p.copy(len, s); | |
323 | } | |
324 | ||
11fdf7f2 TL |
325 | // Time, since the templates are defined in std::chrono |
326 | ||
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; | |
335 | encode(s, bl); | |
336 | encode(ns, bl); | |
337 | } | |
338 | ||
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) { | |
343 | uint32_t s; | |
344 | uint32_t ns; | |
345 | decode(s, p); | |
346 | decode(ns, p); | |
347 | struct timespec ts = { | |
348 | static_cast<time_t>(s), | |
349 | static_cast<long int>(ns)}; | |
350 | ||
351 | t = Clock::from_timespec(ts); | |
352 | } | |
353 | ||
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; | |
9f95a23c TL |
359 | int32_t s = duration_cast<seconds>(d).count(); |
360 | int32_t ns = (duration_cast<nanoseconds>(d) % seconds(1)).count(); | |
11fdf7f2 TL |
361 | encode(s, bl); |
362 | encode(ns, bl); | |
363 | } | |
364 | ||
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) { | |
9f95a23c TL |
369 | int32_t s; |
370 | int32_t ns; | |
11fdf7f2 TL |
371 | decode(s, p); |
372 | decode(ns, p); | |
373 | d = std::chrono::seconds(s) + std::chrono::nanoseconds(ns); | |
7c673cae FG |
374 | } |
375 | ||
7c673cae FG |
376 | // ----------------------------- |
377 | // STL container types | |
378 | ||
11fdf7f2 TL |
379 | template<typename T> |
380 | inline void encode(const boost::optional<T> &p, bufferlist &bl); | |
381 | template<typename T> | |
382 | inline void decode(boost::optional<T> &p, bufferlist::const_iterator &bp); | |
9f95a23c TL |
383 | template<typename T> |
384 | inline void encode(const std::optional<T> &p, bufferlist &bl); | |
385 | template<typename T> | |
386 | inline void decode(std::optional<T> &p, bufferlist::const_iterator &bp); | |
11fdf7f2 TL |
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, | |
416 | bufferlist& bl); | |
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, | |
444 | bufferlist& bl); | |
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, | |
470 | bufferlist& bl, | |
471 | uint64_t features); | |
472 | template<class T, class Alloc> | |
473 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, | |
474 | bufferlist& bl); | |
475 | template<class T, class Alloc> | |
476 | inline void decode(std::vector<std::shared_ptr<T>,Alloc>& v, | |
477 | bufferlist::const_iterator& p); | |
478 | // small_vector | |
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); | |
494 | // std::map | |
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, | |
530 | uint64_t features); | |
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, | |
542 | bufferlist& bl); | |
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, | |
559 | uint64_t features); | |
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); | |
7c673cae | 583 | |
11fdf7f2 TL |
584 | // full bl decoder |
585 | template<class T> | |
586 | inline void decode(T &o, const bufferlist& bl) | |
587 | { | |
588 | auto p = bl.begin(); | |
589 | decode(o, p); | |
590 | ceph_assert(p.end()); | |
591 | } | |
7c673cae FG |
592 | |
593 | // boost optional | |
594 | template<typename T> | |
595 | inline void encode(const boost::optional<T> &p, bufferlist &bl) | |
596 | { | |
597 | __u8 present = static_cast<bool>(p); | |
11fdf7f2 | 598 | encode(present, bl); |
7c673cae FG |
599 | if (p) |
600 | encode(p.get(), bl); | |
601 | } | |
602 | ||
603 | #pragma GCC diagnostic ignored "-Wpragmas" | |
604 | #pragma GCC diagnostic push | |
605 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
7c673cae | 606 | template<typename T> |
11fdf7f2 | 607 | inline void decode(boost::optional<T> &p, bufferlist::const_iterator &bp) |
7c673cae FG |
608 | { |
609 | __u8 present; | |
11fdf7f2 | 610 | decode(present, bp); |
7c673cae | 611 | if (present) { |
181888fb | 612 | p = T{}; |
7c673cae | 613 | decode(p.get(), bp); |
181888fb FG |
614 | } else { |
615 | p = boost::none; | |
7c673cae FG |
616 | } |
617 | } | |
618 | #pragma GCC diagnostic pop | |
619 | #pragma GCC diagnostic warning "-Wpragmas" | |
620 | ||
9f95a23c TL |
621 | // std optional |
622 | template<typename T> | |
623 | inline void encode(const std::optional<T> &p, bufferlist &bl) | |
624 | { | |
625 | __u8 present = static_cast<bool>(p); | |
626 | encode(present, bl); | |
627 | if (p) | |
628 | encode(*p, bl); | |
629 | } | |
630 | ||
631 | #pragma GCC diagnostic ignored "-Wpragmas" | |
632 | #pragma GCC diagnostic push | |
633 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
634 | template<typename T> | |
635 | inline void decode(std::optional<T> &p, bufferlist::const_iterator &bp) | |
636 | { | |
637 | __u8 present; | |
638 | decode(present, bp); | |
639 | if (present) { | |
640 | p = T{}; | |
641 | decode(*p, bp); | |
642 | } else { | |
643 | p = std::nullopt; | |
644 | } | |
645 | } | |
646 | ||
11fdf7f2 TL |
647 | // std::tuple |
648 | template<typename... Ts> | |
649 | inline void encode(const std::tuple<Ts...> &t, bufferlist& bl) | |
650 | { | |
651 | ceph::for_each(t, [&bl](const auto& e) { | |
652 | encode(e, bl); | |
653 | }); | |
654 | } | |
655 | template<typename... Ts> | |
656 | inline void decode(std::tuple<Ts...> &t, bufferlist::const_iterator &bp) | |
657 | { | |
658 | ceph::for_each(t, [&bp](auto& e) { | |
659 | decode(e, bp); | |
660 | }); | |
661 | } | |
662 | ||
663 | //triple boost::tuple | |
7c673cae FG |
664 | template<class A, class B, class C> |
665 | inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl) | |
666 | { | |
667 | encode(boost::get<0>(t), bl); | |
668 | encode(boost::get<1>(t), bl); | |
669 | encode(boost::get<2>(t), bl); | |
670 | } | |
671 | template<class A, class B, class C> | |
11fdf7f2 | 672 | inline void decode(boost::tuple<A, B, C> &t, bufferlist::const_iterator &bp) |
7c673cae FG |
673 | { |
674 | decode(boost::get<0>(t), bp); | |
675 | decode(boost::get<1>(t), bp); | |
676 | decode(boost::get<2>(t), bp); | |
677 | } | |
678 | ||
679 | // std::pair<A,B> | |
680 | template<class A, class B, | |
11fdf7f2 TL |
681 | typename a_traits, typename b_traits> |
682 | inline std::enable_if_t<!a_traits::supported || !b_traits::supported> | |
7c673cae FG |
683 | encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features) |
684 | { | |
685 | encode(p.first, bl, features); | |
686 | encode(p.second, bl, features); | |
687 | } | |
688 | template<class A, class B, | |
11fdf7f2 TL |
689 | typename a_traits, typename b_traits> |
690 | inline std::enable_if_t<!a_traits::supported || | |
691 | !b_traits::supported> | |
7c673cae FG |
692 | encode(const std::pair<A,B> &p, bufferlist &bl) |
693 | { | |
694 | encode(p.first, bl); | |
695 | encode(p.second, bl); | |
696 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
701 | { |
702 | decode(pa.first, p); | |
703 | decode(pa.second, p); | |
704 | } | |
705 | ||
706 | // std::list<T> | |
11fdf7f2 TL |
707 | template<class T, class Alloc, typename traits> |
708 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
709 | encode(const std::list<T, Alloc>& ls, bufferlist& bl) |
710 | { | |
711 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
712 | encode(n, bl); | |
713 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
714 | encode(*p, bl); | |
715 | } | |
11fdf7f2 TL |
716 | template<class T, class Alloc, typename traits> |
717 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
718 | encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features) |
719 | { | |
9f95a23c TL |
720 | using counter_encode_t = ceph_le32; |
721 | unsigned n = 0; | |
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. | |
726 | ++n; | |
727 | encode(item, bl, features); | |
7c673cae | 728 | } |
9f95a23c TL |
729 | counter_encode_t en; |
730 | en = n; | |
731 | filler.copy_in(sizeof(en), reinterpret_cast<char*>(&en)); | |
7c673cae | 732 | } |
9f95a23c | 733 | |
11fdf7f2 TL |
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) | |
7c673cae FG |
737 | { |
738 | __u32 n; | |
739 | decode(n, p); | |
740 | ls.clear(); | |
741 | while (n--) { | |
11fdf7f2 TL |
742 | ls.emplace_back(); |
743 | decode(ls.back(), p); | |
7c673cae FG |
744 | } |
745 | } | |
746 | ||
11fdf7f2 | 747 | // std::list<std::shared_ptr<T>> |
7c673cae | 748 | template<class T, class Alloc> |
11fdf7f2 | 749 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, |
7c673cae FG |
750 | bufferlist& bl) |
751 | { | |
752 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
753 | encode(n, bl); | |
11fdf7f2 TL |
754 | for (const auto& ref : ls) { |
755 | encode(*ref, bl); | |
756 | } | |
7c673cae FG |
757 | } |
758 | template<class T, class Alloc> | |
11fdf7f2 | 759 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, |
7c673cae FG |
760 | bufferlist& bl, uint64_t features) |
761 | { | |
762 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
763 | encode(n, bl); | |
11fdf7f2 TL |
764 | for (const auto& ref : ls) { |
765 | encode(*ref, bl, features); | |
766 | } | |
7c673cae FG |
767 | } |
768 | template<class T, class Alloc> | |
11fdf7f2 TL |
769 | inline void decode(std::list<std::shared_ptr<T>, Alloc>& ls, |
770 | bufferlist::const_iterator& p) | |
7c673cae FG |
771 | { |
772 | __u32 n; | |
773 | decode(n, p); | |
774 | ls.clear(); | |
775 | while (n--) { | |
11fdf7f2 TL |
776 | auto ref = std::make_shared<T>(); |
777 | decode(*ref, p); | |
778 | ls.emplace_back(std::move(ref)); | |
7c673cae FG |
779 | } |
780 | } | |
781 | ||
782 | // std::set<T> | |
11fdf7f2 TL |
783 | template<class T, class Comp, class Alloc, typename traits> |
784 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
785 | encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl) |
786 | { | |
787 | __u32 n = (__u32)(s.size()); | |
788 | encode(n, bl); | |
789 | for (auto p = s.begin(); p != s.end(); ++p) | |
790 | encode(*p, bl); | |
791 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
795 | { |
796 | __u32 n; | |
797 | decode(n, p); | |
798 | s.clear(); | |
799 | while (n--) { | |
800 | T v; | |
801 | decode(v, p); | |
802 | s.insert(v); | |
803 | } | |
804 | } | |
805 | ||
11fdf7f2 | 806 | template<class T, class Comp, class Alloc, typename traits> |
7c673cae FG |
807 | inline typename std::enable_if<!traits::supported>::type |
808 | encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
809 | { | |
810 | for (auto p = s.begin(); p != s.end(); ++p) | |
811 | encode(*p, bl); | |
812 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
816 | { |
817 | for (int i=0; i<len; i++) { | |
818 | T v; | |
819 | decode(v, p); | |
820 | s.insert(v); | |
821 | } | |
822 | } | |
823 | ||
824 | // boost::container::flat_set<T> | |
11fdf7f2 TL |
825 | template<class T, class Comp, class Alloc, typename traits> |
826 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
827 | encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl) |
828 | { | |
829 | __u32 n = (__u32)(s.size()); | |
830 | encode(n, bl); | |
831 | for (const auto& e : s) | |
832 | encode(e, bl); | |
833 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
837 | { |
838 | __u32 n; | |
839 | decode(n, p); | |
840 | s.clear(); | |
31f18b77 | 841 | s.reserve(n); |
7c673cae FG |
842 | while (n--) { |
843 | T v; | |
844 | decode(v, p); | |
845 | s.insert(v); | |
846 | } | |
847 | } | |
848 | ||
11fdf7f2 TL |
849 | template<class T, class Comp, class Alloc, typename traits> |
850 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
851 | encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s, |
852 | bufferlist& bl) | |
853 | { | |
854 | for (const auto& e : s) | |
855 | encode(e, bl); | |
856 | } | |
11fdf7f2 TL |
857 | template<class T, class Comp, class Alloc, typename traits> |
858 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
859 | decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s, |
860 | bufferlist::iterator& p) | |
861 | { | |
31f18b77 | 862 | s.reserve(len); |
7c673cae FG |
863 | for (int i=0; i<len; i++) { |
864 | T v; | |
865 | decode(v, p); | |
866 | s.insert(v); | |
867 | } | |
868 | } | |
869 | ||
870 | // multiset | |
871 | template<class T, class Comp, class Alloc> | |
872 | inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl) | |
873 | { | |
874 | __u32 n = (__u32)(s.size()); | |
875 | encode(n, bl); | |
876 | for (auto p = s.begin(); p != s.end(); ++p) | |
877 | encode(*p, bl); | |
878 | } | |
879 | template<class T, class Comp, class Alloc> | |
11fdf7f2 | 880 | inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::const_iterator& p) |
7c673cae FG |
881 | { |
882 | __u32 n; | |
883 | decode(n, p); | |
884 | s.clear(); | |
885 | while (n--) { | |
886 | T v; | |
887 | decode(v, p); | |
888 | s.insert(v); | |
889 | } | |
890 | } | |
891 | ||
11fdf7f2 TL |
892 | template<class T, class Alloc, typename traits> |
893 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
894 | encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features) |
895 | { | |
896 | __u32 n = (__u32)(v.size()); | |
897 | encode(n, bl); | |
898 | for (auto p = v.begin(); p != v.end(); ++p) | |
899 | encode(*p, bl, features); | |
900 | } | |
11fdf7f2 TL |
901 | template<class T, class Alloc, typename traits> |
902 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
903 | encode(const std::vector<T,Alloc>& v, bufferlist& bl) |
904 | { | |
905 | __u32 n = (__u32)(v.size()); | |
906 | encode(n, bl); | |
907 | for (auto p = v.begin(); p != v.end(); ++p) | |
908 | encode(*p, bl); | |
909 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
913 | { |
914 | __u32 n; | |
915 | decode(n, p); | |
916 | v.resize(n); | |
917 | for (__u32 i=0; i<n; i++) | |
918 | decode(v[i], p); | |
919 | } | |
920 | ||
11fdf7f2 TL |
921 | template<class T, class Alloc, typename traits> |
922 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
923 | encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl) |
924 | { | |
925 | for (auto p = v.begin(); p != v.end(); ++p) | |
926 | encode(*p, bl); | |
927 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
931 | { |
932 | v.resize(len); | |
933 | for (__u32 i=0; i<v.size(); i++) | |
934 | decode(v[i], p); | |
935 | } | |
936 | ||
11fdf7f2 TL |
937 | // small vector |
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) | |
941 | { | |
942 | __u32 n = (__u32)(v.size()); | |
943 | encode(n, bl); | |
944 | for (const auto& i : v) | |
945 | encode(i, bl, features); | |
946 | } | |
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) | |
950 | { | |
951 | __u32 n = (__u32)(v.size()); | |
952 | encode(n, bl); | |
953 | for (const auto& i : v) | |
954 | encode(i, bl); | |
955 | } | |
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) | |
959 | { | |
960 | __u32 n; | |
961 | decode(n, p); | |
962 | v.resize(n); | |
963 | for (auto& i : v) | |
964 | decode(i, p); | |
965 | } | |
966 | ||
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) | |
970 | { | |
971 | for (const auto& i : v) | |
972 | encode(i, bl); | |
973 | } | |
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) | |
977 | { | |
978 | v.resize(len); | |
979 | for (auto& i : v) | |
980 | decode(i, p); | |
981 | } | |
982 | ||
983 | ||
7c673cae FG |
984 | // vector (shared_ptr) |
985 | template<class T,class Alloc> | |
11fdf7f2 | 986 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, |
7c673cae FG |
987 | bufferlist& bl, |
988 | uint64_t features) | |
989 | { | |
990 | __u32 n = (__u32)(v.size()); | |
991 | encode(n, bl); | |
11fdf7f2 TL |
992 | for (const auto& ref : v) { |
993 | if (ref) | |
994 | encode(*ref, bl, features); | |
7c673cae FG |
995 | else |
996 | encode(T(), bl, features); | |
11fdf7f2 | 997 | } |
7c673cae FG |
998 | } |
999 | template<class T, class Alloc> | |
11fdf7f2 | 1000 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, |
7c673cae FG |
1001 | bufferlist& bl) |
1002 | { | |
1003 | __u32 n = (__u32)(v.size()); | |
1004 | encode(n, bl); | |
11fdf7f2 TL |
1005 | for (const auto& ref : v) { |
1006 | if (ref) | |
1007 | encode(*ref, bl); | |
7c673cae FG |
1008 | else |
1009 | encode(T(), bl); | |
7c673cae FG |
1010 | } |
1011 | } | |
11fdf7f2 TL |
1012 | template<class T, class Alloc> |
1013 | inline void decode(std::vector<std::shared_ptr<T>,Alloc>& v, | |
1014 | bufferlist::const_iterator& p) | |
7c673cae FG |
1015 | { |
1016 | __u32 n; | |
1017 | decode(n, p); | |
11fdf7f2 TL |
1018 | v.clear(); |
1019 | v.reserve(n); | |
7c673cae | 1020 | while (n--) { |
11fdf7f2 TL |
1021 | auto ref = std::make_shared<T>(); |
1022 | decode(*ref, p); | |
1023 | v.emplace_back(std::move(ref)); | |
7c673cae | 1024 | } |
11fdf7f2 | 1025 | } |
7c673cae FG |
1026 | |
1027 | // map | |
1028 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1029 | typename t_traits, typename u_traits> |
1030 | inline std::enable_if_t<!t_traits::supported || | |
1031 | !u_traits::supported> | |
7c673cae FG |
1032 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) |
1033 | { | |
1034 | __u32 n = (__u32)(m.size()); | |
1035 | encode(n, bl); | |
1036 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1037 | encode(p->first, bl); | |
1038 | encode(p->second, bl); | |
1039 | } | |
1040 | } | |
1041 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1042 | typename t_traits, typename u_traits> |
1043 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1044 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) |
1045 | { | |
1046 | __u32 n = (__u32)(m.size()); | |
1047 | encode(n, bl); | |
1048 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1049 | encode(p->first, bl, features); | |
1050 | encode(p->second, bl, features); | |
1051 | } | |
1052 | } | |
1053 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
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) | |
7c673cae FG |
1057 | { |
1058 | __u32 n; | |
1059 | decode(n, p); | |
1060 | m.clear(); | |
1061 | while (n--) { | |
1062 | T k; | |
1063 | decode(k, p); | |
1064 | decode(m[k], p); | |
1065 | } | |
1066 | } | |
1067 | template<class T, class U, class Comp, class Alloc> | |
11fdf7f2 | 1068 | inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1069 | { |
1070 | __u32 n; | |
1071 | decode(n, p); | |
1072 | while (n--) { | |
1073 | T k; | |
1074 | decode(k, p); | |
1075 | decode(m[k], p); | |
1076 | } | |
1077 | } | |
1078 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1079 | typename t_traits, typename u_traits> |
1080 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1081 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) |
1082 | { | |
1083 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1084 | encode(p->first, bl); | |
1085 | encode(p->second, bl); | |
1086 | } | |
1087 | } | |
1088 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1089 | typename t_traits, typename u_traits> |
1090 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1091 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) |
1092 | { | |
1093 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1094 | encode(p->first, bl, features); | |
1095 | encode(p->second, bl, features); | |
1096 | } | |
1097 | } | |
1098 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
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) | |
7c673cae FG |
1102 | { |
1103 | m.clear(); | |
1104 | while (n--) { | |
1105 | T k; | |
1106 | decode(k, p); | |
1107 | decode(m[k], p); | |
1108 | } | |
1109 | } | |
1110 | ||
1111 | // boost::container::flat-map | |
1112 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1113 | typename t_traits, typename u_traits> |
1114 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1115 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl) |
1116 | { | |
1117 | __u32 n = (__u32)(m.size()); | |
1118 | encode(n, bl); | |
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); | |
1123 | } | |
1124 | } | |
1125 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1126 | typename t_traits, typename u_traits> |
1127 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1128 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl, |
1129 | uint64_t features) | |
1130 | { | |
1131 | __u32 n = (__u32)(m.size()); | |
1132 | encode(n, bl); | |
1133 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1134 | encode(p->first, bl, features); | |
1135 | encode(p->second, bl, features); | |
1136 | } | |
1137 | } | |
1138 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
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) | |
7c673cae FG |
1142 | { |
1143 | __u32 n; | |
1144 | decode(n, p); | |
1145 | m.clear(); | |
31f18b77 | 1146 | m.reserve(n); |
7c673cae FG |
1147 | while (n--) { |
1148 | T k; | |
1149 | decode(k, p); | |
1150 | decode(m[k], p); | |
1151 | } | |
1152 | } | |
1153 | template<class T, class U, class Comp, class Alloc> | |
1154 | inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m, | |
11fdf7f2 | 1155 | bufferlist::const_iterator& p) |
7c673cae FG |
1156 | { |
1157 | __u32 n; | |
1158 | decode(n, p); | |
31f18b77 | 1159 | m.reserve(m.size() + n); |
7c673cae FG |
1160 | while (n--) { |
1161 | T k; | |
1162 | decode(k, p); | |
1163 | decode(m[k], p); | |
1164 | } | |
1165 | } | |
1166 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1167 | typename t_traits, typename u_traits> |
1168 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1169 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, |
1170 | bufferlist& bl) | |
1171 | { | |
1172 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1173 | encode(p->first, bl); | |
1174 | encode(p->second, bl); | |
1175 | } | |
1176 | } | |
1177 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1178 | typename t_traits, typename u_traits> |
1179 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1180 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, |
1181 | bufferlist& bl, uint64_t features) | |
1182 | { | |
1183 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1184 | encode(p->first, bl, features); | |
1185 | encode(p->second, bl, features); | |
1186 | } | |
1187 | } | |
1188 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1189 | typename t_traits, typename u_traits> |
1190 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae | 1191 | decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m, |
11fdf7f2 | 1192 | bufferlist::const_iterator& p) |
7c673cae FG |
1193 | { |
1194 | m.clear(); | |
1195 | while (n--) { | |
1196 | T k; | |
1197 | decode(k, p); | |
1198 | decode(m[k], p); | |
1199 | } | |
1200 | } | |
1201 | ||
1202 | // multimap | |
1203 | template<class T, class U, class Comp, class Alloc> | |
1204 | inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl) | |
1205 | { | |
1206 | __u32 n = (__u32)(m.size()); | |
1207 | encode(n, bl); | |
1208 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1209 | encode(p->first, bl); | |
1210 | encode(p->second, bl); | |
1211 | } | |
1212 | } | |
1213 | template<class T, class U, class Comp, class Alloc> | |
11fdf7f2 | 1214 | inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1215 | { |
1216 | __u32 n; | |
1217 | decode(n, p); | |
1218 | m.clear(); | |
1219 | while (n--) { | |
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); | |
1224 | } | |
1225 | } | |
1226 | ||
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, | |
1230 | uint64_t features) | |
1231 | { | |
1232 | __u32 n = (__u32)(m.size()); | |
1233 | encode(n, bl); | |
1234 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1235 | encode(p->first, bl, features); | |
1236 | encode(p->second, bl, features); | |
1237 | } | |
1238 | } | |
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) | |
1241 | { | |
1242 | __u32 n = (__u32)(m.size()); | |
1243 | encode(n, bl); | |
1244 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1245 | encode(p->first, bl); | |
1246 | encode(p->second, bl); | |
1247 | } | |
1248 | } | |
1249 | template<class T, class U, class Hash, class Pred, class Alloc> | |
11fdf7f2 | 1250 | inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1251 | { |
1252 | __u32 n; | |
1253 | decode(n, p); | |
1254 | m.clear(); | |
1255 | while (n--) { | |
1256 | T k; | |
1257 | decode(k, p); | |
1258 | decode(m[k], p); | |
1259 | } | |
1260 | } | |
1261 | ||
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) | |
1265 | { | |
1266 | __u32 n = (__u32)(m.size()); | |
1267 | encode(n, bl); | |
1268 | for (auto p = m.begin(); p != m.end(); ++p) | |
1269 | encode(*p, bl); | |
1270 | } | |
1271 | template<class T, class Hash, class Pred, class Alloc> | |
11fdf7f2 | 1272 | inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1273 | { |
1274 | __u32 n; | |
1275 | decode(n, p); | |
1276 | m.clear(); | |
1277 | while (n--) { | |
1278 | T k; | |
1279 | decode(k, p); | |
1280 | m.insert(k); | |
1281 | } | |
1282 | } | |
1283 | ||
1284 | // deque | |
1285 | template<class T, class Alloc> | |
1286 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
1287 | { | |
1288 | __u32 n = ls.size(); | |
1289 | encode(n, bl); | |
1290 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
1291 | encode(*p, bl, features); | |
1292 | } | |
1293 | template<class T, class Alloc> | |
1294 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl) | |
1295 | { | |
1296 | __u32 n = ls.size(); | |
1297 | encode(n, bl); | |
1298 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
1299 | encode(*p, bl); | |
1300 | } | |
1301 | template<class T, class Alloc> | |
11fdf7f2 | 1302 | inline void decode(std::deque<T,Alloc>& ls, bufferlist::const_iterator& p) |
7c673cae FG |
1303 | { |
1304 | __u32 n; | |
1305 | decode(n, p); | |
1306 | ls.clear(); | |
1307 | while (n--) { | |
11fdf7f2 TL |
1308 | ls.emplace_back(); |
1309 | decode(ls.back(), p); | |
7c673cae FG |
1310 | } |
1311 | } | |
1312 | ||
1313 | // std::array<T, N> | |
11fdf7f2 TL |
1314 | template<class T, size_t N, typename traits> |
1315 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
1316 | encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features) |
1317 | { | |
1318 | for (const auto& e : v) | |
1319 | encode(e, bl, features); | |
1320 | } | |
11fdf7f2 TL |
1321 | template<class T, size_t N, typename traits> |
1322 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
1323 | encode(const std::array<T, N>& v, bufferlist& bl) |
1324 | { | |
1325 | for (const auto& e : v) | |
1326 | encode(e, bl); | |
1327 | } | |
11fdf7f2 TL |
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) | |
7c673cae FG |
1331 | { |
1332 | for (auto& e : v) | |
1333 | decode(e, p); | |
1334 | } | |
11fdf7f2 | 1335 | } |
7c673cae FG |
1336 | |
1337 | /* | |
1338 | * guards | |
1339 | */ | |
1340 | ||
1341 | /** | |
1342 | * start encoding block | |
1343 | * | |
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 | |
11fdf7f2 | 1347 | * |
7c673cae FG |
1348 | */ |
1349 | #define ENCODE_START(v, compat, bl) \ | |
11fdf7f2 TL |
1350 | __u8 struct_v = v; \ |
1351 | __u8 struct_compat = compat; \ | |
7c673cae | 1352 | ceph_le32 struct_len; \ |
9f95a23c | 1353 | auto filler = (bl).append_hole(sizeof(struct_v) + \ |
11fdf7f2 TL |
1354 | sizeof(struct_compat) + sizeof(struct_len)); \ |
1355 | const auto starting_bl_len = (bl).length(); \ | |
1356 | using ::ceph::encode; \ | |
7c673cae FG |
1357 | do { |
1358 | ||
1359 | /** | |
1360 | * finish encoding block | |
1361 | * | |
1362 | * @param bl bufferlist we were encoding to | |
1363 | * @param new_struct_compat struct-compat value to use | |
1364 | */ | |
11fdf7f2 TL |
1365 | #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \ |
1366 | } while (false); \ | |
1367 | if (new_struct_compat) { \ | |
1368 | struct_compat = new_struct_compat; \ | |
1369 | } \ | |
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); | |
7c673cae FG |
1375 | |
1376 | #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0) | |
1377 | ||
1378 | #define DECODE_ERR_OLDVERSION(func, v, compatv) \ | |
91327a77 | 1379 | (std::string(func) + " no longer understand old encoding version " #v " < " + std::to_string(compatv)) |
7c673cae FG |
1380 | |
1381 | #define DECODE_ERR_PAST(func) \ | |
1382 | (std::string(func) + " decode past end of struct encoding") | |
1383 | ||
1384 | /** | |
1385 | * check for very old encoding | |
1386 | * | |
1387 | * If the encoded data is older than oldestv, raise an exception. | |
1388 | * | |
1389 | * @param oldestv oldest version of the code we can successfully decode. | |
1390 | */ | |
1391 | #define DECODE_OLDEST(oldestv) \ | |
1392 | if (struct_v < oldestv) \ | |
11fdf7f2 | 1393 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv)); |
7c673cae FG |
1394 | |
1395 | /** | |
1396 | * start a decoding block | |
1397 | * | |
1398 | * @param v current version of the encoding that the code supports/encodes | |
1399 | * @param bl bufferlist::iterator for the encoded data | |
1400 | */ | |
1401 | #define DECODE_START(v, bl) \ | |
1402 | __u8 struct_v, struct_compat; \ | |
11fdf7f2 TL |
1403 | using ::ceph::decode; \ |
1404 | decode(struct_v, bl); \ | |
1405 | decode(struct_compat, bl); \ | |
7c673cae | 1406 | if (v < struct_compat) \ |
9f95a23c | 1407 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ |
7c673cae | 1408 | __u32 struct_len; \ |
11fdf7f2 | 1409 | decode(struct_len, bl); \ |
7c673cae | 1410 | if (struct_len > bl.get_remaining()) \ |
11fdf7f2 | 1411 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae FG |
1412 | unsigned struct_end = bl.get_off() + struct_len; \ |
1413 | do { | |
1414 | ||
11fdf7f2 TL |
1415 | /* BEWARE: any change to this macro MUST be also reflected in the duplicative |
1416 | * DECODE_START_LEGACY_COMPAT_LEN! */ | |
7c673cae | 1417 | #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \ |
11fdf7f2 | 1418 | using ::ceph::decode; \ |
7c673cae | 1419 | __u8 struct_v; \ |
11fdf7f2 | 1420 | decode(struct_v, bl); \ |
7c673cae FG |
1421 | if (struct_v >= compatv) { \ |
1422 | __u8 struct_compat; \ | |
11fdf7f2 | 1423 | decode(struct_compat, bl); \ |
7c673cae | 1424 | if (v < struct_compat) \ |
9f95a23c | 1425 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ |
7c673cae | 1426 | } else if (skip_v) { \ |
11fdf7f2 | 1427 | if (bl.get_remaining() < skip_v) \ |
9f95a23c TL |
1428 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
1429 | bl += skip_v; \ | |
7c673cae FG |
1430 | } \ |
1431 | unsigned struct_end = 0; \ | |
1432 | if (struct_v >= lenv) { \ | |
1433 | __u32 struct_len; \ | |
11fdf7f2 | 1434 | decode(struct_len, bl); \ |
7c673cae | 1435 | if (struct_len > bl.get_remaining()) \ |
9f95a23c | 1436 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae FG |
1437 | struct_end = bl.get_off() + struct_len; \ |
1438 | } \ | |
1439 | do { | |
1440 | ||
1441 | /** | |
1442 | * start a decoding block with legacy support for older encoding schemes | |
1443 | * | |
1444 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1445 | * the compat version or length. Skip those fields conditionally. | |
1446 | * | |
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. | |
1449 | * | |
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 | |
1454 | */ | |
11fdf7f2 TL |
1455 | |
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. */ | |
7c673cae | 1459 | #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \ |
11fdf7f2 TL |
1460 | using ::ceph::decode; \ |
1461 | __u8 struct_v; \ | |
1462 | decode(struct_v, bl); \ | |
1463 | if (struct_v >= compatv) { \ | |
1464 | __u8 struct_compat; \ | |
1465 | decode(struct_compat, bl); \ | |
1466 | if (v < struct_compat) \ | |
9f95a23c | 1467 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION( \ |
11fdf7f2 TL |
1468 | __PRETTY_FUNCTION__, v, struct_compat)); \ |
1469 | } \ | |
1470 | unsigned struct_end = 0; \ | |
1471 | if (struct_v >= lenv) { \ | |
1472 | __u32 struct_len; \ | |
1473 | decode(struct_len, bl); \ | |
1474 | if (struct_len > bl.get_remaining()) \ | |
9f95a23c | 1475 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
11fdf7f2 TL |
1476 | struct_end = bl.get_off() + struct_len; \ |
1477 | } \ | |
1478 | do { | |
7c673cae FG |
1479 | |
1480 | /** | |
1481 | * start a decoding block with legacy support for older encoding schemes | |
1482 | * | |
1483 | * This version of the macro assumes the legacy encoding had a 32 bit | |
1484 | * version | |
1485 | * | |
1486 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1487 | * the compat version or length. Skip those fields conditionally. | |
1488 | * | |
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. | |
1491 | * | |
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 | |
1496 | */ | |
1497 | #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \ | |
11fdf7f2 | 1498 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3u, bl) |
7c673cae FG |
1499 | |
1500 | #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \ | |
11fdf7f2 | 1501 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1u, bl) |
7c673cae FG |
1502 | |
1503 | /** | |
1504 | * finish decode block | |
1505 | * | |
1506 | * @param bl bufferlist::iterator we were decoding from | |
1507 | */ | |
1508 | #define DECODE_FINISH(bl) \ | |
1509 | } while (false); \ | |
1510 | if (struct_end) { \ | |
1511 | if (bl.get_off() > struct_end) \ | |
9f95a23c | 1512 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae | 1513 | if (bl.get_off() < struct_end) \ |
9f95a23c | 1514 | bl += struct_end - bl.get_off(); \ |
7c673cae FG |
1515 | } |
1516 | ||
11fdf7f2 TL |
1517 | namespace ceph { |
1518 | ||
7c673cae FG |
1519 | /* |
1520 | * Encoders/decoders to read from current offset in a file handle and | |
1521 | * encode/decode the data according to argument types. | |
1522 | */ | |
1523 | inline ssize_t decode_file(int fd, std::string &str) | |
1524 | { | |
1525 | bufferlist bl; | |
1526 | __u32 len = 0; | |
1527 | bl.read_fd(fd, sizeof(len)); | |
9f95a23c | 1528 | decode(len, bl); |
7c673cae | 1529 | bl.read_fd(fd, len); |
9f95a23c | 1530 | decode(str, bl); |
7c673cae FG |
1531 | return bl.length(); |
1532 | } | |
1533 | ||
1534 | inline ssize_t decode_file(int fd, bufferptr &bp) | |
1535 | { | |
1536 | bufferlist bl; | |
1537 | __u32 len = 0; | |
1538 | bl.read_fd(fd, sizeof(len)); | |
11fdf7f2 | 1539 | decode(len, bl); |
7c673cae | 1540 | bl.read_fd(fd, len); |
11fdf7f2 | 1541 | auto bli = std::cbegin(bl); |
7c673cae | 1542 | |
11fdf7f2 | 1543 | decode(bp, bli); |
7c673cae FG |
1544 | return bl.length(); |
1545 | } | |
11fdf7f2 | 1546 | } |
7c673cae FG |
1547 | |
1548 | #endif |