# Class DataStorage

java.lang.Object
org.apfloat.spi.DataStorage

All Implemented Interfaces:
  `Serializable`

Direct Known Subclasses:
  `DiskDataStorage, DoubleMemoryDataStorage, FloatMemoryDataStorage, IntMemoryDataStorage, LongMemoryDataStorage`

public abstract class DataStorage extends Object implements Serializable
Generic data storage class.

Initially when a data storage is created, it is mutable (it can be modified). After the contents have been properly set, the user should call `setReadOnly()` to set the storage to be immutable. After this the data storage can be safely shared between different users.

Access to `DataStorage` objects is generally not internally synchronized. Accessing multiple non-overlapping parts of the storage concurrently with the `getArray(int,long,int)`, `getArray(int,int,int,int)` or `getTransposedArray(int,int,int,int)` method and with iterators over non-overlapping parts is permitted. Invoking other methods must generally be externally synchronized.

Version:
  1.15.0
Author:
  Mikko Tommila
See Also:
  - Serialized Form

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected class`
  `DataStorage.AbstractIterator`
  Abstract base class for iterators iterating through this `DataStorage`.
  `static class`
  `DataStorage.Iterator`
  Iterator for iterating through elements of the data storage.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final int`
  `READ`
  Read access mode specifier.
  `static final int`
  `READ_WRITE`
  Read-write access mode specifier.
  `static final int`
  `WRITE`
  Write access mode specifier.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `DataStorage()`
  Default constructor.
  `protected`
  `DataStorage(DataStorage dataStorage, long offset, long length)`
  Subsequence constructor.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `final void`
  `copyFrom(DataStorage dataStorage)`
  Copies all data from another data storage to this data storage.
  `final void`
  `copyFrom(DataStorage dataStorage, long size)`
  Copies the specified number of elements from another data storage to this data storage.
  `final ArrayAccess`
  `getArray(int mode, int startColumn, int columns, int rows)`
  Maps a block of data to a memory array when the data is treated as a matrix.
  `final ArrayAccess`
  `getArray(int mode, long offset, int length)`
  Gets an array access to the data of this data storage when the data is treated as a linear block.
  `protected final long`
  `getOffset()`
  Return the sub-sequence offset.
  `final long`
  `getSize()`
  Return the size of the data storage, or the length of this sub-sequence if this data storage is a sub-sequence.
  `final ArrayAccess`
  `getTransposedArray(int mode, int startColumn, int columns, int rows)`
  Maps a transposed block of data to a memory array when the data is treated as a matrix.
  `protected abstract void`
  `implCopyFrom(DataStorage dataStorage, long size)`
  Copies the specified number of elements from another data storage to this data storage.
  `protected abstract ArrayAccess`
  `implGetArray(int mode, int startColumn, int columns, int rows)`
  Maps a block of data to a memory array when the data is treated as a matrix.
  `protected abstract ArrayAccess`
  `implGetArray(int mode, long offset, int length)`
  Gets an array access to the data of this data storage when it is treated as a linear block.
  `protected abstract long`
  `implGetSize()`
  Return the size of the whole data storage, not including sub-sequence settings.
  `protected abstract ArrayAccess`
  `implGetTransposedArray(int mode, int startColumn, int columns, int rows)`
  Maps a transposed block of data to a memory array when the data is treated as a matrix.
  `protected abstract void`
  `implSetSize(long size)`
  Sets the size of the data storage.
  `protected abstract DataStorage`
  `implSubsequence(long offset, long length)`
  Implementation of getting a subsequence of this data storage.
  `abstract boolean`
  `isCached()`
  Is this object cached in memory.
  `final boolean`
  `isReadOnly()`
  Returns the read-only state of this data storage.
  `final boolean`
  `isSubsequenced()`
  Is this object a subsequence of some other object, or do subsequences of this object exist.
  `abstract DataStorage.Iterator`
  `iterator(int mode, long startPosition, long endPosition)`
  Constructs a new iterator.
  `final void`
  `setReadOnly()`
  Sets this data storage as read-only.
  `final void`
  `setSize(long size)`
  Sets the size of the data storage.
  `final DataStorage`
  `subsequence(long offset, long length)`
  Get a subsequence of this data storage.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### READ

    public static final int READ
    Read access mode specifier.
    See Also:
      - Constant Field Values

  - ### WRITE

    public static final int WRITE
    Write access mode specifier.
    See Also:
      - Constant Field Values

  - ### READ_WRITE

    public static final int READ_WRITE
    Read-write access mode specifier. For convenience, equivalent to `READ | WRITE`.
    See Also:
      - Constant Field Values

- ## Constructor Details

  - ### DataStorage

    protected DataStorage()
    Default constructor. To be called by subclasses when creating a new empty `DataStorage`.

  - ### DataStorage

    protected DataStorage(DataStorage dataStorage, long offset, long length)
    Subsequence constructor. To be called by subclasses when creating a subsequence of an existing DataStorage.
    Parameters:
      `dataStorage` - The originating data storage.
      `offset` - The subsequence starting position.
      `length` - The subsequence length.

