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 Strided1DWritableBuffer 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 byteAt(i) will be equal to storage[index0+stride*i]
* (whatever the sign of {@code stride}), valid for 0≤{@code i}<{@code count}.
*
* The constructed PyBuffer meets the consumer's expectations as expressed in the
* flags 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 storage array, the lowest and highest index, is not
* explicitly passed, but is implicit in index0, count and
* stride. 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 null)
* @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 storage is null
* @throws ArrayIndexOutOfBoundsException if index0, count and
* stride are inconsistent with storage.length
* @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}
*
* Declared final returning true in
* Strided1DWritableBuffer 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}
*
* Strided1DWritableBuffer 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 Strided1DWritableBuffer.SlicedView 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;
}
}
}
Ads help maintain this website.