X Tutup
package org.python.core.buffer; import org.python.core.BufferProtocol; import org.python.core.PyBuffer; import org.python.core.PyException; import org.python.core.util.StringUtil; /** * Buffer API over a read-only one-dimensional array of one-byte items. */ public class SimpleBuffer extends BaseArrayBuffer { /** * Provide an instance of SimpleBuffer with navigation variables initialised, for * sub-class use. The buffer ({@link #storage}, {@link #index0}), and the {@link #shape} array * will be initialised from the arguments (which are not checked for range). The * {@link #strides} is set for a one-byte stride. Only the call to * {@link #checkRequestFlags(int)}, passing the consumer's request flags really remains for the * sub-class constructor to do. * *
     * super(storage, index0, size);
     * checkRequestFlags(flags);        // Check request is compatible with type
     * 
* * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object * @param index0 offset where the data starts in that array (item[0]) * @param size the number of bytes occupied * @throws NullPointerException if storage is null */ protected SimpleBuffer(BufferProtocol obj, byte[] storage, int index0, int size) throws PyException, ArrayIndexOutOfBoundsException { super(storage, CONTIGUITY | SIMPLE, index0, size, 1); this.obj = obj; } /** * Provide an instance of SimpleBuffer, on a slice of a byte array, meeting the * consumer's expectations as expressed in the flags argument, which is checked * against the capabilities of the buffer type. * * @param flags consumer requirements * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object * @param index0 offset where the data starts in that array (item[0]) * @param size the number of bytes occupied * @throws NullPointerException if storage is null * @throws ArrayIndexOutOfBoundsException if index0 and size are * inconsistent with storage.length * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int size) throws PyException, ArrayIndexOutOfBoundsException, NullPointerException { this(obj, storage, index0, size); // Construct checked SimpleBuffer checkRequestFlags(flags); // Check request is compatible with type // Check arguments using the "all non-negative" trick if ((index0 | size | storage.length - (index0 + size)) < 0) { throw new ArrayIndexOutOfBoundsException(); } } /** * Provide an instance of SimpleBuffer, on the entirety of a byte array, with * navigation variables initialised, for sub-class use. The buffer ( {@link #storage}, * {@link #index0}), and the navigation ({@link #shape} array) will be initialised from the * array argument. * * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object * @throws NullPointerException if storage is null */ protected SimpleBuffer(BufferProtocol obj, byte[] storage) throws NullPointerException { this(obj, storage, 0, storage.length); } /** * Provide an instance of SimpleBuffer, on the entirety of a byte array, meeting * the consumer's expectations as expressed in the flags argument, which is checked * against the capabilities of the buffer type. * * @param flags consumer requirements * @param obj exporting object (or null) * @param storage the array of bytes storing the implementation of the exporting object * @throws NullPointerException if storage is null * @throws PyException {@code BufferError} when expectations do not correspond with the type */ public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage) throws PyException, NullPointerException { this(obj, storage); // Construct SimpleBuffer on whole array checkRequestFlags(flags); // Check request is compatible with type } /** * {@inheritDoc} *

* SimpleBuffer provides an implementation optimised for contiguous bytes in * one-dimension. */ @Override public int getLen() { // Simplify for one-dimensional contiguous bytes return shape[0]; } /** * {@inheritDoc} *

* In SimpleBuffer the calculation is specialised for one dimension, no striding, * and an item size of 1. */ @Override public int byteIndex(int index) throws IndexOutOfBoundsException { if (index < 0 || index >= shape[0]) { throw new IndexOutOfBoundsException(); } return index0 + index; } // XXX Consider moving to clauses in getBufferSlice(int, int, int, int) // to avoid delegation loop where that delegates to this but in BaseBuffer the reverse. @Override public PyBuffer getBufferSlice(int flags, int start, int count) { if (count > 0) { // Translate relative to underlying buffer int compIndex0 = index0 + start; // Create the slice from the sub-range of the buffer return new SimpleView(getRoot(), flags, storage, compIndex0, count); } else { // Special case for count==0 where above logic would fail. Efficient too. return new ZeroByteBuffer.View(getRoot(), flags); } } /** * {@inheritDoc} *

* SimpleBuffer provides an implementation for slicing contiguous bytes in one * dimension. In that case, x(i) = u(r+i) for i = 0..L-1 where u is the underlying * buffer, and r and L are the start and count with which x was created * from u. Thus y(k) = u(r+s+km), that is, the composite offset is r+s and * the stride is m. */ @Override public PyBuffer getBufferSlice(int flags, int start, int count, int stride) { if (stride == 1 || count < 2) { // Unstrided slice of simple buffer is itself simple return getBufferSlice(flags, start, count); } else { // Translate relative to underlying buffer int compIndex0 = index0 + start; // Construct a view, taking a lock on the root object (this or this.root) return new Strided1DBuffer.SlicedView(getRoot(), flags, storage, compIndex0, count, stride); } } @SuppressWarnings("deprecation") @Override public Pointer getPointer(int index) throws IndexOutOfBoundsException { return new Pointer(storage, index0 + index); } @SuppressWarnings("deprecation") @Override public Pointer getPointer(int... indices) throws IndexOutOfBoundsException { checkDimension(indices.length); return getPointer(indices[0]); } @Override public String toString() { // For contiguous bytes in one dimension we can avoid the intAt() calls return StringUtil.fromBytes(storage, index0, shape[0]); } /** * A SimpleBuffer.SimpleView represents a contiguous subsequence of another * SimpleBuffer. */ static class SimpleView extends SimpleBuffer { /** The buffer on which this is a slice view */ PyBuffer root; /** * Construct a slice of a SimpleBuffer. * * @param root buffer which will be acquired and must be released ultimately * @param flags the request flags of the consumer that requested the slice * @param storage the array of bytes storing the implementation of the exporting object * @param offset where the data starts in that array (item[0]) * @param size the number of bytes occupied */ public SimpleView(PyBuffer root, int flags, byte[] storage, int offset, int size) { // Create a new SimpleBuffer on the buffer passed in (part of the root) super(flags, root.getObj(), storage, offset, size); // Get a lease on the root PyBuffer this.root = root.getBuffer(FULL_RO); } @Override protected PyBuffer getRoot() { return root; } } }

X Tutup