/*
 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "config.h"
#include <wtf/text/AtomString.h>

#include <mutex>
#include <wtf/MainThread.h>
#include <wtf/text/IntegerToStringConversion.h>

#include <wtf/dtoa.h>

namespace WTF {

template<AtomString::CaseConvertType type>
ALWAYS_INLINE AtomString AtomString::convertASCIICase() const
{
    StringImpl* impl = this->impl();
    if (UNLIKELY(!impl))
        return nullAtom();

    // Convert short strings without allocating a new StringImpl, since
    // there's a good chance these strings are already in the atom
    // string table and so no memory allocation will be required.
    unsigned length;
    const unsigned localBufferSize = 100;
    if (impl->is8Bit() && (length = impl->length()) <= localBufferSize) {
        const LChar* characters = impl->characters8();
        unsigned failingIndex;
        for (unsigned i = 0; i < length; ++i) {
            if (type == CaseConvertType::Lower ? UNLIKELY(isASCIIUpper(characters[i])) : LIKELY(isASCIILower(characters[i]))) {
                failingIndex = i;
                goto SlowPath;
            }
        }
        return *this;
SlowPath:
        LChar localBuffer[localBufferSize];
        for (unsigned i = 0; i < failingIndex; ++i)
            localBuffer[i] = characters[i];
        for (unsigned i = failingIndex; i < length; ++i)
            localBuffer[i] = type == CaseConvertType::Lower ? toASCIILower(characters[i]) : toASCIIUpper(characters[i]);
        return AtomString(localBuffer, length);
    }

    Ref<StringImpl> convertedString = type == CaseConvertType::Lower ? impl->convertToASCIILowercase() : impl->convertToASCIIUppercase();
    if (LIKELY(convertedString.ptr() == impl))
        return *this;

    AtomString result;
    result.m_string = AtomStringImpl::add(convertedString.ptr());
    return result;
}

AtomString AtomString::convertToASCIILowercase() const
{
    return convertASCIICase<CaseConvertType::Lower>();
}

AtomString AtomString::convertToASCIIUppercase() const
{
    return convertASCIICase<CaseConvertType::Upper>();
}

AtomString AtomString::number(int number)
{
    return numberToStringSigned<AtomString>(number);
}

AtomString AtomString::number(unsigned number)
{
    return numberToStringUnsigned<AtomString>(number);
}

AtomString AtomString::number(unsigned long number)
{
    return numberToStringUnsigned<AtomString>(number);
}

AtomString AtomString::number(unsigned long long number)
{
    return numberToStringUnsigned<AtomString>(number);
}

AtomString AtomString::number(float number)
{
    NumberToStringBuffer buffer;
    return numberToString(number, buffer);
}

AtomString AtomString::number(double number)
{
    NumberToStringBuffer buffer;
    return numberToString(number, buffer);
}

AtomString AtomString::fromUTF8Internal(const char* start, const char* end)
{
    ASSERT(start);

    // Caller needs to handle empty string.
    ASSERT(!end || end > start);
    ASSERT(end || start[0]);

    return AtomStringImpl::addUTF8(start, end ? end : start + std::strlen(start));
}

#ifndef NDEBUG

void AtomString::show() const
{
    m_string.show();
}

#endif

WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomString> nullAtomData;
WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomString> emptyAtomData;
WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomString> starAtomData;
WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomString> xmlAtomData;
WTF_EXPORT_PRIVATE LazyNeverDestroyed<AtomString> xmlnsAtomData;

void AtomString::init()
{
    static std::once_flag initializeKey;
    std::call_once(initializeKey, [] {
        // Initialization is not thread safe, so this function must be called from the main thread first.
        ASSERT(isUIThread());

        nullAtomData.construct();
        emptyAtomData.construct("");
        starAtomData.construct("*", AtomString::ConstructFromLiteral);
        xmlAtomData.construct("xml", AtomString::ConstructFromLiteral);
        xmlnsAtomData.construct("xmlns", AtomString::ConstructFromLiteral);
    });
}

} // namespace WTF
