Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef ArrayBuffer_h
     27 #define ArrayBuffer_h
     28 
     29 #include "wtf/ArrayBufferContents.h"
     30 #include "wtf/HashSet.h"
     31 #include "wtf/PassRefPtr.h"
     32 #include "wtf/RefCounted.h"
     33 #include "wtf/Vector.h"
     34 #include "wtf/WTFExport.h"
     35 
     36 namespace WTF {
     37 
     38 class ArrayBuffer;
     39 class ArrayBufferView;
     40 
     41 class WTF_EXPORT ArrayBuffer : public RefCounted<ArrayBuffer> {
     42 public:
     43     static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize);
     44     static inline PassRefPtr<ArrayBuffer> create(ArrayBuffer*);
     45     static inline PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength);
     46     static inline PassRefPtr<ArrayBuffer> create(ArrayBufferContents&);
     47 
     48     // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::getAsArrayBuffer.
     49     static inline PassRefPtr<ArrayBuffer> createUninitialized(unsigned numElements, unsigned elementByteSize);
     50 
     51     inline void* data();
     52     inline const void* data() const;
     53     inline unsigned byteLength() const;
     54 
     55     // Creates a new ArrayBuffer object with copy of bytes in this object
     56     // ranging from |begin| upto but not including |end|.
     57     inline PassRefPtr<ArrayBuffer> slice(int begin, int end) const;
     58     inline PassRefPtr<ArrayBuffer> slice(int begin) const;
     59 
     60     void addView(ArrayBufferView*);
     61     void removeView(ArrayBufferView*);
     62 
     63     bool transfer(ArrayBufferContents&);
     64     bool isNeutered() { return m_isNeutered; }
     65 
     66     void setDeallocationObserver(ArrayBufferDeallocationObserver* observer) { m_contents.setDeallocationObserver(observer); }
     67 
     68     ~ArrayBuffer() { }
     69 
     70 private:
     71     static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy);
     72 
     73     inline ArrayBuffer(ArrayBufferContents&);
     74     inline PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const;
     75     inline unsigned clampIndex(int index) const;
     76     static inline int clampValue(int x, int left, int right);
     77 
     78     ArrayBufferContents m_contents;
     79     ArrayBufferView* m_firstView;
     80     bool m_isNeutered;
     81 };
     82 
     83 int ArrayBuffer::clampValue(int x, int left, int right)
     84 {
     85     ASSERT(left <= right);
     86     if (x < left)
     87         x = left;
     88     if (right < x)
     89         x = right;
     90     return x;
     91 }
     92 
     93 PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize)
     94 {
     95     return create(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize);
     96 }
     97 
     98 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other)
     99 {
    100     return ArrayBuffer::create(other->data(), other->byteLength());
    101 }
    102 
    103 PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength)
    104 {
    105     ArrayBufferContents contents(byteLength, 1, ArrayBufferContents::ZeroInitialize);
    106     if (!contents.data())
    107         return nullptr;
    108     RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents));
    109     memcpy(buffer->data(), source, byteLength);
    110     return buffer.release();
    111 }
    112 
    113 PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents)
    114 {
    115     return adoptRef(new ArrayBuffer(contents));
    116 }
    117 
    118 PassRefPtr<ArrayBuffer> ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize)
    119 {
    120     return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize);
    121 }
    122 
    123 PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy)
    124 {
    125     ArrayBufferContents contents(numElements, elementByteSize, policy);
    126     if (!contents.data())
    127         return nullptr;
    128     return adoptRef(new ArrayBuffer(contents));
    129 }
    130 
    131 ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents)
    132     : m_firstView(0), m_isNeutered(false)
    133 {
    134     contents.transfer(m_contents);
    135 }
    136 
    137 void* ArrayBuffer::data()
    138 {
    139     return m_contents.data();
    140 }
    141 
    142 const void* ArrayBuffer::data() const
    143 {
    144     return m_contents.data();
    145 }
    146 
    147 unsigned ArrayBuffer::byteLength() const
    148 {
    149     return m_contents.sizeInBytes();
    150 }
    151 
    152 PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const
    153 {
    154     return sliceImpl(clampIndex(begin), clampIndex(end));
    155 }
    156 
    157 PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const
    158 {
    159     return sliceImpl(clampIndex(begin), byteLength());
    160 }
    161 
    162 PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const
    163 {
    164     unsigned size = begin <= end ? end - begin : 0;
    165     return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size);
    166 }
    167 
    168 unsigned ArrayBuffer::clampIndex(int index) const
    169 {
    170     unsigned currentLength = byteLength();
    171     if (index < 0)
    172         index = currentLength + index;
    173     return clampValue(index, 0, currentLength);
    174 }
    175 
    176 } // namespace WTF
    177 
    178 using WTF::ArrayBuffer;
    179 
    180 #endif // ArrayBuffer_h
    181