1/*
2 * Copyright (C) 2013, 2016 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 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 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#pragma once
27
28#include "GenericTypedArrayView.h"
29#include "JSGlobalObject.h"
30
31namespace JSC {
32
33template<typename Adaptor>
34GenericTypedArrayView<Adaptor>::GenericTypedArrayView(
35RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
36 : ArrayBufferView(WTFMove(buffer), byteOffset, length * sizeof(typename Adaptor::Type))
37{
38}
39
40template<typename Adaptor>
41Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(unsigned length)
42{
43 auto result = tryCreate(length);
44 RELEASE_ASSERT(result);
45 return result.releaseNonNull();
46}
47
48template<typename Adaptor>
49Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
50 const typename Adaptor::Type* array, unsigned length)
51{
52 auto result = tryCreate(array, length);
53 RELEASE_ASSERT(result);
54 return result.releaseNonNull();
55}
56
57template<typename Adaptor>
58Ref<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::create(
59 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
60{
61 auto result = tryCreate(WTFMove(buffer), byteOffset, length);
62 RELEASE_ASSERT(result);
63 return result.releaseNonNull();
64}
65
66template<typename Adaptor>
67RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(unsigned length)
68{
69 auto buffer = ArrayBuffer::tryCreate(length, sizeof(typename Adaptor::Type));
70 if (!buffer)
71 return nullptr;
72 return tryCreate(WTFMove(buffer), 0, length);
73}
74
75template<typename Adaptor>
76RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
77 const typename Adaptor::Type* array, unsigned length)
78{
79 RefPtr<GenericTypedArrayView> result = tryCreate(length);
80 if (!result)
81 return nullptr;
82 memcpy(result->data(), array, length * sizeof(typename Adaptor::Type));
83 return result;
84}
85
86template<typename Adaptor>
87RefPtr<GenericTypedArrayView<Adaptor>> GenericTypedArrayView<Adaptor>::tryCreate(
88 RefPtr<ArrayBuffer>&& buffer, unsigned byteOffset, unsigned length)
89{
90 ASSERT(buffer);
91 if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, length, sizeof(typename Adaptor::Type))
92 || !verifyByteOffsetAlignment(byteOffset, sizeof(typename Adaptor::Type))) {
93 return nullptr;
94 }
95
96 return adoptRef(new GenericTypedArrayView(WTFMove(buffer), byteOffset, length));
97}
98
99template<typename Adaptor>
100Ref<GenericTypedArrayView<Adaptor>>
101GenericTypedArrayView<Adaptor>::createUninitialized(unsigned length)
102{
103 auto result = tryCreateUninitialized(length);
104 RELEASE_ASSERT(result);
105 return result.releaseNonNull();
106}
107
108template<typename Adaptor>
109RefPtr<GenericTypedArrayView<Adaptor>>
110GenericTypedArrayView<Adaptor>::tryCreateUninitialized(unsigned length)
111{
112 RefPtr<ArrayBuffer> buffer =
113 ArrayBuffer::tryCreateUninitialized(length, sizeof(typename Adaptor::Type));
114 if (!buffer)
115 return nullptr;
116 return tryCreate(WTFMove(buffer), 0, length);
117}
118
119template<typename Adaptor>
120RefPtr<GenericTypedArrayView<Adaptor>>
121GenericTypedArrayView<Adaptor>::subarray(int start) const
122{
123 return subarray(start, length());
124}
125
126template<typename Adaptor>
127RefPtr<GenericTypedArrayView<Adaptor>>
128GenericTypedArrayView<Adaptor>::subarray(int start, int end) const
129{
130 unsigned offset, length;
131 calculateOffsetAndLength(start, end, this->length(), &offset, &length);
132 ArrayBuffer* buffer = possiblySharedBuffer();
133 ASSERT(buffer);
134 clampOffsetAndNumElements<Adaptor::Type>(*buffer, byteOffset(), &offset, &length);
135 return tryCreate(buffer, offset, length);
136}
137
138template<typename Adaptor>
139JSArrayBufferView* GenericTypedArrayView<Adaptor>::wrap(
140 ExecState* exec, JSGlobalObject* globalObject)
141{
142 return Adaptor::JSViewType::create(
143 exec->vm(), globalObject->typedArrayStructure(Adaptor::typeValue), this);
144}
145
146} // namespace JSC
147