/*
 * Copyright (C) 2010-2018 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 <cstring>
#include <wtf/CheckedArithmetic.h>
#include <wtf/text/AtomString.h>
#include <wtf/text/StringView.h>

// This macro is helpful for testing how many intermediate Strings are created while evaluating an
// expression containing operator+.
#ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING
#define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0)
#endif

namespace WTF {

template<> class StringTypeAdapter<char, void> {
public:
    StringTypeAdapter(char character)
        : m_character { character }
    {
    }

    unsigned length() { return 1; }
    bool is8Bit() { return true; }
    template<typename CharacterType> void writeTo(CharacterType* destination) const { *destination = m_character; }

private:
    char m_character;
};

template<> class StringTypeAdapter<UChar, void> {
public:
    StringTypeAdapter(UChar character)
        : m_character { character }
    {
    }

    unsigned length() const { return 1; }
    bool is8Bit() const { return isLatin1(m_character); }

    void writeTo(LChar* destination) const
    {
        ASSERT(is8Bit());
        *destination = m_character;
    }

    void writeTo(UChar* destination) const { *destination = m_character; }

private:
    UChar m_character;
};

template<> class StringTypeAdapter<const LChar*, void> {
public:
    StringTypeAdapter(const LChar* characters)
        : m_characters { characters }
        , m_length { computeLength(characters) }
    {
    }

    unsigned length() const { return m_length; }
    bool is8Bit() const { return true; }
    template<typename CharacterType> void writeTo(CharacterType* destination) const { StringImpl::copyCharacters(destination, m_characters, m_length); }

private:
    static unsigned computeLength(const LChar* characters)
    {
        size_t length = std::strlen(reinterpret_cast<const char*>(characters));
        RELEASE_ASSERT(length <= String::MaxLength);
        return static_cast<unsigned>(length);
    }

    const LChar* m_characters;
    unsigned m_length;
};

template<> class StringTypeAdapter<const UChar*, void> {
public:
    StringTypeAdapter(const UChar* characters)
        : m_characters { characters }
        , m_length { computeLength(characters) }
    {
    }

    unsigned length() const { return m_length; }
    bool is8Bit() const { return !m_length; }
    void writeTo(LChar*) const { ASSERT(!m_length); }
    void writeTo(UChar* destination) const { StringImpl::copyCharacters(destination, m_characters, m_length); }

private:
    static unsigned computeLength(const UChar* characters)
    {
        size_t length = 0;
        while (characters[length])
            ++length;
        RELEASE_ASSERT(length <= String::MaxLength);
        return static_cast<unsigned>(length);
    }

    const UChar* m_characters;
    unsigned m_length;
};

template<> class StringTypeAdapter<const char*, void> : public StringTypeAdapter<const LChar*, void> {
public:
    StringTypeAdapter(const char* characters)
        : StringTypeAdapter<const LChar*, void> { reinterpret_cast<const LChar*>(characters) }
    {
    }
};

template<> class StringTypeAdapter<char*, void> : public StringTypeAdapter<const char*, void> {
public:
    StringTypeAdapter(const char* characters)
        : StringTypeAdapter<const char*, void> { characters }
    {
    }
};

template<> class StringTypeAdapter<ASCIILiteral, void> : public StringTypeAdapter<const char*, void> {
public:
    StringTypeAdapter(ASCIILiteral characters)
        : StringTypeAdapter<const char*, void> { characters }
    {
    }
};

template<> class StringTypeAdapter<Vector<char>, void> {
public:
    StringTypeAdapter(const Vector<char>& vector)
        : m_vector { vector }
    {
    }

    size_t length() const { return m_vector.size(); }
    bool is8Bit() const { return true; }
    template<typename CharacterType> void writeTo(CharacterType* destination) const { StringImpl::copyCharacters(destination, characters(), length()); }

private:
    const LChar* characters() const
    {
        return reinterpret_cast<const LChar*>(m_vector.data());
    }

    const Vector<char>& m_vector;
};

template<> class StringTypeAdapter<String, void> {
public:
    StringTypeAdapter(const String& string)
        : m_string { string }
    {
    }

    unsigned length() const { return m_string.length(); }
    bool is8Bit() const { return m_string.isNull() || m_string.is8Bit(); }
    template<typename CharacterType> void writeTo(CharacterType* destination) const
    {
        StringView { m_string }.getCharactersWithUpconvert(destination);
        WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING();
    }

private:
    const String& m_string;
};

template<> class StringTypeAdapter<AtomString, void> : public StringTypeAdapter<String, void> {
public:
    StringTypeAdapter(const AtomString& string)
        : StringTypeAdapter<String, void> { string.string() }
    {
    }
};

template<typename UnderlyingElementType> struct PaddingSpecification {
    LChar character;
    unsigned length;
    UnderlyingElementType underlyingElement;
};

template<typename UnderlyingElementType> PaddingSpecification<UnderlyingElementType> pad(char character, unsigned length, UnderlyingElementType element)
{
    return { static_cast<LChar>(character), length, element };
}

template<typename UnderlyingElementType> class StringTypeAdapter<PaddingSpecification<UnderlyingElementType>> {
public:
    StringTypeAdapter(const PaddingSpecification<UnderlyingElementType>& padding)
        : m_padding { padding }
        , m_underlyingAdapter { m_padding.underlyingElement }
    {
    }

    unsigned length() const { return std::max(m_padding.length, m_underlyingAdapter.length()); }
    bool is8Bit() const { return m_underlyingAdapter.is8Bit(); }
    template<typename CharacterType> void writeTo(CharacterType* destination) const
    {
        unsigned underlyingLength = m_underlyingAdapter.length();
        unsigned count = 0;
        if (underlyingLength < m_padding.length) {
            count = m_padding.length - underlyingLength;
            for (unsigned i = 0; i < count; ++i)
                destination[i] = m_padding.character;
        }
        m_underlyingAdapter.writeTo(destination + count);
    }

private:
    const PaddingSpecification<UnderlyingElementType>& m_padding;
    StringTypeAdapter<UnderlyingElementType> m_underlyingAdapter;
};

template<unsigned N>
struct Indentation {
    unsigned operator++() { return ++value; }
    unsigned operator++(int) { return value++; }
    unsigned operator--() { return --value; }
    unsigned operator--(int) { return value--; }

    unsigned value { 0 };
};


template<unsigned N>
struct IndentationScope {
    IndentationScope(Indentation<N>& indentation)
        : m_indentation(indentation)
    {
        ++m_indentation;
    }
    ~IndentationScope()
    {
        --m_indentation;
    }

    Indentation<N>& m_indentation;
};

template<unsigned N> class StringTypeAdapter<Indentation<N>, void> {
public:
    StringTypeAdapter(Indentation<N> indentation)
        : m_indentation { indentation }
    {
    }

    unsigned length()
    {
        return m_indentation.value * N;
    }

    bool is8Bit()
    {
        return true;
    }

    template<typename CharacterType> void writeTo(CharacterType* destination)
    {
        std::fill_n(destination, m_indentation.value * N, ' ');
    }

private:
    Indentation<N> m_indentation;
};

struct ASCIICaseConverter {
    StringView::CaseConvertType type;
    StringView string;
};

inline ASCIICaseConverter lowercase(const StringView& stringView)
{
    return { StringView::CaseConvertType::Lower, stringView };
}

inline ASCIICaseConverter uppercase(const StringView& stringView)
{
    return { StringView::CaseConvertType::Upper, stringView };
}

template<> class StringTypeAdapter<ASCIICaseConverter, void> {
public:
    StringTypeAdapter(const ASCIICaseConverter& converter)
        : m_converter { converter }
    {
    }

    unsigned length() const { return m_converter.string.length(); }
    bool is8Bit() const { return m_converter.string.is8Bit(); }
    template<typename CharacterType> void writeTo(CharacterType* destination) const
    {
        m_converter.string.getCharactersWithASCIICase(m_converter.type, destination);
    }

private:
    const ASCIICaseConverter& m_converter;
};

template<typename Adapter>
inline bool are8Bit(Adapter adapter)
{
    return adapter.is8Bit();
}

template<typename Adapter, typename... Adapters>
inline bool are8Bit(Adapter adapter, Adapters ...adapters)
{
    return adapter.is8Bit() && are8Bit(adapters...);
}

template<typename ResultType, typename Adapter>
inline void stringTypeAdapterAccumulator(ResultType* result, Adapter adapter)
{
    adapter.writeTo(result);
}

template<typename ResultType, typename Adapter, typename... Adapters>
inline void stringTypeAdapterAccumulator(ResultType* result, Adapter adapter, Adapters ...adapters)
{
    adapter.writeTo(result);
    stringTypeAdapterAccumulator(result + adapter.length(), adapters...);
}

template<typename StringTypeAdapter, typename... StringTypeAdapters>
String tryMakeStringFromAdapters(StringTypeAdapter adapter, StringTypeAdapters ...adapters)
{
    static_assert(String::MaxLength == std::numeric_limits<int32_t>::max(), "");
    auto sum = checkedSum<int32_t>(adapter.length(), adapters.length()...);
    if (sum.hasOverflowed())
        return String();

    unsigned length = sum.unsafeGet();
    ASSERT(length <= String::MaxLength);
    if (are8Bit(adapter, adapters...)) {
        LChar* buffer;
        RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
        if (!resultImpl)
            return String();

        stringTypeAdapterAccumulator(buffer, adapter, adapters...);

        return resultImpl;
    }

    UChar* buffer;
    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
    if (!resultImpl)
        return String();

    stringTypeAdapterAccumulator(buffer, adapter, adapters...);

    return resultImpl;
}

template<typename... StringTypes>
String tryMakeString(StringTypes ...strings)
{
    return tryMakeStringFromAdapters(StringTypeAdapter<StringTypes>(strings)...);
}

template<typename... StringTypes>
String makeString(StringTypes... strings)
{
    String result = tryMakeString(strings...);
    if (!result)
        CRASH();
    return result;
}

} // namespace WTF

using WTF::Indentation;
using WTF::IndentationScope;
using WTF::makeString;
using WTF::pad;
using WTF::lowercase;
using WTF::tryMakeString;
using WTF::uppercase;

#include <wtf/text/StringOperators.h>
