/*
 *  Copyright (C) 2008-2021 Apple Inc. All Rights Reserved.
 *
 *  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
 *
 */

#pragma once

#include "ButterflyInlines.h"
#include "GCDeferralContextInlines.h"
#include "JSArray.h"
#include "JSCInlines.h"
#include "JSGlobalObject.h"
#include "ObjectConstructor.h"
#include "RegExpInlines.h"
#include "RegExpObject.h"

namespace JSC {

static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
static const PropertyOffset RegExpMatchesArrayGroupsPropertyOffset = 102;
static const PropertyOffset RegExpMatchesArrayIndicesPropertyOffset = 103;
static const PropertyOffset RegExpMatchesIndicesGroupsPropertyOffset = 100;

ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
{
    VM& vm = scope.vm();
    unsigned vectorLength = initialLength;
    if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
        return nullptr;

    const bool hasIndexingHeader = true;
    Butterfly* butterfly = Butterfly::tryCreateUninitialized(vm, nullptr, 0, structure->outOfLineCapacity(), hasIndexingHeader, vectorLength * sizeof(EncodedJSValue), deferralContext);
    if (UNLIKELY(!butterfly))
        return nullptr;

    butterfly->setVectorLength(vectorLength);
    butterfly->setPublicLength(initialLength);

    for (unsigned i = initialLength; i < vectorLength; ++i)
        butterfly->contiguous().atUnsafe(i).clear();

    JSArray* result = JSArray::createWithButterfly(vm, deferralContext, structure, butterfly);

    scope.notifyAllocated(result);
    return result;
}

ALWAYS_INLINE JSArray* createRegExpMatchesArray(
    VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue,
    RegExp* regExp, unsigned startOffset, MatchResult& result)
{
    if constexpr (validateDFGDoesGC)
        vm.verifyCanGC();

    Vector<int, 32> subpatternResults;
    int position = regExp->matchInline(globalObject, vm, inputValue, startOffset, subpatternResults);
    if (position == -1) {
        result = MatchResult::failed();
        return nullptr;
    }

    result.start = position;
    result.end = subpatternResults[1];
    
    JSArray* array;
    JSArray* indicesArray = nullptr;

    // FIXME: This should handle array allocation errors gracefully.
    // https://bugs.webkit.org/show_bug.cgi?id=155144
    
    unsigned numSubpatterns = regExp->numSubpatterns();
    bool hasNamedCaptures = regExp->hasNamedCaptures();
    bool createIndices = regExp->hasIndices();
    JSObject* groups = hasNamedCaptures ? constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()) : nullptr;
    Structure* matchStructure = createIndices ? globalObject->regExpMatchesArrayWithIndicesStructure() : globalObject->regExpMatchesArrayStructure();

