diff options
author | Vincent Ambo <mail@tazj.in> | 2020-07-15T07·20+0100 |
---|---|---|
committer | Vincent Ambo <mail@tazj.in> | 2020-07-15T07·23+0100 |
commit | 1213b086a1015a662ab7ebd658f784534fd3116a (patch) | |
tree | d3bc8f3b7f40b8b60f0ef6fbd649cf765f4fdfb6 /third_party/immer/immer/detail/arrays/node.hpp | |
parent | 1390827b9ea1e04bc9863e48930bfd16db3b716e (diff) | |
parent | 7f19d641647ac4ef313ed88d6b5c140983ce5436 (diff) |
merge(3p/immer): Subtree merge at 'ad3e3556d' as 'third_party/immer' r/1299
Change-Id: I9636a41ad44b4218293833fd3e9456d9b07c731b
Diffstat (limited to 'third_party/immer/immer/detail/arrays/node.hpp')
-rw-r--r-- | third_party/immer/immer/detail/arrays/node.hpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/third_party/immer/immer/detail/arrays/node.hpp b/third_party/immer/immer/detail/arrays/node.hpp new file mode 100644 index 000000000000..f96a63a9f4af --- /dev/null +++ b/third_party/immer/immer/detail/arrays/node.hpp @@ -0,0 +1,127 @@ +// +// 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 <immer/detail/combine_standard_layout.hpp> +#include <immer/detail/type_traits.hpp> +#include <immer/detail/util.hpp> + +#include <limits> + +namespace immer { +namespace detail { +namespace arrays { + +template <typename T, typename MemoryPolicy> +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<T> buffer; + }; + + using impl_t = combine_standard_layout_t<data_t, refs_t, ownee_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<refs_t>(impl)); } + + const ownee_t& ownee() const { return get<ownee_t>(impl); } + ownee_t& ownee() { return get<ownee_t>(impl); } + + const T* data() const { return reinterpret_cast<const T*>(&impl.d.buffer); } + T* data() { return reinterpret_cast<T*>(&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 <typename Iter, + typename Sent, + std::enable_if_t<detail::compatible_sentinel_v<Iter, Sent>, + 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 <typename Iter> + 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 |