-
Notifications
You must be signed in to change notification settings - Fork 230
Expand file tree
/
Copy pathStrided1DWritableBuffer.java
More file actions
123 lines (110 loc) · 5.22 KB
/
Copy pathStrided1DWritableBuffer.java
File metadata and controls
123 lines (110 loc) · 5.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package org.python.core.buffer;
import org.python.core.BufferProtocol;
import org.python.core.PyBuffer;
import org.python.core.PyException;
/**
* Read-write buffer API over a one-dimensional array of one-byte items, that are evenly-spaced in a
* storage array. The storage conventions are described in {@link Strided1DBuffer} of which this is
* an extension providing write operations and a writable slice.
*/
public class Strided1DWritableBuffer extends Strided1DBuffer {
/**
* Provide an instance of <code>Strided1DWritableBuffer</code> on a particular array of bytes
* specifying a starting index, the number of items in the result, and a byte-indexing stride.
* The result of <code>byteAt(i)</code> will be equal to <code>storage[index0+stride*i]</code>
* (whatever the sign of {@code stride}), valid for 0≤{@code i}<{@code count}.
* <p>
* The constructed <code>PyBuffer</code> meets the consumer's expectations as expressed in the
* <code>flags</code> argument, or an exception will be thrown if these are incompatible with
* the type (e.g. the consumer does not specify that it understands the strides array). Note
* that the actual range in the <code>storage</code> array, the lowest and highest index, is not
* explicitly passed, but is implicit in <code>index0</code>, <code>count</code> and
* <code>stride</code>. The caller is responsible for checking these fall within the array, or
* the sub-range the caller is allowed to use.
*
* @param flags consumer requirements
* @param obj exporting object (or <code>null</code>)
* @param storage raw byte array containing exported data
* @param index0 index into storage of item[0]
* @param count number of items in the slice
* @param stride byte-index distance from one element to the next in the new PyBuffer
* @throws NullPointerException if <code>storage</code> is null
* @throws ArrayIndexOutOfBoundsException if <code>index0</code>, <code>count</code> and
* <code>stride</code> are inconsistent with <code>storage.length</code>
* @throws PyException {@code BufferError} when expectations do not correspond with the type
*/
public Strided1DWritableBuffer(int flags, BufferProtocol obj, byte[] storage, int index0,
int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException,
PyException {
super(obj, storage, index0, count, stride);
addFeatureFlags(WRITABLE);
checkRequestFlags(flags); // Check request is compatible with type
}
/**
* {@inheritDoc}
* <p>
* Declared <code>final</code> returning <code>true</code> in
* <code>Strided1DWritableBuffer</code> to make checks unnecessary.
*/
@Override
public final boolean isReadonly() {
return false;
}
/** Do nothing: the buffer is writable. */
@Override
protected final void checkWritable() {}
@Override
protected void storeAtImpl(byte value, int byteIndex) {
// Implement directly and don't ask whether read-only
storage[byteIndex] = value;
}
/**
* {@inheritDoc}
* <p>
* <code>Strided1DWritableBuffer</code> provides an implementation that returns a writable
* slice.
*/
@Override
public PyBuffer getBufferSlice(int flags, int start, int count, int stride) {
if (count > 0) {
// Translate start relative to underlying buffer
int compStride = this.stride * stride;
int compIndex0 = index0 + start * this.stride;
// Construct a view, taking a lock on the root object (this or this.root)
return new SlicedView(getRoot(), flags, storage, compIndex0, count, compStride);
} else {
// Special case for count==0 where above logic would fail. Efficient too.
return new ZeroByteBuffer.View(getRoot(), flags);
}
}
/**
* A <code>Strided1DWritableBuffer.SlicedView</code> represents a non-contiguous subsequence of
* a simple buffer.
*/
static class SlicedView extends Strided1DWritableBuffer {
/** The buffer on which this is a slice view */
PyBuffer root;
/**
* Construct a slice of a one-dimensional byte buffer.
*
* @param root on which release must be called when this is released
* @param flags consumer requirements
* @param storage raw byte array containing exported data
* @param index0 index into storage of item[0]
* @param count number of items in the sliced view
* @param stride in between successive elements of the new PyBuffer
* @throws PyException {@code BufferError} when expectations do not correspond with the type
*/
public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count,
int stride) throws PyException {
// Create a new on the buffer passed in (part of the root)
super(flags, root.getObj(), storage, index0, count, stride);
// Get a lease on the root PyBuffer (writable)
this.root = root.getBuffer(FULL);
}
@Override
protected PyBuffer getRoot() {
return root;
}
}
}