Line data Source code
1 : #pragma once
2 :
3 : #include "BLEAPI.hpp"
4 :
5 : #include <cassert>
6 : #include <functional>
7 : #include <utility>
8 :
9 : #include <AH/Error/Error.hpp>
10 :
11 : BEGIN_CS_NAMESPACE
12 :
13 : struct BLEDataGenerator::Iface {
14 15 : virtual ~Iface() = default;
15 : virtual BLEDataView next() = 0;
16 : virtual Iface *move_into(void *storage) noexcept = 0;
17 :
18 : Iface(const Iface &) = delete;
19 : Iface &operator=(const Iface &) = delete;
20 :
21 : protected:
22 15 : Iface() = default;
23 0 : Iface(Iface &&) = default;
24 : };
25 :
26 : template <class T>
27 : struct BLEDataGenerator::Impl : Iface {
28 : T inst;
29 : template <class... Args>
30 15 : Impl(Args &&...args) : inst {std::forward<Args>(args)...} {}
31 : #if __cplusplus >= 201703L
32 30 : BLEDataView next() override { return std::invoke(inst); }
33 : #else
34 : BLEDataView next() override { return inst(); }
35 : #endif
36 0 : Iface *move_into(void *storage) noexcept override {
37 0 : return new (storage) Impl {std::move(*this)};
38 : }
39 : };
40 :
41 30 : inline BLEDataView BLEDataGenerator::operator()() {
42 30 : assert(instance);
43 30 : return instance->next();
44 : }
45 :
46 15 : inline void BLEDataGenerator::clear() {
47 : #if __cplusplus >= 201402
48 15 : if (auto *inst = std::exchange(instance, nullptr))
49 15 : inst->~Iface();
50 : #else
51 : if (instance)
52 : instance->~Iface();
53 : instance = nullptr;
54 : #endif
55 15 : }
56 :
57 : template <class T, class... Args>
58 15 : BLEDataGenerator::BLEDataGenerator(compat::in_place_type_t<T>, Args &&...args) {
59 : static_assert(sizeof(Impl<T>) <= sizeof(storage), "");
60 : static_assert(alignof(Impl<T>) <= alignof(buffer_align_t), "");
61 15 : instance = new (storage) Impl<T> {std::forward<Args>(args)...};
62 15 : }
63 :
64 : template <class T>
65 15 : BLEDataGenerator::BLEDataGenerator(compat::in_place_t, T &&t)
66 : : BLEDataGenerator(
67 : compat::in_place_type<typename compat::remove_cvref<T>::type>,
68 15 : std::forward<T>(t)) {}
69 :
70 : inline BLEDataGenerator::BLEDataGenerator(BLEDataGenerator &&other) noexcept {
71 : if (other.instance) {
72 : this->instance = other.instance->move_into(this->storage);
73 : other.clear();
74 : }
75 : }
76 :
77 : inline BLEDataGenerator &
78 : BLEDataGenerator::operator=(BLEDataGenerator &&other) noexcept {
79 : clear();
80 : if (other.instance) {
81 : this->instance = other.instance->move_into(this->storage);
82 : other.clear();
83 : }
84 : return *this;
85 : }
86 :
87 : END_CS_NAMESPACE
|