/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkData.h"
#include "include/core/SkSpan.h"

#include "include/core/SkStream.h"
#include "include/private/SkAssert.h"
#include "include/private/SkMalloc.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkStreamPriv.h"

#include <cstddef>
#include <cstring>
#include <new>

SkData::SkData(SkSpan<std::byte> span, ReleaseProc proc, void* context)
    : fReleaseProc(proc)
    , fReleaseProcContext(context)
    , fSpan(span)
{}

/** This constructor means we are inline with our fPtr's contents.
 *  Thus we set fPtr to point right after this.
 */
SkData::SkData(size_t size)
    : fReleaseProc(nullptr)
    , fReleaseProcContext(nullptr)
    , fSpan{(std::byte*)(this + 1), size}
{}

SkData::~SkData() {
    if (fReleaseProc) {
        fReleaseProc(fSpan.data(), fReleaseProcContext);
    }
}

bool SkData::operator==(const SkData& other) const {
    if (this == &other) {
        return true;
    }
    return size() == other.size() && !sk_careful_memcmp(data(), other.data(), size());
}

size_t SkData::copyRange(size_t offset, size_t length, void* buffer) const {
    size_t available = this->size();
    if (offset >= available || 0 == length) {
        return 0;
    }
    available -= offset;
    if (length > available) {
        length = available;
    }
    SkASSERT(length > 0);

    if (buffer) {
        memcpy(buffer, this->bytes() + offset, length);
    }
    return length;
}


#define RETURN_EMPTY_FOR_ZERO_SIZE(size)    \
    do {                                    \
        if ((size) == 0) {                  \
            return SkData::MakeEmpty();     \
        }                                   \
    } while (false)

#define VALIDATE_SUBSET(size, offset, length)           \
    do {                                                \
        if (offset > size || length > size - offset) {  \
            return nullptr;                             \
        }                                               \
    } while (0)

sk_sp<SkData> SkData::shareSubset(size_t offset, size_t length) {
    VALIDATE_SUBSET(this->size(), offset, length);

    if (offset == 0 && length == this->size()) {
        return sk_ref_sp(this);
    }

    RETURN_EMPTY_FOR_ZERO_SIZE(length);

    this->ref();
    return SkData::MakeWithProc(this->bytes() + offset, length, [](const void*, void* ctx) {
        ((SkData*)ctx)->unref();
    }, this);
}

sk_sp<const SkData> SkData::shareSubset(size_t offset, size_t length) const {
    return const_cast<SkData*>(this)->shareSubset(offset, length);
}

sk_sp<SkData> SkData::copySubset(size_t offset, size_t length) const {
    VALIDATE_SUBSET(this->size(), offset, length);

    return SkData::MakeWithCopy(this->bytes() + offset, length);
}

void SkData::operator delete(void* p) {
    ::operator delete(p);
}

sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
    if (0 == length) {
        return SkData::MakeEmpty();
    }

    const size_t actualLength = length + sizeof(SkData);
    SkASSERT_RELEASE(length < actualLength);  // Check for overflow.

    void* storage = ::operator new (actualLength);
    sk_sp<SkData> data(new (storage) SkData(length));
    if (srcOrNull) {
        memcpy(data->writable_data(), srcOrNull, length);
    }
    return data;
}

void SkData::NoopReleaseProc(const void*, void*) {}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkData> SkData::MakeEmpty() {
    static SkData* empty = new SkData({}, nullptr, nullptr);
    return sk_ref_sp(empty);
}

// assumes fPtr was allocated via sk_malloc
static void sk_free_releaseproc(const void* ptr, void*) {
    sk_free(const_cast<void*>(ptr));
}

sk_sp<SkData> SkData::MakeFromMalloc(const void* data, size_t length) {
    std::byte* ptr = static_cast<std::byte*>(const_cast<void*>(data));
    return sk_sp<SkData>(new SkData({ptr, length}, sk_free_releaseproc, nullptr));
}

sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
    SkASSERT(src);
    return PrivateNewWithCopy(src, length);
}

sk_sp<SkData> SkData::MakeUninitialized(size_t length) {
    return PrivateNewWithCopy(nullptr, length);
}

sk_sp<SkData> SkData::MakeZeroInitialized(size_t length) {
    auto data = MakeUninitialized(length);
    if (length != 0) {
        memset(data->writable_data(), 0, data->size());
    }
    return data;
}

sk_sp<SkData> SkData::MakeWithProc(const void* data, size_t length, ReleaseProc proc, void* ctx) {
    std::byte* ptr = static_cast<std::byte*>(const_cast<void*>(data));
    return sk_sp<SkData>(new SkData({ptr, length}, proc, ctx));
}

// assumes fPtr was allocated with sk_fmmap
static void sk_mmap_releaseproc(const void* addr, void* ctx) {
    size_t length = reinterpret_cast<size_t>(ctx);
    sk_fmunmap(addr, length);
}

sk_sp<SkData> SkData::MakeFromFILE(FILE* f) {
    size_t size;
    void* addr = sk_fmmap(f, &size);
    if (nullptr == addr) {
        return nullptr;
    }

    return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
}

sk_sp<SkData> SkData::MakeFromFileName(const char path[]) {
    FILE* f = path ? sk_fopen(path, kRead_SkFILE_Flag) : nullptr;
    if (nullptr == f) {
        return nullptr;
    }
    auto data = MakeFromFILE(f);
    sk_fclose(f);
    return data;
}

sk_sp<SkData> SkData::MakeFromFD(int fd) {
    size_t size;
    void* addr = sk_fdmmap(fd, &size);
    if (nullptr == addr) {
        return nullptr;
    }
    return SkData::MakeWithProc(addr, size, sk_mmap_releaseproc, reinterpret_cast<void*>(size));
}

sk_sp<SkData> SkData::MakeWithCString(const char cstr[]) {
    size_t size;
    if (nullptr == cstr) {
        cstr = "";
        size = 1;
    } else {
        size = strlen(cstr) + 1;
    }
    return MakeWithCopy(cstr, size);
}

///////////////////////////////////////////////////////////////////////////////

sk_sp<SkData> SkData::MakeFromStream(SkStream* stream, size_t size) {
    // reduce the chance of OOM by checking that the stream has enough bytes to read from before
    // allocating that potentially large buffer.
    if (SkStreamPriv::RemainingLengthIsBelow(stream, size)) {
        return nullptr;
    }
    sk_sp<SkData> data(SkData::MakeUninitialized(size));
    if (stream->read(data->writable_data(), size) != size) {
        return nullptr;
    }
    return data;
}
