/*
 * 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 UStringImpl_h
#define UStringImpl_h

#include <limits>
#include <wtf/CrossThreadRefCounted.h>
#include <wtf/OwnFastMallocPtr.h>
#include <wtf/PossiblyNull.h>
#include <wtf/StringHashFunctions.h>
#include <wtf/Vector.h>
#include <wtf/unicode/Unicode.h>

namespace JSC {

class IdentifierTable;

typedef OwnFastMallocPtr<const UChar> SharableUChar;
typedef CrossThreadRefCounted<SharableUChar> SharedUChar;

class UStringOrRopeImpl : public Noncopyable {
public:
    bool isRope() { return (m_refCountAndFlags & s_refCountIsRope) == s_refCountIsRope; }
    unsigned length() const { return m_length; }

    void ref() { m_refCountAndFlags += s_refCountIncrement; }
    inline void deref();

protected:
    enum BufferOwnership {
        BufferInternal,
        BufferOwned,
        BufferSubstring,
        BufferShared,
    };

    using Noncopyable::operator new;

    // For SmallStringStorage, which allocates an array and uses an in-place new.
    UStringOrRopeImpl() { }

    UStringOrRopeImpl(unsigned length, BufferOwnership ownership)
        : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership)
        , m_length(length)
    {
        ASSERT(!isRope());
    }

    enum StaticStringConstructType { ConstructStaticString };
    UStringOrRopeImpl(unsigned length, StaticStringConstructType)
        : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned)
        , m_length(length)
    {
        ASSERT(!isRope());
    }

    enum RopeConstructType { ConstructRope };
    UStringOrRopeImpl(RopeConstructType)
        : m_refCountAndFlags(s_refCountIncrement | s_refCountIsRope)
        , m_length(0)
    {
        ASSERT(isRope());
    }

    // The bottom 5 bits hold flags, the top 27 bits hold the ref count.
    // When dereferencing UStringImpls we check for the ref count AND the
    // static bit both being zero - static strings are never deleted.
    static const unsigned s_refCountMask = 0xFFFFFFE0;
    static const unsigned s_refCountIncrement = 0x20;
    static const unsigned s_refCountFlagStatic = 0x10;
    static const unsigned s_refCountFlagShouldReportedCost = 0x8;
    static const unsigned s_refCountFlagIsIdentifier = 0x4;
    static const unsigned s_refCountMaskBufferOwnership = 0x3;
    // Use an otherwise invalid permutation of flags (static & shouldReportedCost -
    // static strings do not set shouldReportedCost in the constructor, and this bit
    // is only ever cleared, not set) to identify objects that are ropes.
    static const unsigned s_refCountIsRope = s_refCountFlagStatic | s_refCountFlagShouldReportedCost;

    unsigned m_refCountAndFlags;
    unsigned m_length;
};

class UStringImpl : public UStringOrRopeImpl {
    friend class CStringTranslator;
    friend class UCharBufferTranslator;
    friend class JIT;
    friend class SmallStringsStorage;
    friend class UStringOrRopeImpl;
    friend void initializeUString();
private:
    // For SmallStringStorage, which allocates an array and uses an in-place new.
    UStringImpl() { }

    // Used to construct static strings, which have an special refCount that can never hit zero.
    // This means that the static string will never be destroyed, which is important because
    // static strings will be shared across threads & ref-counted in a non-threadsafe manner.
    UStringImpl(const UChar* characters, unsigned length, StaticStringConstructType)
        : UStringOrRopeImpl(length, ConstructStaticString)
        , m_data(characters)
        , m_buffer(0)
        , m_hash(0)
    {
        hash();
    }

    // Create a normal string with internal storage (BufferInternal)
    UStringImpl(unsigned length)
        : UStringOrRopeImpl(length, BufferInternal)
        , m_data(reinterpret_cast<UChar*>(this + 1))
        , m_buffer(0)
        , m_hash(0)
    {
        ASSERT(m_data);
        ASSERT(m_length);
    }

    // Create a UStringImpl adopting ownership of the provided buffer (BufferOwned)
    UStringImpl(const UChar* characters, unsigned length)
        : UStringOrRopeImpl(length, BufferOwned)
        , m_data(characters)
        , m_buffer(0)
        , m_hash(0)
    {
        ASSERT(m_data);
        ASSERT(m_length);
    }

    // Used to create new strings that are a substring of an existing UStringImpl (BufferSubstring)
    UStringImpl(const UChar* characters, unsigned length, PassRefPtr<UStringImpl> base)
        : UStringOrRopeImpl(length, BufferSubstring)
        , m_data(characters)
        , m_substringBuffer(base.releaseRef())
        , m_hash(0)
    {
        ASSERT(m_data);
        ASSERT(m_length);
        ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring);
    }

    // Used to construct new strings sharing an existing SharedUChar (BufferShared)
    UStringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
        : UStringOrRopeImpl(length, BufferShared)
        , m_data(characters)
        , m_sharedBuffer(sharedBuffer.releaseRef())
        , m_hash(0)
    {
        ASSERT(m_data);
        ASSERT(m_length);
    }

    // For use only by Identifier's XXXTranslator helpers.
    void setHash(unsigned hash)
    {
        ASSERT(!isStatic());
        ASSERT(!m_hash);
        ASSERT(hash == computeHash(m_data, m_length));
        m_hash = hash;
    }

public:
    ~UStringImpl();

    static PassRefPtr<UStringImpl> create(const UChar*, unsigned length);
    static PassRefPtr<UStringImpl> create(const char*, unsigned length);
    static PassRefPtr<UStringImpl> create(const char*);
    static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar>, const UChar*, unsigned length);
    static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned length)
    {
        ASSERT(rep);
        ASSERT(length <= rep->length());

        if (!length)
            return empty();

        UStringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get();
        return adoptRef(new UStringImpl(rep->m_data + offset, length, ownerRep));
    }

    static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output);
    static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
    {
        if (!length) {
            output = 0;
            return empty();
        }

        if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar)))
            return 0;
        UStringImpl* resultImpl;
        if (!tryFastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)).getValue(resultImpl))
            return 0;
        output = reinterpret_cast<UChar*>(resultImpl + 1);
        return adoptRef(new(resultImpl) UStringImpl(length));
    }

    template<size_t inlineCapacity>
    static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
    {
        if (size_t size = vector.size()) {
            ASSERT(vector.data());
            return adoptRef(new UStringImpl(vector.releaseBuffer(), size));
        }
        return empty();
    }

    SharedUChar* sharedBuffer();
    const UChar* characters() const { return m_data; }

    size_t cost()
    {
        // For substrings, return the cost of the base string.
        if (bufferOwnership() == BufferSubstring)
            return m_substringBuffer->cost();

        if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) {
            m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost;
            return m_length;
        }
        return 0;
    }

    bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; }
    void setIsIdentifier(bool isIdentifier)
    {
        ASSERT(!isStatic());
        if (isIdentifier)
            m_refCountAndFlags |= s_refCountFlagIsIdentifier;
        else
            m_refCountAndFlags &= ~s_refCountFlagIsIdentifier;
    }

    unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; }
    unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
    static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); }
    static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); }
    static unsigned computeHash(const char* data) { return WTF::stringHash(data); }

    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }

    static UStringImpl* empty();

    static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters)
    {
        if (numCharacters <= s_copyCharsInlineCutOff) {
            for (unsigned i = 0; i < numCharacters; ++i)
                destination[i] = source[i];
        } else
            memcpy(destination, source, numCharacters * sizeof(UChar));
    }

private:
    // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings.
    static const unsigned s_copyCharsInlineCutOff = 20;

    BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); }
    bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; }

    const UChar* m_data;
    union {
        void* m_buffer;
        UStringImpl* m_substringBuffer;
        SharedUChar* m_sharedBuffer;
    };
    mutable unsigned m_hash;
};

class URopeImpl : public UStringOrRopeImpl {
    friend class UStringOrRopeImpl;
public:
    // A URopeImpl is composed from a set of smaller strings called Fibers.
    // Each Fiber in a rope is either UStringImpl or another URopeImpl.
    typedef UStringOrRopeImpl* Fiber;

    // Creates a URopeImpl comprising of 'fiberCount' Fibers.
    // The URopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the URopeImpl.
    static PassRefPtr<URopeImpl> tryCreateUninitialized(unsigned fiberCount)
    {
        void* allocation;
        if (tryFastMalloc(sizeof(URopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation))
            return adoptRef(new (allocation) URopeImpl(fiberCount));
        return 0;
    }

    void initializeFiber(unsigned &index, Fiber fiber)
    {
        m_fibers[index++] = fiber;
        fiber->ref();
        m_length += fiber->length();
    }

    unsigned fiberCount() { return m_fiberCount; }
    Fiber& fibers(unsigned index) { return m_fibers[index]; }

    ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); }

private:
    URopeImpl(unsigned fiberCount) : UStringOrRopeImpl(ConstructRope), m_fiberCount(fiberCount) {}

    void destructNonRecursive();
    void derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue);

    bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; }

    unsigned m_fiberCount;
    Fiber m_fibers[1];
};

inline void UStringOrRopeImpl::deref()
{
    if (isRope())
        static_cast<URopeImpl*>(this)->deref();
    else
        static_cast<UStringImpl*>(this)->deref();
}

bool equal(const UStringImpl*, const UStringImpl*);

}

#endif
