# SeekableDevice

## Definition

A SeekableDevice is a Device whose `mode_of` refines seekable.

## Description

A SeekableDevice provides read- write- and random-access to a sequence of characters of a given type, with a single repositionable read/write head. A SeekableDevice may expose this sequence in two ways:

1. by defining member functions `read`, `write` and `seek`; or
2. by defining member functions `input_sequence` and `output_sequence`, returning pairs of pointers delimiting the sequences in its entirety. The return values of these two functions must be the same.[1]

A SeekableDevice has mode `seekable`.

## Note

To be usable with streams and stream buffers, SeekableDevices must model Blocking.

## Example

A model of SeekableDevice can be defined as follows:

    struct SeekableDevice {
        typedef char                 char_type;
        typedef seekable_device_tag  category;
        std::streamsize read(char* s, std::streamsize n)
            {
                // Read up to n characters from the input
                // sequence into the buffer s, returning
                // the number of characters read, or -1
                // to indicate end-of-sequence.
            }
        void write(const char* s, std::streamsize n)
            {
                // Write up to n characters from the buffer
                // s to the output sequence, returning the
                // number of characters written
            }
        std::streampos seek(stream_offset off, std::ios_base::seekdir way)
            {
                // Advances the read/write head by off characters,
                // returning the new position, where the offset is
                // calculated from:
                //  - the start of the sequence if way == ios_base::beg
                //  - the current position if way == ios_base::cur
                //  - the end of the sequence if way == ios_base::end
            }
    };

Here `seekable_device_tag` is a category tag identifying the containing type as a model of SeekableDevice. When defining a new SeekableDevice, it suffices to use the tag `seekable_device_tag`. One can also derive from the helper classes `device<seekable>` or `wdevice<seekable>`.

## Refinement of

Source, Sink.

## Associated Types

Same as Device, with the following additional requirements:

Category | A type convertible to `device_tag` and to `seekable`

## Notation

`D` | - A type which is a model of SeekableDevice
`Ch` | - The character type of `D`
`dev` | - Object of type `D`
`s1` | - Object of type `Ch*`
`s2` | - Object of type `const Ch*`
`n` | - Object of type `std::streamsize`
`off` | - Object of type `stream_offset`
`way` | - Object of type `std::ios_base::seekdir`
`io` | - Alias for namespace `boost::iostreams`

## Valid Expressions / Semantics

Same as Device, with the following additional requirements:

Expression | Expression Type | Category Precondition | Semantics
--- | --- | --- | ---
    io::read(dev, s1, n)
| `std::streamsize` | Not convertible to `direct_tag` | Reads up to `n` characters from the sequence controlled by `dev` into `s1`, returning the number of characters read, or `-1` to indicate end-of-sequence
    io::write(dev, s2, n)
| `std::streamsize` | Writes up to `n` characters from the sequence beginning at `s2` to the sequence controlled by `dev`, returning the number of characters written
    io::seek(dev, off, way)
| `std::streampos` | Advances the read/write head by `off` characters, returning the new position, where the offset is calculated from:

- the start of the sequence if `way` is `ios_base::beg`
- the current position if `way` is `ios_base::cur`
- the end of the sequence if `way` is `ios_base::end`

    dev.input_sequence()
    std::pair<Ch*,Ch*>
| Convertible to `direct_tag` | Returns a pair of pointers delimiting the sequence controlled by `dev`
    dev.output_sequence()
    std::pair<Ch*,Ch*>
| Returns a pair of pointers delimiting the sequence controlled by `dev`

## Exceptions

Errors which occur during the execution of member functions `read`, `write`, `seek`, `input_sequence` or `output_sequence` are indicated by throwing exceptions. Reaching the end of the sequence is not an error, but attempting to write past the end of the sequence is.

After an exception is thrown, a SeekableDevice must be in a consistent state; further i/o operations may throw exceptions but must have well-defined behaviour.

## Models

- `array`, `file`, `file_descriptor`, `mapped_file`.

[1]A more elegant specification would require a single member function `sequence`; the present version was selected to simplify the implementation of `stream_buffer`.

Revised 20 May, 2004

© Copyright Jonathan Turkanis, 2004

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)