    JSObject* indicesGroups = createIndices && hasNamedCaptures ? constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()) : nullptr;

    auto setProperties = [&] () {
        array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start));
        array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
        array->putDirect(vm, RegExpMatchesArrayGroupsPropertyOffset, hasNamedCaptures ? groups : jsUndefined());

        ASSERT(!array->butterfly()->indexingHeader()->preCapacity(matchStructure));
        auto capacity = matchStructure->outOfLineCapacity();
        auto size = matchStructure->outOfLineSize();
        gcSafeZeroMemory(static_cast<JSValue*>(array->butterfly()->base(0, capacity)), (capacity - size) * sizeof(JSValue));

        if (createIndices) {
            array->putDirect(vm, RegExpMatchesArrayIndicesPropertyOffset, indicesArray);

            Structure* indicesStructure = globalObject->regExpMatchesIndicesArrayStructure();

            indicesArray->putDirect(vm, RegExpMatchesIndicesGroupsPropertyOffset, indicesGroups ? indicesGroups : jsUndefined());

            ASSERT(!indicesArray->butterfly()->indexingHeader()->preCapacity(indicesStructure));
            auto indicesCapacity = indicesStructure->outOfLineCapacity();
            auto indicesSize = indicesStructure->outOfLineSize();
            gcSafeZeroMemory(static_cast<JSValue*>(indicesArray->butterfly()->base(0, indicesCapacity)), (indicesCapacity - indicesSize) * sizeof(JSValue));
        }
    };

    auto createIndexArray = [&] (GCDeferralContext& deferralContext, int start, int end) {
        ObjectInitializationScope scope(vm);

        JSArray* result = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 2);
        result->initializeIndexWithoutBarrier(scope, 0, jsNumber(start));
        result->initializeIndexWithoutBarrier(scope, 1, jsNumber(end));
        
        return result;
    };

    if (UNLIKELY(globalObject->isHavingABadTime())) {
        GCDeferralContext deferralContext(vm);
        ObjectInitializationScope matchesArrayScope(vm);
        ObjectInitializationScope indicesArrayScope(vm);
        array = JSArray::tryCreateUninitializedRestricted(matchesArrayScope, &deferralContext, matchStructure, numSubpatterns + 1);

        if (createIndices)
            indicesArray = JSArray::tryCreateUninitializedRestricted(indicesArrayScope, &deferralContext, globalObject->regExpMatchesIndicesArrayStructure(), numSubpatterns + 1);

        // FIXME: we should probably throw an out of memory error here, but
        // when making this change we should check that all clients of this
        // function will correctly handle an exception being thrown from here.
        // https://bugs.webkit.org/show_bug.cgi?id=169786
        RELEASE_ASSERT(array);

        setProperties();
        
        array->initializeIndexWithoutBarrier(matchesArrayScope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));

        for (unsigned i = 1; i <= numSubpatterns; ++i) {
            int start = subpatternResults[2 * i];
            JSValue value;
            if (start >= 0)
                value = jsSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
            else
                value = jsUndefined();
            array->initializeIndexWithoutBarrier(matchesArrayScope, i, value);
        }

        if (createIndices) {
            for (unsigned i = 0; i <= numSubpatterns; ++i) {
                int start = subpatternResults[2 * i];
                JSValue value;
                if (start >= 0)
                    indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, createIndexArray(deferralContext, start, subpatternResults[2 * i + 1]));
                else
                    indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, jsUndefined());
            }
        }
    } else {
        GCDeferralContext deferralContext(vm);
        ObjectInitializationScope matchesArrayScope(vm);
        ObjectInitializationScope indicesArrayScope(vm);
        array = tryCreateUninitializedRegExpMatchesArray(matchesArrayScope, &deferralContext, matchStructure, numSubpatterns + 1);

        if (createIndices)
            indicesArray = tryCreateUninitializedRegExpMatchesArray(indicesArrayScope, &deferralContext, globalObject->regExpMatchesIndicesArrayStructure(), numSubpatterns + 1);

        // FIXME: we should probably throw an out of memory error here, but
        // when making this change we should check that all clients of this
        // function will correctly handle an exception being thrown from here.
        // https://bugs.webkit.org/show_bug.cgi?id=169786
        RELEASE_ASSERT(array);
        
        setProperties();
        
        array->initializeIndexWithoutBarrier(matchesArrayScope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);
        
        for (unsigned i = 1; i <= numSubpatterns; ++i) {
            int start = subpatternResults[2 * i];
            JSValue value;
            if (start >= 0)
                value = jsSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
            else
                value = jsUndefined();
            array->initializeIndexWithoutBarrier(matchesArrayScope, i, value, ArrayWithContiguous);
        }

        if (createIndices) {
            for (unsigned i = 0; i <= numSubpatterns; ++i) {
                int start = subpatternResults[2 * i];
                JSValue value;
                if (start >= 0)
                    indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, createIndexArray(deferralContext, start, subpatternResults[2 * i + 1]));
                else
                    indicesArray->initializeIndexWithoutBarrier(indicesArrayScope, i, jsUndefined());
            }
        }
    }

    // Now the object is safe to scan by GC.

    // We initialize the groups and indices objects late as they could allocate, which with the current API could cause
    // allocations.
    if (hasNamedCaptures) {
        for (unsigned i = 1; i <= numSubpatterns; ++i) {
            String groupName = regExp->getCaptureGroupName(i);
            if (!groupName.isEmpty()) {
                groups->putDirect(vm, Identifier::fromString(vm, groupName), array->getIndexQuickly(i));
                if (createIndices)
                    indicesGroups->putDirect(vm, Identifier::fromString(vm, groupName), indicesArray->getIndexQuickly(i));
            }
        }
    }

    return array;
}

inline JSArray* createRegExpMatchesArray(JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset)
{
    VM& vm = getVM(globalObject);
    auto scope = DECLARE_THROW_SCOPE(vm);

    MatchResult ignoredResult;
    String input = string->value(globalObject);
    RETURN_IF_EXCEPTION(scope, { });

    RELEASE_AND_RETURN(scope, createRegExpMatchesArray(vm, globalObject, string, input, regExp, startOffset, ignoredResult));
}
JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*);
Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*);
Structure* createRegExpMatchesArrayWithIndicesStructure(VM&, JSGlobalObject*);
Structure* createRegExpMatchesIndicesArrayStructure(VM&, JSGlobalObject*);
Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*);
Structure* createRegExpMatchesArrayWithIndicesSlowPutStructure(VM&, JSGlobalObject*);
Structure* createRegExpMatchesIndicesArraySlowPutStructure(VM&, JSGlobalObject*);

} // namespace JSC
