// // immer: immutable data structures for C++ // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente // // This software is distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt // #pragma once #include #include #include #include namespace immer { namespace detail { namespace arrays { template struct node { using memory = MemoryPolicy; using heap = typename MemoryPolicy::heap::type; using transience = typename memory::transience_t; using refs_t = typename memory::refcount; using ownee_t = typename transience::ownee; using node_t = node; using edit_t = typename transience::edit; struct data_t { aligned_storage_for buffer; }; using impl_t = combine_standard_layout_t; impl_t impl; constexpr static std::size_t sizeof_n(size_t count) { return immer_offsetof(impl_t, d.buffer) + sizeof(T) * (count == 0 ? 1 : count); } refs_t& refs() const { return auto_const_cast(get(impl)); } const ownee_t& ownee() const { return get(impl); } ownee_t& ownee() { return get(impl); } const T* data() const { return reinterpret_cast(&impl.d.buffer); } T* data() { return reinterpret_cast(&impl.d.buffer); } bool can_mutate(edit_t e) const { return refs().unique() || ownee().can_mutate(e); } static void delete_n(node_t* p, size_t sz, size_t cap) { destroy_n(p->data(), sz); heap::deallocate(sizeof_n(cap), p); } static node_t* make_n(size_t n) { return new (heap::allocate(sizeof_n(n))) node_t{}; } static node_t* make_e(edit_t e, size_t n) { auto p = make_n(n); p->ownee() = e; return p; } static node_t* fill_n(size_t n, T v) { auto p = make_n(n); try { std::uninitialized_fill_n(p->data(), n, v); return p; } catch (...) { heap::deallocate(sizeof_n(n), p); throw; } } template , bool> = true> static node_t* copy_n(size_t n, Iter first, Sent last) { auto p = make_n(n); try { uninitialized_copy(first, last, p->data()); return p; } catch (...) { heap::deallocate(sizeof_n(n), p); throw; } } static node_t* copy_n(size_t n, node_t* p, size_t count) { return copy_n(n, p->data(), p->data() + count); } template static node_t* copy_e(edit_t e, size_t n, Iter first, Iter last) { auto p = copy_n(n, first, last); p->ownee() = e; return p; } static node_t* copy_e(edit_t e, size_t n, node_t* p, size_t count) { return copy_e(e, n, p->data(), p->data() + count); } }; } // namespace arrays } // namespace detail } // namespace immer