/*
 *  Copyright (C) 2018 Igalia S.L
 *  Copyright (C) 2018 Metrological Group B.V.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "config.h"
#include "GstAllocatorFastMalloc.h"

#include <gst/gst.h>
#include <wtf/FastMalloc.h>

typedef struct {
    GstMemory base;

    uint8_t* data;
} GstMemoryFastMalloc;

typedef struct {
    GstAllocator parent;
} GstAllocatorFastMalloc;

typedef struct {
    GstAllocatorClass parent;
} GstAllocatorFastMallocClass;

G_DEFINE_TYPE(GstAllocatorFastMalloc, gst_allocator_fast_malloc, GST_TYPE_ALLOCATOR)

static GstMemoryFastMalloc* gstMemoryFastMallocNew(GstAllocator* allocator, gsize size, gsize alignment, gsize offset, gsize padding, GstMemoryFlags flags)
{
    // alignment should be a (power-of-two - 1).
    alignment |= gst_memory_alignment;
    ASSERT(!((alignment + 1) & alignment));

    gsize headerSize = (sizeof(GstMemoryFastMalloc) + alignment) & ~alignment;
    gsize allocationSize = offset + size + padding;
    auto* memory = static_cast<GstMemoryFastMalloc*>(tryFastAlignedMalloc(alignment + 1, headerSize + allocationSize));
    if (!memory)
        return nullptr;

    memory->data = reinterpret_cast<uint8_t*>(memory) + headerSize;

    if (offset && (flags & GST_MEMORY_FLAG_ZERO_PREFIXED))
        std::memset(memory->data, 0, offset);
    if (padding && (flags & GST_MEMORY_FLAG_ZERO_PADDED))
        std::memset(memory->data + offset + size, 0, padding);

    gst_memory_init(GST_MEMORY_CAST(memory), flags, allocator, nullptr, allocationSize, alignment, offset, size);

    return memory;
}

static GstMemory* gstAllocatorFastMallocAlloc(GstAllocator* allocator, gsize size, GstAllocationParams* params)
{
    ASSERT(G_TYPE_CHECK_INSTANCE_TYPE(allocator, gst_allocator_fast_malloc_get_type()));

    return GST_MEMORY_CAST(gstMemoryFastMallocNew(allocator, size, params->align, params->prefix, params->padding, params->flags));
}

static void gstAllocatorFastMallocFree(GstAllocator* allocator, GstMemory* memory)
{
#if !ASSERT_DISABLED
    ASSERT(G_TYPE_CHECK_INSTANCE_TYPE(allocator, gst_allocator_fast_malloc_get_type()));
#else
    UNUSED_PARAM(allocator);
#endif

    fastAlignedFree(memory);
}

static gpointer gstAllocatorFastMallocMemMap(GstMemoryFastMalloc* memory, gsize, GstMapFlags)
{
    return memory->data;
}

static void gstAllocatorFastMallocMemUnmap(GstMemoryFastMalloc*)
{
}

static GstMemoryFastMalloc* gstAllocatorFastMallocMemCopy(GstMemoryFastMalloc* memory, gssize offset, gsize size)
{
    if (size == static_cast<gsize>(-1))
        size = memory->base.size > static_cast<gsize>(offset) ? memory->base.size - offset : 0;

    auto* copy = gstMemoryFastMallocNew(memory->base.allocator, size, memory->base.align, 0, 0, static_cast<GstMemoryFlags>(0));
    if (!copy)
        return nullptr;

    std::memcpy(copy->data, memory->data + memory->base.offset + offset, size);
    return copy;
}

static GstMemoryFastMalloc* gstAllocatorFastMallocMemShare(GstMemoryFastMalloc* memory, gssize offset, gsize size)
{
    GstMemoryFastMalloc* sharedMemory;
    if (!tryFastMalloc(sizeof(GstMemoryFastMalloc)).getValue(sharedMemory))
        return nullptr;

    sharedMemory->data = memory->data;

    if (size == static_cast<gsize>(-1))
        size = memory->base.size - offset;

    auto* parent = memory->base.parent ? memory->base.parent : GST_MEMORY_CAST(memory);
    gst_memory_init(GST_MEMORY_CAST(sharedMemory),
        static_cast<GstMemoryFlags>(GST_MINI_OBJECT_FLAGS(parent) | GST_MINI_OBJECT_FLAG_LOCK_READONLY),
        memory->base.allocator, parent, memory->base.maxsize, memory->base.align,
        memory->base.offset + offset, size);

    return sharedMemory;
}

static gboolean gstAllocatorFastMallocMemIsSpan(GstMemoryFastMalloc* memory, GstMemoryFastMalloc* other, gsize* offset)
{
    if (offset) {
        auto* parent = reinterpret_cast<GstMemoryFastMalloc*>(memory->base.parent);
        ASSERT(parent);
        *offset = memory->base.offset - parent->base.offset;
    }

    return memory->data + memory->base.offset + memory->base.size == other->data + other->base.offset;
}

static void gst_allocator_fast_malloc_class_init(GstAllocatorFastMallocClass* klass)
{
    auto* gstAllocatorClass = GST_ALLOCATOR_CLASS(klass);
    gstAllocatorClass->alloc = gstAllocatorFastMallocAlloc;
    gstAllocatorClass->free = gstAllocatorFastMallocFree;
}

static void gst_allocator_fast_malloc_init(GstAllocatorFastMalloc* allocator)
{
    auto* baseAllocator = GST_ALLOCATOR_CAST(allocator);

    baseAllocator->mem_type = "FastMalloc";
    baseAllocator->mem_map = reinterpret_cast<GstMemoryMapFunction>(gstAllocatorFastMallocMemMap);
    baseAllocator->mem_unmap = reinterpret_cast<GstMemoryUnmapFunction>(gstAllocatorFastMallocMemUnmap);
    baseAllocator->mem_copy = reinterpret_cast<GstMemoryCopyFunction>(gstAllocatorFastMallocMemCopy);
    baseAllocator->mem_share = reinterpret_cast<GstMemoryShareFunction>(gstAllocatorFastMallocMemShare);
    baseAllocator->mem_is_span = reinterpret_cast<GstMemoryIsSpanFunction>(gstAllocatorFastMallocMemIsSpan);
}
