/*
 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
 *  Copyright (C) 2004-2019 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
 *
 */

#include "config.h"
#include "StringConstructor.h"

#include "Error.h"
#include "JITCode.h"
#include "JSFunction.h"
#include "JSGlobalObject.h"
#include "JSCInlines.h"
#include "StringPrototype.h"
#include <wtf/text/StringBuilder.h>

namespace JSC {

static EncodedJSValue JSC_HOST_CALL stringFromCharCode(JSGlobalObject*, CallFrame*);
static EncodedJSValue JSC_HOST_CALL stringFromCodePoint(JSGlobalObject*, CallFrame*);

}

#include "StringConstructor.lut.h"

namespace JSC {

const ClassInfo StringConstructor::s_info = { "Function", &InternalFunction::s_info, &stringConstructorTable, nullptr, CREATE_METHOD_TABLE(StringConstructor) };

/* Source for StringConstructor.lut.h
@begin stringConstructorTable
  fromCharCode          stringFromCharCode         DontEnum|Function 1 FromCharCodeIntrinsic
  fromCodePoint         stringFromCodePoint        DontEnum|Function 1
  raw                   JSBuiltin                  DontEnum|Function 1
@end
*/

STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(StringConstructor);


static EncodedJSValue JSC_HOST_CALL callStringConstructor(JSGlobalObject*, CallFrame*);
static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(JSGlobalObject*, CallFrame*);

StringConstructor::StringConstructor(VM& vm, Structure* structure)
    : InternalFunction(vm, structure, callStringConstructor, constructWithStringConstructor)
{
}

void StringConstructor::finishCreation(VM& vm, StringPrototype* stringPrototype)
{
    Base::finishCreation(vm, vm.propertyNames->String.string(), NameAdditionMode::WithoutStructureTransition);
    putDirectWithoutTransition(vm, vm.propertyNames->prototype, stringPrototype, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum | PropertyAttribute::DontDelete);
    putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
}

// ------------------------------ Functions --------------------------------

static EncodedJSValue JSC_HOST_CALL stringFromCharCode(JSGlobalObject* globalObject, CallFrame* callFrame)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    unsigned length = callFrame->argumentCount();
    if (LIKELY(length == 1)) {
        scope.release();
        unsigned code = callFrame->uncheckedArgument(0).toUInt32(globalObject);
        // Not checking for an exception here is ok because jsSingleCharacterString will just fetch an unused string if there's an exception.
        return JSValue::encode(jsSingleCharacterString(vm, code));
    }

    LChar* buf8Bit;
    auto impl8Bit = StringImpl::createUninitialized(length, buf8Bit);
    for (unsigned i = 0; i < length; ++i) {
        UChar character = static_cast<UChar>(callFrame->uncheckedArgument(i).toUInt32(globalObject));
        RETURN_IF_EXCEPTION(scope, encodedJSValue());
        if (UNLIKELY(!isLatin1(character))) {
            UChar* buf16Bit;
            auto impl16Bit = StringImpl::createUninitialized(length, buf16Bit);
            StringImpl::copyCharacters(buf16Bit, buf8Bit, i);
            buf16Bit[i] = character;
            ++i;
            for (; i < length; ++i) {
                buf16Bit[i] = static_cast<UChar>(callFrame->uncheckedArgument(i).toUInt32(globalObject));
                RETURN_IF_EXCEPTION(scope, encodedJSValue());
            }
            RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, WTFMove(impl16Bit))));
        }
        buf8Bit[i] = static_cast<LChar>(character);
    }
    RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, WTFMove(impl8Bit))));
}

JSString* JSC_HOST_CALL stringFromCharCode(JSGlobalObject* globalObject, int32_t arg)
{
    return jsSingleCharacterString(globalObject->vm(), arg);
}

static EncodedJSValue JSC_HOST_CALL stringFromCodePoint(JSGlobalObject* globalObject, CallFrame* callFrame)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    unsigned length = callFrame->argumentCount();
    StringBuilder builder;
    builder.reserveCapacity(length);

    for (unsigned i = 0; i < length; ++i) {
        double codePointAsDouble = callFrame->uncheckedArgument(i).toNumber(globalObject);
        RETURN_IF_EXCEPTION(scope, encodedJSValue());

        uint32_t codePoint = static_cast<uint32_t>(codePointAsDouble);

        if (codePoint != codePointAsDouble || codePoint > UCHAR_MAX_VALUE)
            return throwVMError(globalObject, scope, createRangeError(globalObject, "Arguments contain a value that is out of range of code points"_s));

        if (U_IS_BMP(codePoint))
            builder.append(static_cast<UChar>(codePoint));
        else {
            builder.append(U16_LEAD(codePoint));
            builder.append(U16_TRAIL(codePoint));
        }
    }

    RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, builder.toString())));
}

static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(JSGlobalObject* globalObject, CallFrame* callFrame)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    Structure* structure = InternalFunction::createSubclassStructure(globalObject, callFrame->jsCallee(), callFrame->newTarget(), globalObject->stringObjectStructure());
    RETURN_IF_EXCEPTION(scope, encodedJSValue());

    if (!callFrame->argumentCount())
        return JSValue::encode(StringObject::create(vm, structure));
    JSString* str = callFrame->uncheckedArgument(0).toString(globalObject);
    RETURN_IF_EXCEPTION(scope, encodedJSValue());
    return JSValue::encode(StringObject::create(vm, structure, str));
}

JSString* stringConstructor(JSGlobalObject* globalObject, JSValue argument)
{
    VM& vm = globalObject->vm();
    if (argument.isSymbol())
        return jsNontrivialString(vm, asSymbol(argument)->descriptiveString());
    return argument.toString(globalObject);
}

static EncodedJSValue JSC_HOST_CALL callStringConstructor(JSGlobalObject* globalObject, CallFrame* callFrame)
{
    VM& vm = globalObject->vm();
    if (!callFrame->argumentCount())
        return JSValue::encode(jsEmptyString(vm));
    return JSValue::encode(stringConstructor(globalObject, callFrame->uncheckedArgument(0)));
}

} // namespace JSC
