/*
 * Copyright (C) 2009 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. 
 */

#ifndef JSStringBuilder_h
#define JSStringBuilder_h

#include "ExceptionHelpers.h"
#include "JSString.h"
#include <wtf/Vector.h>

namespace JSC {

// FIXME: Should move the last few callers over from this to WTF::StringBuilder.
class JSStringBuilder {
public:
    JSStringBuilder()
        : m_okay(true)
        , m_is8Bit(true)
    {
    }

    void append(LChar character)
    {
        if (m_is8Bit) {
            m_okay &= buffer8.tryAppend(&character, 1);
            return;
        }
        UChar upconvertedCharacter = character;
        m_okay &= buffer16.tryAppend(&upconvertedCharacter, 1);
    }

    void append(UChar character)
    {
        if (m_is8Bit) {
            if (character < 0x100) {
                LChar narrowedCharacter = character;
                m_okay &= buffer8.tryAppend(&narrowedCharacter, 1);
                return;
            }
            upConvert();
        }
        m_okay &= buffer16.tryAppend(&character, 1);
    }

    void append(const char* str)
    {
        append(reinterpret_cast<const LChar*>(str), strlen(str));
    }

    JSValue build(ExecState* exec)
    {
        if (!m_okay)
            return throwOutOfMemoryError(exec);
        if (m_is8Bit) {
            buffer8.shrinkToFit();
            if (!buffer8.data())
                return throwOutOfMemoryError(exec);
            return jsString(exec, String::adopt(buffer8));
        }
        buffer16.shrinkToFit();
        if (!buffer16.data())
            return throwOutOfMemoryError(exec);
        return jsString(exec, String::adopt(buffer16));
    }

private:
    void append(const LChar* characters, size_t length)
    {
        if (m_is8Bit) {
            m_okay &= buffer8.tryAppend(characters, length);
            return;
        }
        // FIXME: There must be a more efficient way of doing this.
        m_okay &= buffer16.tryReserveCapacity(buffer16.size() + length);
        for (size_t i = 0; i < length; i++) {
            UChar upconvertedCharacter = characters[i];
            m_okay &= buffer16.tryAppend(&upconvertedCharacter, 1);
        }
    }

    void upConvert()
    {
        ASSERT(m_is8Bit);
        size_t len = buffer8.size();

        for (size_t i = 0; i < len; i++)
            buffer16.append(buffer8[i]);

        buffer8.clear();
        m_is8Bit = false;
    }

    Vector<LChar, 64, UnsafeVectorOverflow> buffer8;
    Vector<UChar, 64, UnsafeVectorOverflow> buffer16;
    bool m_okay;
    bool m_is8Bit;
};

template<typename StringType>
inline JSValue jsMakeNontrivialString(ExecState* exec, StringType&& string)
{
    return jsNontrivialString(exec, std::forward<StringType>(string));
}

template<typename StringType, typename... StringTypes>
inline JSValue jsMakeNontrivialString(ExecState* exec, const StringType& string, const StringTypes&... strings)
{
    String result = WTF::tryMakeString(string, strings...);
    if (!result)
        return throwOutOfMemoryError(exec);
    return jsNontrivialString(exec, WTFMove(result));
}

}

#endif
