/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2015-2018 Danny Robson <danny@nerdcruft.net>
 */

#pragma once

#include "../view.hpp"

#include <cstddef>
#include <utility>

// C++11 allocator concept conformant(ish) allocator adaptor, going from our
// allocator interface to that of the STL and friends.
namespace cruft::alloc {
    template <typename ValueT, typename BackingT>
    class allocator {
    public:
        typedef ValueT value_type;


        template <typename ...Args>
        explicit allocator (Args&& ...args):
            m_backing (std::forward<Args> (args)...)
        { ; }


        cruft::view<ValueT*>
        allocate (size_t count)
        {
            return {
                reinterpret_cast<ValueT*> (
                    m_backing.template allocate (
                        sizeof (ValueT) * count,
                        alignof (ValueT)
                    )
                ),
                count
            };
        }


        void
        deallocate (ValueT *t, size_t count)
        {
            return m_backing.template deallocate (t, sizeof (ValueT) * count);
        }


    private:
        BackingT &m_backing;
    };


    ///////////////////////////////////////////////////////////////////////////
    // convenience type-inferring constructor for allocators.
    template <typename ValueT, typename BackingT>
    auto
    make_allocator (BackingT &backing)
    {
        return allocator<ValueT,BackingT> (backing);
    }
}