Class BaseBuffer

  • All Implemented Interfaces:
    java.lang.AutoCloseable, BufferProtocol, PyBUF, PyBuffer
    Direct Known Subclasses:
    Base1DBuffer

    public abstract class BaseBuffer
    extends java.lang.Object
    implements PyBuffer
    Base implementation of the Buffer API providing variables and accessors for the navigation arrays, methods for expressing and checking the buffer request flags, methods and mechanism for get-release counting, boilerplate error checks and their associated exceptions, and default implementations of some methods for access to the buffer content. The design aim is to ensure unglamorous common code need only be implemented once.

    This class leaves undefined the storage mechanism for the bytes (typically byte[] or java.nio.ByteBuffer), while remaining definite that it is an indexable sequence of bytes. A concrete class that extends this one must provide elementary accessors byteAtImpl(int), storeAtImpl(byte, int) that abstract this storage, a factory getNIOByteBufferImpl() for ByteBuffers that wrap the storage, and a factory for slices PyBuffer.getBufferSlice(int, int, int, int).

    The sub-class constructor must specify the feature flags (see #BaseBuffer(int)), set index0, shape and strides, and finally check the client capabilities with checkRequestFlags(int). Sub-classes intended to represent slices of exporters that must count their exports as part of a locking protocol, as does bytearray, must override getRoot() so that a buffer view release() on a slice, propagates to the buffer view that provided it.

    Access methods provided here necessarily work with the abstracted byteAtImpl(int), storeAtImpl(byte, int) interface, but subclasses are able to override them with more efficient versions that employ knowledge of the particular storage type used.

    This base implementation is writable only if PyBUF.WRITABLE is in the feature flags passed to the constructor. Otherwise, all methods for write access raise a TypeError and isReadonly() returns true. However, a client intending to write should have presented PyBUF.WRITABLE in its client request flags when getting the buffer, and been prevented by a BufferError exception at that point.

    At the time of writing, only one-dimensional buffers of item size one are used in the Jython core.

    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      byte byteAt​(int index)
      Return the byte indexed from a one-dimensional buffer with item size one.
      byte byteAt​(int... indices)
      Return the byte indexed from an N-dimensional buffer with item size one.
      int byteIndex​(int index)
      Convert an item index (for a one-dimensional buffer) to an absolute byte index in the storage shared by the exporter.
      int byteIndex​(int... indices)
      Convert a multi-dimensional item index to an absolute byte index in the storage shared by the exporter.
      void close()
      An alias for PyBuffer.release() to satisfy AutoCloseable.
      void copyFrom​(byte[] src, int srcPos, int destIndex, int count)
      Copy from a slice of a (Java) byte array into the buffer starting at a given destination item-index.
      void copyFrom​(PyBuffer src)
      Copy the whole of another PyBuffer into this buffer.
      void copyTo​(byte[] dest, int destPos)
      Copy the contents of the buffer to the destination byte array.
      void copyTo​(int srcIndex, byte[] dest, int destPos, int count)
      Copy a simple slice of the buffer-view to the destination byte array, defined by a starting item-index in the source buffer and the count of items to copy.
      PyBuffer.Pointer getBuf()
      Return a structure describing the slice of a byte array that holds the data being exported to the consumer.
      PyBuffer getBuffer​(int flags)
      Method by which the consumer requests the buffer from the exporter.
      BaseBuffer getBufferAgain​(int flags)
      Allow an exporter to re-use this object again even if it has been "finally" released.
      PyBuffer getBufferSlice​(int flags, int start, int count)
      Equivalent to PyBuffer.getBufferSlice(int, int, int, int) with stride 1.
      java.lang.String getFormat()
      A format string in the language of Python structs describing how the bytes of each item should be interpreted.
      int getItemsize()
      The number of bytes stored in each indexable item.
      int getLen()
      The total number of bytes represented by the view, which will be the product of the elements of the shape array, and the item size in bytes.
      int getNdim()
      The number of dimensions to the buffer.
      java.nio.ByteBuffer getNIOByteBuffer()
      Obtain a ByteBuffer giving access to the bytes that hold the data being exported by the original object.
      BufferProtocol getObj()
      Return the underlying exporting object (or null if no object implementing the BufferProtocol is in that role).
      PyBuffer.Pointer getPointer​(int index)
      Return a structure describing the position in a byte array of a single item from the data being exported to the consumer.
      PyBuffer.Pointer getPointer​(int... indices)
      Return a structure describing the position in a byte array of a single item from the data being exported to the consumer, in the case that array may be multi-dimensional.
      int[] getShape()
      An array reporting the size of the buffer, considered as a multidimensional array, in each dimension and (by its length) giving the number of dimensions.
      int[] getStrides()
      The strides array gives the distance in the storage array between adjacent items (in each dimension).
      int[] getSuboffsets()
      The suboffsets array is a further part of the support for interpreting the buffer as an n-dimensional array of items, where the array potentially uses indirect addressing (like a real Java array of arrays, in fact).
      boolean hasArray()
      Report whether the exporter is able to offer direct access to the exported storage as a Java byte array (through the API that involves class PyBuffer.Pointer), or only supports the abstract API.
      int intAt​(int index)
      Return the unsigned byte value indexed from a one-dimensional buffer with item size one.
      int intAt​(int... indices)
      Return the unsigned byte value indexed from an N-dimensional buffer with item size one.
      boolean isContiguous​(char order)
      Enquire whether the array is represented contiguously in the backing storage, according to C or Fortran ordering.
      boolean isReadonly()
      Determine whether the consumer is entitled to write to the exported storage.
      boolean isReleased()
      True only if the buffer has been released with (the required number of calls to) PyBuffer.release() or some equivalent operation.
      void release()
      A buffer is (usually) a view onto to the internal state of an exporting object, and that object may have to restrict its behaviour while the buffer exists.
      void storeAt​(byte value, int index)
      Store the given byte at the indexed location in of a one-dimensional buffer with item size one.
      void storeAt​(byte value, int... indices)
      Store the given byte at the indexed location in of an N-dimensional buffer with item size one.
      java.lang.String toString()
      The toString() method of a buffer reproduces the values in the buffer (as unsigned integers) as the character codes of a String.
      • Methods inherited from class java.lang.Object

        equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Method Detail

      • isReadonly

        public boolean isReadonly()
        Description copied from interface: PyBUF
        Determine whether the consumer is entitled to write to the exported storage.
        Specified by:
        isReadonly in interface PyBUF
        Returns:
        true if writing is not allowed, false if it is.
      • getNdim

        public int getNdim()
        Description copied from interface: PyBUF
        The number of dimensions to the buffer. This number is the length of the shape array. The actual storage may be a linear array, but this is the number of dimensions in the interpretation that the exporting object gives the data.
        Specified by:
        getNdim in interface PyBUF
        Returns:
        number of dimensions
      • getShape

        public int[] getShape()
        Description copied from interface: PyBUF
        An array reporting the size of the buffer, considered as a multidimensional array, in each dimension and (by its length) giving the number of dimensions. The size of the buffer is its size in "items". An item is the amount of buffer content addressed by one index or set of indices. In the simplest case an item is a single unit (byte), and there is one dimension. In complex cases, the array is multi-dimensional, and the item at each location is multi-unit (multi-byte). The consumer must not modify this array. A valid shape array is always returned (difference from CPython).
        Specified by:
        getShape in interface PyBUF
        Returns:
        the dimensions of the buffer as an array
      • getLen

        public int getLen()
        Description copied from interface: PyBUF
        The total number of bytes represented by the view, which will be the product of the elements of the shape array, and the item size in bytes.
        Specified by:
        getLen in interface PyBUF
        Returns:
        the total number of bytes represented.
      • getObj

        public final BufferProtocol getObj()
        Description copied from interface: PyBuffer
        Return the underlying exporting object (or null if no object implementing the BufferProtocol is in that role). This will often be a PyObject.
        Specified by:
        getObj in interface PyBuffer
        Returns:
        exporting object (or null)
      • byteAt

        public byte byteAt​(int index)
                    throws java.lang.IndexOutOfBoundsException
        Return the byte indexed from a one-dimensional buffer with item size one. This is part of the fully-encapsulated API: the buffer implementation exported takes care of navigating the structure of the buffer. Results are undefined where the number of dimensions is not one or if itemsize>1.

        The BaseBuffer implementation delegates to byteAtImpl(int) via byteAtImpl(byteIndex(index)).

        Specified by:
        byteAt in interface PyBuffer
        Parameters:
        index - to retrieve from
        Returns:
        the item at index, which is a byte
        Throws:
        java.lang.IndexOutOfBoundsException
      • intAt

        public int intAt​(int index)
                  throws java.lang.IndexOutOfBoundsException
        Return the unsigned byte value indexed from a one-dimensional buffer with item size one. This is part of the fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. Results are undefined where the number of dimensions is not one or if itemsize>1.

        The BaseBuffer implementation delegates to byteAtImpl(int) via byteAtImpl(byteIndex(index)), cast unsigned to an int.

        Specified by:
        intAt in interface PyBuffer
        Parameters:
        index - to retrieve from
        Returns:
        the item at index, treated as an unsigned byte, =0xff & byteAt(index)
        Throws:
        java.lang.IndexOutOfBoundsException
      • storeAt

        public void storeAt​(byte value,
                            int index)
                     throws java.lang.IndexOutOfBoundsException,
                            PyException
        Store the given byte at the indexed location in of a one-dimensional buffer with item size one. This is part of the fully-encapsulated API: the buffer implementation exported takes care of navigating the structure of the buffer. Results are undefined where the number of dimensions is not one or if itemsize>1.

        The BaseBuffer implementation delegates to storeAtImpl(byte, int) via storeAtImpl(value, byteIndex(index)).

        Specified by:
        storeAt in interface PyBuffer
        Parameters:
        value - to store
        index - to location
        Throws:
        java.lang.IndexOutOfBoundsException
        PyException
      • byteAt

        public byte byteAt​(int... indices)
                    throws java.lang.IndexOutOfBoundsException
        Return the byte indexed from an N-dimensional buffer with item size one. This is part of the fully-encapsulated API: the buffer implementation exported takes care of navigating the structure of the buffer. The indices must be correct in number and range for the array shape. Results are undefined where itemsize>1.

        The BaseBuffer implementation delegates to byteAtImpl(int) via byteAtImpl(byteIndex(indices)).

        Specified by:
        byteAt in interface PyBuffer
        Parameters:
        indices - specifying location to retrieve from
        Returns:
        the item at location, which is a byte
        Throws:
        java.lang.IndexOutOfBoundsException
      • intAt

        public int intAt​(int... indices)
                  throws java.lang.IndexOutOfBoundsException
        Return the unsigned byte value indexed from an N-dimensional buffer with item size one. This is part of the fully-encapsulated API: the buffer implementation exported takes care of navigating the structure of the buffer. The indices must be correct in number and range for the array shape. Results are undefined where itemsize>1.

        The BaseBuffer implementation delegates to byteAtImpl(int) via byteAtImpl(byteIndex(indices)), cast unsigned to an int.

        Specified by:
        intAt in interface PyBuffer
        Parameters:
        indices - specifying location to retrieve from
        Returns:
        the item at location, treated as an unsigned byte, =0xff & byteAt(index)
        Throws:
        java.lang.IndexOutOfBoundsException
      • storeAt

        public void storeAt​(byte value,
                            int... indices)
                     throws java.lang.IndexOutOfBoundsException,
                            PyException
        Store the given byte at the indexed location in of an N-dimensional buffer with item size one. This is part of the fully-encapsulated API: the exporter takes care of navigating the structure of the buffer. The indices must be correct in number and range for the array shape. Results are undefined where itemsize>1.

        The BaseBuffer implementation delegates to storeAtImpl(byte, int) via storeAtImpl(value, byteIndex(indices)).

        Specified by:
        storeAt in interface PyBuffer
        Parameters:
        value - to store
        indices - specifying location to store at
        Throws:
        java.lang.IndexOutOfBoundsException
        PyException
      • byteIndex

        public int byteIndex​(int index)
                      throws java.lang.IndexOutOfBoundsException
        Description copied from interface: PyBuffer
        Convert an item index (for a one-dimensional buffer) to an absolute byte index in the storage shared by the exporter. The storage exported as a PyBuffer is a linearly-indexed sequence of bytes, although it may not actually be a heap-allocated Java byte[] object. The purpose of this method is to allow the exporter to define the relationship between the item index (as used in PyBuffer.byteAt(int)) and the byte-index (as used with the ByteBuffer returned by PyBuffer.getNIOByteBuffer()). See PyBuffer.byteIndex(int[]) for discussion of the multi-dimensional case.
        Specified by:
        byteIndex in interface PyBuffer
        Parameters:
        index - item-index from consumer
        Returns:
        corresponding byte-index in actual storage
        Throws:
        java.lang.IndexOutOfBoundsException
      • byteIndex

        public int byteIndex​(int... indices)
                      throws java.lang.IndexOutOfBoundsException
        Description copied from interface: PyBuffer
        Convert a multi-dimensional item index to an absolute byte index in the storage shared by the exporter. The storage exported as a PyBuffer is a linearly-indexed sequence of bytes, although it may not actually be a heap-allocated Java byte[] object. The purpose of this method is to allow the exporter to define the relationship between the item index (as used in PyBuffer.byteAt(int...) and the byte-index (as used with the ByteBuffer returned by PyBuffer.getNIOByteBuffer()).
        Specified by:
        byteIndex in interface PyBuffer
        Parameters:
        indices - n-dimensional item-index from consumer
        Returns:
        corresponding byte-index in actual storage
        Throws:
        java.lang.IndexOutOfBoundsException
      • copyTo

        public void copyTo​(byte[] dest,
                           int destPos)
                    throws java.lang.IndexOutOfBoundsException
        Copy the contents of the buffer to the destination byte array. The number of bytes will be that returned by PyBUF.getLen(), and the order is the storage order in the exporter. (Note: Correct ordering for multidimensional arrays, including those with indirection needs further study.)

        The default implementation in BaseBuffer deals with the general one-dimensional case of arbitrary item size and stride.

        Specified by:
        copyTo in interface PyBuffer
        Parameters:
        dest - destination byte array
        destPos - byte-index in the destination array of the byte [0]
        Throws:
        java.lang.IndexOutOfBoundsException - if the destination cannot hold it
      • copyTo

        public void copyTo​(int srcIndex,
                           byte[] dest,
                           int destPos,
                           int count)
                    throws java.lang.IndexOutOfBoundsException,
                           PyException
        Copy a simple slice of the buffer-view to the destination byte array, defined by a starting item-index in the source buffer and the count of items to copy. This may validly be done only for a one-dimensional buffer, as the meaning of the starting item-index is otherwise not defined. count*itemsize bytes will be occupied in the destination.

        The default implementation in BaseBuffer deals with the general one-dimensional case of arbitrary item size and stride, but is unable to optimise access to sequential bytes.

        Specified by:
        copyTo in interface PyBuffer
        Parameters:
        srcIndex - starting item-index in the source buffer
        dest - destination byte array
        destPos - byte-index in the destination array of the source item [0,...]
        count - number of items to copy
        Throws:
        java.lang.IndexOutOfBoundsException - if access out of bounds in source or destination
        PyException
      • copyFrom

        public void copyFrom​(byte[] src,
                             int srcPos,
                             int destIndex,
                             int count)
                      throws java.lang.IndexOutOfBoundsException,
                             PyException
        Copy from a slice of a (Java) byte array into the buffer starting at a given destination item-index. This may validly be done only for a one-dimensional buffer, as the meaning of the destination index is not otherwise defined. count*itemsize bytes will be read from the source.

        The default implementation in BaseBuffer deals with the general one-dimensional case of arbitrary item size and stride, but is unable to optimise access to sequential bytes.

        Specified by:
        copyFrom in interface PyBuffer
        Parameters:
        src - source byte array
        srcPos - location in source of first byte to copy
        destIndex - starting item-index in the destination (i.e. this)
        count - number of items to copy in
        Throws:
        java.lang.IndexOutOfBoundsException - if access out of bounds in source or destination
        PyException - (TypeError) if read-only buffer
      • copyFrom

        public void copyFrom​(PyBuffer src)
                      throws java.lang.IndexOutOfBoundsException,
                             PyException
        Copy the whole of another PyBuffer into this buffer. This may validly be done only for buffers that are consistent in their dimensions. When it is necessary to copy partial buffers, this may be achieved using a buffer slice on the source or destination.

        The default implementation in BaseBuffer deals with the general one-dimensional case of arbitrary item size and stride, but is unable to optimise access to sequential bytes.

        Specified by:
        copyFrom in interface PyBuffer
        Parameters:
        src - source buffer
        Throws:
        java.lang.IndexOutOfBoundsException - if access out of bounds in source or destination
        PyException - (TypeError) if read-only buffer
      • getBuffer

        public PyBuffer getBuffer​(int flags)
        Description copied from interface: PyBuffer
        Method by which the consumer requests the buffer from the exporter. The consumer provides information on its intended method of navigation and the features the buffer object is asked (or assumed) to provide. Each consumer requesting a buffer in this way, when it has finished using it, should make a corresponding call to PyBuffer.release() on the buffer it obtained, since some objects alter their behaviour while buffers are exported.

        When a PyBuffer is the target, the same checks are carried out on the consumer flags, and a return will normally be a reference to that buffer. A Jython PyBuffer keeps count of these re-exports in order to match them with the number of calls to PyBuffer.release(). When the last matching release() arrives it is considered "final", and release actions may then take place on the exporting object. After the final release of a buffer, a call to getBuffer should raise an exception.

        Specified by:
        getBuffer in interface BufferProtocol
        Specified by:
        getBuffer in interface PyBuffer
        Parameters:
        flags - specifying features demanded and the navigational capabilities of the consumer
        Returns:
        exported buffer
      • getBufferAgain

        public BaseBuffer getBufferAgain​(int flags)
        Allow an exporter to re-use this object again even if it has been "finally" released. Many sub-classes of BaseBytes can be re-used even after a final release by consumers, simply by incrementing the exports count again: the navigation arrays and the buffer view of the exporter's state all remain valid. We do not let consumers do this through the PyBuffer interface: from their perspective, calling PyBuffer.release() should mean the end of their access, although we can't stop them holding a reference to the PyBuffer. Only the exporting object, which handles the implementation type is trusted to know when re-use is safe.

        An exporter will use this method as part of its implementation of BufferProtocol.getBuffer(int). On return from that, the buffer and the exporting object must then be in effectively the same state as if the buffer had just been constructed by that method. Exporters that destroy related resources on final release of their buffer (by overriding releaseAction()), or permit themselves structural change invalidating the buffer, must either reconstruct the missing resources or avoid getBufferAgain.

      • release

        public void release()
        A buffer is (usually) a view onto to the internal state of an exporting object, and that object may have to restrict its behaviour while the buffer exists. The consumer must therefore say when it has finished with the buffer if the exporting object is to be released from this constraint. Each consumer that obtains a reference to a buffer by means of a call to BufferProtocol.getBuffer(int) or PyBuffer.getBuffer(int) should make a matching call to PyBuffer.release(). The consumer may be sharing the PyBuffer with other consumers and the buffer uses the pairing of getBuffer and release to manage the lock on behalf of the exporter. It is an error to make more than one call to release for a single call to getBuffer.

        When the final matching release occurs (that is the number of release calls equals the number of getBuffer calls), the implementation here calls releaseAction(), which the implementer of a specific buffer type should override if it needs specific actions to take place.

        Note that, when this is a sliced view obtained from another PyBuffer the implementation in BaseBuffer automatically sends one release() Sub-classes should not propagate the release themselves when overriding releaseAction().

        Specified by:
        release in interface PyBuffer
      • close

        public void close()
        Description copied from interface: PyBuffer
        An alias for PyBuffer.release() to satisfy AutoCloseable.
        Specified by:
        close in interface java.lang.AutoCloseable
        Specified by:
        close in interface PyBuffer
      • isReleased

        public boolean isReleased()
        Description copied from interface: PyBuffer
        True only if the buffer has been released with (the required number of calls to) PyBuffer.release() or some equivalent operation. The consumer may be sharing the reference with other consumers and the buffer only achieves the released state when all consumers who called getBuffer have called release.
        Specified by:
        isReleased in interface PyBuffer
      • getBufferSlice

        public PyBuffer getBufferSlice​(int flags,
                                       int start,
                                       int count)
        Description copied from interface: PyBuffer
        Equivalent to PyBuffer.getBufferSlice(int, int, int, int) with stride 1.
        Specified by:
        getBufferSlice in interface PyBuffer
        Parameters:
        flags - specifying features demanded and the navigational capabilities of the consumer
        start - index in the current buffer
        count - number of items in the required slice
        Returns:
        a buffer representing the slice
      • getNIOByteBuffer

        public java.nio.ByteBuffer getNIOByteBuffer()
        Description copied from interface: PyBuffer
        Obtain a ByteBuffer giving access to the bytes that hold the data being exported by the original object. The position of the buffer is at the first byte of the item with zero index (quite possibly not the lowest valid byte-index), the limit of the buffer is beyond the largest valid byte index, and the mark is undefined.

        For a one-dimensional contiguous buffer, the limit is one byte beyond the last item, so that consecutive reads from the ByteBuffer return the data in order. Assuming the following client code where obj has type BufferProtocol:

         PyBuffer a = obj.getBuffer(PyBUF.SIMPLE);
         int itemsize = a.getItemsize();
         ByteBuffer bb = a.getNIOBuffer();
         
        the item with index k is in bb at positions bb.pos()+k*itemsize to bb.pos()+(k+1)*itemsize - 1 inclusive. And if itemsize==1, the item is simply the byte at position bb.pos()+k.

        If the buffer is multidimensional or non-contiguous (strided), the buffer position is still the (first byte of) the item at index [0] or [0,...,0]. However, it is necessary to navigate bb using the shape, strides and maybe suboffsets provided by the API.

        Specified by:
        getNIOByteBuffer in interface PyBuffer
        Returns:
        a ByteBuffer onto the exported data contents.
      • hasArray

        public boolean hasArray()
        Description copied from interface: PyBuffer
        Report whether the exporter is able to offer direct access to the exported storage as a Java byte array (through the API that involves class PyBuffer.Pointer), or only supports the abstract API. See also PyBUF.AS_ARRAY.
        Specified by:
        hasArray in interface PyBuffer
        Returns:
        true if array access is supported, false if it is not.
      • getBuf

        public PyBuffer.Pointer getBuf()
        Description copied from interface: PyBuffer
        Return a structure describing the slice of a byte array that holds the data being exported to the consumer. For a one-dimensional contiguous buffer, assuming the following client code where obj has type BufferProtocol:
         PyBuffer a = obj.getBuffer(PyBUF.SIMPLE);
         int itemsize = a.getItemsize();
         PyBuffer.Pointer b = a.getBuf();
         
        the item with index k is in the array b.storage at index [b.offset + k*itemsize] to [b.offset + (k+1)*itemsize - 1] inclusive. And if itemsize==1, the item is simply the byte b.storage[b.offset + k]

        If the buffer is multidimensional or non-contiguous, storage[offset] is still the (first byte of) the item at index [0] or [0,...,0]. However, it is necessary to navigate b.storage using the shape, strides and maybe suboffsets provided by the API.

        Specified by:
        getBuf in interface PyBuffer
        Returns:
        structure defining the byte[] slice that is the shared data
      • getPointer

        public PyBuffer.Pointer getPointer​(int index)
                                    throws java.lang.IndexOutOfBoundsException
        Description copied from interface: PyBuffer
        Return a structure describing the position in a byte array of a single item from the data being exported to the consumer. For a one-dimensional contiguous buffer, assuming the following client code where obj has type BufferProtocol:
         int k = ... ;
         PyBuffer a = obj.getBuffer(PyBUF.FULL);
         int itemsize = a.getItemsize();
         PyBuffer.Pointer b = a.getPointer(k);
         
        the item with index k is in the array b.storage at index [b.offset] to [b.offset + itemsize - 1] inclusive. And if itemsize==1, the item is simply the byte b.storage[b.offset]

        Essentially this is a method for computing the offset of a particular index. The client is free to navigate the underlying buffer b.storage without respecting these boundaries.

        Specified by:
        getPointer in interface PyBuffer
        Parameters:
        index - in the buffer to position the pointer
        Returns:
        structure defining the byte[] slice that is the shared data
        Throws:
        java.lang.IndexOutOfBoundsException
      • getPointer

        public PyBuffer.Pointer getPointer​(int... indices)
                                    throws java.lang.IndexOutOfBoundsException
        Description copied from interface: PyBuffer
        Return a structure describing the position in a byte array of a single item from the data being exported to the consumer, in the case that array may be multi-dimensional. For a 3-dimensional contiguous buffer, assuming the following client code where obj has type BufferProtocol:
         int i, j, k;
         // ... calculation that assigns i, j, k
         PyBuffer a = obj.getBuffer(PyBUF.FULL);
         int itemsize = a.getItemsize();
         PyBuffer.Pointer b = a.getPointer(i,j,k);
         
        the item with index [i,j,k] is in the array b.storage at index [b.offset] to [b.offset + itemsize - 1] inclusive. And if itemsize==1, the item is simply the byte b.storage[b.offset]

        Essentially this is a method for computing the offset of a particular index. The client is free to navigate the underlying buffer b.storage without respecting these boundaries. If the buffer is non-contiguous, the above description is still valid (since a multi-byte item must itself be contiguously stored), but in any additional navigation of b.storage[] to other items, the client must use the shape, strides and sub-offsets provided by the API. Normally one starts b = a.getBuf() in order to establish the offset of index [0,...,0].

        Specified by:
        getPointer in interface PyBuffer
        Parameters:
        indices - multidimensional index at which to position the pointer
        Returns:
        structure defining the byte[] slice that is the shared data
        Throws:
        java.lang.IndexOutOfBoundsException
      • getStrides

        public int[] getStrides()
        Description copied from interface: PyBUF
        The strides array gives the distance in the storage array between adjacent items (in each dimension). In the rawest parts of the buffer API, the consumer of the buffer is able to navigate the exported storage. The "strides" array is part of the support for interpreting the buffer as an n-dimensional array of items. It provides the coefficients of the "addressing polynomial". (More on this in the CPython documentation.) The consumer must not modify this array. A valid strides array is always returned (difference from CPython).
        Specified by:
        getStrides in interface PyBUF
        Returns:
        the distance in the storage array between adjacent items (in each dimension)
      • getSuboffsets

        public int[] getSuboffsets()
        Description copied from interface: PyBUF
        The suboffsets array is a further part of the support for interpreting the buffer as an n-dimensional array of items, where the array potentially uses indirect addressing (like a real Java array of arrays, in fact). This is only applicable when there is more than 1 dimension, and it works in conjunction with the strides array. (More on this in the CPython documentation.) When used, suboffsets[k] is an integer index, not a byte offset as in CPython. The consumer must not modify this array. When not needed for navigation null is returned (as in CPython).
        Specified by:
        getSuboffsets in interface PyBUF
        Returns:
        suboffsets array or null if not necessary for navigation
      • isContiguous

        public boolean isContiguous​(char order)
        Description copied from interface: PyBUF
        Enquire whether the array is represented contiguously in the backing storage, according to C or Fortran ordering. A one-dimensional contiguous array is both.
        Specified by:
        isContiguous in interface PyBUF
        Parameters:
        order - 'C', 'F' or 'A', as the storage order is C, Fortran or either.
        Returns:
        true iff the array is stored contiguously in the order specified
      • getFormat

        public java.lang.String getFormat()
        Description copied from interface: PyBuffer
        A format string in the language of Python structs describing how the bytes of each item should be interpreted. Irrespective of the PyBUF.FORMAT bit in the consumer's call to getBuffer, a valid format string is always returned (difference from CPython).

        Jython only implements "B" so far, and it is debatable whether anything fancier than "<n>B" can be supported in Java.

        Specified by:
        getFormat in interface PyBuffer
        Returns:
        the format string
      • getItemsize

        public int getItemsize()
        Description copied from interface: PyBUF
        The number of bytes stored in each indexable item.
        Specified by:
        getItemsize in interface PyBUF
        Returns:
        the number of bytes comprising each item.
      • toString

        public java.lang.String toString()
        The toString() method of a buffer reproduces the values in the buffer (as unsigned integers) as the character codes of a String.
        Specified by:
        toString in interface PyBuffer
        Overrides:
        toString in class java.lang.Object