# InputFilter

Definition
Description
Examples
Detailed Specification

## Definition

An InputFilter is a Filter whose `mode_of` refines input.

## Description

An InputFilter operates on the character sequence controlled by a Source, providing access to a filtered sequence having the same character type. It may expose the filtered sequence in two ways:

1. by defining a member function `get`
2. by defining a member function `read`

The second alternative is provided for enhanced performance. InputFilters implementing this alternative are referred to as Multi-Character. (See Multi-Character Filter.)

## Examples

#### I. Ordinary InputFilter

The following example shows an InputFilter which removes all non-alphabetic characters from a sequence.

        #include <ctype.h>                 // isalpha
        #include <cstdio.h>                // EOF
        #include <boost/iostreams/categories.hpp> // input_filter_tag
        #include <boost/iostreams/operations.hpp> // get, WOULD_BLOCK

        using namespace std;
        using namespace boost::iostreams;

        struct alphabetic_input_filter {
            typedef char              char_type;
            typedef input_filter_tag  category;

            template<typename Source>
            int get(Source& src)
            {
                int c;
                while ( (c = boost::iostreams::get(src)) != EOF &&
                         c != WOULD_BLOCK &&
                        !isalpha((unsigned char) c) )
                    ;
                return c;
            }
        };

Here `char_type` is the character type of the Filter, `input_filter_tag` is a category tag identifying the Filter as a model of InputFilter, and the function `boost::iostreams::get` reads a character from an arbitrary Source.[1] The constant `WOULD_BLOCK`, defined in the header `<boost/iostreams/char_traits.hpp>`, is used to indicate that input is temporarily unavilable.

The Iostreams library defines two convenience classes, `input_filter` and `input_wfilter`, which provide member `typedef`s `char_type` and `category` as well as default implementations of several member functions. When defining a new model of InputFilter, it is often sufficient to derive from `input_filter` or `input_wfilter` and to define a member function `get`.

#### II. Multi-Character InputFilter

The following example shows a Multi-Character InputFilter which performs the same filtering operation as the Filter in Example I.

        #include <ctype.h>                 // isalpha
        #include <cstdio.h>                // EOF
        #include <boost/iostreams/categories.hpp> // input_filter_tag
        #include <boost/iostreams/operations.hpp> // get

        using namespace std;
        using namespace boost::io;

        struct alphabetic_input_filter {
            typedef char                       char_type;
            typedef multichar_input_filter_tag  category;

            template<typename Source>
            streamsize read(Source& src, char* s, streamsize n)
                {
                    int   c;
                    char* first = s;
                    char* last  = s + n;
                    while ( first != last &&
                            (c = boost::iostreams::get(src)) != EOF &&
                             c != WOULD_BLOCK &&
                            isalpha((unsigned char) c) )
                    {
                        *first++ = c;
                    }
                    streamsize result = static_cast<streamsize>(first - s);
                    return result == 0 && c != WOULD_BLOCK ?
                        -1 :
                        result;
                }
        };

Here `multichar_input_filter_tag` is a category tag identifying the Filter as a Multi-Character InputFilter.

The Iostreams library defines two convenience classes, `multichar_input_filter` and `multichar_input_wfilter`, which provide the member `typedef`s `char_type` and `category` as well as default implementations of several member functions. When defining a new Multi-Character InputFilter, it is often sufficient to derive from `multichar_input_filter` or `multichar_input_wfilter` and to define a member function `read`.

## Refinement of

Filter.

## Associated Types

Character type | The type of the characters in the filtered sequences
Category | A type convertible to `filter_tag` and to `input`
Mode | The unique most-derived mode tag to which Category is convertible

## Notation

`F` | - A type which is a model of InputFilter
`D` | - A type which is a model of Device, with the same character type as `F` and with mode refining the mode of `F`
`Ch` | - The character type of `F`
`Tr` | - `boost::iostreams::char_traits<Ch>`
`f` | - Object of type `F`
`d` | - Object of type `D`
`s` | - Object of type `Ch*`
`n` | - Object of type `std::streamsize`
`io` | - Alias for namespace `boost::iostreams`

## Valid Expressions / Semantics

Expression | Expression Type | Category Precondition | Semantics
--- | --- | --- | ---
    typename char_type_of<F>::type
| `typename` of the character type | - | -
    typename category_of<F>::type
| `typename` of the category | - | -
    f.get(d)
| `Tr::int_type` | Convertible to `input` but not to `multichar_tag` | Returns the next character in the input sequence controlled by `f`, `Tr::eof()` if the end of the sequence has been reached or `Tr::would_block()` if input is temporarily unavilable because a call to `d` has produced fewer characters than requested. The input sequence controlled by `d` may be accessed using `io::get`, `io::read` and `io::putback`.
    f.read(d, s, n)
    std::streamsize
| Convertible to `input` and to `multichar_tag` | Reads up to `n` characters from the input sequence controlled by `f` into the buffer `s`, returning the number of characters read or `-1` to indicate end-of-sequence. A value less than `n` may be returned only at end-of-sequence or if input is temporarily unavilable because a call to `d` has produced fewer characters than requested. The input sequence controlled by `d` may be accessed using `io::get`, `io::read` and `io::putback`.

## Exceptions

Errors which occur during the execution of `get` and `read` are indicated by throwing exceptions. Reaching the end of the sequence is not an error.

After an exception is thrown, an InputFilter must be in a consistent state; further i/o operations may throw exceptions but must have well-defined behaviour. Furthermore, unless it is Closable, it must be ready to begin processing a new character sequence.

## Models

- The Text Processing Filters.
- The compression and decompression filters.

## Acknowledgments

The concept InputFilter was inspired by the extractors of [Kanze].

[1]Technically, `boost::iostreams::get` requires that a Source be indirect.

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)