/*
 * Copyright (C) 2012, 2014 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 "PropertyStorage.h"

namespace JSC {

class ArrayBuffer;
class Butterfly;
class LLIntOffsetsExtractor;
class Structure;
struct ArrayStorage;

class IndexingHeader {
public:
    // Define the maximum storage vector length to be 2^32 / sizeof(JSValue) / 2 to ensure that
    // there is no risk of overflow.
    static constexpr unsigned maximumLength = 0x10000000;
    
    static ptrdiff_t offsetOfIndexingHeader() { return -static_cast<ptrdiff_t>(sizeof(IndexingHeader)); }
    
    static ptrdiff_t offsetOfArrayBuffer() { return OBJECT_OFFSETOF(IndexingHeader, u.typedArray.buffer); }
    static ptrdiff_t offsetOfPublicLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.publicLength); }
    static ptrdiff_t offsetOfVectorLength() { return OBJECT_OFFSETOF(IndexingHeader, u.lengths.vectorLength); }
    
    IndexingHeader()
    {
        u.lengths.publicLength = 0;
        u.lengths.vectorLength = 0;
    }
    
    uint32_t vectorLength() const { return u.lengths.vectorLength; }
    
    void setVectorLength(uint32_t length)
    {
        RELEASE_ASSERT(length <= maximumLength);
        u.lengths.vectorLength = length;
    }
    
    uint32_t publicLength() const { return u.lengths.publicLength; }
    void setPublicLength(uint32_t auxWord) { u.lengths.publicLength = auxWord; }
    
    ArrayBuffer* arrayBuffer() { return u.typedArray.buffer; }
    void setArrayBuffer(ArrayBuffer* buffer) { u.typedArray.buffer = buffer; }
    
    static IndexingHeader* from(Butterfly* butterfly)
    {
        return reinterpret_cast<IndexingHeader*>(butterfly) - 1;
    }
    
    static const IndexingHeader* from(const Butterfly* butterfly)
    {
        return reinterpret_cast<const IndexingHeader*>(butterfly) - 1;
    }
    
    static IndexingHeader* from(ArrayStorage* arrayStorage)
    {
        return const_cast<IndexingHeader*>(from(const_cast<const ArrayStorage*>(arrayStorage)));
    }
    
    static const IndexingHeader* from(const ArrayStorage* arrayStorage)
    {
        return reinterpret_cast<const IndexingHeader*>(arrayStorage) - 1;
    }
    
    static IndexingHeader* fromEndOf(PropertyStorage propertyStorage)
    {
        return reinterpret_cast<IndexingHeader*>(propertyStorage);
    }
    
    PropertyStorage propertyStorage()
    {
        return reinterpret_cast_ptr<PropertyStorage>(this);
    }
    
    ConstPropertyStorage propertyStorage() const
    {
        return reinterpret_cast_ptr<ConstPropertyStorage>(this);
    }
    
    ArrayStorage* arrayStorage()
    {
        return reinterpret_cast<ArrayStorage*>(this + 1);
    }
    
    Butterfly* butterfly()
    {
        return reinterpret_cast<Butterfly*>(this + 1);
    }
    
    // These methods are not standalone in the sense that they cannot be
    // used on a copy of the IndexingHeader.
    size_t preCapacity(Structure*);
    size_t indexingPayloadSizeInBytes(Structure*);
    
private:
    friend class LLIntOffsetsExtractor;

    union {
        struct {
            // FIXME: vectorLength should be least significant, so that it's really hard to craft a pointer by
            // mucking with the butterfly.
            // https://bugs.webkit.org/show_bug.cgi?id=174927
            uint32_t publicLength; // The meaning of this field depends on the array type, but for all JSArrays we rely on this being the publicly visible length (array.length).
            uint32_t vectorLength; // The length of the indexed property storage. The actual size of the storage depends on this, and the type.
        } lengths;
        
        struct {
            ArrayBuffer* buffer;
        } typedArray;
    } u;
};

} // namespace JSC
