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