]>
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 | ||
95 | // FIXME: we need to choose some portable floating point encoding here | |
96 | WRITE_RAW_ENCODER(float) | |
97 | WRITE_RAW_ENCODER(double) | |
98 | ||
99 | inline void encode(const bool &v, bufferlist& bl) { | |
100 | __u8 vv = v; | |
101 | encode_raw(vv, bl); | |
102 | } | |
11fdf7f2 | 103 | inline void decode(bool &v, bufferlist::const_iterator& p) { |
7c673cae FG |
104 | __u8 vv; |
105 | decode_raw(vv, p); | |
106 | v = vv; | |
107 | } | |
108 | ||
109 | ||
110 | // ----------------------------------- | |
111 | // int types | |
112 | ||
113 | #define WRITE_INTTYPE_ENCODER(type, etype) \ | |
11fdf7f2 | 114 | inline void encode(type v, ::ceph::bufferlist& bl, uint64_t features=0) { \ |
7c673cae FG |
115 | ceph_##etype e; \ |
116 | e = v; \ | |
11fdf7f2 | 117 | ::ceph::encode_raw(e, bl); \ |
7c673cae | 118 | } \ |
11fdf7f2 | 119 | inline void decode(type &v, ::ceph::bufferlist::const_iterator& p) { \ |
7c673cae | 120 | ceph_##etype e; \ |
11fdf7f2 | 121 | ::ceph::decode_raw(e, p); \ |
7c673cae FG |
122 | v = e; \ |
123 | } | |
124 | ||
125 | WRITE_INTTYPE_ENCODER(uint64_t, le64) | |
126 | WRITE_INTTYPE_ENCODER(int64_t, le64) | |
127 | WRITE_INTTYPE_ENCODER(uint32_t, le32) | |
128 | WRITE_INTTYPE_ENCODER(int32_t, le32) | |
129 | WRITE_INTTYPE_ENCODER(uint16_t, le16) | |
130 | WRITE_INTTYPE_ENCODER(int16_t, le16) | |
131 | ||
132 | // see denc.h for ENCODE_DUMP_PATH discussion and definition. | |
133 | #ifdef ENCODE_DUMP_PATH | |
134 | # define ENCODE_DUMP_PRE() \ | |
135 | unsigned pre_off = bl.length() | |
136 | # define ENCODE_DUMP_POST(cl) \ | |
137 | do { \ | |
138 | static int i = 0; \ | |
139 | i++; \ | |
140 | int bits = 0; \ | |
141 | for (unsigned t = i; t; bits++) \ | |
142 | t &= t - 1; \ | |
143 | if (bits > 2) \ | |
144 | break; \ | |
145 | char fn[PATH_MAX]; \ | |
146 | snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \ | |
91327a77 | 147 | int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644); \ |
7c673cae | 148 | if (fd >= 0) { \ |
11fdf7f2 | 149 | ::ceph::bufferlist sub; \ |
7c673cae FG |
150 | sub.substr_of(bl, pre_off, bl.length() - pre_off); \ |
151 | sub.write_fd(fd); \ | |
152 | ::close(fd); \ | |
153 | } \ | |
154 | } while (0) | |
155 | #else | |
156 | # define ENCODE_DUMP_PRE() | |
157 | # define ENCODE_DUMP_POST(cl) | |
158 | #endif | |
159 | ||
160 | ||
161 | #define WRITE_CLASS_ENCODER(cl) \ | |
9f95a23c | 162 | inline void encode(const cl& c, ::ceph::buffer::list &bl, uint64_t features=0) { \ |
7c673cae | 163 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 164 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
165 | |
166 | #define WRITE_CLASS_MEMBER_ENCODER(cl) \ | |
11fdf7f2 | 167 | inline void encode(const cl &c, ::ceph::bufferlist &bl) const { \ |
7c673cae | 168 | ENCODE_DUMP_PRE(); c.encode(bl); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 169 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
170 | |
171 | #define WRITE_CLASS_ENCODER_FEATURES(cl) \ | |
11fdf7f2 | 172 | inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features) { \ |
7c673cae | 173 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 174 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
175 | |
176 | #define WRITE_CLASS_ENCODER_OPTIONAL_FEATURES(cl) \ | |
11fdf7f2 | 177 | inline void encode(const cl &c, ::ceph::bufferlist &bl, uint64_t features = 0) { \ |
7c673cae | 178 | ENCODE_DUMP_PRE(); c.encode(bl, features); ENCODE_DUMP_POST(cl); } \ |
11fdf7f2 | 179 | inline void decode(cl &c, ::ceph::bufferlist::const_iterator &p) { c.decode(p); } |
7c673cae FG |
180 | |
181 | ||
182 | // string | |
11fdf7f2 | 183 | inline void encode(std::string_view s, bufferlist& bl, uint64_t features=0) |
7c673cae FG |
184 | { |
185 | __u32 len = s.length(); | |
186 | encode(len, bl); | |
187 | if (len) | |
188 | bl.append(s.data(), len); | |
189 | } | |
94b18763 FG |
190 | inline void encode(const std::string& s, bufferlist& bl, uint64_t features=0) |
191 | { | |
11fdf7f2 | 192 | return encode(std::string_view(s), bl, features); |
94b18763 | 193 | } |
11fdf7f2 | 194 | inline void decode(std::string& s, bufferlist::const_iterator& p) |
7c673cae FG |
195 | { |
196 | __u32 len; | |
197 | decode(len, p); | |
198 | s.clear(); | |
199 | p.copy(len, s); | |
200 | } | |
201 | ||
11fdf7f2 | 202 | inline void encode_nohead(std::string_view s, bufferlist& bl) |
7c673cae FG |
203 | { |
204 | bl.append(s.data(), s.length()); | |
205 | } | |
94b18763 FG |
206 | inline void encode_nohead(const std::string& s, bufferlist& bl) |
207 | { | |
11fdf7f2 | 208 | encode_nohead(std::string_view(s), bl); |
94b18763 | 209 | } |
11fdf7f2 | 210 | inline void decode_nohead(int len, std::string& s, bufferlist::const_iterator& p) |
7c673cae FG |
211 | { |
212 | s.clear(); | |
213 | p.copy(len, s); | |
214 | } | |
215 | ||
216 | // const char* (encode only, string compatible) | |
217 | inline void encode(const char *s, bufferlist& bl) | |
218 | { | |
11fdf7f2 | 219 | encode(std::string_view(s, strlen(s)), bl); |
7c673cae FG |
220 | } |
221 | ||
222 | ||
7c673cae FG |
223 | // ----------------------------- |
224 | // buffers | |
225 | ||
226 | // bufferptr (encapsulated) | |
227 | inline void encode(const buffer::ptr& bp, bufferlist& bl) | |
228 | { | |
229 | __u32 len = bp.length(); | |
230 | encode(len, bl); | |
231 | if (len) | |
232 | bl.append(bp); | |
233 | } | |
11fdf7f2 | 234 | inline void decode(buffer::ptr& bp, bufferlist::const_iterator& p) |
7c673cae FG |
235 | { |
236 | __u32 len; | |
237 | decode(len, p); | |
238 | ||
239 | bufferlist s; | |
240 | p.copy(len, s); | |
241 | ||
242 | if (len) { | |
243 | if (s.get_num_buffers() == 1) | |
244 | bp = s.front(); | |
245 | else | |
246 | bp = buffer::copy(s.c_str(), s.length()); | |
247 | } | |
248 | } | |
249 | ||
250 | // bufferlist (encapsulated) | |
251 | inline void encode(const bufferlist& s, bufferlist& bl) | |
252 | { | |
253 | __u32 len = s.length(); | |
254 | encode(len, bl); | |
255 | bl.append(s); | |
256 | } | |
257 | inline void encode_destructively(bufferlist& s, bufferlist& bl) | |
258 | { | |
259 | __u32 len = s.length(); | |
260 | encode(len, bl); | |
261 | bl.claim_append(s); | |
262 | } | |
11fdf7f2 | 263 | inline void decode(bufferlist& s, bufferlist::const_iterator& p) |
7c673cae FG |
264 | { |
265 | __u32 len; | |
266 | decode(len, p); | |
267 | s.clear(); | |
268 | p.copy(len, s); | |
269 | } | |
270 | ||
271 | inline void encode_nohead(const bufferlist& s, bufferlist& bl) | |
272 | { | |
273 | bl.append(s); | |
274 | } | |
11fdf7f2 | 275 | inline void decode_nohead(int len, bufferlist& s, bufferlist::const_iterator& p) |
7c673cae FG |
276 | { |
277 | s.clear(); | |
278 | p.copy(len, s); | |
279 | } | |
280 | ||
11fdf7f2 TL |
281 | // Time, since the templates are defined in std::chrono |
282 | ||
283 | template<typename Clock, typename Duration, | |
284 | typename std::enable_if_t<converts_to_timespec_v<Clock>>* = nullptr> | |
285 | void encode(const std::chrono::time_point<Clock, Duration>& t, | |
286 | ceph::bufferlist &bl) { | |
287 | auto ts = Clock::to_timespec(t); | |
288 | // A 32 bit count of seconds causes me vast unhappiness. | |
289 | uint32_t s = ts.tv_sec; | |
290 | uint32_t ns = ts.tv_nsec; | |
291 | encode(s, bl); | |
292 | encode(ns, bl); | |
293 | } | |
294 | ||
295 | template<typename Clock, typename Duration, | |
296 | typename std::enable_if_t<converts_to_timespec_v<Clock>>* = nullptr> | |
297 | void decode(std::chrono::time_point<Clock, Duration>& t, | |
298 | bufferlist::const_iterator& p) { | |
299 | uint32_t s; | |
300 | uint32_t ns; | |
301 | decode(s, p); | |
302 | decode(ns, p); | |
303 | struct timespec ts = { | |
304 | static_cast<time_t>(s), | |
305 | static_cast<long int>(ns)}; | |
306 | ||
307 | t = Clock::from_timespec(ts); | |
308 | } | |
309 | ||
310 | template<typename Rep, typename Period, | |
311 | typename std::enable_if_t<std::is_integral_v<Rep>>* = nullptr> | |
312 | void encode(const std::chrono::duration<Rep, Period>& d, | |
313 | ceph::bufferlist &bl) { | |
314 | using namespace std::chrono; | |
9f95a23c TL |
315 | int32_t s = duration_cast<seconds>(d).count(); |
316 | int32_t ns = (duration_cast<nanoseconds>(d) % seconds(1)).count(); | |
11fdf7f2 TL |
317 | encode(s, bl); |
318 | encode(ns, bl); | |
319 | } | |
320 | ||
321 | template<typename Rep, typename Period, | |
322 | typename std::enable_if_t<std::is_integral_v<Rep>>* = nullptr> | |
323 | void decode(std::chrono::duration<Rep, Period>& d, | |
324 | bufferlist::const_iterator& p) { | |
9f95a23c TL |
325 | int32_t s; |
326 | int32_t ns; | |
11fdf7f2 TL |
327 | decode(s, p); |
328 | decode(ns, p); | |
329 | d = std::chrono::seconds(s) + std::chrono::nanoseconds(ns); | |
7c673cae FG |
330 | } |
331 | ||
7c673cae FG |
332 | // ----------------------------- |
333 | // STL container types | |
334 | ||
11fdf7f2 TL |
335 | template<typename T> |
336 | inline void encode(const boost::optional<T> &p, bufferlist &bl); | |
337 | template<typename T> | |
338 | inline void decode(boost::optional<T> &p, bufferlist::const_iterator &bp); | |
9f95a23c TL |
339 | template<typename T> |
340 | inline void encode(const std::optional<T> &p, bufferlist &bl); | |
341 | template<typename T> | |
342 | inline void decode(std::optional<T> &p, bufferlist::const_iterator &bp); | |
11fdf7f2 TL |
343 | template<class A, class B, class C> |
344 | inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl); | |
345 | template<class A, class B, class C> | |
346 | inline void decode(boost::tuple<A, B, C> &t, bufferlist::const_iterator &bp); | |
347 | template<class A, class B, | |
348 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
349 | inline std::enable_if_t<!a_traits::supported || !b_traits::supported> | |
350 | encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features); | |
351 | template<class A, class B, | |
352 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
353 | inline std::enable_if_t<!a_traits::supported || | |
354 | !b_traits::supported> | |
355 | encode(const std::pair<A,B> &p, bufferlist &bl); | |
356 | template<class A, class B, | |
357 | typename a_traits=denc_traits<A>, typename b_traits=denc_traits<B>> | |
358 | inline std::enable_if_t<!a_traits::supported || | |
359 | !b_traits::supported> | |
360 | decode(std::pair<A,B> &pa, bufferlist::const_iterator &p); | |
361 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
362 | inline std::enable_if_t<!traits::supported> | |
363 | encode(const std::list<T, Alloc>& ls, bufferlist& bl); | |
364 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
365 | inline std::enable_if_t<!traits::supported> | |
366 | encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features); | |
367 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
368 | inline std::enable_if_t<!traits::supported> | |
369 | decode(std::list<T,Alloc>& ls, bufferlist::const_iterator& p); | |
370 | template<class T, class Alloc> | |
371 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, | |
372 | bufferlist& bl); | |
373 | template<class T, class Alloc> | |
374 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, | |
375 | bufferlist& bl, uint64_t features); | |
376 | template<class T, class Alloc> | |
377 | inline void decode(std::list<std::shared_ptr<T>, Alloc>& ls, | |
378 | bufferlist::const_iterator& p); | |
379 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
380 | inline std::enable_if_t<!traits::supported> | |
381 | encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl); | |
382 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
383 | inline std::enable_if_t<!traits::supported> | |
384 | decode(std::set<T,Comp,Alloc>& s, bufferlist::const_iterator& p); | |
385 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
386 | inline std::enable_if_t<!traits::supported> | |
387 | encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl); | |
388 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
389 | inline std::enable_if_t<!traits::supported> | |
390 | decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::iterator& p); | |
391 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
392 | inline std::enable_if_t<!traits::supported> | |
393 | encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl); | |
394 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
395 | inline std::enable_if_t<!traits::supported> | |
396 | decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::const_iterator& p); | |
397 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
398 | inline std::enable_if_t<!traits::supported> | |
399 | encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s, | |
400 | bufferlist& bl); | |
401 | template<class T, class Comp, class Alloc, typename traits=denc_traits<T>> | |
402 | inline std::enable_if_t<!traits::supported> | |
403 | decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s, | |
404 | bufferlist::iterator& p); | |
405 | template<class T, class Comp, class Alloc> | |
406 | inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl); | |
407 | template<class T, class Comp, class Alloc> | |
408 | inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::const_iterator& p); | |
409 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
410 | inline std::enable_if_t<!traits::supported> | |
411 | encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features); | |
412 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
413 | inline std::enable_if_t<!traits::supported> | |
414 | encode(const std::vector<T,Alloc>& v, bufferlist& bl); | |
415 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
416 | inline std::enable_if_t<!traits::supported> | |
417 | decode(std::vector<T,Alloc>& v, bufferlist::const_iterator& p); | |
418 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
419 | inline std::enable_if_t<!traits::supported> | |
420 | encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl); | |
421 | template<class T, class Alloc, typename traits=denc_traits<T>> | |
422 | inline std::enable_if_t<!traits::supported> | |
423 | decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::const_iterator& p); | |
424 | template<class T,class Alloc> | |
425 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, | |
426 | bufferlist& bl, | |
427 | uint64_t features); | |
428 | template<class T, class Alloc> | |
429 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, | |
430 | bufferlist& bl); | |
431 | template<class T, class Alloc> | |
432 | inline void decode(std::vector<std::shared_ptr<T>,Alloc>& v, | |
433 | bufferlist::const_iterator& p); | |
434 | // small_vector | |
435 | template<class T, std::size_t N, class Alloc, typename traits=denc_traits<T>> | |
436 | inline std::enable_if_t<!traits::supported> | |
437 | encode(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl, uint64_t features); | |
438 | template<class T, std::size_t N, class Alloc, typename traits=denc_traits<T>> | |
439 | inline std::enable_if_t<!traits::supported> | |
440 | encode(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl); | |
441 | template<class T, std::size_t N, class Alloc, typename traits=denc_traits<T>> | |
442 | inline std::enable_if_t<!traits::supported> | |
443 | decode(boost::container::small_vector<T,N,Alloc>& v, bufferlist::const_iterator& p); | |
444 | template<class T, std::size_t N, class Alloc, typename traits=denc_traits<T>> | |
445 | inline std::enable_if_t<!traits::supported> | |
446 | encode_nohead(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl); | |
447 | template<class T, std::size_t N, class Alloc, typename traits=denc_traits<T>> | |
448 | inline std::enable_if_t<!traits::supported> | |
449 | decode_nohead(int len, boost::container::small_vector<T,N,Alloc>& v, bufferlist::const_iterator& p); | |
450 | // std::map | |
451 | template<class T, class U, class Comp, class Alloc, | |
452 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
453 | inline std::enable_if_t<!t_traits::supported || | |
454 | !u_traits::supported> | |
455 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl); | |
456 | template<class T, class U, class Comp, class Alloc, | |
457 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
458 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
459 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features); | |
460 | template<class T, class U, class Comp, class Alloc, | |
461 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
462 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
463 | decode(std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p); | |
464 | template<class T, class U, class Comp, class Alloc> | |
465 | inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p); | |
466 | template<class T, class U, class Comp, class Alloc, | |
467 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
468 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
469 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl); | |
470 | template<class T, class U, class Comp, class Alloc, | |
471 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
472 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
473 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features); | |
474 | template<class T, class U, class Comp, class Alloc, | |
475 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
476 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
477 | decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p); | |
478 | template<class T, class U, class Comp, class Alloc, | |
479 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
480 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
481 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl); | |
482 | template<class T, class U, class Comp, class Alloc, | |
483 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
484 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
485 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl, | |
486 | uint64_t features); | |
487 | template<class T, class U, class Comp, class Alloc, | |
488 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
489 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
490 | decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p); | |
491 | template<class T, class U, class Comp, class Alloc> | |
492 | inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m, | |
493 | bufferlist::const_iterator& p); | |
494 | template<class T, class U, class Comp, class Alloc, | |
495 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
496 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
497 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
498 | bufferlist& bl); | |
499 | template<class T, class U, class Comp, class Alloc, | |
500 | typename t_traits=denc_traits<T>, typename u_traits=denc_traits<U>> | |
501 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
502 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, | |
503 | 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_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m, | |
508 | bufferlist::const_iterator& p); | |
509 | template<class T, class U, class Comp, class Alloc> | |
510 | inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl); | |
511 | template<class T, class U, class Comp, class Alloc> | |
512 | inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p); | |
513 | template<class T, class U, class Hash, class Pred, class Alloc> | |
514 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl, | |
515 | uint64_t features); | |
516 | template<class T, class U, class Hash, class Pred, class Alloc> | |
517 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl); | |
518 | template<class T, class U, class Hash, class Pred, class Alloc> | |
519 | inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p); | |
520 | template<class T, class Hash, class Pred, class Alloc> | |
521 | inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl); | |
522 | template<class T, class Hash, class Pred, class Alloc> | |
523 | inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p); | |
524 | template<class T, class Alloc> | |
525 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features); | |
526 | template<class T, class Alloc> | |
527 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl); | |
528 | template<class T, class Alloc> | |
529 | inline void decode(std::deque<T,Alloc>& ls, bufferlist::const_iterator& p); | |
530 | template<class T, size_t N, typename traits = denc_traits<T>> | |
531 | inline std::enable_if_t<!traits::supported> | |
532 | encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features); | |
533 | template<class T, size_t N, typename traits = denc_traits<T>> | |
534 | inline std::enable_if_t<!traits::supported> | |
535 | encode(const std::array<T, N>& v, bufferlist& bl); | |
536 | template<class T, size_t N, typename traits = denc_traits<T>> | |
537 | inline std::enable_if_t<!traits::supported> | |
538 | decode(std::array<T, N>& v, bufferlist::const_iterator& p); | |
7c673cae | 539 | |
11fdf7f2 TL |
540 | // full bl decoder |
541 | template<class T> | |
542 | inline void decode(T &o, const bufferlist& bl) | |
543 | { | |
544 | auto p = bl.begin(); | |
545 | decode(o, p); | |
546 | ceph_assert(p.end()); | |
547 | } | |
7c673cae FG |
548 | |
549 | // boost optional | |
550 | template<typename T> | |
551 | inline void encode(const boost::optional<T> &p, bufferlist &bl) | |
552 | { | |
553 | __u8 present = static_cast<bool>(p); | |
11fdf7f2 | 554 | encode(present, bl); |
7c673cae FG |
555 | if (p) |
556 | encode(p.get(), bl); | |
557 | } | |
558 | ||
559 | #pragma GCC diagnostic ignored "-Wpragmas" | |
560 | #pragma GCC diagnostic push | |
561 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
7c673cae | 562 | template<typename T> |
11fdf7f2 | 563 | inline void decode(boost::optional<T> &p, bufferlist::const_iterator &bp) |
7c673cae FG |
564 | { |
565 | __u8 present; | |
11fdf7f2 | 566 | decode(present, bp); |
7c673cae | 567 | if (present) { |
181888fb | 568 | p = T{}; |
7c673cae | 569 | decode(p.get(), bp); |
181888fb FG |
570 | } else { |
571 | p = boost::none; | |
7c673cae FG |
572 | } |
573 | } | |
574 | #pragma GCC diagnostic pop | |
575 | #pragma GCC diagnostic warning "-Wpragmas" | |
576 | ||
9f95a23c TL |
577 | // std optional |
578 | template<typename T> | |
579 | inline void encode(const std::optional<T> &p, bufferlist &bl) | |
580 | { | |
581 | __u8 present = static_cast<bool>(p); | |
582 | encode(present, bl); | |
583 | if (p) | |
584 | encode(*p, bl); | |
585 | } | |
586 | ||
587 | #pragma GCC diagnostic ignored "-Wpragmas" | |
588 | #pragma GCC diagnostic push | |
589 | #pragma GCC diagnostic ignored "-Wuninitialized" | |
590 | template<typename T> | |
591 | inline void decode(std::optional<T> &p, bufferlist::const_iterator &bp) | |
592 | { | |
593 | __u8 present; | |
594 | decode(present, bp); | |
595 | if (present) { | |
596 | p = T{}; | |
597 | decode(*p, bp); | |
598 | } else { | |
599 | p = std::nullopt; | |
600 | } | |
601 | } | |
602 | ||
11fdf7f2 TL |
603 | // std::tuple |
604 | template<typename... Ts> | |
605 | inline void encode(const std::tuple<Ts...> &t, bufferlist& bl) | |
606 | { | |
607 | ceph::for_each(t, [&bl](const auto& e) { | |
608 | encode(e, bl); | |
609 | }); | |
610 | } | |
611 | template<typename... Ts> | |
612 | inline void decode(std::tuple<Ts...> &t, bufferlist::const_iterator &bp) | |
613 | { | |
614 | ceph::for_each(t, [&bp](auto& e) { | |
615 | decode(e, bp); | |
616 | }); | |
617 | } | |
618 | ||
619 | //triple boost::tuple | |
7c673cae FG |
620 | template<class A, class B, class C> |
621 | inline void encode(const boost::tuple<A, B, C> &t, bufferlist& bl) | |
622 | { | |
623 | encode(boost::get<0>(t), bl); | |
624 | encode(boost::get<1>(t), bl); | |
625 | encode(boost::get<2>(t), bl); | |
626 | } | |
627 | template<class A, class B, class C> | |
11fdf7f2 | 628 | inline void decode(boost::tuple<A, B, C> &t, bufferlist::const_iterator &bp) |
7c673cae FG |
629 | { |
630 | decode(boost::get<0>(t), bp); | |
631 | decode(boost::get<1>(t), bp); | |
632 | decode(boost::get<2>(t), bp); | |
633 | } | |
634 | ||
635 | // std::pair<A,B> | |
636 | template<class A, class B, | |
11fdf7f2 TL |
637 | typename a_traits, typename b_traits> |
638 | inline std::enable_if_t<!a_traits::supported || !b_traits::supported> | |
7c673cae FG |
639 | encode(const std::pair<A,B> &p, bufferlist &bl, uint64_t features) |
640 | { | |
641 | encode(p.first, bl, features); | |
642 | encode(p.second, bl, features); | |
643 | } | |
644 | template<class A, class B, | |
11fdf7f2 TL |
645 | typename a_traits, typename b_traits> |
646 | inline std::enable_if_t<!a_traits::supported || | |
647 | !b_traits::supported> | |
7c673cae FG |
648 | encode(const std::pair<A,B> &p, bufferlist &bl) |
649 | { | |
650 | encode(p.first, bl); | |
651 | encode(p.second, bl); | |
652 | } | |
11fdf7f2 TL |
653 | template<class A, class B, typename a_traits, typename b_traits> |
654 | inline std::enable_if_t<!a_traits::supported || | |
655 | !b_traits::supported> | |
656 | decode(std::pair<A,B> &pa, bufferlist::const_iterator &p) | |
7c673cae FG |
657 | { |
658 | decode(pa.first, p); | |
659 | decode(pa.second, p); | |
660 | } | |
661 | ||
662 | // std::list<T> | |
11fdf7f2 TL |
663 | template<class T, class Alloc, typename traits> |
664 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
665 | encode(const std::list<T, Alloc>& ls, bufferlist& bl) |
666 | { | |
667 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
668 | encode(n, bl); | |
669 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
670 | encode(*p, bl); | |
671 | } | |
11fdf7f2 TL |
672 | template<class T, class Alloc, typename traits> |
673 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
674 | encode(const std::list<T,Alloc>& ls, bufferlist& bl, uint64_t features) |
675 | { | |
9f95a23c TL |
676 | using counter_encode_t = ceph_le32; |
677 | unsigned n = 0; | |
678 | auto filler = bl.append_hole(sizeof(counter_encode_t)); | |
679 | for (const auto& item : ls) { | |
680 | // we count on our own because of buggy std::list::size() implementation | |
681 | // which doesn't follow the O(1) complexity constraint C++11 has brought. | |
682 | ++n; | |
683 | encode(item, bl, features); | |
7c673cae | 684 | } |
9f95a23c TL |
685 | counter_encode_t en; |
686 | en = n; | |
687 | filler.copy_in(sizeof(en), reinterpret_cast<char*>(&en)); | |
7c673cae | 688 | } |
9f95a23c | 689 | |
11fdf7f2 TL |
690 | template<class T, class Alloc, typename traits> |
691 | inline std::enable_if_t<!traits::supported> | |
692 | decode(std::list<T,Alloc>& ls, bufferlist::const_iterator& p) | |
7c673cae FG |
693 | { |
694 | __u32 n; | |
695 | decode(n, p); | |
696 | ls.clear(); | |
697 | while (n--) { | |
11fdf7f2 TL |
698 | ls.emplace_back(); |
699 | decode(ls.back(), p); | |
7c673cae FG |
700 | } |
701 | } | |
702 | ||
11fdf7f2 | 703 | // std::list<std::shared_ptr<T>> |
7c673cae | 704 | template<class T, class Alloc> |
11fdf7f2 | 705 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, |
7c673cae FG |
706 | bufferlist& bl) |
707 | { | |
708 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
709 | encode(n, bl); | |
11fdf7f2 TL |
710 | for (const auto& ref : ls) { |
711 | encode(*ref, bl); | |
712 | } | |
7c673cae FG |
713 | } |
714 | template<class T, class Alloc> | |
11fdf7f2 | 715 | inline void encode(const std::list<std::shared_ptr<T>, Alloc>& ls, |
7c673cae FG |
716 | bufferlist& bl, uint64_t features) |
717 | { | |
718 | __u32 n = (__u32)(ls.size()); // c++11 std::list::size() is O(1) | |
719 | encode(n, bl); | |
11fdf7f2 TL |
720 | for (const auto& ref : ls) { |
721 | encode(*ref, bl, features); | |
722 | } | |
7c673cae FG |
723 | } |
724 | template<class T, class Alloc> | |
11fdf7f2 TL |
725 | inline void decode(std::list<std::shared_ptr<T>, Alloc>& ls, |
726 | bufferlist::const_iterator& p) | |
7c673cae FG |
727 | { |
728 | __u32 n; | |
729 | decode(n, p); | |
730 | ls.clear(); | |
731 | while (n--) { | |
11fdf7f2 TL |
732 | auto ref = std::make_shared<T>(); |
733 | decode(*ref, p); | |
734 | ls.emplace_back(std::move(ref)); | |
7c673cae FG |
735 | } |
736 | } | |
737 | ||
738 | // std::set<T> | |
11fdf7f2 TL |
739 | template<class T, class Comp, class Alloc, typename traits> |
740 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
741 | encode(const std::set<T,Comp,Alloc>& s, bufferlist& bl) |
742 | { | |
743 | __u32 n = (__u32)(s.size()); | |
744 | encode(n, bl); | |
745 | for (auto p = s.begin(); p != s.end(); ++p) | |
746 | encode(*p, bl); | |
747 | } | |
11fdf7f2 TL |
748 | template<class T, class Comp, class Alloc, typename traits> |
749 | inline std::enable_if_t<!traits::supported> | |
750 | decode(std::set<T,Comp,Alloc>& s, bufferlist::const_iterator& p) | |
7c673cae FG |
751 | { |
752 | __u32 n; | |
753 | decode(n, p); | |
754 | s.clear(); | |
755 | while (n--) { | |
756 | T v; | |
757 | decode(v, p); | |
758 | s.insert(v); | |
759 | } | |
760 | } | |
761 | ||
11fdf7f2 | 762 | template<class T, class Comp, class Alloc, typename traits> |
7c673cae FG |
763 | inline typename std::enable_if<!traits::supported>::type |
764 | encode_nohead(const std::set<T,Comp,Alloc>& s, bufferlist& bl) | |
765 | { | |
766 | for (auto p = s.begin(); p != s.end(); ++p) | |
767 | encode(*p, bl); | |
768 | } | |
11fdf7f2 TL |
769 | template<class T, class Comp, class Alloc, typename traits> |
770 | inline std::enable_if_t<!traits::supported> | |
771 | decode_nohead(int len, std::set<T,Comp,Alloc>& s, bufferlist::const_iterator& p) | |
7c673cae FG |
772 | { |
773 | for (int i=0; i<len; i++) { | |
774 | T v; | |
775 | decode(v, p); | |
776 | s.insert(v); | |
777 | } | |
778 | } | |
779 | ||
780 | // boost::container::flat_set<T> | |
11fdf7f2 TL |
781 | template<class T, class Comp, class Alloc, typename traits> |
782 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
783 | encode(const boost::container::flat_set<T, Comp, Alloc>& s, bufferlist& bl) |
784 | { | |
785 | __u32 n = (__u32)(s.size()); | |
786 | encode(n, bl); | |
787 | for (const auto& e : s) | |
788 | encode(e, bl); | |
789 | } | |
11fdf7f2 TL |
790 | template<class T, class Comp, class Alloc, typename traits> |
791 | inline std::enable_if_t<!traits::supported> | |
792 | decode(boost::container::flat_set<T, Comp, Alloc>& s, bufferlist::const_iterator& p) | |
7c673cae FG |
793 | { |
794 | __u32 n; | |
795 | decode(n, p); | |
796 | s.clear(); | |
31f18b77 | 797 | s.reserve(n); |
7c673cae FG |
798 | while (n--) { |
799 | T v; | |
800 | decode(v, p); | |
801 | s.insert(v); | |
802 | } | |
803 | } | |
804 | ||
11fdf7f2 TL |
805 | template<class T, class Comp, class Alloc, typename traits> |
806 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
807 | encode_nohead(const boost::container::flat_set<T, Comp, Alloc>& s, |
808 | bufferlist& bl) | |
809 | { | |
810 | for (const auto& e : s) | |
811 | encode(e, bl); | |
812 | } | |
11fdf7f2 TL |
813 | template<class T, class Comp, class Alloc, typename traits> |
814 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
815 | decode_nohead(int len, boost::container::flat_set<T, Comp, Alloc>& s, |
816 | bufferlist::iterator& p) | |
817 | { | |
31f18b77 | 818 | s.reserve(len); |
7c673cae FG |
819 | for (int i=0; i<len; i++) { |
820 | T v; | |
821 | decode(v, p); | |
822 | s.insert(v); | |
823 | } | |
824 | } | |
825 | ||
826 | // multiset | |
827 | template<class T, class Comp, class Alloc> | |
828 | inline void encode(const std::multiset<T,Comp,Alloc>& s, bufferlist& bl) | |
829 | { | |
830 | __u32 n = (__u32)(s.size()); | |
831 | encode(n, bl); | |
832 | for (auto p = s.begin(); p != s.end(); ++p) | |
833 | encode(*p, bl); | |
834 | } | |
835 | template<class T, class Comp, class Alloc> | |
11fdf7f2 | 836 | inline void decode(std::multiset<T,Comp,Alloc>& s, bufferlist::const_iterator& p) |
7c673cae FG |
837 | { |
838 | __u32 n; | |
839 | decode(n, p); | |
840 | s.clear(); | |
841 | while (n--) { | |
842 | T v; | |
843 | decode(v, p); | |
844 | s.insert(v); | |
845 | } | |
846 | } | |
847 | ||
11fdf7f2 TL |
848 | template<class T, class Alloc, typename traits> |
849 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
850 | encode(const std::vector<T,Alloc>& v, bufferlist& bl, uint64_t features) |
851 | { | |
852 | __u32 n = (__u32)(v.size()); | |
853 | encode(n, bl); | |
854 | for (auto p = v.begin(); p != v.end(); ++p) | |
855 | encode(*p, bl, features); | |
856 | } | |
11fdf7f2 TL |
857 | template<class T, class Alloc, typename traits> |
858 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
859 | encode(const std::vector<T,Alloc>& v, bufferlist& bl) |
860 | { | |
861 | __u32 n = (__u32)(v.size()); | |
862 | encode(n, bl); | |
863 | for (auto p = v.begin(); p != v.end(); ++p) | |
864 | encode(*p, bl); | |
865 | } | |
11fdf7f2 TL |
866 | template<class T, class Alloc, typename traits> |
867 | inline std::enable_if_t<!traits::supported> | |
868 | decode(std::vector<T,Alloc>& v, bufferlist::const_iterator& p) | |
7c673cae FG |
869 | { |
870 | __u32 n; | |
871 | decode(n, p); | |
872 | v.resize(n); | |
873 | for (__u32 i=0; i<n; i++) | |
874 | decode(v[i], p); | |
875 | } | |
876 | ||
11fdf7f2 TL |
877 | template<class T, class Alloc, typename traits> |
878 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
879 | encode_nohead(const std::vector<T,Alloc>& v, bufferlist& bl) |
880 | { | |
881 | for (auto p = v.begin(); p != v.end(); ++p) | |
882 | encode(*p, bl); | |
883 | } | |
11fdf7f2 TL |
884 | template<class T, class Alloc, typename traits> |
885 | inline std::enable_if_t<!traits::supported> | |
886 | decode_nohead(int len, std::vector<T,Alloc>& v, bufferlist::const_iterator& p) | |
7c673cae FG |
887 | { |
888 | v.resize(len); | |
889 | for (__u32 i=0; i<v.size(); i++) | |
890 | decode(v[i], p); | |
891 | } | |
892 | ||
11fdf7f2 TL |
893 | // small vector |
894 | template<class T, std::size_t N, class Alloc, typename traits> | |
895 | inline std::enable_if_t<!traits::supported> | |
896 | encode(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl, uint64_t features) | |
897 | { | |
898 | __u32 n = (__u32)(v.size()); | |
899 | encode(n, bl); | |
900 | for (const auto& i : v) | |
901 | encode(i, bl, features); | |
902 | } | |
903 | template<class T, std::size_t N, class Alloc, typename traits> | |
904 | inline std::enable_if_t<!traits::supported> | |
905 | encode(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl) | |
906 | { | |
907 | __u32 n = (__u32)(v.size()); | |
908 | encode(n, bl); | |
909 | for (const auto& i : v) | |
910 | encode(i, bl); | |
911 | } | |
912 | template<class T, std::size_t N, class Alloc, typename traits> | |
913 | inline std::enable_if_t<!traits::supported> | |
914 | decode(boost::container::small_vector<T,N,Alloc>& v, bufferlist::const_iterator& p) | |
915 | { | |
916 | __u32 n; | |
917 | decode(n, p); | |
918 | v.resize(n); | |
919 | for (auto& i : v) | |
920 | decode(i, p); | |
921 | } | |
922 | ||
923 | template<class T, std::size_t N, class Alloc, typename traits> | |
924 | inline std::enable_if_t<!traits::supported> | |
925 | encode_nohead(const boost::container::small_vector<T,N,Alloc>& v, bufferlist& bl) | |
926 | { | |
927 | for (const auto& i : v) | |
928 | encode(i, bl); | |
929 | } | |
930 | template<class T, std::size_t N, class Alloc, typename traits> | |
931 | inline std::enable_if_t<!traits::supported> | |
932 | decode_nohead(int len, boost::container::small_vector<T,N,Alloc>& v, bufferlist::const_iterator& p) | |
933 | { | |
934 | v.resize(len); | |
935 | for (auto& i : v) | |
936 | decode(i, p); | |
937 | } | |
938 | ||
939 | ||
7c673cae FG |
940 | // vector (shared_ptr) |
941 | template<class T,class Alloc> | |
11fdf7f2 | 942 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, |
7c673cae FG |
943 | bufferlist& bl, |
944 | uint64_t features) | |
945 | { | |
946 | __u32 n = (__u32)(v.size()); | |
947 | encode(n, bl); | |
11fdf7f2 TL |
948 | for (const auto& ref : v) { |
949 | if (ref) | |
950 | encode(*ref, bl, features); | |
7c673cae FG |
951 | else |
952 | encode(T(), bl, features); | |
11fdf7f2 | 953 | } |
7c673cae FG |
954 | } |
955 | template<class T, class Alloc> | |
11fdf7f2 | 956 | inline void encode(const std::vector<std::shared_ptr<T>,Alloc>& v, |
7c673cae FG |
957 | bufferlist& bl) |
958 | { | |
959 | __u32 n = (__u32)(v.size()); | |
960 | encode(n, bl); | |
11fdf7f2 TL |
961 | for (const auto& ref : v) { |
962 | if (ref) | |
963 | encode(*ref, bl); | |
7c673cae FG |
964 | else |
965 | encode(T(), bl); | |
7c673cae FG |
966 | } |
967 | } | |
11fdf7f2 TL |
968 | template<class T, class Alloc> |
969 | inline void decode(std::vector<std::shared_ptr<T>,Alloc>& v, | |
970 | bufferlist::const_iterator& p) | |
7c673cae FG |
971 | { |
972 | __u32 n; | |
973 | decode(n, p); | |
11fdf7f2 TL |
974 | v.clear(); |
975 | v.reserve(n); | |
7c673cae | 976 | while (n--) { |
11fdf7f2 TL |
977 | auto ref = std::make_shared<T>(); |
978 | decode(*ref, p); | |
979 | v.emplace_back(std::move(ref)); | |
7c673cae | 980 | } |
11fdf7f2 | 981 | } |
7c673cae FG |
982 | |
983 | // map | |
984 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
985 | typename t_traits, typename u_traits> |
986 | inline std::enable_if_t<!t_traits::supported || | |
987 | !u_traits::supported> | |
7c673cae FG |
988 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) |
989 | { | |
990 | __u32 n = (__u32)(m.size()); | |
991 | encode(n, bl); | |
992 | for (auto p = m.begin(); p != m.end(); ++p) { | |
993 | encode(p->first, bl); | |
994 | encode(p->second, bl); | |
995 | } | |
996 | } | |
997 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
998 | typename t_traits, typename u_traits> |
999 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1000 | encode(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) |
1001 | { | |
1002 | __u32 n = (__u32)(m.size()); | |
1003 | encode(n, bl); | |
1004 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1005 | encode(p->first, bl, features); | |
1006 | encode(p->second, bl, features); | |
1007 | } | |
1008 | } | |
1009 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1010 | typename t_traits, typename u_traits> |
1011 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
1012 | decode(std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) | |
7c673cae FG |
1013 | { |
1014 | __u32 n; | |
1015 | decode(n, p); | |
1016 | m.clear(); | |
1017 | while (n--) { | |
1018 | T k; | |
1019 | decode(k, p); | |
1020 | decode(m[k], p); | |
1021 | } | |
1022 | } | |
1023 | template<class T, class U, class Comp, class Alloc> | |
11fdf7f2 | 1024 | inline void decode_noclear(std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1025 | { |
1026 | __u32 n; | |
1027 | decode(n, p); | |
1028 | while (n--) { | |
1029 | T k; | |
1030 | decode(k, p); | |
1031 | decode(m[k], p); | |
1032 | } | |
1033 | } | |
1034 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1035 | typename t_traits, typename u_traits> |
1036 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1037 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl) |
1038 | { | |
1039 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1040 | encode(p->first, bl); | |
1041 | encode(p->second, bl); | |
1042 | } | |
1043 | } | |
1044 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1045 | typename t_traits, typename u_traits> |
1046 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1047 | encode_nohead(const std::map<T,U,Comp,Alloc>& m, bufferlist& bl, uint64_t features) |
1048 | { | |
1049 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1050 | encode(p->first, bl, features); | |
1051 | encode(p->second, bl, features); | |
1052 | } | |
1053 | } | |
1054 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1055 | typename t_traits, typename u_traits> |
1056 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
1057 | decode_nohead(int n, std::map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) | |
7c673cae FG |
1058 | { |
1059 | m.clear(); | |
1060 | while (n--) { | |
1061 | T k; | |
1062 | decode(k, p); | |
1063 | decode(m[k], p); | |
1064 | } | |
1065 | } | |
1066 | ||
1067 | // boost::container::flat-map | |
1068 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1069 | typename t_traits, typename u_traits> |
1070 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1071 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl) |
1072 | { | |
1073 | __u32 n = (__u32)(m.size()); | |
1074 | encode(n, bl); | |
1075 | for (typename boost::container::flat_map<T,U,Comp>::const_iterator p | |
1076 | = m.begin(); p != m.end(); ++p) { | |
1077 | encode(p->first, bl); | |
1078 | encode(p->second, bl); | |
1079 | } | |
1080 | } | |
1081 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1082 | typename t_traits, typename u_traits> |
1083 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1084 | encode(const boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist& bl, |
1085 | uint64_t features) | |
1086 | { | |
1087 | __u32 n = (__u32)(m.size()); | |
1088 | encode(n, bl); | |
1089 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1090 | encode(p->first, bl, features); | |
1091 | encode(p->second, bl, features); | |
1092 | } | |
1093 | } | |
1094 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1095 | typename t_traits, typename u_traits> |
1096 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
1097 | decode(boost::container::flat_map<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) | |
7c673cae FG |
1098 | { |
1099 | __u32 n; | |
1100 | decode(n, p); | |
1101 | m.clear(); | |
31f18b77 | 1102 | m.reserve(n); |
7c673cae FG |
1103 | while (n--) { |
1104 | T k; | |
1105 | decode(k, p); | |
1106 | decode(m[k], p); | |
1107 | } | |
1108 | } | |
1109 | template<class T, class U, class Comp, class Alloc> | |
1110 | inline void decode_noclear(boost::container::flat_map<T,U,Comp,Alloc>& m, | |
11fdf7f2 | 1111 | bufferlist::const_iterator& p) |
7c673cae FG |
1112 | { |
1113 | __u32 n; | |
1114 | decode(n, p); | |
31f18b77 | 1115 | m.reserve(m.size() + n); |
7c673cae FG |
1116 | while (n--) { |
1117 | T k; | |
1118 | decode(k, p); | |
1119 | decode(m[k], p); | |
1120 | } | |
1121 | } | |
1122 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1123 | typename t_traits, typename u_traits> |
1124 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1125 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, |
1126 | bufferlist& bl) | |
1127 | { | |
1128 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1129 | encode(p->first, bl); | |
1130 | encode(p->second, bl); | |
1131 | } | |
1132 | } | |
1133 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1134 | typename t_traits, typename u_traits> |
1135 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae FG |
1136 | encode_nohead(const boost::container::flat_map<T,U,Comp,Alloc>& m, |
1137 | bufferlist& bl, uint64_t features) | |
1138 | { | |
1139 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1140 | encode(p->first, bl, features); | |
1141 | encode(p->second, bl, features); | |
1142 | } | |
1143 | } | |
1144 | template<class T, class U, class Comp, class Alloc, | |
11fdf7f2 TL |
1145 | typename t_traits, typename u_traits> |
1146 | inline std::enable_if_t<!t_traits::supported || !u_traits::supported> | |
7c673cae | 1147 | decode_nohead(int n, boost::container::flat_map<T,U,Comp,Alloc>& m, |
11fdf7f2 | 1148 | bufferlist::const_iterator& p) |
7c673cae FG |
1149 | { |
1150 | m.clear(); | |
1151 | while (n--) { | |
1152 | T k; | |
1153 | decode(k, p); | |
1154 | decode(m[k], p); | |
1155 | } | |
1156 | } | |
1157 | ||
1158 | // multimap | |
1159 | template<class T, class U, class Comp, class Alloc> | |
1160 | inline void encode(const std::multimap<T,U,Comp,Alloc>& m, bufferlist& bl) | |
1161 | { | |
1162 | __u32 n = (__u32)(m.size()); | |
1163 | encode(n, bl); | |
1164 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1165 | encode(p->first, bl); | |
1166 | encode(p->second, bl); | |
1167 | } | |
1168 | } | |
1169 | template<class T, class U, class Comp, class Alloc> | |
11fdf7f2 | 1170 | inline void decode(std::multimap<T,U,Comp,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1171 | { |
1172 | __u32 n; | |
1173 | decode(n, p); | |
1174 | m.clear(); | |
1175 | while (n--) { | |
1176 | typename std::pair<T,U> tu = std::pair<T,U>(); | |
1177 | decode(tu.first, p); | |
1178 | typename std::multimap<T,U,Comp,Alloc>::iterator it = m.insert(tu); | |
1179 | decode(it->second, p); | |
1180 | } | |
1181 | } | |
1182 | ||
1183 | // ceph::unordered_map | |
1184 | template<class T, class U, class Hash, class Pred, class Alloc> | |
1185 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl, | |
1186 | uint64_t features) | |
1187 | { | |
1188 | __u32 n = (__u32)(m.size()); | |
1189 | encode(n, bl); | |
1190 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1191 | encode(p->first, bl, features); | |
1192 | encode(p->second, bl, features); | |
1193 | } | |
1194 | } | |
1195 | template<class T, class U, class Hash, class Pred, class Alloc> | |
1196 | inline void encode(const unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist& bl) | |
1197 | { | |
1198 | __u32 n = (__u32)(m.size()); | |
1199 | encode(n, bl); | |
1200 | for (auto p = m.begin(); p != m.end(); ++p) { | |
1201 | encode(p->first, bl); | |
1202 | encode(p->second, bl); | |
1203 | } | |
1204 | } | |
1205 | template<class T, class U, class Hash, class Pred, class Alloc> | |
11fdf7f2 | 1206 | inline void decode(unordered_map<T,U,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1207 | { |
1208 | __u32 n; | |
1209 | decode(n, p); | |
1210 | m.clear(); | |
1211 | while (n--) { | |
1212 | T k; | |
1213 | decode(k, p); | |
1214 | decode(m[k], p); | |
1215 | } | |
1216 | } | |
1217 | ||
1218 | // ceph::unordered_set | |
1219 | template<class T, class Hash, class Pred, class Alloc> | |
1220 | inline void encode(const ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist& bl) | |
1221 | { | |
1222 | __u32 n = (__u32)(m.size()); | |
1223 | encode(n, bl); | |
1224 | for (auto p = m.begin(); p != m.end(); ++p) | |
1225 | encode(*p, bl); | |
1226 | } | |
1227 | template<class T, class Hash, class Pred, class Alloc> | |
11fdf7f2 | 1228 | inline void decode(ceph::unordered_set<T,Hash,Pred,Alloc>& m, bufferlist::const_iterator& p) |
7c673cae FG |
1229 | { |
1230 | __u32 n; | |
1231 | decode(n, p); | |
1232 | m.clear(); | |
1233 | while (n--) { | |
1234 | T k; | |
1235 | decode(k, p); | |
1236 | m.insert(k); | |
1237 | } | |
1238 | } | |
1239 | ||
1240 | // deque | |
1241 | template<class T, class Alloc> | |
1242 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl, uint64_t features) | |
1243 | { | |
1244 | __u32 n = ls.size(); | |
1245 | encode(n, bl); | |
1246 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
1247 | encode(*p, bl, features); | |
1248 | } | |
1249 | template<class T, class Alloc> | |
1250 | inline void encode(const std::deque<T,Alloc>& ls, bufferlist& bl) | |
1251 | { | |
1252 | __u32 n = ls.size(); | |
1253 | encode(n, bl); | |
1254 | for (auto p = ls.begin(); p != ls.end(); ++p) | |
1255 | encode(*p, bl); | |
1256 | } | |
1257 | template<class T, class Alloc> | |
11fdf7f2 | 1258 | inline void decode(std::deque<T,Alloc>& ls, bufferlist::const_iterator& p) |
7c673cae FG |
1259 | { |
1260 | __u32 n; | |
1261 | decode(n, p); | |
1262 | ls.clear(); | |
1263 | while (n--) { | |
11fdf7f2 TL |
1264 | ls.emplace_back(); |
1265 | decode(ls.back(), p); | |
7c673cae FG |
1266 | } |
1267 | } | |
1268 | ||
1269 | // std::array<T, N> | |
11fdf7f2 TL |
1270 | template<class T, size_t N, typename traits> |
1271 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
1272 | encode(const std::array<T, N>& v, bufferlist& bl, uint64_t features) |
1273 | { | |
1274 | for (const auto& e : v) | |
1275 | encode(e, bl, features); | |
1276 | } | |
11fdf7f2 TL |
1277 | template<class T, size_t N, typename traits> |
1278 | inline std::enable_if_t<!traits::supported> | |
7c673cae FG |
1279 | encode(const std::array<T, N>& v, bufferlist& bl) |
1280 | { | |
1281 | for (const auto& e : v) | |
1282 | encode(e, bl); | |
1283 | } | |
11fdf7f2 TL |
1284 | template<class T, size_t N, typename traits> |
1285 | inline std::enable_if_t<!traits::supported> | |
1286 | decode(std::array<T, N>& v, bufferlist::const_iterator& p) | |
7c673cae FG |
1287 | { |
1288 | for (auto& e : v) | |
1289 | decode(e, p); | |
1290 | } | |
11fdf7f2 | 1291 | } |
7c673cae FG |
1292 | |
1293 | /* | |
1294 | * guards | |
1295 | */ | |
1296 | ||
1297 | /** | |
1298 | * start encoding block | |
1299 | * | |
1300 | * @param v current (code) version of the encoding | |
1301 | * @param compat oldest code version that can decode it | |
1302 | * @param bl bufferlist to encode to | |
11fdf7f2 | 1303 | * |
7c673cae FG |
1304 | */ |
1305 | #define ENCODE_START(v, compat, bl) \ | |
11fdf7f2 TL |
1306 | __u8 struct_v = v; \ |
1307 | __u8 struct_compat = compat; \ | |
7c673cae | 1308 | ceph_le32 struct_len; \ |
9f95a23c | 1309 | auto filler = (bl).append_hole(sizeof(struct_v) + \ |
11fdf7f2 TL |
1310 | sizeof(struct_compat) + sizeof(struct_len)); \ |
1311 | const auto starting_bl_len = (bl).length(); \ | |
1312 | using ::ceph::encode; \ | |
7c673cae FG |
1313 | do { |
1314 | ||
1315 | /** | |
1316 | * finish encoding block | |
1317 | * | |
1318 | * @param bl bufferlist we were encoding to | |
1319 | * @param new_struct_compat struct-compat value to use | |
1320 | */ | |
11fdf7f2 TL |
1321 | #define ENCODE_FINISH_NEW_COMPAT(bl, new_struct_compat) \ |
1322 | } while (false); \ | |
1323 | if (new_struct_compat) { \ | |
1324 | struct_compat = new_struct_compat; \ | |
1325 | } \ | |
1326 | struct_len = (bl).length() - starting_bl_len; \ | |
1327 | filler.copy_in(sizeof(struct_v), (char *)&struct_v); \ | |
1328 | filler.copy_in(sizeof(struct_compat), \ | |
1329 | (char *)&struct_compat); \ | |
1330 | filler.copy_in(sizeof(struct_len), (char *)&struct_len); | |
7c673cae FG |
1331 | |
1332 | #define ENCODE_FINISH(bl) ENCODE_FINISH_NEW_COMPAT(bl, 0) | |
1333 | ||
1334 | #define DECODE_ERR_OLDVERSION(func, v, compatv) \ | |
91327a77 | 1335 | (std::string(func) + " no longer understand old encoding version " #v " < " + std::to_string(compatv)) |
7c673cae FG |
1336 | |
1337 | #define DECODE_ERR_PAST(func) \ | |
1338 | (std::string(func) + " decode past end of struct encoding") | |
1339 | ||
1340 | /** | |
1341 | * check for very old encoding | |
1342 | * | |
1343 | * If the encoded data is older than oldestv, raise an exception. | |
1344 | * | |
1345 | * @param oldestv oldest version of the code we can successfully decode. | |
1346 | */ | |
1347 | #define DECODE_OLDEST(oldestv) \ | |
1348 | if (struct_v < oldestv) \ | |
11fdf7f2 | 1349 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, oldestv)); |
7c673cae FG |
1350 | |
1351 | /** | |
1352 | * start a decoding block | |
1353 | * | |
1354 | * @param v current version of the encoding that the code supports/encodes | |
1355 | * @param bl bufferlist::iterator for the encoded data | |
1356 | */ | |
1357 | #define DECODE_START(v, bl) \ | |
1358 | __u8 struct_v, struct_compat; \ | |
11fdf7f2 TL |
1359 | using ::ceph::decode; \ |
1360 | decode(struct_v, bl); \ | |
1361 | decode(struct_compat, bl); \ | |
7c673cae | 1362 | if (v < struct_compat) \ |
9f95a23c | 1363 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ |
7c673cae | 1364 | __u32 struct_len; \ |
11fdf7f2 | 1365 | decode(struct_len, bl); \ |
7c673cae | 1366 | if (struct_len > bl.get_remaining()) \ |
11fdf7f2 | 1367 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae FG |
1368 | unsigned struct_end = bl.get_off() + struct_len; \ |
1369 | do { | |
1370 | ||
11fdf7f2 TL |
1371 | /* BEWARE: any change to this macro MUST be also reflected in the duplicative |
1372 | * DECODE_START_LEGACY_COMPAT_LEN! */ | |
7c673cae | 1373 | #define __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, skip_v, bl) \ |
11fdf7f2 | 1374 | using ::ceph::decode; \ |
7c673cae | 1375 | __u8 struct_v; \ |
11fdf7f2 | 1376 | decode(struct_v, bl); \ |
7c673cae FG |
1377 | if (struct_v >= compatv) { \ |
1378 | __u8 struct_compat; \ | |
11fdf7f2 | 1379 | decode(struct_compat, bl); \ |
7c673cae | 1380 | if (v < struct_compat) \ |
9f95a23c | 1381 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION(__PRETTY_FUNCTION__, v, struct_compat)); \ |
7c673cae | 1382 | } else if (skip_v) { \ |
11fdf7f2 | 1383 | if (bl.get_remaining() < skip_v) \ |
9f95a23c TL |
1384 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
1385 | bl += skip_v; \ | |
7c673cae FG |
1386 | } \ |
1387 | unsigned struct_end = 0; \ | |
1388 | if (struct_v >= lenv) { \ | |
1389 | __u32 struct_len; \ | |
11fdf7f2 | 1390 | decode(struct_len, bl); \ |
7c673cae | 1391 | if (struct_len > bl.get_remaining()) \ |
9f95a23c | 1392 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae FG |
1393 | struct_end = bl.get_off() + struct_len; \ |
1394 | } \ | |
1395 | do { | |
1396 | ||
1397 | /** | |
1398 | * start a decoding block with legacy support for older encoding schemes | |
1399 | * | |
1400 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1401 | * the compat version or length. Skip those fields conditionally. | |
1402 | * | |
1403 | * Most of the time, v, compatv, and lenv will all match the version | |
1404 | * where the structure was switched over to the new macros. | |
1405 | * | |
1406 | * @param v current version of the encoding that the code supports/encodes | |
1407 | * @param compatv oldest version that includes a __u8 compat version field | |
1408 | * @param lenv oldest version that includes a __u32 length wrapper | |
1409 | * @param bl bufferlist::iterator containing the encoded data | |
1410 | */ | |
11fdf7f2 TL |
1411 | |
1412 | /* BEWARE: this is duplication of __DECODE_START_LEGACY_COMPAT_LEN which | |
1413 | * MUST be changed altogether. For the rationale behind code duplication, | |
1414 | * please `git blame` and refer to the commit message. */ | |
7c673cae | 1415 | #define DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, bl) \ |
11fdf7f2 TL |
1416 | using ::ceph::decode; \ |
1417 | __u8 struct_v; \ | |
1418 | decode(struct_v, bl); \ | |
1419 | if (struct_v >= compatv) { \ | |
1420 | __u8 struct_compat; \ | |
1421 | decode(struct_compat, bl); \ | |
1422 | if (v < struct_compat) \ | |
9f95a23c | 1423 | throw ::ceph::buffer::malformed_input(DECODE_ERR_OLDVERSION( \ |
11fdf7f2 TL |
1424 | __PRETTY_FUNCTION__, v, struct_compat)); \ |
1425 | } \ | |
1426 | unsigned struct_end = 0; \ | |
1427 | if (struct_v >= lenv) { \ | |
1428 | __u32 struct_len; \ | |
1429 | decode(struct_len, bl); \ | |
1430 | if (struct_len > bl.get_remaining()) \ | |
9f95a23c | 1431 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
11fdf7f2 TL |
1432 | struct_end = bl.get_off() + struct_len; \ |
1433 | } \ | |
1434 | do { | |
7c673cae FG |
1435 | |
1436 | /** | |
1437 | * start a decoding block with legacy support for older encoding schemes | |
1438 | * | |
1439 | * This version of the macro assumes the legacy encoding had a 32 bit | |
1440 | * version | |
1441 | * | |
1442 | * The old encoding schemes has a __u8 struct_v only, or lacked either | |
1443 | * the compat version or length. Skip those fields conditionally. | |
1444 | * | |
1445 | * Most of the time, v, compatv, and lenv will all match the version | |
1446 | * where the structure was switched over to the new macros. | |
1447 | * | |
1448 | * @param v current version of the encoding that the code supports/encodes | |
1449 | * @param compatv oldest version that includes a __u8 compat version field | |
1450 | * @param lenv oldest version that includes a __u32 length wrapper | |
1451 | * @param bl bufferlist::iterator containing the encoded data | |
1452 | */ | |
1453 | #define DECODE_START_LEGACY_COMPAT_LEN_32(v, compatv, lenv, bl) \ | |
11fdf7f2 | 1454 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 3u, bl) |
7c673cae FG |
1455 | |
1456 | #define DECODE_START_LEGACY_COMPAT_LEN_16(v, compatv, lenv, bl) \ | |
11fdf7f2 | 1457 | __DECODE_START_LEGACY_COMPAT_LEN(v, compatv, lenv, 1u, bl) |
7c673cae FG |
1458 | |
1459 | /** | |
1460 | * finish decode block | |
1461 | * | |
1462 | * @param bl bufferlist::iterator we were decoding from | |
1463 | */ | |
1464 | #define DECODE_FINISH(bl) \ | |
1465 | } while (false); \ | |
1466 | if (struct_end) { \ | |
1467 | if (bl.get_off() > struct_end) \ | |
9f95a23c | 1468 | throw ::ceph::buffer::malformed_input(DECODE_ERR_PAST(__PRETTY_FUNCTION__)); \ |
7c673cae | 1469 | if (bl.get_off() < struct_end) \ |
9f95a23c | 1470 | bl += struct_end - bl.get_off(); \ |
7c673cae FG |
1471 | } |
1472 | ||
11fdf7f2 TL |
1473 | namespace ceph { |
1474 | ||
7c673cae FG |
1475 | /* |
1476 | * Encoders/decoders to read from current offset in a file handle and | |
1477 | * encode/decode the data according to argument types. | |
1478 | */ | |
1479 | inline ssize_t decode_file(int fd, std::string &str) | |
1480 | { | |
1481 | bufferlist bl; | |
1482 | __u32 len = 0; | |
1483 | bl.read_fd(fd, sizeof(len)); | |
9f95a23c | 1484 | decode(len, bl); |
7c673cae | 1485 | bl.read_fd(fd, len); |
9f95a23c | 1486 | decode(str, bl); |
7c673cae FG |
1487 | return bl.length(); |
1488 | } | |
1489 | ||
1490 | inline ssize_t decode_file(int fd, bufferptr &bp) | |
1491 | { | |
1492 | bufferlist bl; | |
1493 | __u32 len = 0; | |
1494 | bl.read_fd(fd, sizeof(len)); | |
11fdf7f2 | 1495 | decode(len, bl); |
7c673cae | 1496 | bl.read_fd(fd, len); |
11fdf7f2 | 1497 | auto bli = std::cbegin(bl); |
7c673cae | 1498 | |
11fdf7f2 | 1499 | decode(bp, bli); |
7c673cae FG |
1500 | return bl.length(); |
1501 | } | |
11fdf7f2 | 1502 | } |
7c673cae FG |
1503 | |
1504 | #endif |