1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (c) 2010, Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef TypedArrayBase_h
28#define TypedArrayBase_h
29
30#include "wtf/ArrayBuffer.h"
31#include "wtf/ArrayBufferView.h"
32
33namespace WTF {
34
35template <typename T>
36class TypedArrayBase : public ArrayBufferView {
37  public:
38    T* data() const { return static_cast<T*>(baseAddress()); }
39
40    bool set(TypedArrayBase<T>* array, unsigned offset)
41    {
42        return setImpl(array, offset * sizeof(T));
43    }
44
45    bool setRange(const T* data, size_t dataLength, unsigned offset)
46    {
47        return setRangeImpl(reinterpret_cast<const char*>(data), dataLength * sizeof(T), offset * sizeof(T));
48    }
49
50    bool zeroRange(unsigned offset, size_t length)
51    {
52        return zeroRangeImpl(offset * sizeof(T), length * sizeof(T));
53    }
54
55    // Overridden from ArrayBufferView. This must be public because of
56    // rules about inheritance of members in template classes, and
57    // because it is accessed via pointers to subclasses.
58    unsigned length() const
59    {
60        return m_length;
61    }
62
63    virtual unsigned byteLength() const override final
64    {
65        return m_length * sizeof(T);
66    }
67
68    // Invoked by the indexed getter. Does not perform range checks; caller
69    // is responsible for doing so and returning undefined as necessary.
70    T item(unsigned index) const
71    {
72        ASSERT_WITH_SECURITY_IMPLICATION(index < TypedArrayBase<T>::m_length);
73        return TypedArrayBase<T>::data()[index];
74    }
75
76    bool checkInboundData(unsigned offset, unsigned pos) const
77    {
78        return (offset <= m_length
79            && offset + pos <= m_length
80            // check overflow
81            && offset + pos >= offset);
82    }
83
84protected:
85    TypedArrayBase(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
86        : ArrayBufferView(buffer, byteOffset)
87        , m_length(length)
88    {
89    }
90
91    template <class Subclass>
92    static PassRefPtr<Subclass> create(unsigned length)
93    {
94        RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, sizeof(T));
95        if (!buffer.get())
96            return nullptr;
97        return create<Subclass>(buffer, 0, length);
98    }
99
100    template <class Subclass>
101    static PassRefPtr<Subclass> create(const T* array, unsigned length)
102    {
103        RefPtr<Subclass> a = create<Subclass>(length);
104        if (a)
105            for (unsigned i = 0; i < length; ++i)
106                a->set(i, array[i]);
107        return a;
108    }
109
110    template <class Subclass>
111    static PassRefPtr<Subclass> create(PassRefPtr<ArrayBuffer> buffer,
112                                       unsigned byteOffset,
113                                       unsigned length)
114    {
115        RefPtr<ArrayBuffer> buf(buffer);
116        if (!verifySubRange<T>(buf, byteOffset, length))
117            return nullptr;
118
119        return adoptRef(new Subclass(buf, byteOffset, length));
120    }
121
122    template <class Subclass>
123    static PassRefPtr<Subclass> createUninitialized(unsigned length)
124    {
125        RefPtr<ArrayBuffer> buffer = ArrayBuffer::createUninitialized(length, sizeof(T));
126        if (!buffer.get())
127            return nullptr;
128        return create<Subclass>(buffer, 0, length);
129    }
130
131    template <class Subclass>
132    PassRefPtr<Subclass> subarrayImpl(int start, int end) const
133    {
134        unsigned offset, length;
135        calculateOffsetAndLength(start, end, m_length, &offset, &length);
136        clampOffsetAndNumElements<T>(buffer(), m_byteOffset, &offset, &length);
137        return create<Subclass>(buffer(), offset, length);
138    }
139
140    virtual void neuter() override final
141    {
142        ArrayBufferView::neuter();
143        m_length = 0;
144    }
145
146    // We do not want to have to access this via a virtual function in subclasses,
147    // which is why it is protected rather than private.
148    unsigned m_length;
149};
150
151} // namespace WTF
152
153using WTF::TypedArrayBase;
154
155#endif // TypedArrayBase_h
156