]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
denc: add boost::container::small_vector support
authorKefu Chai <kchai@redhat.com>
Sat, 4 Jul 2020 10:10:55 +0000 (18:10 +0800)
committerKefu Chai <kchai@redhat.com>
Sat, 11 Jul 2020 17:19:37 +0000 (01:19 +0800)
i could use `_denc::container_base<>` and `_denc::pushback_details<>` to
implement the traits for boost::container::small_vector (bcs for short),
but the second template parameter of bcs is a value of type size_t, so
the value it not a type, forunately, C++17 allows us to declare non-type
template parameter using `auto`, but when instantiating
_denc::container_base<>, the compiler complains that it expects a
constatnt of `auto` but `T` is passed in. because i have to change the
signature of `container_base` to something like
```
template<template<auto...> class C, typename Details, auto ...Ts>
  struct container_base {
```

so, in this change, the traits for bsc is implemented from scratch.

Signed-off-by: Kefu Chai <kchai@redhat.com>
src/include/denc.h

index 24fe8b08d215cb5d98cb6030d79cc6d0725e4072..a463f7647df55ace76e28294bdc893e4a245418b 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <boost/container/flat_map.hpp>
 #include <boost/container/flat_set.hpp>
+#include <boost/container/small_vector.hpp>
 #include <boost/intrusive/set.hpp>
 #include <boost/optional.hpp>
 
@@ -1085,6 +1086,106 @@ struct denc_traits<
                                 _denc::pushback_details<std::vector<T, Ts...>>,
                                 T, Ts...> {};
 
+template<typename T, std::size_t N, typename ...Ts>
+struct denc_traits<
+  boost::container::small_vector<T, N, Ts...>,
+  typename std::enable_if_t<denc_traits<T>::supported>> {
+private:
+  using container = boost::container::small_vector<T, N, Ts...>;
+public:
+  using traits = denc_traits<T>;
+
+  static constexpr bool supported = true;
+  static constexpr bool featured = traits::featured;
+  static constexpr bool bounded = false;
+  static constexpr bool need_contiguous = traits::need_contiguous;
+
+  template<typename U=T>
+  static void bound_encode(const container& s, size_t& p, uint64_t f = 0) {
+    p += sizeof(uint32_t);
+    if constexpr (traits::bounded) {
+      if (!s.empty()) {
+       const auto elem_num = s.size();
+       size_t elem_size = 0;
+       if constexpr (traits::featured) {
+         denc(*s.begin(), elem_size, f);
+        } else {
+          denc(*s.begin(), elem_size);
+        }
+        p += elem_size * elem_num;
+      }
+    } else {
+      for (const T& e : s) {
+       if constexpr (traits::featured) {
+         denc(e, p, f);
+       } else {
+         denc(e, p);
+       }
+      }
+    }
+  }
+
+  template<typename U=T>
+  static void encode(const container& s,
+                    ceph::buffer::list::contiguous_appender& p,
+                    uint64_t f = 0) {
+    denc((uint32_t)s.size(), p);
+    if constexpr (traits::featured) {
+      encode_nohead(s, p, f);
+    } else {
+      encode_nohead(s, p);
+    }
+  }
+  static void decode(container& s, ceph::buffer::ptr::const_iterator& p,
+                    uint64_t f = 0) {
+    uint32_t num;
+    denc(num, p);
+    decode_nohead(num, s, p, f);
+  }
+  template<typename U=T>
+  static std::enable_if_t<!!sizeof(U) && !need_contiguous>
+  decode(container& s, ceph::buffer::list::const_iterator& p) {
+    uint32_t num;
+    denc(num, p);
+    decode_nohead(num, s, p);
+  }
+
+  // nohead
+  static void encode_nohead(const container& s, ceph::buffer::list::contiguous_appender& p,
+                           uint64_t f = 0) {
+    for (const T& e : s) {
+      if constexpr (traits::featured) {
+        denc(e, p, f);
+      } else {
+        denc(e, p);
+      }
+    }
+  }
+  static void decode_nohead(size_t num, container& s,
+                           ceph::buffer::ptr::const_iterator& p,
+                           uint64_t f=0) {
+    s.clear();
+    s.reserve(num);
+    while (num--) {
+      T t;
+      denc(t, p, f);
+      s.push_back(std::move(t));
+    }
+  }
+  template<typename U=T>
+  static std::enable_if_t<!!sizeof(U) && !need_contiguous>
+  decode_nohead(size_t num, container& s,
+               ceph::buffer::list::const_iterator& p) {
+    s.clear();
+    s.reserve(num);
+    while (num--) {
+      T t;
+      denc(t, p);
+      s.push_back(std::move(t));
+    }
+  }
+};
+
 namespace _denc {
   template<typename Container>
   struct setlike_details : public container_details_base<Container> {