/*
 * 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 2018 Danny Robson <danny@nerdcruft.net>
 */

#pragma once

#include "../view.hpp"

#include <cstddef>
#include <cstdlib>

#if defined(PLATFORM_WIN32)
inline int
posix_memalign (void **ptr, std::size_t align, std::size_t size)
{
    *ptr = _aligned_malloc (size, align);
    return *ptr ? 0 : errno;
}
#endif

namespace cruft::alloc {
    class malloc {
    public:
        template <typename T>
        cruft::view<T*> allocate (size_t count)
        {
            return {
                reinterpret_cast<T*> (malloc (sizeof (T) * count)),
                count
            };
        }

        template <typename T>
        cruft::view<T*>
        allocate (size_t count, size_t align)
        {
            void* ptr;
            auto err = posix_memalign (&ptr, align, sizeof (T) * count);
            if (err or !ptr)
                throw std::bad_alloc ();

            return { reinterpret_cast<T*> (ptr), count };
        }

        template <typename T>
        void
        deallocate (cruft::view<std::byte*> ptr)
        {
            ::free (ptr.data ());
        }
    };
}