- ## Method Details

  - ### subsequence

    public final DataStorage subsequence(long offset, long length) throws IllegalArgumentException, ApfloatRuntimeException
    Get a subsequence of this data storage.
    Parameters:
      `offset` - The subsequence starting position.
      `length` - The subsequence length.
    Returns:
      Data storage that represents the specified part of this data storage.
    Throws:
      `IllegalArgumentException` - If the requested subsequence is out of range.
      `ApfloatRuntimeException`

  - ### implSubsequence

    protected abstract DataStorage implSubsequence(long offset, long length) throws ApfloatRuntimeException
    Implementation of getting a subsequence of this data storage. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `offset` - The subsequence starting position.
      `length` - The subsequence length.
    Returns:
      Data storage that represents the specified part of this data storage.
    Throws:
      `ApfloatRuntimeException`

  - ### copyFrom

    public final void copyFrom(DataStorage dataStorage) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Copies all data from another data storage to this data storage.
    Parameters:
      `dataStorage` - The data storage where the data should be copied from.
    Throws:
      `IllegalArgumentException` - If the origin data source has a size of zero.
      `IllegalStateException` - If this data storage is read-only or has subsequences.
      `ApfloatRuntimeException`

  - ### copyFrom

    public final void copyFrom(DataStorage dataStorage, long size) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Copies the specified number of elements from another data storage to this data storage.
    Parameters:
      `dataStorage` - The data storage where the data should be copied from.
      `size` - The number of elements to be copied.
    Throws:
      `IllegalArgumentException` - If the size is invalid or zero.
      `IllegalStateException` - If this data storage is read-only or has subsequences.
      `ApfloatRuntimeException`

  - ### implCopyFrom

    protected abstract void implCopyFrom(DataStorage dataStorage, long size) throws ApfloatRuntimeException
    Copies the specified number of elements from another data storage to this data storage. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `dataStorage` - The data storage where the data should be copied from.
      `size` - The number of elements to be copied.
    Throws:
      `ApfloatRuntimeException`

  - ### getSize

    public final long getSize() throws ApfloatRuntimeException
    Return the size of the data storage, or the length of this sub-sequence if this data storage is a sub-sequence.
    Returns:
      The size of the data storage.
    Throws:
      `ApfloatRuntimeException`

  - ### implGetSize

    protected abstract long implGetSize() throws ApfloatRuntimeException
    Return the size of the whole data storage, not including sub-sequence settings.
    Returns:
      The size of the whole data storage, not including sub-sequence settings.
    Throws:
      `ApfloatRuntimeException`

  - ### setSize

    public final void setSize(long size) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Sets the size of the data storage.
    Parameters:
      `size` - The size of the data storage.
    Throws:
      `IllegalArgumentException` - If the size is invalid or zero.
      `IllegalStateException` - If this data storage is read-only or has subsequences.
      `ApfloatRuntimeException`

  - ### implSetSize

    protected abstract void implSetSize(long size) throws ApfloatRuntimeException
    Sets the size of the data storage. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `size` - The size of the data storage.
    Throws:
      `ApfloatRuntimeException`

  - ### isReadOnly

    public final boolean isReadOnly()
    Returns the read-only state of this data storage.
    Returns:
      `true` if this data storage is read-only, otherwise `false`.

  - ### setReadOnly

    public final void setReadOnly() throws ApfloatRuntimeException
    Sets this data storage as read-only. All existing sub-sequences (recursively) of this data storage are set to read-only as well.
    Throws:
      `ApfloatRuntimeException`

  - ### getArray

    public final ArrayAccess getArray(int mode, long offset, int length) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Gets an array access to the data of this data storage when the data is treated as a linear block.
    Parameters:
      `mode` - Access mode for the array access: `READ`, `WRITE` or both.
      `offset` - Starting position of the array access in the data storage.
      `length` - Number of accessible elements in the array access.
    Returns:
      The array access.
    Throws:
      `IllegalArgumentException` - If the offset or length are out of bounds of the data storage.
      `IllegalStateException` - If write access is requested for a read-only data storage.
      `ApfloatRuntimeException`

  - ### implGetArray

    protected abstract ArrayAccess implGetArray(int mode, long offset, int length) throws ApfloatRuntimeException
    Gets an array access to the data of this data storage when it is treated as a linear block. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `mode` - Access mode for the array access: `READ`, `WRITE` or both.
      `offset` - Starting position of the array access in the data storage.
      `length` - Number of accessible elements in the array access.
    Returns:
      The array access.
    Throws:
      `ApfloatRuntimeException`

  - ### getArray

    public final ArrayAccess getArray(int mode, int startColumn, int columns, int rows) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Maps a block of data to a memory array when the data is treated as a matrix. The matrix size is n1 x n2. The following picture illustrates the block being accessed (in gray):

    Matrix
    `← startColumn →` | `← columns →` | `↑ n1 ↓`
    `← n2 →`

    Parameters:
      `mode` - Whether the array is prepared for reading, writing or both. The value should be `READ`, `WRITE` or a combination of these.
      `startColumn` - The starting column where data is read.
      `columns` - The number of columns of data to read.
      `rows` - The number of rows of data to read. This should be equivalent to n1, number of rows in the matrix.
    Returns:
      Access to an array of size `columns` x `rows` containing the data.
    Throws:
      `IllegalArgumentException` - If the requested area is out of bounds of the data storage.
      `IllegalStateException` - If write access is requested for a read-only data storage.
      `ApfloatRuntimeException`
    Since:
      1.7.0

  - ### implGetArray

    protected abstract ArrayAccess implGetArray(int mode, int startColumn, int columns, int rows) throws ApfloatRuntimeException
    Maps a block of data to a memory array when the data is treated as a matrix. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `mode` - Whether the array is prepared for reading, writing or both. The value should be `READ`, `WRITE` or a combination of these.
      `startColumn` - The starting column where data is read.
      `columns` - The number of columns of data to read.
      `rows` - The number of rows of data to read. This should be equivalent to n1, number of rows in the matrix.
    Returns:
      Access to an array of size `columns` x `rows` containing the data.
    Throws:
      `ApfloatRuntimeException`
    Since:
      1.7.0

  - ### getTransposedArray

    public final ArrayAccess getTransposedArray(int mode, int startColumn, int columns, int rows) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Maps a transposed block of data to a memory array when the data is treated as a matrix. The matrix size is n1 x n2. The accessed block is illustrated in gray in the following picture. The argument `columns` is the value `b`:

    Matrix
    `← startColumn →` | `A` | `↑ n1 ↓`
    `B`
    `C`
    `D`
    `← b →`
    `← n2 →`

    The data is read from an n1 x b area of the matrix, in blocks of b elements, to a b x n1 memory array as follows:

    Read matrix section
    `A` | `↑ b ↓`
    `B`
    `C`
    `D`
    `← n1 →`

    Each b x b block is transposed, to form the final b x n1 array in memory, where the columns are located linearly:

    Transposed matrix section
    `A` | `B` | `C` | `D` | `↑ b ↓`
    `← n1 →`

    Parameters:
      `mode` - Whether the array is prepared for reading, writing or both. The value should be `READ`, `WRITE` or a combination of these.
      `startColumn` - The starting column where data is read.
      `columns` - The number of columns of data to read.
      `rows` - The number of rows of data to read. This should be equivalent to n1, number of rows in the matrix.
    Returns:
      Access to an array of size `columns` x `rows` containing the transposed data.
    Throws:
      `IllegalArgumentException` - If the requested area is out of bounds of the data storage.
      `IllegalStateException` - If write access is requested for a read-only data storage.
      `ApfloatRuntimeException`

  - ### implGetTransposedArray

    protected abstract ArrayAccess implGetTransposedArray(int mode, int startColumn, int columns, int rows) throws ApfloatRuntimeException
    Maps a transposed block of data to a memory array when the data is treated as a matrix. The validity of the arguments of this method do not need to be checked.
    Parameters:
      `mode` - Whether the array is prepared for reading, writing or both. The value should be `READ`, `WRITE` or a combination of these.
      `startColumn` - The starting column where data is read.
      `columns` - The number of columns of data to read.
      `rows` - The number of rows of data to read. This should be equivalent to n1, number of rows in the matrix.
    Returns:
      Access to an array of size `columns` x `rows` containing the transposed data.
    Throws:
      `ApfloatRuntimeException`

  - ### iterator

    public abstract DataStorage.Iterator iterator(int mode, long startPosition, long endPosition) throws IllegalArgumentException, IllegalStateException, ApfloatRuntimeException
    Constructs a new iterator. Elements can be iterated either in forward or in reverse order, depending on if `startPosition` is less than or greater than `endPosition`, correspondingly.
    Parameters:
      `mode` - Access mode for iterator: `READ`, `WRITE` or both.
      `startPosition` - Starting position of iterator in the data set. For reverse access, the first element in the iterator is `startPosition - 1`.
      `endPosition` - End position of iterator in the data set. For forward access, the last accessible element in the iterator is `endPosition - 1`.
    Returns:
      An iterator.
    Throws:
      `IllegalArgumentException` - If the requested area is out of bounds of the data storage.
      `IllegalStateException` - If write access is requested for a read-only data storage.
      `ApfloatRuntimeException`

  - ### isSubsequenced

    public final boolean isSubsequenced()
    Is this object a subsequence of some other object, or do subsequences of this object exist.
    Returns:
      `true` if this object is a subsequence of some other object, or if subsequences of this object exist, `false` otherwise.

  - ### isCached

    public abstract boolean isCached()
    Is this object cached in memory.
    Returns:
      `true` if this object is cached in memory, `false` if not.
    Since:
      1.7.0

  - ### getOffset

    protected final long getOffset()
    Return the sub-sequence offset.
    Returns:
      Absolute offset of the sub-sequence within the (top-level) base data storage.