/*
 * Copyright (C) 2009-2021 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#pragma once

#include "ArrayBuffer.h"
#include "TypedArrayType.h"
#include <algorithm>
#include <limits.h>
#include <wtf/CheckedArithmetic.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>

namespace JSC {

class JSArrayBufferView;
class JSGlobalObject;
class CallFrame;

class ArrayBufferView : public RefCounted<ArrayBufferView> {
public:
    virtual TypedArrayType getType() const = 0;

    bool isDetached() const
    {
        return !m_buffer || m_buffer->isDetached();
    }
    
    RefPtr<ArrayBuffer> possiblySharedBuffer() const
    {
        if (isDetached())
            return nullptr;
        return m_buffer;
    }
    
    RefPtr<ArrayBuffer> unsharedBuffer() const
    {
        RefPtr<ArrayBuffer> result = possiblySharedBuffer();
        RELEASE_ASSERT(!result->isShared());
        return result;
    }
    
    bool isShared() const
    {
        if (isDetached())
            return false;
        return m_buffer->isShared();
    }

    void* baseAddress() const
    {
        if (isDetached())
            return nullptr;
        return m_baseAddress.getMayBeNull(byteLength());
    }

    void* data() const { return baseAddress(); }

    size_t byteOffset() const
    {
        if (isDetached())
            return 0;
        return m_byteOffset;
    }

    size_t byteLength() const { return m_byteLength; }

    JS_EXPORT_PRIVATE void setDetachable(bool);
    bool isDetachable() const { return m_isDetachable; }

    JS_EXPORT_PRIVATE virtual ~ArrayBufferView();

    // Helper to verify byte offset is size aligned.
    static bool verifyByteOffsetAlignment(size_t byteOffset, size_t elementSize)
    {
        return !(byteOffset & (elementSize - 1));
    }

    // Helper to verify that a given sub-range of an ArrayBuffer is within range.
    static bool verifySubRangeLength(const ArrayBuffer& buffer, size_t byteOffset, size_t numElements, unsigned elementSize)
    {
        size_t byteLength = buffer.byteLength();
        if (byteOffset > byteLength)
            return false;
        size_t remainingElements = (byteLength - byteOffset) / static_cast<size_t>(elementSize);
        if (numElements > remainingElements)
            return false;
        return true;
    }
    
    virtual JSArrayBufferView* wrap(JSGlobalObject*, JSGlobalObject*) = 0;
    
protected:
    JS_EXPORT_PRIVATE ArrayBufferView(RefPtr<ArrayBuffer>&&, size_t byteOffset, size_t byteLength);

    inline bool setImpl(ArrayBufferView*, size_t byteOffset);

    inline bool setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset);
    inline bool getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset);

    inline bool zeroRangeImpl(size_t byteOffset, size_t rangeByteLength);

    // Input offset is in number of elements from this array's view;
    // output offset is in number of bytes from the underlying buffer's view.
    template <typename T>
    static void clampOffsetAndNumElements(
        const ArrayBuffer& buffer,
        size_t arrayByteOffset,
        size_t *offset,
        size_t *numElements)
    {
        size_t maxOffset = (std::numeric_limits<size_t>::max() - arrayByteOffset) / sizeof(T);
        if (*offset > maxOffset) {
            *offset = buffer.byteLength();
            *numElements = 0;
            return;
        }
        CheckedSize adjustedOffset = *offset;
        adjustedOffset *= sizeof(T);
        adjustedOffset += arrayByteOffset;
        if (adjustedOffset.hasOverflowed() || adjustedOffset.value() > buffer.byteLength())
            *offset = buffer.byteLength();
        else
            *offset = adjustedOffset.value();
        size_t remainingElements = (buffer.byteLength() - *offset) / sizeof(T);
        *numElements = std::min(remainingElements, *numElements);
    }

#if USE(LARGE_TYPED_ARRAYS)
    uint64_t m_byteOffset : 63;
#else
    uint32_t m_byteOffset : 31;
#endif
    bool m_isDetachable : 1;
    UCPURegister m_byteLength;

    using BaseAddress = CagedPtr<Gigacage::Primitive, void, tagCagedPtr>;
    // This is the address of the ArrayBuffer's storage, plus the byte offset.
    BaseAddress m_baseAddress;

private:
    friend class ArrayBuffer;
    RefPtr<ArrayBuffer> m_buffer;
};

bool ArrayBufferView::setImpl(ArrayBufferView* array, size_t byteOffset)
{
    if (!isSumSmallerThanOrEqual(byteOffset, array->byteLength(), byteLength()))
        return false;

    uint8_t* base = static_cast<uint8_t*>(baseAddress());
    memmove(base + byteOffset, array->baseAddress(), array->byteLength());
    return true;
}

bool ArrayBufferView::setRangeImpl(const void* data, size_t dataByteLength, size_t byteOffset)
{
    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
        return false;

    uint8_t* base = static_cast<uint8_t*>(baseAddress());
    memmove(base + byteOffset, data, dataByteLength);
    return true;
}

bool ArrayBufferView::getRangeImpl(void* destination, size_t dataByteLength, size_t byteOffset)
{
    if (!isSumSmallerThanOrEqual(byteOffset, dataByteLength, byteLength()))
        return false;

    const uint8_t* base = static_cast<const uint8_t*>(baseAddress());
    memmove(destination, base + byteOffset, dataByteLength);
    return true;
}

bool ArrayBufferView::zeroRangeImpl(size_t byteOffset, size_t rangeByteLength)
{
    if (!isSumSmallerThanOrEqual(byteOffset, rangeByteLength, byteLength()))
        return false;

    uint8_t* base = static_cast<uint8_t*>(baseAddress());
    memset(base + byteOffset, 0, rangeByteLength);
    return true;
}

} // namespace JSC

using JSC::ArrayBufferView;
