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 ArrayBufferView_h
     27 #define ArrayBufferView_h
     28 
     29 #include "wtf/ArrayBuffer.h"
     30 
     31 #include <algorithm>
     32 #include <limits.h>
     33 #include "wtf/PassRefPtr.h"
     34 #include "wtf/RefCounted.h"
     35 #include "wtf/RefPtr.h"
     36 #include "wtf/WTFExport.h"
     37 
     38 namespace WTF {
     39 
     40 class WTF_EXPORT ArrayBufferView : public RefCounted<ArrayBufferView> {
     41   public:
     42     enum ViewType {
     43         TypeInt8,
     44         TypeUint8,
     45         TypeUint8Clamped,
     46         TypeInt16,
     47         TypeUint16,
     48         TypeInt32,
     49         TypeUint32,
     50         TypeFloat32,
     51         TypeFloat64,
     52         TypeDataView
     53     };
     54     virtual ViewType type() const = 0;
     55     const char* typeName();
     56 
     57     PassRefPtr<ArrayBuffer> buffer() const
     58     {
     59         return m_buffer;
     60     }
     61 
     62     void* baseAddress() const
     63     {
     64         return m_baseAddress;
     65     }
     66 
     67     unsigned byteOffset() const
     68     {
     69         return m_byteOffset;
     70     }
     71 
     72     virtual unsigned byteLength() const = 0;
     73 
     74     void setNeuterable(bool flag) { m_isNeuterable = flag; }
     75     bool isNeuterable() const { return m_isNeuterable; }
     76 
     77     virtual ~ArrayBufferView();
     78 
     79   protected:
     80     ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset);
     81 
     82     inline bool setImpl(ArrayBufferView*, unsigned byteOffset);
     83 
     84     inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset);
     85 
     86     inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength);
     87 
     88     static inline void calculateOffsetAndLength(int start, int end, unsigned arraySize,
     89                                          unsigned* offset, unsigned* length);
     90 
     91     // Helper to verify that a given sub-range of an ArrayBuffer is
     92     // within range.
     93     template <typename T>
     94     static bool verifySubRange(PassRefPtr<ArrayBuffer> buffer,
     95                                unsigned byteOffset,
     96                                unsigned numElements)
     97     {
     98         if (!buffer)
     99             return false;
    100         if (sizeof(T) > 1 && byteOffset % sizeof(T))
    101             return false;
    102         if (byteOffset > buffer->byteLength())
    103             return false;
    104         unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T);
    105         if (numElements > remainingElements)
    106             return false;
    107         return true;
    108     }
    109 
    110     // Input offset is in number of elements from this array's view;
    111     // output offset is in number of bytes from the underlying buffer's view.
    112     template <typename T>
    113     static void clampOffsetAndNumElements(PassRefPtr<ArrayBuffer> buffer,
    114                                           unsigned arrayByteOffset,
    115                                           unsigned *offset,
    116                                           unsigned *numElements)
    117     {
    118         unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T);
    119         if (*offset > maxOffset) {
    120             *offset = buffer->byteLength();
    121             *numElements = 0;
    122             return;
    123         }
    124         *offset = arrayByteOffset + *offset * sizeof(T);
    125         *offset = std::min(buffer->byteLength(), *offset);
    126         unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T);
    127         *numElements = std::min(remainingElements, *numElements);
    128     }
    129 
    130     virtual void neuter();
    131 
    132     // This is the address of the ArrayBuffer's storage, plus the byte offset.
    133     void* m_baseAddress;
    134 
    135     unsigned m_byteOffset : 31;
    136     bool m_isNeuterable : 1;
    137 
    138   private:
    139     friend class ArrayBuffer;
    140     RefPtr<ArrayBuffer> m_buffer;
    141     ArrayBufferView* m_prevView;
    142     ArrayBufferView* m_nextView;
    143 };
    144 
    145 bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset)
    146 {
    147     if (byteOffset > byteLength()
    148         || byteOffset + array->byteLength() > byteLength()
    149         || byteOffset + array->byteLength() < byteOffset) {
    150         // Out of range offset or overflow
    151         return false;
    152     }
    153 
    154     char* base = static_cast<char*>(baseAddress());
    155     memmove(base + byteOffset, array->baseAddress(), array->byteLength());
    156     return true;
    157 }
    158 
    159 bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset)
    160 {
    161     if (byteOffset > byteLength()
    162         || byteOffset + dataByteLength > byteLength()
    163         || byteOffset + dataByteLength < byteOffset) {
    164         // Out of range offset or overflow
    165         return false;
    166     }
    167 
    168     char* base = static_cast<char*>(baseAddress());
    169     memmove(base + byteOffset, data, dataByteLength);
    170     return true;
    171 }
    172 
    173 bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength)
    174 {
    175     if (byteOffset > byteLength()
    176         || byteOffset + rangeByteLength > byteLength()
    177         || byteOffset + rangeByteLength < byteOffset) {
    178         // Out of range offset or overflow
    179         return false;
    180     }
    181 
    182     char* base = static_cast<char*>(baseAddress());
    183     memset(base + byteOffset, 0, rangeByteLength);
    184     return true;
    185 }
    186 
    187 void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arraySize,
    188                                                unsigned* offset, unsigned* length)
    189 {
    190     if (start < 0)
    191         start += arraySize;
    192     if (start < 0)
    193         start = 0;
    194     if (end < 0)
    195         end += arraySize;
    196     if (end < 0)
    197         end = 0;
    198     if (static_cast<unsigned>(end) > arraySize)
    199         end = arraySize;
    200     if (end < start)
    201         end = start;
    202     *offset = static_cast<unsigned>(start);
    203     *length = static_cast<unsigned>(end - start);
    204 }
    205 
    206 } // namespace WTF
    207 
    208 using WTF::ArrayBufferView;
    209 
    210 #endif // ArrayBufferView_h
    211